/src/solidity/libyul/YulStack.h
Line | Count | Source (jump to first uncovered line) |
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 | | * Full assembly stack that can support Yul as input. |
20 | | */ |
21 | | |
22 | | #pragma once |
23 | | |
24 | | #include <liblangutil/CharStreamProvider.h> |
25 | | #include <liblangutil/DebugInfoSelection.h> |
26 | | #include <liblangutil/ErrorReporter.h> |
27 | | #include <liblangutil/EVMVersion.h> |
28 | | #include <liblangutil/Exceptions.h> |
29 | | |
30 | | #include <libsolutil/JSON.h> |
31 | | |
32 | | #include <libyul/Object.h> |
33 | | #include <libyul/ObjectOptimizer.h> |
34 | | #include <libyul/ObjectParser.h> |
35 | | |
36 | | #include <libsolidity/interface/OptimiserSettings.h> |
37 | | |
38 | | #include <libevmasm/LinkerObject.h> |
39 | | |
40 | | #include <memory> |
41 | | #include <string> |
42 | | |
43 | | namespace solidity::evmasm |
44 | | { |
45 | | class Assembly; |
46 | | } |
47 | | |
48 | | namespace solidity::langutil |
49 | | { |
50 | | class Scanner; |
51 | | } |
52 | | |
53 | | namespace solidity::yul |
54 | | { |
55 | | class AbstractAssembly; |
56 | | |
57 | | |
58 | | struct MachineAssemblyObject |
59 | | { |
60 | | std::shared_ptr<evmasm::LinkerObject> bytecode; |
61 | | std::shared_ptr<evmasm::Assembly> assembly; |
62 | | std::unique_ptr<std::string> sourceMappings; |
63 | | Json ethdebug = Json::object(); |
64 | | }; |
65 | | |
66 | | /* |
67 | | * Full assembly stack that can support EVM-assembly and Yul as input and EVM as output. |
68 | | */ |
69 | | class YulStack: public langutil::CharStreamProvider |
70 | | { |
71 | | public: |
72 | | using Language = yul::Language; |
73 | | enum class Machine { EVM }; |
74 | | enum State { |
75 | | Empty, |
76 | | Parsed, |
77 | | AnalysisSuccessful |
78 | | }; |
79 | | |
80 | | YulStack(): |
81 | | YulStack( |
82 | | langutil::EVMVersion{}, |
83 | | std::nullopt, |
84 | | Language::Assembly, |
85 | | solidity::frontend::OptimiserSettings::none(), |
86 | | langutil::DebugInfoSelection::Default() |
87 | | ) |
88 | 0 | {} |
89 | | |
90 | | YulStack( |
91 | | langutil::EVMVersion _evmVersion, |
92 | | std::optional<uint8_t> _eofVersion, |
93 | | Language _language, |
94 | | solidity::frontend::OptimiserSettings _optimiserSettings, |
95 | | langutil::DebugInfoSelection const& _debugInfoSelection, |
96 | | langutil::CharStreamProvider const* _soliditySourceProvider = nullptr, |
97 | | std::shared_ptr<ObjectOptimizer> _objectOptimizer = nullptr |
98 | | ): |
99 | | m_language(_language), |
100 | | m_evmVersion(_evmVersion), |
101 | | m_eofVersion(_eofVersion), |
102 | | m_optimiserSettings(std::move(_optimiserSettings)), |
103 | | m_debugInfoSelection(_debugInfoSelection), |
104 | | m_soliditySourceProvider(_soliditySourceProvider), |
105 | | m_errorReporter(m_errors), |
106 | | m_objectOptimizer(_objectOptimizer ? std::move(_objectOptimizer) : std::make_shared<ObjectOptimizer>()) |
107 | 179k | {} |
108 | | |
109 | | /// @returns the char stream used during parsing |
110 | | langutil::CharStream const& charStream(std::string const& _sourceName) const override; |
111 | | |
112 | | /// Runs parsing and analysis steps, returns false if input cannot be assembled. |
113 | | /// Multiple calls overwrite the previous state. |
114 | | bool parseAndAnalyze(std::string const& _sourceName, std::string const& _source); |
115 | | |
116 | | /// Run the optimizer suite. Can only be used with Yul or strict assembly. |
117 | | /// If the settings (see constructor) disabled the optimizer, nothing is done here. |
118 | | void optimize(); |
119 | | |
120 | | /// Run the assembly step (should only be called after parseAndAnalyze). |
121 | | MachineAssemblyObject assemble(Machine _machine); |
122 | | |
123 | | /// Run the assembly step (should only be called after parseAndAnalyze). |
124 | | /// In addition to the value returned by @a assemble, returns |
125 | | /// a second object that is the runtime code. |
126 | | /// Only available for EVM. |
127 | | std::pair<MachineAssemblyObject, MachineAssemblyObject> |
128 | | assembleWithDeployed( |
129 | | std::optional<std::string_view> _deployName = {} |
130 | | ); |
131 | | |
132 | | /// Run the assembly step (should only be called after parseAndAnalyze). |
133 | | /// Similar to @a assemblyWithDeployed, but returns EVM assembly objects. |
134 | | /// Only available for EVM. |
135 | | std::pair<std::shared_ptr<evmasm::Assembly>, std::shared_ptr<evmasm::Assembly>> |
136 | | assembleEVMWithDeployed( |
137 | | std::optional<std::string_view> _deployName = {} |
138 | | ); |
139 | | |
140 | | /// @returns the errors generated during parsing, analysis (and potentially assembly). |
141 | 48.8k | langutil::ErrorList const& errors() const { return m_errors; } |
142 | 4.90k | bool hasErrors() const { return m_errorReporter.hasErrors(); } |
143 | 0 | bool hasErrorsWarningsOrInfos() const { return m_errorReporter.hasErrorsWarningsOrInfos(); } |
144 | | |
145 | | /// Pretty-print the input after having parsed it. |
146 | | std::string print() const; |
147 | | Json astJson() const; |
148 | | |
149 | | // return the JSON representation of the YuL CFG (experimental) |
150 | | Json cfgJson() const; |
151 | | |
152 | | /// Return the parsed and analyzed object. |
153 | | std::shared_ptr<Object> parserResult() const; |
154 | | |
155 | | Dialect const& dialect() const; |
156 | | |
157 | 28.5k | langutil::DebugInfoSelection debugInfoSelection() const { return m_debugInfoSelection; } |
158 | | |
159 | | private: |
160 | | bool parse(std::string const& _sourceName, std::string const& _source); |
161 | | bool analyzeParsed(); |
162 | | bool analyzeParsed(yul::Object& _object); |
163 | | |
164 | | void compileEVM(yul::AbstractAssembly& _assembly, bool _optimize) const; |
165 | | |
166 | | /// Prints the Yul object stored internally and parses it again. |
167 | | /// This ensures that the debug info in the AST matches the source that printing would produce |
168 | | /// rather than the initial source. |
169 | | /// @warning Does not update the error list or the original source (@a m_charStream) to make |
170 | | /// it possible to report errors to the user even after the optimization has been performed. |
171 | | void reparse(); |
172 | | |
173 | | void reportUnimplementedFeatureError(langutil::UnimplementedFeatureError const& _error); |
174 | | |
175 | | Language m_language = Language::Assembly; |
176 | | langutil::EVMVersion m_evmVersion; |
177 | | std::optional<uint8_t> m_eofVersion; |
178 | | solidity::frontend::OptimiserSettings m_optimiserSettings; |
179 | | langutil::DebugInfoSelection m_debugInfoSelection{}; |
180 | | |
181 | | /// Provider of the Solidity sources that the Yul code was generated from. |
182 | | /// Necessary when code snippets are requested as a part of debug info. When null, code snippets are omitted. |
183 | | /// NOTE: Not owned by YulStack, the user must ensure that it is not destroyed before the stack is. |
184 | | langutil::CharStreamProvider const* m_soliditySourceProvider{}; |
185 | | |
186 | | std::unique_ptr<langutil::CharStream> m_charStream; |
187 | | |
188 | | State m_stackState = Empty; |
189 | | std::shared_ptr<yul::Object> m_parserResult; |
190 | | langutil::ErrorList m_errors; |
191 | | langutil::ErrorReporter m_errorReporter; |
192 | | |
193 | | std::shared_ptr<ObjectOptimizer> m_objectOptimizer; |
194 | | }; |
195 | | |
196 | | } |