From 72fdf755c99c7e90ac973fad8b28e39aed5cc2fa Mon Sep 17 00:00:00 2001 From: chriseth Date: Fri, 17 Feb 2017 12:03:55 +0100 Subject: Register functions. --- libsolidity/inlineasm/AsmCodeGen.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'libsolidity/inlineasm/AsmCodeGen.cpp') diff --git a/libsolidity/inlineasm/AsmCodeGen.cpp b/libsolidity/inlineasm/AsmCodeGen.cpp index fdfd9abe..d5931960 100644 --- a/libsolidity/inlineasm/AsmCodeGen.cpp +++ b/libsolidity/inlineasm/AsmCodeGen.cpp @@ -66,7 +66,7 @@ struct GeneratorState return size_t(id); } - std::map> scopes; + AsmAnalyzer::Scopes scopes; ErrorList& errors; eth::Assembly& assembly; }; -- cgit v1.2.3 From 5d6747eb32f56f6b8b818eff5635888d250d62e1 Mon Sep 17 00:00:00 2001 From: chriseth Date: Fri, 17 Feb 2017 16:05:22 +0100 Subject: Refactor assembly analysis into scope filling and checking. --- libsolidity/inlineasm/AsmCodeGen.cpp | 55 +++++++++++++----------------------- 1 file changed, 19 insertions(+), 36 deletions(-) (limited to 'libsolidity/inlineasm/AsmCodeGen.cpp') diff --git a/libsolidity/inlineasm/AsmCodeGen.cpp b/libsolidity/inlineasm/AsmCodeGen.cpp index d5931960..1caaa677 100644 --- a/libsolidity/inlineasm/AsmCodeGen.cpp +++ b/libsolidity/inlineasm/AsmCodeGen.cpp @@ -24,6 +24,7 @@ #include #include +#include #include #include @@ -153,12 +154,14 @@ public: }, [=](Scope::Function&) { - solAssert(false, "Not yet implemented"); + solAssert(false, "Function not removed during desugaring."); } ))) { + return; } - else if (!m_identifierAccess || !m_identifierAccess(_identifier, m_state.assembly, CodeGenerator::IdentifierContext::RValue)) + solAssert(m_identifierAccess, "Identifier not found and no external access available."); + if (!m_identifierAccess(_identifier, m_state.assembly, CodeGenerator::IdentifierContext::RValue)) { m_state.addError( Error::Type::DeclarationError, @@ -186,7 +189,7 @@ public: { m_state.assembly.setSourceLocation(_label.location); solAssert(m_scope.identifiers.count(_label.name), ""); - Scope::Label& label = boost::get(m_scope.identifiers[_label.name]); + Scope::Label& label = boost::get(m_scope.identifiers.at(_label.name)); assignLabelIdIfUnset(label); m_state.assembly.append(eth::AssemblyItem(eth::Tag, label.id)); } @@ -208,8 +211,7 @@ public: int height = m_state.assembly.deposit(); boost::apply_visitor(*this, *_varDecl.value); expectDeposit(1, height, locationOf(*_varDecl.value)); - solAssert(m_scope.identifiers.count(_varDecl.name), ""); - auto& var = boost::get(m_scope.identifiers[_varDecl.name]); + auto& var = boost::get(m_scope.identifiers.at(_varDecl.name)); var.stackHeight = height; var.active = true; } @@ -225,31 +227,17 @@ public: private: void generateAssignment(assembly::Identifier const& _variableName, SourceLocation const& _location) { - if (m_scope.lookup(_variableName.name, Scope::Visitor( - [=](Scope::Variable const& _var) - { - if (int heightDiff = variableHeightDiff(_var, _location, true)) - m_state.assembly.append(solidity::swapInstruction(heightDiff - 1)); - m_state.assembly.append(solidity::Instruction::POP); - }, - [=](Scope::Label const&) - { - m_state.addError( - Error::Type::DeclarationError, - "Label \"" + string(_variableName.name) + "\" used as variable." - ); - }, - [=](Scope::Function const&) - { - m_state.addError( - Error::Type::DeclarationError, - "Function \"" + string(_variableName.name) + "\" used as variable." - ); - } - ))) + auto var = m_scope.lookup(_variableName.name); + if (var) { + Scope::Variable const& _var = boost::get(*var); + if (int heightDiff = variableHeightDiff(_var, _location, true)) + m_state.assembly.append(solidity::swapInstruction(heightDiff - 1)); + m_state.assembly.append(solidity::Instruction::POP); + return; } - else if (!m_identifierAccess || !m_identifierAccess(_variableName, m_state.assembly, CodeGenerator::IdentifierContext::LValue)) + solAssert(m_identifierAccess, "Identifier not found and no external access available."); + if (!m_identifierAccess(_variableName, m_state.assembly, CodeGenerator::IdentifierContext::LValue)) m_state.addError( Error::Type::DeclarationError, "Identifier \"" + string(_variableName.name) + "\" not found, not unique or not lvalue." @@ -261,11 +249,6 @@ private: /// errors and the (positive) stack height difference otherwise. int variableHeightDiff(Scope::Variable const& _var, SourceLocation const& _location, bool _forSwap) { - if (!_var.active) - { - m_state.addError( Error::Type::TypeError, "Variable used before it was declared", _location); - return 0; - } int heightDiff = m_state.assembly.deposit() - _var.stackHeight; if (heightDiff <= (_forSwap ? 1 : 0) || heightDiff > (_forSwap ? 17 : 16)) { @@ -314,7 +297,7 @@ bool assembly::CodeGenerator::typeCheck(assembly::CodeGenerator::IdentifierAcces size_t initialErrorLen = m_errors.size(); eth::Assembly assembly; GeneratorState state(m_errors, assembly); - if (!(AsmAnalyzer(state.scopes, m_errors))(m_parsedData)) + if (!(AsmAnalyzer(state.scopes, m_errors, !!_identifierAccess)).analyze(m_parsedData)) return false; CodeTransform(state, m_parsedData, _identifierAccess); return m_errors.size() == initialErrorLen; @@ -324,7 +307,7 @@ eth::Assembly assembly::CodeGenerator::assemble(assembly::CodeGenerator::Identif { eth::Assembly assembly; GeneratorState state(m_errors, assembly); - if (!(AsmAnalyzer(state.scopes, m_errors))(m_parsedData)) + if (!(AsmAnalyzer(state.scopes, m_errors, !!_identifierAccess)).analyze(m_parsedData)) solAssert(false, "Assembly error"); CodeTransform(state, m_parsedData, _identifierAccess); return assembly; @@ -333,7 +316,7 @@ eth::Assembly assembly::CodeGenerator::assemble(assembly::CodeGenerator::Identif void assembly::CodeGenerator::assemble(eth::Assembly& _assembly, assembly::CodeGenerator::IdentifierAccess const& _identifierAccess) { GeneratorState state(m_errors, _assembly); - if (!(AsmAnalyzer(state.scopes, m_errors))(m_parsedData)) + if (!(AsmAnalyzer(state.scopes, m_errors, !!_identifierAccess)).analyze(m_parsedData)) solAssert(false, "Assembly error"); CodeTransform(state, m_parsedData, _identifierAccess); } -- cgit v1.2.3 From e0849f2f3bbb23ebddb37cd770f46266967e789d Mon Sep 17 00:00:00 2001 From: chriseth Date: Tue, 14 Mar 2017 15:41:23 +0100 Subject: Split external identifier access into resolving and code generation. --- libsolidity/inlineasm/AsmCodeGen.cpp | 42 +++++++++++++++++++++++++----------- 1 file changed, 29 insertions(+), 13 deletions(-) (limited to 'libsolidity/inlineasm/AsmCodeGen.cpp') diff --git a/libsolidity/inlineasm/AsmCodeGen.cpp b/libsolidity/inlineasm/AsmCodeGen.cpp index 1caaa677..d094aa97 100644 --- a/libsolidity/inlineasm/AsmCodeGen.cpp +++ b/libsolidity/inlineasm/AsmCodeGen.cpp @@ -81,7 +81,7 @@ public: explicit CodeTransform( GeneratorState& _state, assembly::Block const& _block, - assembly::CodeGenerator::IdentifierAccess const& _identifierAccess = assembly::CodeGenerator::IdentifierAccess() + assembly::ExternalIdentifierAccess const& _identifierAccess = assembly::ExternalIdentifierAccess() ): m_state(_state), m_scope(*m_state.scopes.at(&_block)), @@ -160,15 +160,23 @@ public: { return; } - solAssert(m_identifierAccess, "Identifier not found and no external access available."); - if (!m_identifierAccess(_identifier, m_state.assembly, CodeGenerator::IdentifierContext::RValue)) + solAssert( + m_identifierAccess.resolve && m_identifierAccess.generateCode, + "Identifier not found and no external access available." + ); + // @TODO refactor: Store resolved identifier. + size_t size = m_identifierAccess.resolve(_identifier, IdentifierContext::RValue); + if (size != size_t(-1)) + m_identifierAccess.generateCode(_identifier, IdentifierContext::RValue, m_state.assembly); + else { m_state.addError( Error::Type::DeclarationError, "Identifier not found or not unique", _identifier.location ); - m_state.assembly.append(u256(0)); + for (size_t i = 0; i < size; ++i) + m_state.assembly.append(u256(0)); } } void operator()(FunctionalInstruction const& _instr) @@ -236,12 +244,20 @@ private: m_state.assembly.append(solidity::Instruction::POP); return; } - solAssert(m_identifierAccess, "Identifier not found and no external access available."); - if (!m_identifierAccess(_variableName, m_state.assembly, CodeGenerator::IdentifierContext::LValue)) + solAssert( + m_identifierAccess.resolve && m_identifierAccess.generateCode, + "Identifier not found and no external access available." + ); + size_t size = m_identifierAccess.resolve(_variableName, IdentifierContext::LValue); + if (size != size_t(-1)) + m_identifierAccess.generateCode(_variableName, IdentifierContext::LValue, m_state.assembly); + else + { m_state.addError( Error::Type::DeclarationError, "Identifier \"" + string(_variableName.name) + "\" not found, not unique or not lvalue." ); + } } /// Determines the stack height difference to the given variables. Automatically generates @@ -289,34 +305,34 @@ private: GeneratorState& m_state; Scope& m_scope; int const m_initialDeposit; - assembly::CodeGenerator::IdentifierAccess m_identifierAccess; + ExternalIdentifierAccess m_identifierAccess; }; -bool assembly::CodeGenerator::typeCheck(assembly::CodeGenerator::IdentifierAccess const& _identifierAccess) +bool assembly::CodeGenerator::typeCheck(ExternalIdentifierAccess const& _identifierAccess) { size_t initialErrorLen = m_errors.size(); eth::Assembly assembly; GeneratorState state(m_errors, assembly); - if (!(AsmAnalyzer(state.scopes, m_errors, !!_identifierAccess)).analyze(m_parsedData)) + if (!(AsmAnalyzer(state.scopes, m_errors, !!_identifierAccess.resolve)).analyze(m_parsedData)) return false; CodeTransform(state, m_parsedData, _identifierAccess); return m_errors.size() == initialErrorLen; } -eth::Assembly assembly::CodeGenerator::assemble(assembly::CodeGenerator::IdentifierAccess const& _identifierAccess) +eth::Assembly assembly::CodeGenerator::assemble(ExternalIdentifierAccess const& _identifierAccess) { eth::Assembly assembly; GeneratorState state(m_errors, assembly); - if (!(AsmAnalyzer(state.scopes, m_errors, !!_identifierAccess)).analyze(m_parsedData)) + if (!(AsmAnalyzer(state.scopes, m_errors, !!_identifierAccess.resolve)).analyze(m_parsedData)) solAssert(false, "Assembly error"); CodeTransform(state, m_parsedData, _identifierAccess); return assembly; } -void assembly::CodeGenerator::assemble(eth::Assembly& _assembly, assembly::CodeGenerator::IdentifierAccess const& _identifierAccess) +void assembly::CodeGenerator::assemble(eth::Assembly& _assembly, ExternalIdentifierAccess const& _identifierAccess) { GeneratorState state(m_errors, _assembly); - if (!(AsmAnalyzer(state.scopes, m_errors, !!_identifierAccess)).analyze(m_parsedData)) + if (!(AsmAnalyzer(state.scopes, m_errors, !!_identifierAccess.resolve)).analyze(m_parsedData)) solAssert(false, "Assembly error"); CodeTransform(state, m_parsedData, _identifierAccess); } -- cgit v1.2.3 From c6fa78c73e3a23661014fd03b92d74d2e7df9e81 Mon Sep 17 00:00:00 2001 From: chriseth Date: Tue, 21 Mar 2017 19:38:37 +0100 Subject: Use actual type checking phase of assembler. --- libsolidity/inlineasm/AsmCodeGen.cpp | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) (limited to 'libsolidity/inlineasm/AsmCodeGen.cpp') diff --git a/libsolidity/inlineasm/AsmCodeGen.cpp b/libsolidity/inlineasm/AsmCodeGen.cpp index d094aa97..c1efa292 100644 --- a/libsolidity/inlineasm/AsmCodeGen.cpp +++ b/libsolidity/inlineasm/AsmCodeGen.cpp @@ -308,22 +308,11 @@ private: ExternalIdentifierAccess m_identifierAccess; }; -bool assembly::CodeGenerator::typeCheck(ExternalIdentifierAccess const& _identifierAccess) -{ - size_t initialErrorLen = m_errors.size(); - eth::Assembly assembly; - GeneratorState state(m_errors, assembly); - if (!(AsmAnalyzer(state.scopes, m_errors, !!_identifierAccess.resolve)).analyze(m_parsedData)) - return false; - CodeTransform(state, m_parsedData, _identifierAccess); - return m_errors.size() == initialErrorLen; -} - eth::Assembly assembly::CodeGenerator::assemble(ExternalIdentifierAccess const& _identifierAccess) { eth::Assembly assembly; GeneratorState state(m_errors, assembly); - if (!(AsmAnalyzer(state.scopes, m_errors, !!_identifierAccess.resolve)).analyze(m_parsedData)) + if (!(AsmAnalyzer(state.scopes, m_errors, _identifierAccess.resolve)).analyze(m_parsedData)) solAssert(false, "Assembly error"); CodeTransform(state, m_parsedData, _identifierAccess); return assembly; @@ -332,7 +321,7 @@ eth::Assembly assembly::CodeGenerator::assemble(ExternalIdentifierAccess const& void assembly::CodeGenerator::assemble(eth::Assembly& _assembly, ExternalIdentifierAccess const& _identifierAccess) { GeneratorState state(m_errors, _assembly); - if (!(AsmAnalyzer(state.scopes, m_errors, !!_identifierAccess.resolve)).analyze(m_parsedData)) + if (!(AsmAnalyzer(state.scopes, m_errors, _identifierAccess.resolve)).analyze(m_parsedData)) solAssert(false, "Assembly error"); CodeTransform(state, m_parsedData, _identifierAccess); } -- cgit v1.2.3 From 580921b3294bc582c68db04f1ebf83b9bec206f5 Mon Sep 17 00:00:00 2001 From: chriseth Date: Wed, 22 Mar 2017 13:21:58 +0100 Subject: Perform stack height checks in assembly analysis phase. --- libsolidity/inlineasm/AsmCodeGen.cpp | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) (limited to 'libsolidity/inlineasm/AsmCodeGen.cpp') diff --git a/libsolidity/inlineasm/AsmCodeGen.cpp b/libsolidity/inlineasm/AsmCodeGen.cpp index c1efa292..a79c5a37 100644 --- a/libsolidity/inlineasm/AsmCodeGen.cpp +++ b/libsolidity/inlineasm/AsmCodeGen.cpp @@ -185,7 +185,7 @@ public: { int height = m_state.assembly.deposit(); boost::apply_visitor(*this, *it); - expectDeposit(1, height, locationOf(*it)); + expectDeposit(1, height); } (*this)(_instr.instruction); } @@ -210,7 +210,7 @@ public: { int height = m_state.assembly.deposit(); boost::apply_visitor(*this, *_assignment.value); - expectDeposit(1, height, locationOf(*_assignment.value)); + expectDeposit(1, height); m_state.assembly.setSourceLocation(_assignment.location); generateAssignment(_assignment.variableName, _assignment.location); } @@ -218,7 +218,7 @@ public: { int height = m_state.assembly.deposit(); boost::apply_visitor(*this, *_varDecl.value); - expectDeposit(1, height, locationOf(*_varDecl.value)); + expectDeposit(1, height); auto& var = boost::get(m_scope.identifiers.at(_varDecl.name)); var.stackHeight = height; var.active = true; @@ -279,17 +279,9 @@ private: return heightDiff; } - void expectDeposit(int _deposit, int _oldHeight, SourceLocation const& _location) + void expectDeposit(int _deposit, int _oldHeight) { - if (m_state.assembly.deposit() != _oldHeight + 1) - m_state.addError(Error::Type::TypeError, - "Expected instruction(s) to deposit " + - boost::lexical_cast(_deposit) + - " item(s) to the stack, but did deposit " + - boost::lexical_cast(m_state.assembly.deposit() - _oldHeight) + - " item(s).", - _location - ); + solAssert(m_state.assembly.deposit() == _oldHeight + _deposit, "Invalid stack deposit."); } /// Assigns the label's id to a value taken from eth::Assembly if it has not yet been set. -- cgit v1.2.3 From 4755757c00885be3a9b8dc2b714c90bc45985efe Mon Sep 17 00:00:00 2001 From: chriseth Date: Wed, 22 Mar 2017 13:27:57 +0100 Subject: Remove some errors checks from code generation (was moved to analysis already). --- libsolidity/inlineasm/AsmCodeGen.cpp | 60 ++++++------------------------------ 1 file changed, 10 insertions(+), 50 deletions(-) (limited to 'libsolidity/inlineasm/AsmCodeGen.cpp') diff --git a/libsolidity/inlineasm/AsmCodeGen.cpp b/libsolidity/inlineasm/AsmCodeGen.cpp index a79c5a37..ad413216 100644 --- a/libsolidity/inlineasm/AsmCodeGen.cpp +++ b/libsolidity/inlineasm/AsmCodeGen.cpp @@ -50,11 +50,6 @@ struct GeneratorState GeneratorState(ErrorList& _errors, eth::Assembly& _assembly): errors(_errors), assembly(_assembly) {} - void addError(Error::Type _type, std::string const& _description, SourceLocation const& _location = SourceLocation()) - { - errors.push_back(make_shared(_type, _description, _location)); - } - size_t newLabelId() { return assemblyTagToIdentifier(assembly.newTag()); @@ -99,23 +94,7 @@ public: int deposit = m_state.assembly.deposit() - m_initialDeposit; - // issue warnings for stack height discrepancies - if (deposit < 0) - { - m_state.addError( - Error::Type::Warning, - "Inline assembly block is not balanced. It takes " + toString(-deposit) + " item(s) from the stack.", - _block.location - ); - } - else if (deposit > 0) - { - m_state.addError( - Error::Type::Warning, - "Inline assembly block is not balanced. It leaves " + toString(deposit) + " item(s) on the stack.", - _block.location - ); - } + solAssert(deposit == 0, "Invalid stack height at end of block."); } void operator()(assembly::Instruction const& _instruction) @@ -161,23 +140,10 @@ public: return; } solAssert( - m_identifierAccess.resolve && m_identifierAccess.generateCode, + m_identifierAccess.generateCode, "Identifier not found and no external access available." ); - // @TODO refactor: Store resolved identifier. - size_t size = m_identifierAccess.resolve(_identifier, IdentifierContext::RValue); - if (size != size_t(-1)) - m_identifierAccess.generateCode(_identifier, IdentifierContext::RValue, m_state.assembly); - else - { - m_state.addError( - Error::Type::DeclarationError, - "Identifier not found or not unique", - _identifier.location - ); - for (size_t i = 0; i < size; ++i) - m_state.assembly.append(u256(0)); - } + m_identifierAccess.generateCode(_identifier, IdentifierContext::RValue, m_state.assembly); } void operator()(FunctionalInstruction const& _instr) { @@ -242,21 +208,14 @@ private: if (int heightDiff = variableHeightDiff(_var, _location, true)) m_state.assembly.append(solidity::swapInstruction(heightDiff - 1)); m_state.assembly.append(solidity::Instruction::POP); - return; } - solAssert( - m_identifierAccess.resolve && m_identifierAccess.generateCode, - "Identifier not found and no external access available." - ); - size_t size = m_identifierAccess.resolve(_variableName, IdentifierContext::LValue); - if (size != size_t(-1)) - m_identifierAccess.generateCode(_variableName, IdentifierContext::LValue, m_state.assembly); else { - m_state.addError( - Error::Type::DeclarationError, - "Identifier \"" + string(_variableName.name) + "\" not found, not unique or not lvalue." + solAssert( + m_identifierAccess.generateCode, + "Identifier not found and no external access available." ); + m_identifierAccess.generateCode(_variableName, IdentifierContext::LValue, m_state.assembly); } } @@ -268,11 +227,12 @@ private: int heightDiff = m_state.assembly.deposit() - _var.stackHeight; if (heightDiff <= (_forSwap ? 1 : 0) || heightDiff > (_forSwap ? 17 : 16)) { - m_state.addError( + //@TODO move this to analysis phase. + m_state.errors.push_back(make_shared( Error::Type::TypeError, "Variable inaccessible, too deep inside stack (" + boost::lexical_cast(heightDiff) + ")", _location - ); + )); return 0; } else -- cgit v1.2.3 From dfb7d5ebd955d390142241a2abcb95995ef1ba04 Mon Sep 17 00:00:00 2001 From: chriseth Date: Wed, 12 Apr 2017 18:32:25 +0200 Subject: Move analysis out of code generator. --- libsolidity/inlineasm/AsmCodeGen.cpp | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) (limited to 'libsolidity/inlineasm/AsmCodeGen.cpp') diff --git a/libsolidity/inlineasm/AsmCodeGen.cpp b/libsolidity/inlineasm/AsmCodeGen.cpp index ad413216..68d674f9 100644 --- a/libsolidity/inlineasm/AsmCodeGen.cpp +++ b/libsolidity/inlineasm/AsmCodeGen.cpp @@ -47,8 +47,8 @@ using namespace dev::solidity::assembly; struct GeneratorState { - GeneratorState(ErrorList& _errors, eth::Assembly& _assembly): - errors(_errors), assembly(_assembly) {} + GeneratorState(ErrorList& _errors, AsmAnalyzer::Scopes& _scopes, eth::Assembly& _assembly): + errors(_errors), scopes(_scopes), assembly(_assembly) {} size_t newLabelId() { @@ -62,8 +62,8 @@ struct GeneratorState return size_t(id); } - AsmAnalyzer::Scopes scopes; ErrorList& errors; + AsmAnalyzer::Scopes scopes; eth::Assembly& assembly; }; @@ -260,20 +260,25 @@ private: ExternalIdentifierAccess m_identifierAccess; }; -eth::Assembly assembly::CodeGenerator::assemble(ExternalIdentifierAccess const& _identifierAccess) +eth::Assembly assembly::CodeGenerator::assemble( + Block const& _parsedData, + AsmAnalyzer::Scopes& _scopes, + ExternalIdentifierAccess const& _identifierAccess +) { eth::Assembly assembly; - GeneratorState state(m_errors, assembly); - if (!(AsmAnalyzer(state.scopes, m_errors, _identifierAccess.resolve)).analyze(m_parsedData)) - solAssert(false, "Assembly error"); - CodeTransform(state, m_parsedData, _identifierAccess); + GeneratorState state(m_errors, _scopes, assembly); + CodeTransform(state, _parsedData, _identifierAccess); return assembly; } -void assembly::CodeGenerator::assemble(eth::Assembly& _assembly, ExternalIdentifierAccess const& _identifierAccess) +void assembly::CodeGenerator::assemble( + Block const& _parsedData, + AsmAnalyzer::Scopes& _scopes, + eth::Assembly& _assembly, + ExternalIdentifierAccess const& _identifierAccess +) { - GeneratorState state(m_errors, _assembly); - if (!(AsmAnalyzer(state.scopes, m_errors, _identifierAccess.resolve)).analyze(m_parsedData)) - solAssert(false, "Assembly error"); - CodeTransform(state, m_parsedData, _identifierAccess); + GeneratorState state(m_errors, _scopes, _assembly); + CodeTransform(state, _parsedData, _identifierAccess); } -- cgit v1.2.3 From f3ec2ba39e7f4b85d148a7b696ef5af499fbb6fb Mon Sep 17 00:00:00 2001 From: chriseth Date: Wed, 26 Apr 2017 15:41:08 +0200 Subject: Refactor to combined scope and stack height info. --- libsolidity/inlineasm/AsmCodeGen.cpp | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'libsolidity/inlineasm/AsmCodeGen.cpp') diff --git a/libsolidity/inlineasm/AsmCodeGen.cpp b/libsolidity/inlineasm/AsmCodeGen.cpp index 68d674f9..be52db46 100644 --- a/libsolidity/inlineasm/AsmCodeGen.cpp +++ b/libsolidity/inlineasm/AsmCodeGen.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -47,8 +48,8 @@ using namespace dev::solidity::assembly; struct GeneratorState { - GeneratorState(ErrorList& _errors, AsmAnalyzer::Scopes& _scopes, eth::Assembly& _assembly): - errors(_errors), scopes(_scopes), assembly(_assembly) {} + GeneratorState(ErrorList& _errors, AsmAnalysisInfo& _analysisInfo, eth::Assembly& _assembly): + errors(_errors), info(_analysisInfo), assembly(_assembly) {} size_t newLabelId() { @@ -63,7 +64,7 @@ struct GeneratorState } ErrorList& errors; - AsmAnalyzer::Scopes scopes; + AsmAnalysisInfo info; eth::Assembly& assembly; }; @@ -79,7 +80,7 @@ public: assembly::ExternalIdentifierAccess const& _identifierAccess = assembly::ExternalIdentifierAccess() ): m_state(_state), - m_scope(*m_state.scopes.at(&_block)), + m_scope(*m_state.info.scopes.at(&_block)), m_initialDeposit(m_state.assembly.deposit()), m_identifierAccess(_identifierAccess) { @@ -262,23 +263,23 @@ private: eth::Assembly assembly::CodeGenerator::assemble( Block const& _parsedData, - AsmAnalyzer::Scopes& _scopes, + AsmAnalysisInfo& _analysisInfo, ExternalIdentifierAccess const& _identifierAccess ) { eth::Assembly assembly; - GeneratorState state(m_errors, _scopes, assembly); + GeneratorState state(m_errors, _analysisInfo, assembly); CodeTransform(state, _parsedData, _identifierAccess); return assembly; } void assembly::CodeGenerator::assemble( Block const& _parsedData, - AsmAnalyzer::Scopes& _scopes, + AsmAnalysisInfo& _analysisInfo, eth::Assembly& _assembly, ExternalIdentifierAccess const& _identifierAccess ) { - GeneratorState state(m_errors, _scopes, _assembly); + GeneratorState state(m_errors, _analysisInfo, _assembly); CodeTransform(state, _parsedData, _identifierAccess); } -- cgit v1.2.3 From d7b3ce24a4f26a7bd81f3beade1042ae33974584 Mon Sep 17 00:00:00 2001 From: chriseth Date: Wed, 26 Apr 2017 16:50:54 +0200 Subject: Check stack height during code generation. --- libsolidity/inlineasm/AsmCodeGen.cpp | 40 ++++++++++++++++++++++++++++++------ 1 file changed, 34 insertions(+), 6 deletions(-) (limited to 'libsolidity/inlineasm/AsmCodeGen.cpp') diff --git a/libsolidity/inlineasm/AsmCodeGen.cpp b/libsolidity/inlineasm/AsmCodeGen.cpp index be52db46..9ef3e6e7 100644 --- a/libsolidity/inlineasm/AsmCodeGen.cpp +++ b/libsolidity/inlineasm/AsmCodeGen.cpp @@ -78,12 +78,23 @@ public: GeneratorState& _state, assembly::Block const& _block, assembly::ExternalIdentifierAccess const& _identifierAccess = assembly::ExternalIdentifierAccess() + ): CodeTransform(_state, _block, _identifierAccess, _state.assembly.deposit()) + { + } + +private: + CodeTransform( + GeneratorState& _state, + assembly::Block const& _block, + assembly::ExternalIdentifierAccess const& _identifierAccess, + int _initialDeposit ): m_state(_state), m_scope(*m_state.info.scopes.at(&_block)), - m_initialDeposit(m_state.assembly.deposit()), - m_identifierAccess(_identifierAccess) + m_identifierAccess(_identifierAccess), + m_initialDeposit(_initialDeposit) { + int blockStartDeposit = m_state.assembly.deposit(); std::for_each(_block.statements.begin(), _block.statements.end(), boost::apply_visitor(*this)); m_state.assembly.setSourceLocation(_block.location); @@ -93,15 +104,16 @@ public: if (identifier.second.type() == typeid(Scope::Variable)) m_state.assembly.append(solidity::Instruction::POP); - int deposit = m_state.assembly.deposit() - m_initialDeposit; - + int deposit = m_state.assembly.deposit() - blockStartDeposit; solAssert(deposit == 0, "Invalid stack height at end of block."); } +public: void operator()(assembly::Instruction const& _instruction) { m_state.assembly.setSourceLocation(_instruction.location); m_state.assembly.append(_instruction.instruction); + checkStackHeight(&_instruction); } void operator()(assembly::Literal const& _literal) { @@ -113,6 +125,7 @@ public: solAssert(_literal.value.size() <= 32, ""); m_state.assembly.append(u256(h256(_literal.value, h256::FromBinary, h256::AlignLeft))); } + checkStackHeight(&_literal); } void operator()(assembly::Identifier const& _identifier) { @@ -145,6 +158,7 @@ public: "Identifier not found and no external access available." ); m_identifierAccess.generateCode(_identifier, IdentifierContext::RValue, m_state.assembly); + checkStackHeight(&_identifier); } void operator()(FunctionalInstruction const& _instr) { @@ -155,6 +169,7 @@ public: expectDeposit(1, height); } (*this)(_instr.instruction); + checkStackHeight(&_instr); } void operator()(assembly::FunctionCall const&) { @@ -167,11 +182,13 @@ public: Scope::Label& label = boost::get(m_scope.identifiers.at(_label.name)); assignLabelIdIfUnset(label); m_state.assembly.append(eth::AssemblyItem(eth::Tag, label.id)); + checkStackHeight(&_label); } void operator()(assembly::Assignment const& _assignment) { m_state.assembly.setSourceLocation(_assignment.location); generateAssignment(_assignment.variableName, _assignment.location); + checkStackHeight(&_assignment); } void operator()(FunctionalAssignment const& _assignment) { @@ -180,6 +197,7 @@ public: expectDeposit(1, height); m_state.assembly.setSourceLocation(_assignment.location); generateAssignment(_assignment.variableName, _assignment.location); + checkStackHeight(&_assignment); } void operator()(assembly::VariableDeclaration const& _varDecl) { @@ -192,7 +210,8 @@ public: } void operator()(assembly::Block const& _block) { - CodeTransform(m_state, _block, m_identifierAccess); + CodeTransform(m_state, _block, m_identifierAccess, m_initialDeposit); + checkStackHeight(&_block); } void operator()(assembly::FunctionDefinition const&) { @@ -245,6 +264,15 @@ private: solAssert(m_state.assembly.deposit() == _oldHeight + _deposit, "Invalid stack deposit."); } + void checkStackHeight(void const* _astElement) + { + solAssert(m_state.info.stackHeightInfo.count(_astElement), "Stack height for AST element not found."); + solAssert( + m_state.info.stackHeightInfo.at(_astElement) == m_state.assembly.deposit() - m_initialDeposit, + "Stack height mismatch between analysis and code generation phase." + ); + } + /// Assigns the label's id to a value taken from eth::Assembly if it has not yet been set. void assignLabelIdIfUnset(Scope::Label& _label) { @@ -257,8 +285,8 @@ private: GeneratorState& m_state; Scope& m_scope; - int const m_initialDeposit; ExternalIdentifierAccess m_identifierAccess; + int const m_initialDeposit; }; eth::Assembly assembly::CodeGenerator::assemble( -- cgit v1.2.3