diff options
Diffstat (limited to 'libsolidity/inlineasm/AsmAnalysis.h')
-rw-r--r-- | libsolidity/inlineasm/AsmAnalysis.h | 119 |
1 files changed, 32 insertions, 87 deletions
diff --git a/libsolidity/inlineasm/AsmAnalysis.h b/libsolidity/inlineasm/AsmAnalysis.h index 9726210d..426ee0d2 100644 --- a/libsolidity/inlineasm/AsmAnalysis.h +++ b/libsolidity/inlineasm/AsmAnalysis.h @@ -20,6 +20,8 @@ #pragma once +#include <libsolidity/inlineasm/AsmStack.h> + #include <libsolidity/interface/Exceptions.h> #include <boost/variant.hpp> @@ -46,101 +48,32 @@ 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 (stops and function and assembly boundaries) - /// and returns a valid pointer if found or a nullptr if not found. - /// The pointer will be invalidated if the scope is modified. - Identifier* lookup(std::string const& _name); - /// Looks up the identifier in this and super scopes (stops and function and 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, identifiers from the super scope are not visible here, but they are still - /// taken into account to prevent shadowing. - bool closedScope = false; - std::map<std::string, Identifier> identifiers; -}; +struct Scope; +struct AsmAnalysisInfo; +/** + * Performs the full analysis stage, calls the ScopeFiller internally, then resolves + * references and performs other checks. + * If all these checks pass, code generation should not throw errors. + */ class AsmAnalyzer: public boost::static_visitor<bool> { public: - using Scopes = std::map<assembly::Block const*, std::shared_ptr<Scope>>; - AsmAnalyzer(Scopes& _scopes, ErrorList& _errors); + AsmAnalyzer( + AsmAnalysisInfo& _analysisInfo, + ErrorList& _errors, + ExternalIdentifierAccess::Resolver const& _resolver = ExternalIdentifierAccess::Resolver() + ); + + bool analyze(assembly::Block const& _block); - bool operator()(assembly::Instruction const&) { return true; } + bool operator()(assembly::Instruction const&); 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::Assignment const&); bool operator()(assembly::FunctionalAssignment const& _functionalAssignment); bool operator()(assembly::VariableDeclaration const& _variableDeclaration); bool operator()(assembly::FunctionDefinition const& _functionDefinition); @@ -148,8 +81,20 @@ public: bool operator()(assembly::Block const& _block); private: + /// Verifies that a variable to be assigned to exists and has the same size + /// 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); + Scope& scope(assembly::Block const* _block); + + /// This is used when we enter the body of a function definition. There, the parameters + /// and return parameters appear as variables which are already on the stack before + /// we enter the block. + int m_virtualVariablesInNextBlock = 0; + int m_stackHeight = 0; + ExternalIdentifierAccess::Resolver const& m_resolver; Scope* m_currentScope = nullptr; - Scopes& m_scopes; + AsmAnalysisInfo& m_info; ErrorList& m_errors; }; |