diff options
author | chriseth <c@ethdev.com> | 2017-02-17 23:05:22 +0800 |
---|---|---|
committer | chriseth <chris@ethereum.org> | 2017-04-25 22:49:03 +0800 |
commit | 5d6747eb32f56f6b8b818eff5635888d250d62e1 (patch) | |
tree | 18fbe91e3db1e139683f49ad833a7f2eb1889595 /libsolidity/inlineasm/AsmAnalysis.h | |
parent | 72fdf755c99c7e90ac973fad8b28e39aed5cc2fa (diff) | |
download | dexon-solidity-5d6747eb32f56f6b8b818eff5635888d250d62e1.tar.gz dexon-solidity-5d6747eb32f56f6b8b818eff5635888d250d62e1.tar.zst dexon-solidity-5d6747eb32f56f6b8b818eff5635888d250d62e1.zip |
Refactor assembly analysis into scope filling and checking.
Diffstat (limited to 'libsolidity/inlineasm/AsmAnalysis.h')
-rw-r--r-- | libsolidity/inlineasm/AsmAnalysis.h | 111 |
1 files changed, 16 insertions, 95 deletions
diff --git a/libsolidity/inlineasm/AsmAnalysis.h b/libsolidity/inlineasm/AsmAnalysis.h index 8658a477..c81b7a82 100644 --- a/libsolidity/inlineasm/AsmAnalysis.h +++ b/libsolidity/inlineasm/AsmAnalysis.h @@ -46,104 +46,29 @@ struct Assignment; struct FunctionDefinition; struct FunctionCall; -template <class...> -struct GenericVisitor{}; - -template <class Visitable, class... Others> -struct GenericVisitor<Visitable, Others...>: public GenericVisitor<Others...> -{ - using GenericVisitor<Others...>::operator (); - explicit GenericVisitor( - std::function<void(Visitable&)> _visitor, - std::function<void(Others&)>... _otherVisitors - ): - GenericVisitor<Others...>(_otherVisitors...), - m_visitor(_visitor) - {} - - void operator()(Visitable& _v) const { m_visitor(_v); } - - std::function<void(Visitable&)> m_visitor; -}; -template <> -struct GenericVisitor<>: public boost::static_visitor<> { - void operator()() const {} -}; - - -struct Scope -{ - struct Variable - { - int stackHeight = 0; - bool active = false; - }; - - struct Label - { - size_t id = unassignedLabelId; - static const size_t errorLabelId = -1; - static const size_t unassignedLabelId = 0; - }; - - struct Function - { - Function(size_t _arguments, size_t _returns): arguments(_arguments), returns(_returns) {} - size_t arguments = 0; - size_t returns = 0; - }; - - using Identifier = boost::variant<Variable, Label, Function>; - using Visitor = GenericVisitor<Variable const, Label const, Function const>; - using NonconstVisitor = GenericVisitor<Variable, Label, Function>; - - bool registerVariable(std::string const& _name); - bool registerLabel(std::string const& _name); - bool registerFunction(std::string const& _name, size_t _arguments, size_t _returns); - - /// Looks up the identifier in this or super scopes and returns a valid pointer if found - /// or a nullptr if not found. Variable lookups up across function boundaries will fail, as - /// will any lookups across assembly boundaries. - /// The pointer will be invalidated if the scope is modified. - /// @param _crossedFunction if true, we already crossed a function boundary during recursive lookup - Identifier* lookup(std::string const& _name); - /// Looks up the identifier in this and super scopes (will not find variables across function - /// boundaries and generally stops at assembly boundaries) and calls the visitor, returns - /// false if not found. - template <class V> - bool lookup(std::string const& _name, V const& _visitor) - { - if (Identifier* id = lookup(_name)) - { - boost::apply_visitor(_visitor, *id); - return true; - } - else - return false; - } - /// @returns true if the name exists in this scope or in super scopes (also searches - /// across function and assembly boundaries). - bool exists(std::string const& _name); - Scope* superScope = nullptr; - /// If true, variables from the super scope are not visible here (other identifiers are), - /// but they are still taken into account to prevent shadowing. - bool functionScope = false; - std::map<std::string, Identifier> identifiers; -}; - +struct Scope; +/** + * Performs the full analysis stage, calls the ScopeFiller internally, then resolves + * references and performs other checks. + * @todo Does not yet check for stack height issues. + */ class AsmAnalyzer: public boost::static_visitor<bool> { public: using Scopes = std::map<assembly::Block const*, std::shared_ptr<Scope>>; - AsmAnalyzer(Scopes& _scopes, ErrorList& _errors); + /// @param _allowFailedLookups if true, allow failed lookups for variables (they + /// will be provided from the environment later on) + AsmAnalyzer(Scopes& _scopes, ErrorList& _errors, bool _allowFailedLookups); + + bool analyze(assembly::Block const& _block); bool operator()(assembly::Instruction const&) { return true; } bool operator()(assembly::Literal const& _literal); - bool operator()(assembly::Identifier const&) { return true; } + bool operator()(assembly::Identifier const&); bool operator()(assembly::FunctionalInstruction const& _functionalInstruction); - bool operator()(assembly::Label const& _label); - bool operator()(assembly::Assignment const&) { return true; } + bool operator()(assembly::Label const&) { return true; } + bool operator()(assembly::Assignment const&); bool operator()(assembly::FunctionalAssignment const& _functionalAssignment); bool operator()(assembly::VariableDeclaration const& _variableDeclaration); bool operator()(assembly::FunctionDefinition const& _functionDefinition); @@ -151,14 +76,10 @@ public: bool operator()(assembly::Block const& _block); private: - bool registerVariable( - std::string const& _name, - SourceLocation const& _location, - Scope& _scope - ); - + bool checkAssignment(assembly::Identifier const& _assignment); Scope& scope(assembly::Block const* _block); + bool m_allowFailedLookups = false; Scope* m_currentScope = nullptr; Scopes& m_scopes; ErrorList& m_errors; |