Coverage Report

Created: 2025-09-04 07:34

/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
}