Coverage Report

Created: 2022-08-24 06:43

/src/solidity/libyul/backends/evm/EthAssemblyAdapter.cpp
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
 * Adaptor between AbstractAssembly and libevmasm.
20
 */
21
22
#include <libyul/backends/evm/EthAssemblyAdapter.h>
23
24
#include <libyul/backends/evm/AbstractAssembly.h>
25
#include <libyul/Exceptions.h>
26
27
#include <libevmasm/Assembly.h>
28
#include <libevmasm/AssemblyItem.h>
29
#include <libevmasm/Instruction.h>
30
31
#include <liblangutil/SourceLocation.h>
32
33
#include <memory>
34
#include <functional>
35
36
using namespace std;
37
using namespace solidity;
38
using namespace solidity::yul;
39
using namespace solidity::util;
40
using namespace solidity::langutil;
41
42
EthAssemblyAdapter::EthAssemblyAdapter(evmasm::Assembly& _assembly):
43
  m_assembly(_assembly)
44
39.4k
{
45
39.4k
}
46
47
void EthAssemblyAdapter::setSourceLocation(SourceLocation const& _location)
48
1.96M
{
49
1.96M
  m_assembly.setSourceLocation(_location);
50
1.96M
}
51
52
int EthAssemblyAdapter::stackHeight() const
53
2.72M
{
54
2.72M
  return m_assembly.deposit();
55
2.72M
}
56
57
void EthAssemblyAdapter::setStackHeight(int height)
58
156k
{
59
156k
  m_assembly.setDeposit(height);
60
156k
}
61
62
void EthAssemblyAdapter::appendInstruction(evmasm::Instruction _instruction)
63
1.00M
{
64
1.00M
  m_assembly.append(_instruction);
65
1.00M
}
66
67
void EthAssemblyAdapter::appendConstant(u256 const& _constant)
68
275k
{
69
275k
  m_assembly.append(_constant);
70
275k
}
71
72
void EthAssemblyAdapter::appendLabel(LabelID _labelId)
73
294k
{
74
294k
  m_assembly.append(evmasm::AssemblyItem(evmasm::Tag, _labelId));
75
294k
}
76
77
void EthAssemblyAdapter::appendLabelReference(LabelID _labelId)
78
208k
{
79
208k
  m_assembly.append(evmasm::AssemblyItem(evmasm::PushTag, _labelId));
80
208k
}
81
82
size_t EthAssemblyAdapter::newLabelId()
83
216k
{
84
216k
  return assemblyTagToIdentifier(m_assembly.newTag());
85
216k
}
86
87
size_t EthAssemblyAdapter::namedLabel(std::string const& _name, size_t _params, size_t _returns, std::optional<size_t> _sourceID)
88
78.1k
{
89
78.1k
  return assemblyTagToIdentifier(m_assembly.namedTag(_name, _params, _returns, _sourceID));
90
78.1k
}
91
92
void EthAssemblyAdapter::appendLinkerSymbol(std::string const& _linkerSymbol)
93
1
{
94
1
  m_assembly.appendLibraryAddress(_linkerSymbol);
95
1
}
96
97
void EthAssemblyAdapter::appendVerbatim(bytes _data, size_t _arguments, size_t _returnVariables)
98
0
{
99
0
  m_assembly.appendVerbatim(move(_data), _arguments, _returnVariables);
100
0
}
101
102
void EthAssemblyAdapter::appendJump(int _stackDiffAfter, JumpType _jumpType)
103
164k
{
104
164k
  appendJumpInstruction(evmasm::Instruction::JUMP, _jumpType);
105
164k
  m_assembly.adjustDeposit(_stackDiffAfter);
106
164k
}
107
108
void EthAssemblyAdapter::appendJumpTo(LabelID _labelId, int _stackDiffAfter, JumpType _jumpType)
109
86.4k
{
110
86.4k
  appendLabelReference(_labelId);
111
86.4k
  appendJump(_stackDiffAfter, _jumpType);
112
86.4k
}
113
114
void EthAssemblyAdapter::appendJumpToIf(LabelID _labelId, JumpType _jumpType)
115
51.1k
{
116
51.1k
  appendLabelReference(_labelId);
117
51.1k
  appendJumpInstruction(evmasm::Instruction::JUMPI, _jumpType);
118
51.1k
}
119
120
void EthAssemblyAdapter::appendAssemblySize()
121
0
{
122
0
  m_assembly.appendProgramSize();
123
0
}
124
125
pair<shared_ptr<AbstractAssembly>, AbstractAssembly::SubID> EthAssemblyAdapter::createSubAssembly(bool _creation, string _name)
126
0
{
127
0
  shared_ptr<evmasm::Assembly> assembly{make_shared<evmasm::Assembly>(_creation, std::move(_name))};
128
0
  auto sub = m_assembly.newSub(assembly);
129
0
  return {make_shared<EthAssemblyAdapter>(*assembly), static_cast<size_t>(sub.data())};
130
0
}
131
132
void EthAssemblyAdapter::appendDataOffset(vector<AbstractAssembly::SubID> const& _subPath)
133
0
{
134
0
  if (auto it = m_dataHashBySubId.find(_subPath[0]); it != m_dataHashBySubId.end())
135
0
  {
136
0
    yulAssert(_subPath.size() == 1, "");
137
0
    m_assembly << evmasm::AssemblyItem(evmasm::PushData, it->second);
138
0
    return;
139
0
  }
140
141
0
  m_assembly.pushSubroutineOffset(m_assembly.encodeSubPath(_subPath));
142
0
}
143
144
void EthAssemblyAdapter::appendDataSize(vector<AbstractAssembly::SubID> const& _subPath)
145
0
{
146
0
  if (auto it = m_dataHashBySubId.find(_subPath[0]); it != m_dataHashBySubId.end())
147
0
  {
148
0
    yulAssert(_subPath.size() == 1, "");
149
0
    m_assembly << u256(m_assembly.data(h256(it->second)).size());
150
0
    return;
151
0
  }
152
153
0
  m_assembly.pushSubroutineSize(m_assembly.encodeSubPath(_subPath));
154
0
}
155
156
AbstractAssembly::SubID EthAssemblyAdapter::appendData(bytes const& _data)
157
0
{
158
0
  evmasm::AssemblyItem pushData = m_assembly.newData(_data);
159
0
  SubID subID = m_nextDataCounter++;
160
0
  m_dataHashBySubId[subID] = pushData.data();
161
0
  return subID;
162
0
}
163
164
void EthAssemblyAdapter::appendToAuxiliaryData(bytes const& _data)
165
0
{
166
0
  m_assembly.appendToAuxiliaryData(_data);
167
0
}
168
169
void EthAssemblyAdapter::appendImmutable(std::string const& _identifier)
170
0
{
171
0
  m_assembly.appendImmutable(_identifier);
172
0
}
173
174
void EthAssemblyAdapter::appendImmutableAssignment(std::string const& _identifier)
175
0
{
176
0
  m_assembly.appendImmutableAssignment(_identifier);
177
0
}
178
179
void EthAssemblyAdapter::markAsInvalid()
180
5
{
181
5
  m_assembly.markAsInvalid();
182
5
}
183
184
EthAssemblyAdapter::LabelID EthAssemblyAdapter::assemblyTagToIdentifier(evmasm::AssemblyItem const& _tag)
185
294k
{
186
294k
  u256 id = _tag.data();
187
294k
  yulAssert(id <= std::numeric_limits<LabelID>::max(), "Tag id too large.");
188
294k
  return LabelID(id);
189
294k
}
190
191
void EthAssemblyAdapter::appendJumpInstruction(evmasm::Instruction _instruction, JumpType _jumpType)
192
215k
{
193
215k
  yulAssert(_instruction == evmasm::Instruction::JUMP || _instruction == evmasm::Instruction::JUMPI, "");
194
215k
  evmasm::AssemblyItem jump(_instruction);
195
215k
  switch (_jumpType)
196
215k
  {
197
67.2k
  case JumpType::Ordinary:
198
67.2k
    yulAssert(jump.getJumpType() == evmasm::AssemblyItem::JumpType::Ordinary, "");
199
67.2k
    break;
200
70.4k
  case JumpType::IntoFunction:
201
70.4k
    jump.setJumpType(evmasm::AssemblyItem::JumpType::IntoFunction);
202
70.4k
    break;
203
78.1k
  case JumpType::OutOfFunction:
204
78.1k
    jump.setJumpType(evmasm::AssemblyItem::JumpType::OutOfFunction);
205
78.1k
    break;
206
215k
  }
207
215k
  m_assembly.append(std::move(jump));
208
215k
}