From 47925bc14e80d0c33c491dabc3c3dd3ea787b63c Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Fri, 28 Apr 2017 14:33:52 +0100 Subject: Parse for statement in assembly parser / printer --- libjulia/backends/evm/EVMCodeTransform.cpp | 5 +++++ libjulia/backends/evm/EVMCodeTransform.h | 16 +--------------- 2 files changed, 6 insertions(+), 15 deletions(-) (limited to 'libjulia/backends') diff --git a/libjulia/backends/evm/EVMCodeTransform.cpp b/libjulia/backends/evm/EVMCodeTransform.cpp index 7c14eb8b..00d0bde5 100644 --- a/libjulia/backends/evm/EVMCodeTransform.cpp +++ b/libjulia/backends/evm/EVMCodeTransform.cpp @@ -53,6 +53,11 @@ void CodeTransform::run(Block const& _block) } +void CodeTransform::operator()(ForLoop const&) +{ + solAssert(false, "For loop not removed during desugaring phase."); +} + void CodeTransform::operator()(VariableDeclaration const& _varDecl) { solAssert(m_scope, ""); diff --git a/libjulia/backends/evm/EVMCodeTransform.h b/libjulia/backends/evm/EVMCodeTransform.h index 202f5051..9814f0f5 100644 --- a/libjulia/backends/evm/EVMCodeTransform.h +++ b/libjulia/backends/evm/EVMCodeTransform.h @@ -32,21 +32,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; - struct AsmAnalysisInfo; } } @@ -115,6 +100,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: -- cgit v1.2.3 From 8e5c4bf21dfd9cfaa8de35aef034bb32be290a48 Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 1 Jun 2017 15:41:51 +0200 Subject: Add include file to forward-declare inline assembly structs. --- libjulia/backends/evm/EVMCodeTransform.h | 1 + 1 file changed, 1 insertion(+) (limited to 'libjulia/backends') diff --git a/libjulia/backends/evm/EVMCodeTransform.h b/libjulia/backends/evm/EVMCodeTransform.h index 9814f0f5..7824247a 100644 --- a/libjulia/backends/evm/EVMCodeTransform.h +++ b/libjulia/backends/evm/EVMCodeTransform.h @@ -21,6 +21,7 @@ #include #include +#include #include #include -- cgit v1.2.3 From 78b49db779376b8ddedc0abb91a82a3384def4f1 Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 1 Jun 2017 15:47:11 +0200 Subject: Helper to count the number of variables in a scope. --- libjulia/backends/evm/EVMCodeTransform.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'libjulia/backends') diff --git a/libjulia/backends/evm/EVMCodeTransform.cpp b/libjulia/backends/evm/EVMCodeTransform.cpp index 00d0bde5..64e13f94 100644 --- a/libjulia/backends/evm/EVMCodeTransform.cpp +++ b/libjulia/backends/evm/EVMCodeTransform.cpp @@ -43,9 +43,8 @@ void CodeTransform::run(Block const& _block) 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); + 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."); -- cgit v1.2.3 From 868b5ad3aa9741609e9cd79d6033ee4b172dbe2f Mon Sep 17 00:00:00 2001 From: chriseth Date: Fri, 9 Jun 2017 13:59:16 +0200 Subject: Split block code generation into main and finalize. --- libjulia/backends/evm/EVMCodeTransform.cpp | 43 ++++++++++++++++-------------- libjulia/backends/evm/EVMCodeTransform.h | 7 ++--- 2 files changed, 27 insertions(+), 23 deletions(-) (limited to 'libjulia/backends') diff --git a/libjulia/backends/evm/EVMCodeTransform.cpp b/libjulia/backends/evm/EVMCodeTransform.cpp index 64e13f94..e313e69c 100644 --- a/libjulia/backends/evm/EVMCodeTransform.cpp +++ b/libjulia/backends/evm/EVMCodeTransform.cpp @@ -33,24 +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 (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::operator()(ForLoop const&) { @@ -319,7 +301,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: @@ -364,7 +346,14 @@ void CodeTransform::operator()(FunctionDefinition const& _function) 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(); + std::for_each(_block.statements.begin(), _block.statements.end(), boost::apply_visitor(*this)); + + finalizeBlock(_block, blockStartStackHeight); + m_scope = originalScope; } AbstractAssembly::LabelID CodeTransform::labelFromIdentifier(Identifier const& _identifier) @@ -405,6 +394,20 @@ void CodeTransform::visitExpression(Statement const& _expression) expectDeposit(1, height); } +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 7824247a..57bd4ca5 100644 --- a/libjulia/backends/evm/EVMCodeTransform.h +++ b/libjulia/backends/evm/EVMCodeTransform.h @@ -61,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 { @@ -113,6 +110,10 @@ private: /// Generates code for an expression that is supposed to return a single value. void visitExpression(solidity::assembly::Statement const& _expression); + /// 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 -- cgit v1.2.3 From 0745628a734c5d22b6c9cd878aaa3ec6795df115 Mon Sep 17 00:00:00 2001 From: chriseth Date: Fri, 9 Jun 2017 13:59:26 +0200 Subject: Code generation for for-loops. --- libjulia/backends/evm/EVMCodeTransform.cpp | 44 ++++++++++++++++++++++++++---- 1 file changed, 38 insertions(+), 6 deletions(-) (limited to 'libjulia/backends') diff --git a/libjulia/backends/evm/EVMCodeTransform.cpp b/libjulia/backends/evm/EVMCodeTransform.cpp index e313e69c..a50af9af 100644 --- a/libjulia/backends/evm/EVMCodeTransform.cpp +++ b/libjulia/backends/evm/EVMCodeTransform.cpp @@ -33,12 +33,6 @@ using namespace dev::julia; using namespace dev::solidity; using namespace dev::solidity::assembly; - -void CodeTransform::operator()(ForLoop const&) -{ - solAssert(false, "For loop not removed during desugaring phase."); -} - void CodeTransform::operator()(VariableDeclaration const& _varDecl) { solAssert(m_scope, ""); @@ -344,6 +338,44 @@ 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(); + + for (auto const& statement: _forLoop.pre.statements) + boost::apply_visitor(*this, statement); + + // 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.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) { Scope* originalScope = m_scope; -- cgit v1.2.3 From ce5ef08e05667d74283f18f79c3bb5970f39e946 Mon Sep 17 00:00:00 2001 From: chriseth Date: Wed, 14 Jun 2017 15:35:51 +0200 Subject: Helper for visiting statements. --- libjulia/backends/evm/EVMCodeTransform.cpp | 11 ++++++++--- libjulia/backends/evm/EVMCodeTransform.h | 2 ++ 2 files changed, 10 insertions(+), 3 deletions(-) (limited to 'libjulia/backends') diff --git a/libjulia/backends/evm/EVMCodeTransform.cpp b/libjulia/backends/evm/EVMCodeTransform.cpp index a50af9af..c543a507 100644 --- a/libjulia/backends/evm/EVMCodeTransform.cpp +++ b/libjulia/backends/evm/EVMCodeTransform.cpp @@ -345,8 +345,7 @@ void CodeTransform::operator()(ForLoop const& _forLoop) m_scope = m_info.scopes.at(&_forLoop.pre).get(); int stackStartHeight = m_assembly.stackHeight(); - for (auto const& statement: _forLoop.pre.statements) - boost::apply_visitor(*this, statement); + 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. @@ -382,7 +381,7 @@ void CodeTransform::operator()(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)); + visitStatements(_block.statements); finalizeBlock(_block, blockStartStackHeight); m_scope = originalScope; @@ -426,6 +425,12 @@ void CodeTransform::visitExpression(Statement const& _expression) expectDeposit(1, height); } +void CodeTransform::visitStatements(vector 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); diff --git a/libjulia/backends/evm/EVMCodeTransform.h b/libjulia/backends/evm/EVMCodeTransform.h index 57bd4ca5..d09ee87b 100644 --- a/libjulia/backends/evm/EVMCodeTransform.h +++ b/libjulia/backends/evm/EVMCodeTransform.h @@ -110,6 +110,8 @@ 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 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); -- cgit v1.2.3 From 667a9d32aa5670303b145eddac16a8ad1f7a72e4 Mon Sep 17 00:00:00 2001 From: chriseth Date: Wed, 14 Jun 2017 15:37:14 +0200 Subject: Set source location for for start label. --- libjulia/backends/evm/EVMCodeTransform.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'libjulia/backends') diff --git a/libjulia/backends/evm/EVMCodeTransform.cpp b/libjulia/backends/evm/EVMCodeTransform.cpp index c543a507..b231ecec 100644 --- a/libjulia/backends/evm/EVMCodeTransform.cpp +++ b/libjulia/backends/evm/EVMCodeTransform.cpp @@ -353,6 +353,7 @@ void CodeTransform::operator()(ForLoop const& _forLoop) AbstractAssembly::LabelID loopEnd = m_assembly.newLabelId(); AbstractAssembly::LabelID postPart = m_assembly.newLabelId(); + m_assembly.setSourceLocation(_forLoop.location); m_assembly.appendLabel(loopStart); visitExpression(*_forLoop.condition); -- cgit v1.2.3