/src/solidity/libsolidity/codegen/ContractCompiler.h
Line | Count | Source |
1 | | /* |
2 | | This file is part of solidity. |
3 | | |
4 | | solidity is free software: you can redistribute it and/or modify |
5 | | it under the terms of the GNU General Public License as published by |
6 | | the Free Software Foundation, either version 3 of the License, or |
7 | | (at your option) any later version. |
8 | | |
9 | | solidity is distributed in the hope that it will be useful, |
10 | | but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 | | GNU General Public License for more details. |
13 | | |
14 | | You should have received a copy of the GNU General Public License |
15 | | along with solidity. If not, see <http://www.gnu.org/licenses/>. |
16 | | */ |
17 | | // SPDX-License-Identifier: GPL-3.0 |
18 | | /** |
19 | | * @author Christian <c@ethdev.com> |
20 | | * @date 2014 |
21 | | * Code generator for contracts. |
22 | | */ |
23 | | |
24 | | #pragma once |
25 | | |
26 | | #include <libsolidity/ast/ASTVisitor.h> |
27 | | #include <libsolidity/codegen/CompilerContext.h> |
28 | | #include <libsolidity/interface/DebugSettings.h> |
29 | | #include <libevmasm/Assembly.h> |
30 | | #include <functional> |
31 | | #include <ostream> |
32 | | #include <map> |
33 | | |
34 | | namespace solidity::frontend |
35 | | { |
36 | | |
37 | | /** |
38 | | * Code generator at the contract level. Can be used to generate code for exactly one contract |
39 | | * either in "runtime mode" or "creation mode". |
40 | | */ |
41 | | class ContractCompiler: private ASTConstVisitor |
42 | | { |
43 | | public: |
44 | | explicit ContractCompiler( |
45 | | ContractCompiler* _runtimeCompiler, |
46 | | CompilerContext& _context, |
47 | | OptimiserSettings _optimiserSettings |
48 | | ): |
49 | 27.2k | m_optimiserSettings(std::move(_optimiserSettings)), |
50 | 27.2k | m_runtimeCompiler(_runtimeCompiler), |
51 | 27.2k | m_context(_context) |
52 | 27.2k | { |
53 | 27.2k | } |
54 | | |
55 | | void compileContract( |
56 | | ContractDefinition const& _contract, |
57 | | std::map<ContractDefinition const*, std::shared_ptr<Compiler const>> const& _otherCompilers |
58 | | ); |
59 | | /// Compiles the constructor part of the contract. |
60 | | /// @returns the identifier of the runtime sub-assembly. |
61 | | evmasm::SubAssemblyID compileConstructor( |
62 | | ContractDefinition const& _contract, |
63 | | std::map<ContractDefinition const*, std::shared_ptr<Compiler const>> const& _otherCompilers |
64 | | ); |
65 | | |
66 | | private: |
67 | | /// Registers the non-function objects inside the contract with the context and stores the basic |
68 | | /// information about the contract like the AST annotations. |
69 | | void initializeContext( |
70 | | ContractDefinition const& _contract, |
71 | | std::map<ContractDefinition const*, std::shared_ptr<Compiler const>> const& _otherCompilers |
72 | | ); |
73 | | /// Adds the code that is run at creation time. Should be run after exchanging the run-time context |
74 | | /// with a new and initialized context. Adds the constructor code. |
75 | | /// @returns the identifier of the runtime sub assembly |
76 | | evmasm::SubAssemblyID packIntoContractCreator(ContractDefinition const& _contract); |
77 | | /// Appends code that deploys the given contract as a library. |
78 | | /// Will also add code that modifies the contract in memory by injecting the current address |
79 | | /// for the call protector. |
80 | | evmasm::SubAssemblyID deployLibrary(ContractDefinition const& _contract); |
81 | | /// Appends state variable initialisation and constructor code. |
82 | | void appendInitAndConstructorCode(ContractDefinition const& _contract); |
83 | | void appendBaseConstructor(FunctionDefinition const& _constructor); |
84 | | void appendConstructor(FunctionDefinition const& _constructor); |
85 | | /// Appends code that returns a boolean flag on the stack that tells whether |
86 | | /// the contract has been called via delegatecall (false) or regular call (true). |
87 | | /// This is done by inserting a specific push constant as the first instruction |
88 | | /// whose data will be modified in memory at deploy time. |
89 | | void appendDelegatecallCheck(); |
90 | | /// Appends the function selector. Is called recursively to create a binary search tree. |
91 | | /// @a _runs the number of intended executions of the contract to tune the split point. |
92 | | void appendInternalSelector( |
93 | | std::map<util::FixedHash<4>, evmasm::AssemblyItem const> const& _entryPoints, |
94 | | std::vector<util::FixedHash<4>> const& _ids, |
95 | | evmasm::AssemblyItem const& _notFoundTag, |
96 | | OptimiserSettings::ExecutionCount _runs |
97 | | ); |
98 | | void appendFunctionSelector(ContractDefinition const& _contract); |
99 | | void appendCallValueCheck(); |
100 | | void appendReturnValuePacker(TypePointers const& _typeParameters, bool _isLibrary); |
101 | | |
102 | | void registerStateVariables(ContractDefinition const& _contract); |
103 | | void registerImmutableVariables(ContractDefinition const& _contract); |
104 | | void initializeStateVariables(ContractDefinition const& _contract); |
105 | | |
106 | | bool visit(VariableDeclaration const& _variableDeclaration) override; |
107 | | bool visit(FunctionDefinition const& _function) override; |
108 | | bool visit(InlineAssembly const& _inlineAssembly) override; |
109 | | bool visit(TryStatement const& _tryStatement) override; |
110 | | void handleCatch(std::vector<ASTPointer<TryCatchClause>> const& _catchClauses); |
111 | | bool visit(TryCatchClause const& _clause) override; |
112 | | bool visit(IfStatement const& _ifStatement) override; |
113 | | bool visit(WhileStatement const& _whileStatement) override; |
114 | | bool visit(ForStatement const& _forStatement) override; |
115 | | bool visit(Continue const& _continueStatement) override; |
116 | | bool visit(Break const& _breakStatement) override; |
117 | | bool visit(Return const& _return) override; |
118 | | bool visit(Throw const& _throw) override; |
119 | | bool visit(EmitStatement const& _emit) override; |
120 | | bool visit(RevertStatement const& _revert) override; |
121 | | bool visit(VariableDeclarationStatement const& _variableDeclarationStatement) override; |
122 | | bool visit(ExpressionStatement const& _expressionStatement) override; |
123 | | bool visit(PlaceholderStatement const&) override; |
124 | | bool visit(Block const& _block) override; |
125 | | void endVisit(Block const& _block) override; |
126 | | |
127 | | /// Repeatedly visits all function which are referenced but which are not compiled yet. |
128 | | void appendMissingFunctions(); |
129 | | |
130 | | /// Appends one layer of function modifier code of the current function, or the function |
131 | | /// body itself if the last modifier was reached. |
132 | | void appendModifierOrFunctionCode(); |
133 | | |
134 | | /// Creates a stack slot for the given variable and assigns a default value. |
135 | | /// If the default value is complex (needs memory allocation) and @a _provideDefaultValue |
136 | | /// is false, this might be skipped. |
137 | | void appendStackVariableInitialisation(VariableDeclaration const& _variable, bool _provideDefaultValue); |
138 | | void compileExpression(Expression const& _expression, Type const* _targetType = nullptr); |
139 | | |
140 | | /// Frees the variables of a certain scope (to be used when leaving). |
141 | | void popScopedVariables(ASTNode const* _node); |
142 | | |
143 | | /// Sets the stack height for the visited loop. |
144 | | void storeStackHeight(ASTNode const* _node); |
145 | | |
146 | | OptimiserSettings const m_optimiserSettings; |
147 | | /// Pointer to the runtime compiler in case this is a creation compiler. |
148 | | ContractCompiler* m_runtimeCompiler = nullptr; |
149 | | CompilerContext& m_context; |
150 | | |
151 | | /// Tag to jump to for a "break" statement and the stack height after freeing the local loop variables. |
152 | | std::vector<std::pair<evmasm::AssemblyItem, unsigned>> m_breakTags; |
153 | | /// Tag to jump to for a "continue" statement and the stack height after freeing the local loop variables. |
154 | | std::vector<std::pair<evmasm::AssemblyItem, unsigned>> m_continueTags; |
155 | | /// Tag to jump to for a "return" statement and the stack height after freeing the local function or modifier variables. |
156 | | /// Needs to be stacked because of modifiers. |
157 | | std::vector<std::pair<evmasm::AssemblyItem, unsigned>> m_returnTags; |
158 | | unsigned m_modifierDepth = 0; |
159 | | FunctionDefinition const* m_currentFunction = nullptr; |
160 | | |
161 | | // arguments for base constructors, filled in derived-to-base order |
162 | | std::map<FunctionDefinition const*, ASTNode const*> const* m_baseArguments; |
163 | | |
164 | | /// Stores the variables that were declared inside a specific scope, for each modifier depth. |
165 | | std::map<unsigned, std::map<ASTNode const*, unsigned>> m_scopeStackHeight; |
166 | | }; |
167 | | |
168 | | } |