diff options
author | Christian Parpart <christian@ethereum.org> | 2018-10-15 17:52:35 +0800 |
---|---|---|
committer | Christian Parpart <christian@ethereum.org> | 2018-10-15 17:52:35 +0800 |
commit | 9a4bec7e474a310c7f93ff3b84928e0e9ba9cce6 (patch) | |
tree | 2668ab22a40aad2448081f7bf22c7235d4b4c963 /libyul/backends/evm/EVMCodeTransform.h | |
parent | b965fd6e17f77e94afeb070a27182251b85b8ab3 (diff) | |
download | dexon-solidity-9a4bec7e474a310c7f93ff3b84928e0e9ba9cce6.tar.gz dexon-solidity-9a4bec7e474a310c7f93ff3b84928e0e9ba9cce6.tar.zst dexon-solidity-9a4bec7e474a310c7f93ff3b84928e0e9ba9cce6.zip |
Renaming libjulia to libyul
Diffstat (limited to 'libyul/backends/evm/EVMCodeTransform.h')
-rw-r--r-- | libyul/backends/evm/EVMCodeTransform.h | 158 |
1 files changed, 158 insertions, 0 deletions
diff --git a/libyul/backends/evm/EVMCodeTransform.h b/libyul/backends/evm/EVMCodeTransform.h new file mode 100644 index 00000000..6a0941b6 --- /dev/null +++ b/libyul/backends/evm/EVMCodeTransform.h @@ -0,0 +1,158 @@ +/* + 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/>. +*/ +/** + * Common code generator for translating Yul / inline assembly to EVM and EVM1.5. + */ + +#include <libyul/backends/evm/EVMAssembly.h> + +#include <libyul/ASTDataForward.h> + +#include <libsolidity/inlineasm/AsmScope.h> + +#include <boost/variant.hpp> +#include <boost/optional.hpp> + +namespace dev +{ +namespace solidity +{ +class ErrorReporter; +namespace assembly +{ +struct AsmAnalysisInfo; +} +} +namespace julia +{ +class EVMAssembly; + +class CodeTransform: public boost::static_visitor<> +{ +public: + /// Create the code transformer. + /// @param _identifierAccess used to resolve identifiers external to the inline assembly + CodeTransform( + julia::AbstractAssembly& _assembly, + solidity::assembly::AsmAnalysisInfo& _analysisInfo, + bool _yul = false, + bool _evm15 = false, + ExternalIdentifierAccess const& _identifierAccess = ExternalIdentifierAccess(), + bool _useNamedLabelsForFunctions = false + ): CodeTransform( + _assembly, + _analysisInfo, + _yul, + _evm15, + _identifierAccess, + _useNamedLabelsForFunctions, + _assembly.stackHeight(), + std::make_shared<Context>() + ) + { + } + +protected: + struct Context + { + using Scope = solidity::assembly::Scope; + std::map<Scope::Label const*, AbstractAssembly::LabelID> labelIDs; + std::map<Scope::Function const*, AbstractAssembly::LabelID> functionEntryIDs; + std::map<Scope::Variable const*, int> variableStackHeights; + }; + + CodeTransform( + julia::AbstractAssembly& _assembly, + solidity::assembly::AsmAnalysisInfo& _analysisInfo, + bool _yul, + bool _evm15, + ExternalIdentifierAccess const& _identifierAccess, + bool _useNamedLabelsForFunctions, + int _stackAdjustment, + std::shared_ptr<Context> _context + ): + m_assembly(_assembly), + m_info(_analysisInfo), + m_yul(_yul), + m_evm15(_evm15), + m_useNamedLabelsForFunctions(_useNamedLabelsForFunctions), + m_identifierAccess(_identifierAccess), + m_stackAdjustment(_stackAdjustment), + m_context(_context) + {} + +public: + void operator()(Instruction const& _instruction); + void operator()(Literal const& _literal); + void operator()(Identifier const& _identifier); + void operator()(FunctionalInstruction const& _instr); + void operator()(FunctionCall const&); + void operator()(ExpressionStatement const& _statement); + void operator()(Label const& _label); + void operator()(StackAssignment const& _assignment); + void operator()(Assignment const& _assignment); + void operator()(VariableDeclaration const& _varDecl); + void operator()(If const& _if); + void operator()(Switch const& _switch); + void operator()(FunctionDefinition const&); + void operator()(ForLoop const&); + void operator()(Block const& _block); + +private: + AbstractAssembly::LabelID labelFromIdentifier(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(std::string const& _name, solidity::assembly::Scope::Function const& _function); + /// Generates code for an expression that is supposed to return a single value. + void visitExpression(Expression const& _expression); + + void visitStatements(std::vector<Statement> const& _statements); + + /// Pops all variables declared in the block and checks that the stack height is equal + /// to @a _blackStartStackHeight. + void finalizeBlock(Block const& _block, int _blockStartStackHeight); + + void generateMultiAssignment(std::vector<Identifier> const& _variableNames); + void generateAssignment(Identifier const& _variableName); + + /// Determines the stack height difference to the given variables. Throws + /// if it is not yet in scope or the height difference is too large. Returns + /// the (positive) stack height difference otherwise. + int variableHeightDiff(solidity::assembly::Scope::Variable const& _var, bool _forSwap) const; + + void expectDeposit(int _deposit, int _oldHeight) const; + + void checkStackHeight(void const* _astElement) const; + + julia::AbstractAssembly& m_assembly; + solidity::assembly::AsmAnalysisInfo& m_info; + solidity::assembly::Scope* m_scope = nullptr; + bool m_yul = false; + bool m_evm15 = false; + bool m_useNamedLabelsForFunctions = false; + ExternalIdentifierAccess m_identifierAccess; + /// Adjustment between the stack height as determined during the analysis phase + /// and the stack height in the assembly. This is caused by an initial stack being present + /// 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<Context> m_context; +}; + +} +} |