Skip to content

Commit d0ce643

Browse files
authored
Merge pull request #11894 from ethereum/builtinExpressionVisit
Remove expression visit function from Yul Builtins.
2 parents be95a81 + a683ea7 commit d0ce643

File tree

4 files changed

+38
-79
lines changed

4 files changed

+38
-79
lines changed

libyul/backends/evm/EVMCodeTransform.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -239,9 +239,13 @@ void CodeTransform::operator()(FunctionCall const& _call)
239239

240240
m_assembly.setSourceLocation(extractSourceLocationFromDebugData(_call.debugData));
241241
if (BuiltinFunctionForEVM const* builtin = m_dialect.builtin(_call.functionName.name))
242-
builtin->generateCode(_call, m_assembly, m_builtinContext, [&](Expression const& _expression) {
243-
visitExpression(_expression);
244-
});
242+
{
243+
for (auto&& [i, arg]: _call.arguments | ranges::views::enumerate | ranges::views::reverse)
244+
if (!builtin->literalArgument(i))
245+
visitExpression(arg);
246+
m_assembly.setSourceLocation(extractSourceLocationFromDebugData(_call.debugData));
247+
builtin->generateCode(_call, m_assembly, m_builtinContext);
248+
}
245249
else
246250
{
247251
AbstractAssembly::LabelID returnLabel = m_assembly.newLabelId();

libyul/backends/evm/EVMDialect.cpp

Lines changed: 23 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@
2626
#include <libyul/Object.h>
2727
#include <libyul/Exceptions.h>
2828
#include <libyul/AsmParser.h>
29+
#include <libyul/Utilities.h>
2930
#include <libyul/backends/evm/AbstractAssembly.h>
30-
3131
#include <libevmasm/SemanticInformation.h>
3232
#include <libevmasm/Instruction.h>
3333

@@ -46,19 +46,6 @@ using namespace solidity::util;
4646
namespace
4747
{
4848

49-
void visitArguments(
50-
AbstractAssembly& _assembly,
51-
FunctionCall const& _call,
52-
function<void(Expression const&)> _visitExpression
53-
)
54-
{
55-
for (auto const& arg: _call.arguments | ranges::views::reverse)
56-
_visitExpression(arg);
57-
58-
_assembly.setSourceLocation(_call.debugData->location);
59-
}
60-
61-
6249
pair<YulString, BuiltinFunctionForEVM> createEVMFunction(
6350
string const& _name,
6451
evmasm::Instruction _instruction
@@ -76,12 +63,10 @@ pair<YulString, BuiltinFunctionForEVM> createEVMFunction(
7663
f.literalArguments.clear();
7764
f.instruction = _instruction;
7865
f.generateCode = [_instruction](
79-
FunctionCall const& _call,
66+
FunctionCall const&,
8067
AbstractAssembly& _assembly,
81-
BuiltinContext&,
82-
std::function<void(Expression const&)> _visitExpression
68+
BuiltinContext&
8369
) {
84-
visitArguments(_assembly, _call, _visitExpression);
8570
_assembly.appendInstruction(_instruction);
8671
};
8772

@@ -94,7 +79,7 @@ pair<YulString, BuiltinFunctionForEVM> createFunction(
9479
size_t _returns,
9580
SideEffects _sideEffects,
9681
vector<optional<LiteralKind>> _literalArguments,
97-
std::function<void(FunctionCall const&, AbstractAssembly&, BuiltinContext&, std::function<void(Expression const&)>)> _generateCode
82+
std::function<void(FunctionCall const&, AbstractAssembly&, BuiltinContext&)> _generateCode
9883
)
9984
{
10085
yulAssert(_literalArguments.size() == _params || _literalArguments.empty(), "");
@@ -166,12 +151,10 @@ map<YulString, BuiltinFunctionForEVM> createBuiltins(langutil::EVMVersion _evmVe
166151
builtins.emplace(createFunction("linkersymbol", 1, 1, SideEffects{}, {LiteralKind::String}, [](
167152
FunctionCall const& _call,
168153
AbstractAssembly& _assembly,
169-
BuiltinContext&,
170-
function<void(Expression const&)>
154+
BuiltinContext&
171155
) {
172156
yulAssert(_call.arguments.size() == 1, "");
173157
Expression const& arg = _call.arguments.front();
174-
_assembly.setSourceLocation(_call.debugData->location);
175158
_assembly.appendLinkerSymbol(std::get<Literal>(arg).value.str());
176159
}));
177160

@@ -184,24 +167,24 @@ map<YulString, BuiltinFunctionForEVM> createBuiltins(langutil::EVMVersion _evmVe
184167
[](
185168
FunctionCall const& _call,
186169
AbstractAssembly& _assembly,
187-
BuiltinContext&,
188-
function<void(Expression const&)> _visitExpression
170+
BuiltinContext&
189171
) {
190-
visitArguments(_assembly, _call, _visitExpression);
172+
yulAssert(_call.arguments.size() == 1, "");
173+
Literal const* literal = get_if<Literal>(&_call.arguments.front());
174+
yulAssert(literal, "");
175+
_assembly.appendConstant(valueOfLiteral(*literal));
191176
})
192177
);
193178

194179
builtins.emplace(createFunction("datasize", 1, 1, SideEffects{}, {LiteralKind::String}, [](
195180
FunctionCall const& _call,
196181
AbstractAssembly& _assembly,
197-
BuiltinContext& _context,
198-
std::function<void(Expression const&)> const&
182+
BuiltinContext& _context
199183
) {
200184
yulAssert(_context.currentObject, "No object available.");
201185
yulAssert(_call.arguments.size() == 1, "");
202186
Expression const& arg = _call.arguments.front();
203187
YulString dataName = std::get<Literal>(arg).value;
204-
_assembly.setSourceLocation(_call.debugData->location);
205188
if (_context.currentObject->name == dataName)
206189
_assembly.appendAssemblySize();
207190
else
@@ -217,14 +200,12 @@ map<YulString, BuiltinFunctionForEVM> createBuiltins(langutil::EVMVersion _evmVe
217200
builtins.emplace(createFunction("dataoffset", 1, 1, SideEffects{}, {LiteralKind::String}, [](
218201
FunctionCall const& _call,
219202
AbstractAssembly& _assembly,
220-
BuiltinContext& _context,
221-
std::function<void(Expression const&)> const&
203+
BuiltinContext& _context
222204
) {
223205
yulAssert(_context.currentObject, "No object available.");
224206
yulAssert(_call.arguments.size() == 1, "");
225207
Expression const& arg = _call.arguments.front();
226208
YulString dataName = std::get<Literal>(arg).value;
227-
_assembly.setSourceLocation(_call.debugData->location);
228209
if (_context.currentObject->name == dataName)
229210
_assembly.appendConstant(0);
230211
else
@@ -244,12 +225,10 @@ map<YulString, BuiltinFunctionForEVM> createBuiltins(langutil::EVMVersion _evmVe
244225
SideEffects{false, true, false, false, true, SideEffects::None, SideEffects::None, SideEffects::Write},
245226
{},
246227
[](
247-
FunctionCall const& _call,
228+
FunctionCall const&,
248229
AbstractAssembly& _assembly,
249-
BuiltinContext&,
250-
std::function<void(Expression const&)> _visitExpression
230+
BuiltinContext&
251231
) {
252-
visitArguments(_assembly, _call, _visitExpression);
253232
_assembly.appendInstruction(evmasm::Instruction::CODECOPY);
254233
}
255234
));
@@ -262,15 +241,10 @@ map<YulString, BuiltinFunctionForEVM> createBuiltins(langutil::EVMVersion _evmVe
262241
[](
263242
FunctionCall const& _call,
264243
AbstractAssembly& _assembly,
265-
BuiltinContext&,
266-
std::function<void(Expression const&)> _visitExpression
244+
BuiltinContext&
267245
) {
268246
yulAssert(_call.arguments.size() == 3, "");
269-
270-
_visitExpression(_call.arguments[2]);
271247
YulString identifier = std::get<Literal>(_call.arguments[1]).value;
272-
_visitExpression(_call.arguments[0]);
273-
_assembly.setSourceLocation(_call.debugData->location);
274248
_assembly.appendImmutableAssignment(identifier.str());
275249
}
276250
));
@@ -283,11 +257,9 @@ map<YulString, BuiltinFunctionForEVM> createBuiltins(langutil::EVMVersion _evmVe
283257
[](
284258
FunctionCall const& _call,
285259
AbstractAssembly& _assembly,
286-
BuiltinContext&,
287-
std::function<void(Expression const&)>
260+
BuiltinContext&
288261
) {
289262
yulAssert(_call.arguments.size() == 1, "");
290-
_assembly.setSourceLocation(_call.debugData->location);
291263
_assembly.appendImmutable(std::get<Literal>(_call.arguments.front()).value.str());
292264
}
293265
));
@@ -387,15 +359,11 @@ BuiltinFunctionForEVM const* EVMDialect::verbatimFunction(size_t _arguments, siz
387359
[=](
388360
FunctionCall const& _call,
389361
AbstractAssembly& _assembly,
390-
BuiltinContext&,
391-
std::function<void(Expression const&)> _visitExpression
362+
BuiltinContext&
392363
) {
393364
yulAssert(_call.arguments.size() == (1 + _arguments), "");
394-
for (Expression const& arg: _call.arguments | ranges::views::tail | ranges::views::reverse)
395-
_visitExpression(arg);
396365
Expression const& bytecode = _call.arguments.front();
397366

398-
_assembly.setSourceLocation(_call.debugData->location);
399367
_assembly.appendVerbatim(
400368
asBytes(std::get<Literal>(bytecode).value.str()),
401369
_arguments,
@@ -456,24 +424,19 @@ EVMDialectTyped::EVMDialectTyped(langutil::EVMVersion _evmVersion, bool _objectA
456424
m_functions["popbool"_yulstring].name = "popbool"_yulstring;
457425
m_functions["popbool"_yulstring].parameters = {"bool"_yulstring};
458426
m_functions.insert(createFunction("bool_to_u256", 1, 1, {}, {}, [](
459-
FunctionCall const& _call,
460-
AbstractAssembly& _assembly,
461-
BuiltinContext&,
462-
std::function<void(Expression const&)> _visitExpression
463-
) {
464-
visitArguments(_assembly, _call, _visitExpression);
465-
}));
427+
FunctionCall const&,
428+
AbstractAssembly&,
429+
BuiltinContext&
430+
) {}));
466431
m_functions["bool_to_u256"_yulstring].parameters = {"bool"_yulstring};
467432
m_functions["bool_to_u256"_yulstring].returns = {"u256"_yulstring};
468433
m_functions.insert(createFunction("u256_to_bool", 1, 1, {}, {}, [](
469-
FunctionCall const& _call,
434+
FunctionCall const&,
470435
AbstractAssembly& _assembly,
471-
BuiltinContext&,
472-
std::function<void(Expression const&)> _visitExpression
436+
BuiltinContext&
473437
) {
474438
// TODO this should use a Panic.
475439
// A value larger than 1 causes an invalid instruction.
476-
visitArguments(_assembly, _call, _visitExpression);
477440
_assembly.appendConstant(2);
478441
_assembly.appendInstruction(evmasm::Instruction::DUP2);
479442
_assembly.appendInstruction(evmasm::Instruction::LT);

libyul/backends/evm/EVMDialect.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,10 @@ struct BuiltinFunctionForEVM: public BuiltinFunction
5252
{
5353
std::optional<evmasm::Instruction> instruction;
5454
/// Function to generate code for the given function call and append it to the abstract
55-
/// assembly. The fourth parameter is called to visit (and generate code for) the given
56-
/// argument.
57-
std::function<void(FunctionCall const&, AbstractAssembly&, BuiltinContext&, std::function<void(Expression const&)>)> generateCode;
55+
/// assembly. Expects all non-literal arguments of the call to be on stack in reverse order
56+
/// (i.e. right-most argument pushed first).
57+
/// Expects the caller to set the source location.
58+
std::function<void(FunctionCall const&, AbstractAssembly&, BuiltinContext&)> generateCode;
5859
};
5960

6061

libyul/backends/evm/NoOutputAssembly.cpp

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626

2727
#include <libevmasm/Instruction.h>
2828

29+
#include <range/v3/view/iota.hpp>
2930

3031
using namespace std;
3132
using namespace solidity;
@@ -135,21 +136,11 @@ NoOutputEVMDialect::NoOutputEVMDialect(EVMDialect const& _copyFrom):
135136
for (auto& fun: m_functions)
136137
{
137138
size_t returns = fun.second.returns.size();
138-
fun.second.generateCode = [=](FunctionCall const& _call, AbstractAssembly& _assembly, BuiltinContext&, std::function<void(Expression const&)> _visitExpression)
139+
fun.second.generateCode = [=](FunctionCall const& _call, AbstractAssembly& _assembly, BuiltinContext&)
139140
{
140-
size_t visited = 0;
141-
for (size_t j = 0; j < _call.arguments.size(); j++)
142-
{
143-
size_t const i = _call.arguments.size() - j - 1;
141+
for (size_t i: ranges::views::iota(0u, _call.arguments.size()))
144142
if (!fun.second.literalArgument(i))
145-
{
146-
_visitExpression(_call.arguments[i]);
147-
visited++;
148-
}
149-
}
150-
151-
for (size_t i = 0; i < visited; i++)
152-
_assembly.appendInstruction(evmasm::Instruction::POP);
143+
_assembly.appendInstruction(evmasm::Instruction::POP);
153144

154145
for (size_t i = 0; i < returns; i++)
155146
_assembly.appendConstant(u256(0));

0 commit comments

Comments
 (0)