aboutsummaryrefslogtreecommitdiffstats
path: root/libjulia/backends/evm
diff options
context:
space:
mode:
Diffstat (limited to 'libjulia/backends/evm')
-rw-r--r--libjulia/backends/evm/EVMCodeTransform.cpp89
-rw-r--r--libjulia/backends/evm/EVMCodeTransform.h26
2 files changed, 75 insertions, 40 deletions
diff --git a/libjulia/backends/evm/EVMCodeTransform.cpp b/libjulia/backends/evm/EVMCodeTransform.cpp
index 7c14eb8b..b231ecec 100644
--- a/libjulia/backends/evm/EVMCodeTransform.cpp
+++ b/libjulia/backends/evm/EVMCodeTransform.cpp
@@ -33,26 +33,6 @@ using namespace dev::julia;
using namespace dev::solidity;
using namespace dev::solidity::assembly;
-void CodeTransform::run(Block const& _block)
-{
- m_scope = m_info.scopes.at(&_block).get();
-
- int blockStartStackHeight = m_assembly.stackHeight();
- std::for_each(_block.statements.begin(), _block.statements.end(), boost::apply_visitor(*this));
-
- m_assembly.setSourceLocation(_block.location);
-
- // pop variables
- for (auto const& identifier: m_scope->identifiers)
- if (identifier.second.type() == typeid(Scope::Variable))
- m_assembly.appendInstruction(solidity::Instruction::POP);
-
- int deposit = m_assembly.stackHeight() - blockStartStackHeight;
- solAssert(deposit == 0, "Invalid stack height at end of block.");
- checkStackHeight(&_block);
-}
-
-
void CodeTransform::operator()(VariableDeclaration const& _varDecl)
{
solAssert(m_scope, "");
@@ -315,7 +295,7 @@ void CodeTransform::operator()(FunctionDefinition const& _function)
}
CodeTransform(m_assembly, m_info, m_evm15, m_identifierAccess, localStackAdjustment, m_context)
- .run(_function.body);
+ (_function.body);
{
// The stack layout here is:
@@ -358,9 +338,54 @@ void CodeTransform::operator()(FunctionDefinition const& _function)
checkStackHeight(&_function);
}
+void CodeTransform::operator()(ForLoop const& _forLoop)
+{
+ Scope* originalScope = m_scope;
+ // We start with visiting the block, but not finalizing it.
+ m_scope = m_info.scopes.at(&_forLoop.pre).get();
+ int stackStartHeight = m_assembly.stackHeight();
+
+ visitStatements(_forLoop.pre.statements);
+
+ // TODO: When we implement break and continue, the labels and the stack heights at that point
+ // have to be stored in a stack.
+ AbstractAssembly::LabelID loopStart = m_assembly.newLabelId();
+ AbstractAssembly::LabelID loopEnd = m_assembly.newLabelId();
+ AbstractAssembly::LabelID postPart = m_assembly.newLabelId();
+
+ m_assembly.setSourceLocation(_forLoop.location);
+ m_assembly.appendLabel(loopStart);
+
+ visitExpression(*_forLoop.condition);
+ m_assembly.setSourceLocation(_forLoop.location);
+ m_assembly.appendInstruction(solidity::Instruction::ISZERO);
+ m_assembly.appendJumpToIf(loopEnd);
+
+ (*this)(_forLoop.body);
+
+ m_assembly.setSourceLocation(_forLoop.location);
+ m_assembly.appendLabel(postPart);
+
+ (*this)(_forLoop.post);
+
+ m_assembly.setSourceLocation(_forLoop.location);
+ m_assembly.appendJumpTo(loopStart);
+ m_assembly.appendLabel(loopEnd);
+
+ finalizeBlock(_forLoop.pre, stackStartHeight);
+ m_scope = originalScope;
+}
+
void CodeTransform::operator()(Block const& _block)
{
- CodeTransform(m_assembly, m_info, m_evm15, m_identifierAccess, m_stackAdjustment, m_context).run(_block);
+ Scope* originalScope = m_scope;
+ m_scope = m_info.scopes.at(&_block).get();
+
+ int blockStartStackHeight = m_assembly.stackHeight();
+ visitStatements(_block.statements);
+
+ finalizeBlock(_block, blockStartStackHeight);
+ m_scope = originalScope;
}
AbstractAssembly::LabelID CodeTransform::labelFromIdentifier(Identifier const& _identifier)
@@ -401,6 +426,26 @@ void CodeTransform::visitExpression(Statement const& _expression)
expectDeposit(1, height);
}
+void CodeTransform::visitStatements(vector<Statement> const& _statements)
+{
+ for (auto const& statement: _statements)
+ boost::apply_visitor(*this, statement);
+}
+
+void CodeTransform::finalizeBlock(Block const& _block, int blockStartStackHeight)
+{
+ m_assembly.setSourceLocation(_block.location);
+
+ // pop variables
+ solAssert(m_info.scopes.at(&_block).get() == m_scope, "");
+ for (size_t i = 0; i < m_scope->numberOfVariables(); ++i)
+ m_assembly.appendInstruction(solidity::Instruction::POP);
+
+ int deposit = m_assembly.stackHeight() - blockStartStackHeight;
+ solAssert(deposit == 0, "Invalid stack height at end of block.");
+ checkStackHeight(&_block);
+}
+
void CodeTransform::generateAssignment(Identifier const& _variableName)
{
solAssert(m_scope, "");
diff --git a/libjulia/backends/evm/EVMCodeTransform.h b/libjulia/backends/evm/EVMCodeTransform.h
index 202f5051..d09ee87b 100644
--- a/libjulia/backends/evm/EVMCodeTransform.h
+++ b/libjulia/backends/evm/EVMCodeTransform.h
@@ -21,6 +21,7 @@
#include <libjulia/backends/evm/EVMAssembly.h>
#include <libsolidity/inlineasm/AsmScope.h>
+#include <libsolidity/inlineasm/AsmDataForward.h>
#include <boost/variant.hpp>
#include <boost/optional.hpp>
@@ -32,21 +33,6 @@ namespace solidity
class ErrorReporter;
namespace assembly
{
-struct Literal;
-struct Block;
-struct Switch;
-struct Label;
-struct FunctionalInstruction;
-struct Assignment;
-struct VariableDeclaration;
-struct Instruction;
-struct Identifier;
-struct StackAssignment;
-struct FunctionDefinition;
-struct FunctionCall;
-
-using Statement = boost::variant<Instruction, Literal, Label, StackAssignment, Identifier, Assignment, FunctionCall, FunctionalInstruction, VariableDeclaration, FunctionDefinition, Switch, Block>;
-
struct AsmAnalysisInfo;
}
}
@@ -75,9 +61,6 @@ public:
{
}
- /// Processes the block and appends the resulting code to the assembly.
- void run(solidity::assembly::Block const& _block);
-
protected:
struct Context
{
@@ -115,6 +98,7 @@ public:
void operator()(solidity::assembly::VariableDeclaration const& _varDecl);
void operator()(solidity::assembly::Switch const& _switch);
void operator()(solidity::assembly::FunctionDefinition const&);
+ void operator()(solidity::assembly::ForLoop const&);
void operator()(solidity::assembly::Block const& _block);
private:
@@ -126,6 +110,12 @@ private:
/// Generates code for an expression that is supposed to return a single value.
void visitExpression(solidity::assembly::Statement const& _expression);
+ void visitStatements(std::vector<solidity::assembly::Statement> const& _statements);
+
+ /// Pops all variables declared in the block and checks that the stack height is equal
+ /// to @a _blackStartStackHeight.
+ void finalizeBlock(solidity::assembly::Block const& _block, int _blockStartStackHeight);
+
void generateAssignment(solidity::assembly::Identifier const& _variableName);
/// Determines the stack height difference to the given variables. Throws