From 45d96959f88e951af0e2ccf0217f19d75da66ed1 Mon Sep 17 00:00:00 2001 From: chriseth Date: Tue, 13 Jun 2017 21:58:25 +0200 Subject: Move LabelIDs to generation phase. --- libjulia/backends/evm/EVMCodeTransform.cpp | 43 ++++++++++++++++-------------- libjulia/backends/evm/EVMCodeTransform.h | 29 +++++++++++++++----- libsolidity/inlineasm/AsmScope.h | 6 +---- 3 files changed, 47 insertions(+), 31 deletions(-) diff --git a/libjulia/backends/evm/EVMCodeTransform.cpp b/libjulia/backends/evm/EVMCodeTransform.cpp index cd6fd276..638ff4d9 100644 --- a/libjulia/backends/evm/EVMCodeTransform.cpp +++ b/libjulia/backends/evm/EVMCodeTransform.cpp @@ -91,8 +91,7 @@ void CodeTransform::operator()(Label const& _label) solAssert(m_scope, ""); solAssert(m_scope->identifiers.count(_label.name), ""); Scope::Label& label = boost::get(m_scope->identifiers.at(_label.name)); - assignLabelIdIfUnset(label.id); - m_assembly.appendLabel(*label.id); + m_assembly.appendLabel(labelID(label)); checkStackHeight(&_label); } @@ -120,12 +119,11 @@ void CodeTransform::operator()(FunctionCall const& _call) for (auto const& arg: _call.arguments | boost::adaptors::reversed) visitExpression(arg); m_assembly.setSourceLocation(_call.location); - assignLabelIdIfUnset(function->id); if (m_evm15) - m_assembly.appendJumpsub(*function->id, function->arguments.size(), function->returns.size()); + m_assembly.appendJumpsub(functionEntryID(*function), function->arguments.size(), function->returns.size()); else { - m_assembly.appendJumpTo(*function->id, function->returns.size() - function->arguments.size() - 1); + m_assembly.appendJumpTo(functionEntryID(*function), function->returns.size() - function->arguments.size() - 1); m_assembly.appendLabel(returnLabel); m_stackAdjustment--; } @@ -181,8 +179,7 @@ void CodeTransform::operator()(assembly::Identifier const& _identifier) }, [=](Scope::Label& _label) { - assignLabelIdIfUnset(_label.id); - m_assembly.appendLabelReference(*_label.id); + m_assembly.appendLabelReference(labelID(_label)); }, [=](Scope::Function&) { @@ -282,7 +279,6 @@ void CodeTransform::operator()(FunctionDefinition const& _function) solAssert(m_scope, ""); solAssert(m_scope->identifiers.count(_function.name), ""); Scope::Function& function = boost::get(m_scope->identifiers.at(_function.name)); - assignLabelIdIfUnset(function.id); int const localStackAdjustment = m_evm15 ? 0 : 1; int height = localStackAdjustment; @@ -303,12 +299,12 @@ void CodeTransform::operator()(FunctionDefinition const& _function) if (m_evm15) { m_assembly.appendJumpTo(afterFunction, -stackHeightBefore); - m_assembly.appendBeginsub(*function.id, _function.arguments.size()); + m_assembly.appendBeginsub(functionEntryID(function), _function.arguments.size()); } else { m_assembly.appendJumpTo(afterFunction, -stackHeightBefore + height); - m_assembly.appendLabel(*function.id); + m_assembly.appendLabel(functionEntryID(function)); } m_stackAdjustment += localStackAdjustment; @@ -321,7 +317,7 @@ void CodeTransform::operator()(FunctionDefinition const& _function) m_assembly.appendConstant(u256(0)); } - CodeTransform(m_assembly, m_info, m_evm15, m_identifierAccess, localStackAdjustment) + CodeTransform(m_assembly, m_info, m_evm15, m_identifierAccess, localStackAdjustment, m_context) .run(_function.body); { @@ -367,7 +363,7 @@ void CodeTransform::operator()(FunctionDefinition const& _function) void CodeTransform::operator()(Block const& _block) { - CodeTransform(m_assembly, m_info, m_evm15, m_identifierAccess, m_stackAdjustment).run(_block); + CodeTransform(m_assembly, m_info, m_evm15, m_identifierAccess, m_stackAdjustment, m_context).run(_block); } AbstractAssembly::LabelID CodeTransform::labelFromIdentifier(Identifier const& _identifier) @@ -377,8 +373,7 @@ AbstractAssembly::LabelID CodeTransform::labelFromIdentifier(Identifier const& _ [=](Scope::Variable&) { solAssert(false, "Expected label"); }, [&](Scope::Label& _label) { - assignLabelIdIfUnset(_label.id); - label = *_label.id; + label = labelID(_label); }, [=](Scope::Function&) { solAssert(false, "Expected label"); } ))) @@ -388,6 +383,20 @@ AbstractAssembly::LabelID CodeTransform::labelFromIdentifier(Identifier const& _ return label; } +AbstractAssembly::LabelID CodeTransform::labelID(Scope::Label const& _label) +{ + if (!m_context->labelIDs.count(&_label)) + m_context->labelIDs[&_label] = m_assembly.newLabelId(); + return m_context->labelIDs[&_label]; +} + +AbstractAssembly::LabelID CodeTransform::functionEntryID(Scope::Function const& _function) +{ + if (!m_context->functionEntryIDs.count(&_function)) + m_context->functionEntryIDs[&_function] = m_assembly.newLabelId(); + return m_context->functionEntryIDs[&_function]; +} + void CodeTransform::visitExpression(Statement const& _expression) { int height = m_assembly.stackHeight(); @@ -446,9 +455,3 @@ void CodeTransform::checkStackHeight(void const* _astElement) to_string(m_assembly.stackHeight() - m_stackAdjustment) ); } - -void CodeTransform::assignLabelIdIfUnset(boost::optional& _labelId) -{ - if (!_labelId) - _labelId.reset(m_assembly.newLabelId()); -} diff --git a/libjulia/backends/evm/EVMCodeTransform.h b/libjulia/backends/evm/EVMCodeTransform.h index f65948dc..57781c91 100644 --- a/libjulia/backends/evm/EVMCodeTransform.h +++ b/libjulia/backends/evm/EVMCodeTransform.h @@ -64,7 +64,14 @@ public: solidity::assembly::AsmAnalysisInfo& _analysisInfo, bool _evm15 = false, ExternalIdentifierAccess const& _identifierAccess = ExternalIdentifierAccess() - ): CodeTransform(_assembly, _analysisInfo, _evm15, _identifierAccess, _assembly.stackHeight()) + ): CodeTransform( + _assembly, + _analysisInfo, + _evm15, + _identifierAccess, + _assembly.stackHeight(), + std::make_shared() + ) { } @@ -72,18 +79,26 @@ public: void run(solidity::assembly::Block const& _block); protected: + struct Context + { + std::map labelIDs; + std::map functionEntryIDs; + }; + CodeTransform( julia::AbstractAssembly& _assembly, solidity::assembly::AsmAnalysisInfo& _analysisInfo, bool _evm15, ExternalIdentifierAccess const& _identifierAccess, - int _stackAdjustment + int _stackAdjustment, + std::shared_ptr _context ): m_assembly(_assembly), m_info(_analysisInfo), m_evm15(_evm15), m_identifierAccess(_identifierAccess), - m_stackAdjustment(_stackAdjustment) + m_stackAdjustment(_stackAdjustment), + m_context(_context) {} public: @@ -102,6 +117,10 @@ public: private: AbstractAssembly::LabelID labelFromIdentifier(solidity::assembly::Identifier const& _identifier); + /// @returns the label ID corresponding to the given label, allocating a new one if + /// necessary. + AbstractAssembly::LabelID labelID(solidity::assembly::Scope::Label const& _label); + AbstractAssembly::LabelID functionEntryID(solidity::assembly::Scope::Function const& _function); /// Generates code for an expression that is supposed to return a single value. void visitExpression(solidity::assembly::Statement const& _expression); @@ -116,9 +135,6 @@ private: void checkStackHeight(void const* _astElement); - /// Assigns the label's or function's id to a value taken from eth::Assembly if it has not yet been set. - void assignLabelIdIfUnset(boost::optional& _labelId); - julia::AbstractAssembly& m_assembly; solidity::assembly::AsmAnalysisInfo& m_info; solidity::assembly::Scope* m_scope = nullptr; @@ -129,6 +145,7 @@ private: /// for inline assembly and different stack heights depending on the EVM backend used /// (EVM 1.0 or 1.5). int m_stackAdjustment = 0; + std::shared_ptr m_context; }; } diff --git a/libsolidity/inlineasm/AsmScope.h b/libsolidity/inlineasm/AsmScope.h index ad321f77..5e22c6e7 100644 --- a/libsolidity/inlineasm/AsmScope.h +++ b/libsolidity/inlineasm/AsmScope.h @@ -75,17 +75,13 @@ struct Scope JuliaType type; }; - struct Label - { - boost::optional id; - }; + struct Label { }; struct Function { Function(std::vector const& _arguments, std::vector const& _returns): arguments(_arguments), returns(_returns) {} std::vector arguments; std::vector returns; - boost::optional id; }; using Identifier = boost::variant; -- cgit v1.2.3 From c554145f4d7063422a5e105e2b600b640cf3d8d1 Mon Sep 17 00:00:00 2001 From: chriseth Date: Wed, 14 Jun 2017 00:01:06 +0200 Subject: Move stack height to generation phase. --- libjulia/backends/evm/EVMCodeTransform.cpp | 12 +++++------- libjulia/backends/evm/EVMCodeTransform.h | 6 ++++-- libsolidity/inlineasm/AsmScope.h | 2 -- 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/libjulia/backends/evm/EVMCodeTransform.cpp b/libjulia/backends/evm/EVMCodeTransform.cpp index 638ff4d9..7c14eb8b 100644 --- a/libjulia/backends/evm/EVMCodeTransform.cpp +++ b/libjulia/backends/evm/EVMCodeTransform.cpp @@ -64,8 +64,7 @@ void CodeTransform::operator()(VariableDeclaration const& _varDecl) for (auto const& variable: _varDecl.variables) { auto& var = boost::get(m_scope->identifiers.at(variable.name)); - var.stackHeight = height++; - var.active = true; + m_context->variableStackHeights[&var] = height++; } checkStackHeight(&_varDecl); } @@ -288,8 +287,7 @@ void CodeTransform::operator()(FunctionDefinition const& _function) for (auto const& v: _function.arguments | boost::adaptors::reversed) { auto& var = boost::get(varScope->identifiers.at(v.name)); - var.stackHeight = height++; - var.active = true; + m_context->variableStackHeights[&var] = height++; } m_assembly.setSourceLocation(_function.location); @@ -311,8 +309,7 @@ void CodeTransform::operator()(FunctionDefinition const& _function) for (auto const& v: _function.returns) { auto& var = boost::get(varScope->identifiers.at(v.name)); - var.stackHeight = height++; - var.active = true; + m_context->variableStackHeights[&var] = height++; // Preset stack slots for return variables to zero. m_assembly.appendConstant(u256(0)); } @@ -427,7 +424,8 @@ void CodeTransform::generateAssignment(Identifier const& _variableName) int CodeTransform::variableHeightDiff(solidity::assembly::Scope::Variable const& _var, bool _forSwap) { - int heightDiff = m_assembly.stackHeight() - _var.stackHeight; + solAssert(m_context->variableStackHeights.count(&_var), ""); + int heightDiff = m_assembly.stackHeight() - m_context->variableStackHeights[&_var]; if (heightDiff <= (_forSwap ? 1 : 0) || heightDiff > (_forSwap ? 17 : 16)) { solUnimplemented( diff --git a/libjulia/backends/evm/EVMCodeTransform.h b/libjulia/backends/evm/EVMCodeTransform.h index 57781c91..202f5051 100644 --- a/libjulia/backends/evm/EVMCodeTransform.h +++ b/libjulia/backends/evm/EVMCodeTransform.h @@ -81,8 +81,10 @@ public: protected: struct Context { - std::map labelIDs; - std::map functionEntryIDs; + using Scope = solidity::assembly::Scope; + std::map labelIDs; + std::map functionEntryIDs; + std::map variableStackHeights; }; CodeTransform( diff --git a/libsolidity/inlineasm/AsmScope.h b/libsolidity/inlineasm/AsmScope.h index 5e22c6e7..23cf61f2 100644 --- a/libsolidity/inlineasm/AsmScope.h +++ b/libsolidity/inlineasm/AsmScope.h @@ -67,8 +67,6 @@ struct Scope struct Variable { - /// Used during code generation to store the stack height. @todo move there. - int stackHeight = 0; /// Used during analysis to check whether we already passed the declaration inside the block. /// @todo move there. bool active = false; -- cgit v1.2.3 From 1bf717fd6513dda5336f95104cebfc0f041f3682 Mon Sep 17 00:00:00 2001 From: chriseth Date: Wed, 14 Jun 2017 00:03:08 +0200 Subject: Remove struct constructor. --- libsolidity/inlineasm/AsmScope.cpp | 2 +- libsolidity/inlineasm/AsmScope.h | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/libsolidity/inlineasm/AsmScope.cpp b/libsolidity/inlineasm/AsmScope.cpp index 7a086846..1db5ca41 100644 --- a/libsolidity/inlineasm/AsmScope.cpp +++ b/libsolidity/inlineasm/AsmScope.cpp @@ -46,7 +46,7 @@ bool Scope::registerFunction(string const& _name, std::vector const& { if (exists(_name)) return false; - identifiers[_name] = Function(_arguments, _returns); + identifiers[_name] = Function{_arguments, _returns}; return true; } diff --git a/libsolidity/inlineasm/AsmScope.h b/libsolidity/inlineasm/AsmScope.h index 23cf61f2..c8e38c8a 100644 --- a/libsolidity/inlineasm/AsmScope.h +++ b/libsolidity/inlineasm/AsmScope.h @@ -77,7 +77,6 @@ struct Scope struct Function { - Function(std::vector const& _arguments, std::vector const& _returns): arguments(_arguments), returns(_returns) {} std::vector arguments; std::vector returns; }; -- cgit v1.2.3 From 154002cda05a75203b625d23ce507787bd5fa5e4 Mon Sep 17 00:00:00 2001 From: chriseth Date: Wed, 14 Jun 2017 00:07:13 +0200 Subject: Move "active variable" to analysis phase. --- libsolidity/inlineasm/AsmAnalysis.cpp | 8 ++++---- libsolidity/inlineasm/AsmAnalysis.h | 8 +++++--- libsolidity/inlineasm/AsmScope.h | 10 +--------- 3 files changed, 10 insertions(+), 16 deletions(-) diff --git a/libsolidity/inlineasm/AsmAnalysis.cpp b/libsolidity/inlineasm/AsmAnalysis.cpp index 13852880..bb30fce1 100644 --- a/libsolidity/inlineasm/AsmAnalysis.cpp +++ b/libsolidity/inlineasm/AsmAnalysis.cpp @@ -91,7 +91,7 @@ bool AsmAnalyzer::operator()(assembly::Identifier const& _identifier) if (m_currentScope->lookup(_identifier.name, Scope::Visitor( [&](Scope::Variable const& _var) { - if (!_var.active) + if (!m_activeVariables.count(&_var)) { m_errorReporter.declarationError( _identifier.location, @@ -185,7 +185,7 @@ bool AsmAnalyzer::operator()(assembly::VariableDeclaration const& _varDecl) for (auto const& variable: _varDecl.variables) { expectValidType(variable.type, variable.location); - boost::get(m_currentScope->identifiers.at(variable.name)).active = true; + m_activeVariables.insert(&boost::get(m_currentScope->identifiers.at(variable.name))); } m_info.stackHeightInfo[&_varDecl] = m_stackHeight; return success; @@ -199,7 +199,7 @@ bool AsmAnalyzer::operator()(assembly::FunctionDefinition const& _funDef) for (auto const& var: _funDef.arguments + _funDef.returns) { expectValidType(var.type, var.location); - boost::get(varScope.identifiers.at(var.name)).active = true; + m_activeVariables.insert(&boost::get(varScope.identifiers.at(var.name))); } int const stackHeight = m_stackHeight; @@ -382,7 +382,7 @@ bool AsmAnalyzer::checkAssignment(assembly::Identifier const& _variable, size_t m_errorReporter.typeError(_variable.location, "Assignment requires variable."); success = false; } - else if (!boost::get(*var).active) + else if (!m_activeVariables.count(&boost::get(*var))) { m_errorReporter.declarationError( _variable.location, diff --git a/libsolidity/inlineasm/AsmAnalysis.h b/libsolidity/inlineasm/AsmAnalysis.h index e7748bcf..cd195d97 100644 --- a/libsolidity/inlineasm/AsmAnalysis.h +++ b/libsolidity/inlineasm/AsmAnalysis.h @@ -22,6 +22,8 @@ #include +#include + #include #include @@ -51,9 +53,6 @@ struct FunctionCall; struct Switch; using Statement = boost::variant; - -struct Scope; - struct AsmAnalysisInfo; /** @@ -101,6 +100,9 @@ private: int m_stackHeight = 0; julia::ExternalIdentifierAccess::Resolver m_resolver; Scope* m_currentScope = nullptr; + /// Variables that are active at the current point in assembly (as opposed to + /// "part of the scope but not yet declared") + std::set m_activeVariables; AsmAnalysisInfo& m_info; ErrorReporter& m_errorReporter; bool m_julia = false; diff --git a/libsolidity/inlineasm/AsmScope.h b/libsolidity/inlineasm/AsmScope.h index c8e38c8a..de9119e0 100644 --- a/libsolidity/inlineasm/AsmScope.h +++ b/libsolidity/inlineasm/AsmScope.h @@ -65,16 +65,8 @@ struct Scope using JuliaType = std::string; using LabelID = size_t; - struct Variable - { - /// Used during analysis to check whether we already passed the declaration inside the block. - /// @todo move there. - bool active = false; - JuliaType type; - }; - + struct Variable { JuliaType type; }; struct Label { }; - struct Function { std::vector arguments; -- cgit v1.2.3