/src/solidity/libyul/optimiser/ASTCopier.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 | | * Creates an independent copy of an AST, renaming identifiers to be unique. |
20 | | */ |
21 | | |
22 | | #pragma once |
23 | | |
24 | | #include <libyul/ASTForward.h> |
25 | | |
26 | | #include <libyul/YulName.h> |
27 | | |
28 | | #include <memory> |
29 | | #include <optional> |
30 | | #include <set> |
31 | | #include <vector> |
32 | | #include <map> |
33 | | |
34 | | namespace solidity::yul |
35 | | { |
36 | | |
37 | | class ExpressionCopier |
38 | | { |
39 | | public: |
40 | 4.79M | virtual ~ExpressionCopier() = default; |
41 | | virtual Expression operator()(Literal const& _literal) = 0; |
42 | | virtual Expression operator()(Identifier const& _identifier) = 0; |
43 | | virtual Expression operator()(FunctionCall const&) = 0; |
44 | | }; |
45 | | |
46 | | class StatementCopier |
47 | | { |
48 | | public: |
49 | 4.79M | virtual ~StatementCopier() = default; |
50 | | virtual Statement operator()(ExpressionStatement const& _statement) = 0; |
51 | | virtual Statement operator()(Assignment const& _assignment) = 0; |
52 | | virtual Statement operator()(VariableDeclaration const& _varDecl) = 0; |
53 | | virtual Statement operator()(If const& _if) = 0; |
54 | | virtual Statement operator()(Switch const& _switch) = 0; |
55 | | virtual Statement operator()(FunctionDefinition const&) = 0; |
56 | | virtual Statement operator()(ForLoop const&) = 0; |
57 | | virtual Statement operator()(Break const&) = 0; |
58 | | virtual Statement operator()(Continue const&) = 0; |
59 | | virtual Statement operator()(Leave const&) = 0; |
60 | | virtual Statement operator()(Block const& _block) = 0; |
61 | | }; |
62 | | |
63 | | /** |
64 | | * Creates a copy of a Yul AST potentially replacing identifier names. |
65 | | * Base class to be extended. |
66 | | */ |
67 | | class ASTCopier: public ExpressionCopier, public StatementCopier |
68 | | { |
69 | | public: |
70 | 4.79M | ~ASTCopier() override = default; |
71 | | Expression operator()(Literal const& _literal) override; |
72 | | Expression operator()(Identifier const& _identifier) override; |
73 | | Expression operator()(FunctionCall const&) override; |
74 | | Statement operator()(ExpressionStatement const& _statement) override; |
75 | | Statement operator()(Assignment const& _assignment) override; |
76 | | Statement operator()(VariableDeclaration const& _varDecl) override; |
77 | | Statement operator()(If const& _if) override; |
78 | | Statement operator()(Switch const& _switch) override; |
79 | | Statement operator()(FunctionDefinition const&) override; |
80 | | Statement operator()(ForLoop const&) override; |
81 | | Statement operator()(Break const&) override; |
82 | | Statement operator()(Continue const&) override; |
83 | | Statement operator()(Leave const&) override; |
84 | | Statement operator()(Block const& _block) override; |
85 | | |
86 | | virtual Expression translate(Expression const& _expression); |
87 | | virtual Statement translate(Statement const& _statement); |
88 | | |
89 | | Block translate(Block const& _block); |
90 | | protected: |
91 | | template <typename T> |
92 | | std::vector<T> translateVector(std::vector<T> const& _values); |
93 | | |
94 | | template <typename T> |
95 | | std::unique_ptr<T> translate(std::unique_ptr<T> const& _v) |
96 | 20.8M | { |
97 | 20.8M | return _v ? std::make_unique<T>(translate(*_v)) : nullptr; |
98 | 20.8M | } std::__1::unique_ptr<std::__1::variant<solidity::yul::FunctionCall, solidity::yul::Identifier, solidity::yul::Literal>, std::__1::default_delete<std::__1::variant<solidity::yul::FunctionCall, solidity::yul::Identifier, solidity::yul::Literal> > > solidity::yul::ASTCopier::translate<std::__1::variant<solidity::yul::FunctionCall, solidity::yul::Identifier, solidity::yul::Literal> >(std::__1::unique_ptr<std::__1::variant<solidity::yul::FunctionCall, solidity::yul::Identifier, solidity::yul::Literal>, std::__1::default_delete<std::__1::variant<solidity::yul::FunctionCall, solidity::yul::Identifier, solidity::yul::Literal> > > const&) Line | Count | Source | 96 | 20.2M | { | 97 | 20.2M | return _v ? std::make_unique<T>(translate(*_v)) : nullptr; | 98 | 20.2M | } |
std::__1::unique_ptr<solidity::yul::Literal, std::__1::default_delete<solidity::yul::Literal> > solidity::yul::ASTCopier::translate<solidity::yul::Literal>(std::__1::unique_ptr<solidity::yul::Literal, std::__1::default_delete<solidity::yul::Literal> > const&) Line | Count | Source | 96 | 616k | { | 97 | 616k | return _v ? std::make_unique<T>(translate(*_v)) : nullptr; | 98 | 616k | } |
|
99 | | |
100 | | Case translate(Case const& _case); |
101 | | virtual Identifier translate(Identifier const& _identifier); |
102 | | Literal translate(Literal const& _literal); |
103 | | FunctionName translate(FunctionName const& _functionName); |
104 | | NameWithDebugData translate(NameWithDebugData const& _typedName); |
105 | | |
106 | 5.51M | virtual void enterScope(Block const&) { } |
107 | 5.51M | virtual void leaveScope(Block const&) { } |
108 | 774k | virtual void enterFunction(FunctionDefinition const&) { } |
109 | 774k | virtual void leaveFunction(FunctionDefinition const&) { } |
110 | 8.44M | virtual YulName translateIdentifier(YulName _name) { return _name; } |
111 | | }; |
112 | | |
113 | | template <typename T> |
114 | | std::vector<T> ASTCopier::translateVector(std::vector<T> const& _values) |
115 | 43.5M | { |
116 | 43.5M | std::vector<T> translated; |
117 | 43.5M | for (auto const& v: _values) |
118 | 78.8M | translated.emplace_back(translate(v)); |
119 | 43.5M | return translated; |
120 | 43.5M | } std::__1::vector<solidity::yul::NameWithDebugData, std::__1::allocator<solidity::yul::NameWithDebugData> > solidity::yul::ASTCopier::translateVector<solidity::yul::NameWithDebugData>(std::__1::vector<solidity::yul::NameWithDebugData, std::__1::allocator<solidity::yul::NameWithDebugData> > const&) Line | Count | Source | 115 | 18.8M | { | 116 | 18.8M | std::vector<T> translated; | 117 | 18.8M | for (auto const& v: _values) | 118 | 19.0M | translated.emplace_back(translate(v)); | 119 | 18.8M | return translated; | 120 | 18.8M | } |
std::__1::vector<solidity::yul::Identifier, std::__1::allocator<solidity::yul::Identifier> > solidity::yul::ASTCopier::translateVector<solidity::yul::Identifier>(std::__1::vector<solidity::yul::Identifier, std::__1::allocator<solidity::yul::Identifier> > const&) Line | Count | Source | 115 | 1.89M | { | 116 | 1.89M | std::vector<T> translated; | 117 | 1.89M | for (auto const& v: _values) | 118 | 1.89M | translated.emplace_back(translate(v)); | 119 | 1.89M | return translated; | 120 | 1.89M | } |
std::__1::vector<std::__1::variant<solidity::yul::FunctionCall, solidity::yul::Identifier, solidity::yul::Literal>, std::__1::allocator<std::__1::variant<solidity::yul::FunctionCall, solidity::yul::Identifier, solidity::yul::Literal> > > solidity::yul::ASTCopier::translateVector<std::__1::variant<solidity::yul::FunctionCall, solidity::yul::Identifier, solidity::yul::Literal> >(std::__1::vector<std::__1::variant<solidity::yul::FunctionCall, solidity::yul::Identifier, solidity::yul::Literal>, std::__1::allocator<std::__1::variant<solidity::yul::FunctionCall, solidity::yul::Identifier, solidity::yul::Literal> > > const&) Line | Count | Source | 115 | 16.7M | { | 116 | 16.7M | std::vector<T> translated; | 117 | 16.7M | for (auto const& v: _values) | 118 | 29.4M | translated.emplace_back(translate(v)); | 119 | 16.7M | return translated; | 120 | 16.7M | } |
std::__1::vector<solidity::yul::Case, std::__1::allocator<solidity::yul::Case> > solidity::yul::ASTCopier::translateVector<solidity::yul::Case>(std::__1::vector<solidity::yul::Case, std::__1::allocator<solidity::yul::Case> > const&) Line | Count | Source | 115 | 239k | { | 116 | 239k | std::vector<T> translated; | 117 | 239k | for (auto const& v: _values) | 118 | 616k | translated.emplace_back(translate(v)); | 119 | 239k | return translated; | 120 | 239k | } |
std::__1::vector<std::__1::variant<solidity::yul::ExpressionStatement, solidity::yul::Assignment, solidity::yul::VariableDeclaration, solidity::yul::FunctionDefinition, solidity::yul::If, solidity::yul::Switch, solidity::yul::ForLoop, solidity::yul::Break, solidity::yul::Continue, solidity::yul::Leave, solidity::yul::Block>, std::__1::allocator<std::__1::variant<solidity::yul::ExpressionStatement, solidity::yul::Assignment, solidity::yul::VariableDeclaration, solidity::yul::FunctionDefinition, solidity::yul::If, solidity::yul::Switch, solidity::yul::ForLoop, solidity::yul::Break, solidity::yul::Continue, solidity::yul::Leave, solidity::yul::Block> > > solidity::yul::ASTCopier::translateVector<std::__1::variant<solidity::yul::ExpressionStatement, solidity::yul::Assignment, solidity::yul::VariableDeclaration, solidity::yul::FunctionDefinition, solidity::yul::If, solidity::yul::Switch, solidity::yul::ForLoop, solidity::yul::Break, solidity::yul::Continue, solidity::yul::Leave, solidity::yul::Block> >(std::__1::vector<std::__1::variant<solidity::yul::ExpressionStatement, solidity::yul::Assignment, solidity::yul::VariableDeclaration, solidity::yul::FunctionDefinition, solidity::yul::If, solidity::yul::Switch, solidity::yul::ForLoop, solidity::yul::Break, solidity::yul::Continue, solidity::yul::Leave, solidity::yul::Block>, std::__1::allocator<std::__1::variant<solidity::yul::ExpressionStatement, solidity::yul::Assignment, solidity::yul::VariableDeclaration, solidity::yul::FunctionDefinition, solidity::yul::If, solidity::yul::Switch, solidity::yul::ForLoop, solidity::yul::Break, solidity::yul::Continue, solidity::yul::Leave, solidity::yul::Block> > > const&) Line | Count | Source | 115 | 5.77M | { | 116 | 5.77M | std::vector<T> translated; | 117 | 5.77M | for (auto const& v: _values) | 118 | 27.7M | translated.emplace_back(translate(v)); | 119 | 5.77M | return translated; | 120 | 5.77M | } |
|
121 | | |
122 | | /// Helper class that creates a copy of the function definition, replacing the names of the variable |
123 | | /// declarations with new names. |
124 | | class FunctionCopier: public ASTCopier |
125 | | { |
126 | | public: |
127 | | FunctionCopier( |
128 | | std::map<YulName, YulName> const& _translations |
129 | | ): |
130 | | m_translations(_translations) |
131 | 228k | {} |
132 | | using ASTCopier::operator(); |
133 | | YulName translateIdentifier(YulName _name) override; |
134 | | private: |
135 | | /// A mapping between old and new names. We replace the names of variable declarations contained |
136 | | /// in the mapping with their new names. |
137 | | std::map<YulName, YulName> const& m_translations; |
138 | | }; |
139 | | |
140 | | } |