diff options
-rw-r--r-- | libsolidity/analysis/ReferencesResolver.cpp | 7 | ||||
-rw-r--r-- | libsolidity/analysis/TypeChecker.cpp | 10 | ||||
-rw-r--r-- | libsolidity/ast/ASTAnnotations.h | 12 | ||||
-rw-r--r-- | libsolidity/codegen/ContractCompiler.cpp | 3 | ||||
-rw-r--r-- | libsolidity/inlineasm/AsmAnalysis.cpp | 44 | ||||
-rw-r--r-- | libsolidity/inlineasm/AsmAnalysis.h | 13 | ||||
-rw-r--r-- | libsolidity/inlineasm/AsmAnalysisInfo.cpp | 26 | ||||
-rw-r--r-- | libsolidity/inlineasm/AsmAnalysisInfo.h | 61 | ||||
-rw-r--r-- | libsolidity/inlineasm/AsmCodeGen.cpp | 17 | ||||
-rw-r--r-- | libsolidity/inlineasm/AsmCodeGen.h | 4 | ||||
-rw-r--r-- | libsolidity/inlineasm/AsmStack.cpp | 17 |
11 files changed, 151 insertions, 63 deletions
diff --git a/libsolidity/analysis/ReferencesResolver.cpp b/libsolidity/analysis/ReferencesResolver.cpp index a8231b13..9433976a 100644 --- a/libsolidity/analysis/ReferencesResolver.cpp +++ b/libsolidity/analysis/ReferencesResolver.cpp @@ -26,6 +26,7 @@ #include <libsolidity/interface/Exceptions.h> #include <libsolidity/analysis/ConstantEvaluator.h> #include <libsolidity/inlineasm/AsmAnalysis.h> +#include <libsolidity/inlineasm/AsmAnalysisInfo.h> #include <libsolidity/inlineasm/AsmData.h> #include <boost/algorithm/string.hpp> @@ -190,8 +191,10 @@ bool ReferencesResolver::visit(InlineAssembly const& _inlineAssembly) _inlineAssembly.annotation().externalReferences[&_identifier].declaration = declarations.front(); return size_t(1); }; - assembly::AsmAnalyzer::Scopes scopes; - assembly::AsmAnalyzer(scopes, errorsIgnored, resolver).analyze(_inlineAssembly.operations()); + + // Will be re-generated later with correct information + assembly::AsmAnalysisInfo analysisInfo; + assembly::AsmAnalyzer(analysisInfo, errorsIgnored, resolver).analyze(_inlineAssembly.operations()); return false; } diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 08a49f51..38cdc1f8 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -25,6 +25,7 @@ #include <boost/range/adaptor/reversed.hpp> #include <libsolidity/ast/AST.h> #include <libsolidity/inlineasm/AsmAnalysis.h> +#include <libsolidity/inlineasm/AsmAnalysisInfo.h> #include <libsolidity/inlineasm/AsmData.h> using namespace std; @@ -705,8 +706,13 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly) ref->second.valueSize = 1; return size_t(1); }; - solAssert(_inlineAssembly.annotation().scopes.empty(), ""); - assembly::AsmAnalyzer analyzer(_inlineAssembly.annotation().scopes, m_errors, identifierAccess); + solAssert(!_inlineAssembly.annotation().analysisInfo, ""); + _inlineAssembly.annotation().analysisInfo = make_shared<assembly::AsmAnalysisInfo>(); + assembly::AsmAnalyzer analyzer( + *_inlineAssembly.annotation().analysisInfo, + m_errors, + identifierAccess + ); if (!analyzer.analyze(_inlineAssembly.operations())) return false; return true; diff --git a/libsolidity/ast/ASTAnnotations.h b/libsolidity/ast/ASTAnnotations.h index 0b6c8991..a7d89248 100644 --- a/libsolidity/ast/ASTAnnotations.h +++ b/libsolidity/ast/ASTAnnotations.h @@ -22,11 +22,12 @@ #pragma once +#include <libsolidity/ast/ASTForward.h> + #include <map> #include <memory> #include <vector> #include <set> -#include <libsolidity/ast/ASTForward.h> namespace dev { @@ -112,9 +113,8 @@ struct StatementAnnotation: ASTAnnotation, DocumentedAnnotation namespace assembly { -struct Identifier; // forward -struct Block; // forward -struct Scope; // forward + struct AsmAnalysisInfo; + struct Identifier; } struct InlineAssemblyAnnotation: StatementAnnotation @@ -129,8 +129,8 @@ struct InlineAssemblyAnnotation: StatementAnnotation /// Mapping containing resolved references to external identifiers and their value size std::map<assembly::Identifier const*, ExternalIdentifierInfo> externalReferences; - /// Mapping containing the scopes (the result of the analysis phase). - std::map<assembly::Block const*, std::shared_ptr<assembly::Scope>> scopes; + /// Information generated during analysis phase. + std::shared_ptr<assembly::AsmAnalysisInfo> analysisInfo; }; struct ReturnAnnotation: StatementAnnotation diff --git a/libsolidity/codegen/ContractCompiler.cpp b/libsolidity/codegen/ContractCompiler.cpp index 6cff9d0b..34ef13c0 100644 --- a/libsolidity/codegen/ContractCompiler.cpp +++ b/libsolidity/codegen/ContractCompiler.cpp @@ -637,9 +637,10 @@ bool ContractCompiler::visit(InlineAssembly const& _inlineAssembly) _assembly.append(Instruction::POP); } }; + solAssert(_inlineAssembly.annotation().analysisInfo, ""); codeGen.assemble( _inlineAssembly.operations(), - _inlineAssembly.annotation().scopes, + *_inlineAssembly.annotation().analysisInfo, m_context.nonConstAssembly(), identifierAccess ); diff --git a/libsolidity/inlineasm/AsmAnalysis.cpp b/libsolidity/inlineasm/AsmAnalysis.cpp index 68c5a064..dad05a78 100644 --- a/libsolidity/inlineasm/AsmAnalysis.cpp +++ b/libsolidity/inlineasm/AsmAnalysis.cpp @@ -23,6 +23,7 @@ #include <libsolidity/inlineasm/AsmData.h> #include <libsolidity/inlineasm/AsmScopeFiller.h> #include <libsolidity/inlineasm/AsmScope.h> +#include <libsolidity/inlineasm/AsmAnalysisInfo.h> #include <libsolidity/interface/Exceptions.h> #include <libsolidity/interface/Utils.h> @@ -37,35 +38,34 @@ using namespace dev; using namespace dev::solidity; using namespace dev::solidity::assembly; - AsmAnalyzer::AsmAnalyzer( - AsmAnalyzer::Scopes& _scopes, + AsmAnalysisInfo& _analysisInfo, ErrorList& _errors, - ExternalIdentifierAccess::Resolver const& _resolver, - StackHeightInfo* _stackHeightInfo + ExternalIdentifierAccess::Resolver const& _resolver ): - m_resolver(_resolver), m_scopes(_scopes), m_errors(_errors), m_stackHeightInfo(_stackHeightInfo) + m_resolver(_resolver), m_info(_analysisInfo), m_errors(_errors) { } bool AsmAnalyzer::analyze(Block const& _block) { - if (!(ScopeFiller(m_scopes, m_errors))(_block)) + if (!(ScopeFiller(m_info.scopes, m_errors))(_block)) return false; return (*this)(_block); } -bool AsmAnalyzer::operator()(const Label& _label) +bool AsmAnalyzer::operator()(Label const& _label) { - storeStackHeight(_label); return true; + m_info.stackHeightInfo[&_label] = m_stackHeight; + return true; } bool AsmAnalyzer::operator()(assembly::Instruction const& _instruction) { auto const& info = instructionInfo(_instruction.instruction); m_stackHeight += info.ret - info.args; - storeStackHeight(_instruction); + m_info.stackHeightInfo[&_instruction] = m_stackHeight; return true; } @@ -81,7 +81,7 @@ bool AsmAnalyzer::operator()(assembly::Literal const& _literal) )); return false; } - storeStackHeight(_literal); + m_info.stackHeightInfo[&_literal] = m_stackHeight; return true; } @@ -137,7 +137,7 @@ bool AsmAnalyzer::operator()(assembly::Identifier const& _identifier) } m_stackHeight += stackSize == size_t(-1) ? 1 : stackSize; } - storeStackHeight(_identifier); + m_info.stackHeightInfo[&_identifier] = m_stackHeight; return success; } @@ -156,14 +156,14 @@ bool AsmAnalyzer::operator()(FunctionalInstruction const& _instr) solAssert(instructionInfo(_instr.instruction.instruction).args == int(_instr.arguments.size()), ""); if (!(*this)(_instr.instruction)) success = false; - storeStackHeight(_instr); + m_info.stackHeightInfo[&_instr] = m_stackHeight; return success; } bool AsmAnalyzer::operator()(assembly::Assignment const& _assignment) { bool success = checkAssignment(_assignment.variableName, size_t(-1)); - storeStackHeight(_assignment); + m_info.stackHeightInfo[&_assignment] = m_stackHeight; return success; } @@ -175,7 +175,7 @@ bool AsmAnalyzer::operator()(FunctionalAssignment const& _assignment) solAssert(m_stackHeight >= stackHeight, "Negative value size."); if (!checkAssignment(_assignment.variableName, m_stackHeight - stackHeight)) success = false; - storeStackHeight(_assignment); + m_info.stackHeightInfo[&_assignment] = m_stackHeight; return success; } @@ -185,7 +185,7 @@ bool AsmAnalyzer::operator()(assembly::VariableDeclaration const& _varDecl) bool success = boost::apply_visitor(*this, *_varDecl.value); solAssert(m_stackHeight - stackHeight == 1, "Invalid value size."); boost::get<Scope::Variable>(m_currentScope->identifiers.at(_varDecl.name)).active = true; - storeStackHeight(_varDecl); + m_info.stackHeightInfo[&_varDecl] = m_stackHeight; return success; } @@ -202,7 +202,7 @@ bool AsmAnalyzer::operator()(assembly::FunctionDefinition const& _funDef) bool success = (*this)(_funDef.body); m_stackHeight = stackHeight; - storeStackHeight(_funDef); + m_info.stackHeightInfo[&_funDef] = m_stackHeight; return success; } @@ -269,7 +269,7 @@ bool AsmAnalyzer::operator()(assembly::FunctionCall const& _funCall) success = false; } m_stackHeight += int(returns) - int(arguments); - storeStackHeight(_funCall); + m_info.stackHeightInfo[&_funCall] = m_stackHeight; return success; } @@ -306,7 +306,7 @@ bool AsmAnalyzer::operator()(Block const& _block) } m_currentScope = m_currentScope->superScope; - storeStackHeight(_block); + m_info.stackHeightInfo[&_block] = m_stackHeight; return success; } @@ -372,12 +372,6 @@ bool AsmAnalyzer::checkAssignment(assembly::Identifier const& _variable, size_t return success; } -void AsmAnalyzer::storeStackHeight(const assembly::Statement& _statement) -{ - if (m_stackHeightInfo) - (*m_stackHeightInfo)[&_statement] = m_stackHeight; -} - bool AsmAnalyzer::expectDeposit(int const _deposit, int const _oldHeight, SourceLocation const& _location) { int stackDiff = m_stackHeight - _oldHeight; @@ -400,7 +394,7 @@ bool AsmAnalyzer::expectDeposit(int const _deposit, int const _oldHeight, Source Scope& AsmAnalyzer::scope(Block const* _block) { - auto scopePtr = m_scopes.at(_block); + auto scopePtr = m_info.scopes.at(_block); solAssert(scopePtr, "Scope requested but not present."); return *scopePtr; } diff --git a/libsolidity/inlineasm/AsmAnalysis.h b/libsolidity/inlineasm/AsmAnalysis.h index 8256ed3c..426ee0d2 100644 --- a/libsolidity/inlineasm/AsmAnalysis.h +++ b/libsolidity/inlineasm/AsmAnalysis.h @@ -50,8 +50,7 @@ struct FunctionCall; struct Scope; -using Statement = boost::variant<Instruction, Literal, Label, Assignment, Identifier, FunctionalAssignment, FunctionCall, FunctionalInstruction, VariableDeclaration, FunctionDefinition, Block>; -using StackHeightInfo = std::map<assembly::Statement const*, int>; +struct AsmAnalysisInfo; /** * Performs the full analysis stage, calls the ScopeFiller internally, then resolves @@ -61,12 +60,10 @@ using StackHeightInfo = std::map<assembly::Statement const*, int>; class AsmAnalyzer: public boost::static_visitor<bool> { public: - using Scopes = std::map<assembly::Block const*, std::shared_ptr<Scope>>; AsmAnalyzer( - Scopes& _scopes, + AsmAnalysisInfo& _analysisInfo, ErrorList& _errors, - ExternalIdentifierAccess::Resolver const& _resolver = ExternalIdentifierAccess::Resolver(), - StackHeightInfo* _stackHeightInfo = nullptr + ExternalIdentifierAccess::Resolver const& _resolver = ExternalIdentifierAccess::Resolver() ); bool analyze(assembly::Block const& _block); @@ -88,7 +85,6 @@ private: /// as the value, @a _valueSize, unless that is equal to -1. bool checkAssignment(assembly::Identifier const& _assignment, size_t _valueSize = size_t(-1)); bool expectDeposit(int _deposit, int _oldHeight, SourceLocation const& _location); - void storeStackHeight(assembly::Statement const& _statement); Scope& scope(assembly::Block const* _block); /// This is used when we enter the body of a function definition. There, the parameters @@ -98,9 +94,8 @@ private: int m_stackHeight = 0; ExternalIdentifierAccess::Resolver const& m_resolver; Scope* m_currentScope = nullptr; - Scopes& m_scopes; + AsmAnalysisInfo& m_info; ErrorList& m_errors; - StackHeightInfo* m_stackHeightInfo; }; } diff --git a/libsolidity/inlineasm/AsmAnalysisInfo.cpp b/libsolidity/inlineasm/AsmAnalysisInfo.cpp new file mode 100644 index 00000000..22318b12 --- /dev/null +++ b/libsolidity/inlineasm/AsmAnalysisInfo.cpp @@ -0,0 +1,26 @@ +/* + This file is part of solidity. + + solidity is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + solidity is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with solidity. If not, see <http://www.gnu.org/licenses/>. +*/ +/** + * Information generated during analyzer part of inline assembly. + */ + +#include <libsolidity/inlineasm/AsmAnalysisInfo.h> + +#include <libsolidity/inlineasm/AsmScope.h> + +#include <ostream> + diff --git a/libsolidity/inlineasm/AsmAnalysisInfo.h b/libsolidity/inlineasm/AsmAnalysisInfo.h new file mode 100644 index 00000000..e21eb2c5 --- /dev/null +++ b/libsolidity/inlineasm/AsmAnalysisInfo.h @@ -0,0 +1,61 @@ +/* + This file is part of solidity. + + solidity is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + solidity is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with solidity. If not, see <http://www.gnu.org/licenses/>. +*/ +/** + * Information generated during analyzer part of inline assembly. + */ + +#pragma once + +#include <boost/variant.hpp> + +#include <map> +#include <memory> + +namespace dev +{ +namespace solidity +{ +namespace assembly +{ + +struct Literal; +struct Block; +struct Label; +struct FunctionalInstruction; +struct FunctionalAssignment; +struct VariableDeclaration; +struct Instruction; +struct Identifier; +struct Assignment; +struct FunctionDefinition; +struct FunctionCall; + +struct Scope; + +using Statement = boost::variant<Instruction, Literal, Label, Assignment, Identifier, FunctionalAssignment, FunctionCall, FunctionalInstruction, VariableDeclaration, FunctionDefinition, Block>; + +struct AsmAnalysisInfo +{ + using StackHeightInfo = std::map<void const*, int>; + using Scopes = std::map<assembly::Block const*, std::shared_ptr<Scope>>; + Scopes scopes; + StackHeightInfo stackHeightInfo; +}; + +} +} +} 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 <libsolidity/inlineasm/AsmData.h> #include <libsolidity/inlineasm/AsmScope.h> #include <libsolidity/inlineasm/AsmAnalysis.h> +#include <libsolidity/inlineasm/AsmAnalysisInfo.h> #include <libevmasm/Assembly.h> #include <libevmasm/SourceLocation.h> @@ -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); } diff --git a/libsolidity/inlineasm/AsmCodeGen.h b/libsolidity/inlineasm/AsmCodeGen.h index 18165cbd..e830e047 100644 --- a/libsolidity/inlineasm/AsmCodeGen.h +++ b/libsolidity/inlineasm/AsmCodeGen.h @@ -47,13 +47,13 @@ public: /// Performs code generation and @returns the result. eth::Assembly assemble( Block const& _parsedData, - AsmAnalyzer::Scopes& _scopes, + AsmAnalysisInfo& _analysisInfo, ExternalIdentifierAccess const& _identifierAccess = ExternalIdentifierAccess() ); /// Performs code generation and appends generated to to _assembly. void assemble( Block const& _parsedData, - AsmAnalyzer::Scopes& _scopes, + AsmAnalysisInfo& _analysisInfo, eth::Assembly& _assembly, ExternalIdentifierAccess const& _identifierAccess = ExternalIdentifierAccess() ); diff --git a/libsolidity/inlineasm/AsmStack.cpp b/libsolidity/inlineasm/AsmStack.cpp index 5defae4c..c2a7d8ea 100644 --- a/libsolidity/inlineasm/AsmStack.cpp +++ b/libsolidity/inlineasm/AsmStack.cpp @@ -26,6 +26,7 @@ #include <libsolidity/inlineasm/AsmCodeGen.h> #include <libsolidity/inlineasm/AsmPrinter.h> #include <libsolidity/inlineasm/AsmAnalysis.h> +#include <libsolidity/inlineasm/AsmAnalysisInfo.h> #include <libsolidity/parsing/Scanner.h> @@ -51,8 +52,8 @@ bool InlineAssemblyStack::parse( return false; *m_parserResult = std::move(*result); - AsmAnalyzer::Scopes scopes; - return (AsmAnalyzer(scopes, m_errors, _resolver)).analyze(*m_parserResult); + AsmAnalysisInfo analysisInfo; + return (AsmAnalyzer(analysisInfo, m_errors, _resolver)).analyze(*m_parserResult); } string InlineAssemblyStack::toString() @@ -62,11 +63,11 @@ string InlineAssemblyStack::toString() eth::Assembly InlineAssemblyStack::assemble() { - AsmAnalyzer::Scopes scopes; - AsmAnalyzer analyzer(scopes, m_errors); + AsmAnalysisInfo analysisInfo; + AsmAnalyzer analyzer(analysisInfo, m_errors); solAssert(analyzer.analyze(*m_parserResult), ""); CodeGenerator codeGen(m_errors); - return codeGen.assemble(*m_parserResult, scopes); + return codeGen.assemble(*m_parserResult, analysisInfo); } bool InlineAssemblyStack::parseAndAssemble( @@ -82,10 +83,10 @@ bool InlineAssemblyStack::parseAndAssemble( return false; solAssert(parserResult, ""); - AsmAnalyzer::Scopes scopes; - AsmAnalyzer analyzer(scopes, errors, _identifierAccess.resolve); + AsmAnalysisInfo analysisInfo; + AsmAnalyzer analyzer(analysisInfo, errors, _identifierAccess.resolve); solAssert(analyzer.analyze(*parserResult), ""); - CodeGenerator(errors).assemble(*parserResult, scopes, _assembly, _identifierAccess); + CodeGenerator(errors).assemble(*parserResult, analysisInfo, _assembly, _identifierAccess); // At this point, the assembly might be messed up, but we should throw an // internal compiler error anyway. |