mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Remove the expression callback from the code generator functions of Yul builtins.
This commit is contained in:
parent
be95a8172b
commit
a683ea7646
@ -239,9 +239,13 @@ void CodeTransform::operator()(FunctionCall const& _call)
|
|||||||
|
|
||||||
m_assembly.setSourceLocation(extractSourceLocationFromDebugData(_call.debugData));
|
m_assembly.setSourceLocation(extractSourceLocationFromDebugData(_call.debugData));
|
||||||
if (BuiltinFunctionForEVM const* builtin = m_dialect.builtin(_call.functionName.name))
|
if (BuiltinFunctionForEVM const* builtin = m_dialect.builtin(_call.functionName.name))
|
||||||
builtin->generateCode(_call, m_assembly, m_builtinContext, [&](Expression const& _expression) {
|
{
|
||||||
visitExpression(_expression);
|
for (auto&& [i, arg]: _call.arguments | ranges::views::enumerate | ranges::views::reverse)
|
||||||
});
|
if (!builtin->literalArgument(i))
|
||||||
|
visitExpression(arg);
|
||||||
|
m_assembly.setSourceLocation(extractSourceLocationFromDebugData(_call.debugData));
|
||||||
|
builtin->generateCode(_call, m_assembly, m_builtinContext);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
AbstractAssembly::LabelID returnLabel = m_assembly.newLabelId();
|
AbstractAssembly::LabelID returnLabel = m_assembly.newLabelId();
|
||||||
|
@ -26,8 +26,8 @@
|
|||||||
#include <libyul/Object.h>
|
#include <libyul/Object.h>
|
||||||
#include <libyul/Exceptions.h>
|
#include <libyul/Exceptions.h>
|
||||||
#include <libyul/AsmParser.h>
|
#include <libyul/AsmParser.h>
|
||||||
|
#include <libyul/Utilities.h>
|
||||||
#include <libyul/backends/evm/AbstractAssembly.h>
|
#include <libyul/backends/evm/AbstractAssembly.h>
|
||||||
|
|
||||||
#include <libevmasm/SemanticInformation.h>
|
#include <libevmasm/SemanticInformation.h>
|
||||||
#include <libevmasm/Instruction.h>
|
#include <libevmasm/Instruction.h>
|
||||||
|
|
||||||
@ -46,19 +46,6 @@ using namespace solidity::util;
|
|||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
|
||||||
void visitArguments(
|
|
||||||
AbstractAssembly& _assembly,
|
|
||||||
FunctionCall const& _call,
|
|
||||||
function<void(Expression const&)> _visitExpression
|
|
||||||
)
|
|
||||||
{
|
|
||||||
for (auto const& arg: _call.arguments | ranges::views::reverse)
|
|
||||||
_visitExpression(arg);
|
|
||||||
|
|
||||||
_assembly.setSourceLocation(_call.debugData->location);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
pair<YulString, BuiltinFunctionForEVM> createEVMFunction(
|
pair<YulString, BuiltinFunctionForEVM> createEVMFunction(
|
||||||
string const& _name,
|
string const& _name,
|
||||||
evmasm::Instruction _instruction
|
evmasm::Instruction _instruction
|
||||||
@ -76,12 +63,10 @@ pair<YulString, BuiltinFunctionForEVM> createEVMFunction(
|
|||||||
f.literalArguments.clear();
|
f.literalArguments.clear();
|
||||||
f.instruction = _instruction;
|
f.instruction = _instruction;
|
||||||
f.generateCode = [_instruction](
|
f.generateCode = [_instruction](
|
||||||
FunctionCall const& _call,
|
FunctionCall const&,
|
||||||
AbstractAssembly& _assembly,
|
AbstractAssembly& _assembly,
|
||||||
BuiltinContext&,
|
BuiltinContext&
|
||||||
std::function<void(Expression const&)> _visitExpression
|
|
||||||
) {
|
) {
|
||||||
visitArguments(_assembly, _call, _visitExpression);
|
|
||||||
_assembly.appendInstruction(_instruction);
|
_assembly.appendInstruction(_instruction);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -94,7 +79,7 @@ pair<YulString, BuiltinFunctionForEVM> createFunction(
|
|||||||
size_t _returns,
|
size_t _returns,
|
||||||
SideEffects _sideEffects,
|
SideEffects _sideEffects,
|
||||||
vector<optional<LiteralKind>> _literalArguments,
|
vector<optional<LiteralKind>> _literalArguments,
|
||||||
std::function<void(FunctionCall const&, AbstractAssembly&, BuiltinContext&, std::function<void(Expression const&)>)> _generateCode
|
std::function<void(FunctionCall const&, AbstractAssembly&, BuiltinContext&)> _generateCode
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
yulAssert(_literalArguments.size() == _params || _literalArguments.empty(), "");
|
yulAssert(_literalArguments.size() == _params || _literalArguments.empty(), "");
|
||||||
@ -166,12 +151,10 @@ map<YulString, BuiltinFunctionForEVM> createBuiltins(langutil::EVMVersion _evmVe
|
|||||||
builtins.emplace(createFunction("linkersymbol", 1, 1, SideEffects{}, {LiteralKind::String}, [](
|
builtins.emplace(createFunction("linkersymbol", 1, 1, SideEffects{}, {LiteralKind::String}, [](
|
||||||
FunctionCall const& _call,
|
FunctionCall const& _call,
|
||||||
AbstractAssembly& _assembly,
|
AbstractAssembly& _assembly,
|
||||||
BuiltinContext&,
|
BuiltinContext&
|
||||||
function<void(Expression const&)>
|
|
||||||
) {
|
) {
|
||||||
yulAssert(_call.arguments.size() == 1, "");
|
yulAssert(_call.arguments.size() == 1, "");
|
||||||
Expression const& arg = _call.arguments.front();
|
Expression const& arg = _call.arguments.front();
|
||||||
_assembly.setSourceLocation(_call.debugData->location);
|
|
||||||
_assembly.appendLinkerSymbol(std::get<Literal>(arg).value.str());
|
_assembly.appendLinkerSymbol(std::get<Literal>(arg).value.str());
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@ -184,24 +167,24 @@ map<YulString, BuiltinFunctionForEVM> createBuiltins(langutil::EVMVersion _evmVe
|
|||||||
[](
|
[](
|
||||||
FunctionCall const& _call,
|
FunctionCall const& _call,
|
||||||
AbstractAssembly& _assembly,
|
AbstractAssembly& _assembly,
|
||||||
BuiltinContext&,
|
BuiltinContext&
|
||||||
function<void(Expression const&)> _visitExpression
|
|
||||||
) {
|
) {
|
||||||
visitArguments(_assembly, _call, _visitExpression);
|
yulAssert(_call.arguments.size() == 1, "");
|
||||||
|
Literal const* literal = get_if<Literal>(&_call.arguments.front());
|
||||||
|
yulAssert(literal, "");
|
||||||
|
_assembly.appendConstant(valueOfLiteral(*literal));
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
builtins.emplace(createFunction("datasize", 1, 1, SideEffects{}, {LiteralKind::String}, [](
|
builtins.emplace(createFunction("datasize", 1, 1, SideEffects{}, {LiteralKind::String}, [](
|
||||||
FunctionCall const& _call,
|
FunctionCall const& _call,
|
||||||
AbstractAssembly& _assembly,
|
AbstractAssembly& _assembly,
|
||||||
BuiltinContext& _context,
|
BuiltinContext& _context
|
||||||
std::function<void(Expression const&)> const&
|
|
||||||
) {
|
) {
|
||||||
yulAssert(_context.currentObject, "No object available.");
|
yulAssert(_context.currentObject, "No object available.");
|
||||||
yulAssert(_call.arguments.size() == 1, "");
|
yulAssert(_call.arguments.size() == 1, "");
|
||||||
Expression const& arg = _call.arguments.front();
|
Expression const& arg = _call.arguments.front();
|
||||||
YulString dataName = std::get<Literal>(arg).value;
|
YulString dataName = std::get<Literal>(arg).value;
|
||||||
_assembly.setSourceLocation(_call.debugData->location);
|
|
||||||
if (_context.currentObject->name == dataName)
|
if (_context.currentObject->name == dataName)
|
||||||
_assembly.appendAssemblySize();
|
_assembly.appendAssemblySize();
|
||||||
else
|
else
|
||||||
@ -217,14 +200,12 @@ map<YulString, BuiltinFunctionForEVM> createBuiltins(langutil::EVMVersion _evmVe
|
|||||||
builtins.emplace(createFunction("dataoffset", 1, 1, SideEffects{}, {LiteralKind::String}, [](
|
builtins.emplace(createFunction("dataoffset", 1, 1, SideEffects{}, {LiteralKind::String}, [](
|
||||||
FunctionCall const& _call,
|
FunctionCall const& _call,
|
||||||
AbstractAssembly& _assembly,
|
AbstractAssembly& _assembly,
|
||||||
BuiltinContext& _context,
|
BuiltinContext& _context
|
||||||
std::function<void(Expression const&)> const&
|
|
||||||
) {
|
) {
|
||||||
yulAssert(_context.currentObject, "No object available.");
|
yulAssert(_context.currentObject, "No object available.");
|
||||||
yulAssert(_call.arguments.size() == 1, "");
|
yulAssert(_call.arguments.size() == 1, "");
|
||||||
Expression const& arg = _call.arguments.front();
|
Expression const& arg = _call.arguments.front();
|
||||||
YulString dataName = std::get<Literal>(arg).value;
|
YulString dataName = std::get<Literal>(arg).value;
|
||||||
_assembly.setSourceLocation(_call.debugData->location);
|
|
||||||
if (_context.currentObject->name == dataName)
|
if (_context.currentObject->name == dataName)
|
||||||
_assembly.appendConstant(0);
|
_assembly.appendConstant(0);
|
||||||
else
|
else
|
||||||
@ -244,12 +225,10 @@ map<YulString, BuiltinFunctionForEVM> createBuiltins(langutil::EVMVersion _evmVe
|
|||||||
SideEffects{false, true, false, false, true, SideEffects::None, SideEffects::None, SideEffects::Write},
|
SideEffects{false, true, false, false, true, SideEffects::None, SideEffects::None, SideEffects::Write},
|
||||||
{},
|
{},
|
||||||
[](
|
[](
|
||||||
FunctionCall const& _call,
|
FunctionCall const&,
|
||||||
AbstractAssembly& _assembly,
|
AbstractAssembly& _assembly,
|
||||||
BuiltinContext&,
|
BuiltinContext&
|
||||||
std::function<void(Expression const&)> _visitExpression
|
|
||||||
) {
|
) {
|
||||||
visitArguments(_assembly, _call, _visitExpression);
|
|
||||||
_assembly.appendInstruction(evmasm::Instruction::CODECOPY);
|
_assembly.appendInstruction(evmasm::Instruction::CODECOPY);
|
||||||
}
|
}
|
||||||
));
|
));
|
||||||
@ -262,15 +241,10 @@ map<YulString, BuiltinFunctionForEVM> createBuiltins(langutil::EVMVersion _evmVe
|
|||||||
[](
|
[](
|
||||||
FunctionCall const& _call,
|
FunctionCall const& _call,
|
||||||
AbstractAssembly& _assembly,
|
AbstractAssembly& _assembly,
|
||||||
BuiltinContext&,
|
BuiltinContext&
|
||||||
std::function<void(Expression const&)> _visitExpression
|
|
||||||
) {
|
) {
|
||||||
yulAssert(_call.arguments.size() == 3, "");
|
yulAssert(_call.arguments.size() == 3, "");
|
||||||
|
|
||||||
_visitExpression(_call.arguments[2]);
|
|
||||||
YulString identifier = std::get<Literal>(_call.arguments[1]).value;
|
YulString identifier = std::get<Literal>(_call.arguments[1]).value;
|
||||||
_visitExpression(_call.arguments[0]);
|
|
||||||
_assembly.setSourceLocation(_call.debugData->location);
|
|
||||||
_assembly.appendImmutableAssignment(identifier.str());
|
_assembly.appendImmutableAssignment(identifier.str());
|
||||||
}
|
}
|
||||||
));
|
));
|
||||||
@ -283,11 +257,9 @@ map<YulString, BuiltinFunctionForEVM> createBuiltins(langutil::EVMVersion _evmVe
|
|||||||
[](
|
[](
|
||||||
FunctionCall const& _call,
|
FunctionCall const& _call,
|
||||||
AbstractAssembly& _assembly,
|
AbstractAssembly& _assembly,
|
||||||
BuiltinContext&,
|
BuiltinContext&
|
||||||
std::function<void(Expression const&)>
|
|
||||||
) {
|
) {
|
||||||
yulAssert(_call.arguments.size() == 1, "");
|
yulAssert(_call.arguments.size() == 1, "");
|
||||||
_assembly.setSourceLocation(_call.debugData->location);
|
|
||||||
_assembly.appendImmutable(std::get<Literal>(_call.arguments.front()).value.str());
|
_assembly.appendImmutable(std::get<Literal>(_call.arguments.front()).value.str());
|
||||||
}
|
}
|
||||||
));
|
));
|
||||||
@ -387,15 +359,11 @@ BuiltinFunctionForEVM const* EVMDialect::verbatimFunction(size_t _arguments, siz
|
|||||||
[=](
|
[=](
|
||||||
FunctionCall const& _call,
|
FunctionCall const& _call,
|
||||||
AbstractAssembly& _assembly,
|
AbstractAssembly& _assembly,
|
||||||
BuiltinContext&,
|
BuiltinContext&
|
||||||
std::function<void(Expression const&)> _visitExpression
|
|
||||||
) {
|
) {
|
||||||
yulAssert(_call.arguments.size() == (1 + _arguments), "");
|
yulAssert(_call.arguments.size() == (1 + _arguments), "");
|
||||||
for (Expression const& arg: _call.arguments | ranges::views::tail | ranges::views::reverse)
|
|
||||||
_visitExpression(arg);
|
|
||||||
Expression const& bytecode = _call.arguments.front();
|
Expression const& bytecode = _call.arguments.front();
|
||||||
|
|
||||||
_assembly.setSourceLocation(_call.debugData->location);
|
|
||||||
_assembly.appendVerbatim(
|
_assembly.appendVerbatim(
|
||||||
asBytes(std::get<Literal>(bytecode).value.str()),
|
asBytes(std::get<Literal>(bytecode).value.str()),
|
||||||
_arguments,
|
_arguments,
|
||||||
@ -456,24 +424,19 @@ EVMDialectTyped::EVMDialectTyped(langutil::EVMVersion _evmVersion, bool _objectA
|
|||||||
m_functions["popbool"_yulstring].name = "popbool"_yulstring;
|
m_functions["popbool"_yulstring].name = "popbool"_yulstring;
|
||||||
m_functions["popbool"_yulstring].parameters = {"bool"_yulstring};
|
m_functions["popbool"_yulstring].parameters = {"bool"_yulstring};
|
||||||
m_functions.insert(createFunction("bool_to_u256", 1, 1, {}, {}, [](
|
m_functions.insert(createFunction("bool_to_u256", 1, 1, {}, {}, [](
|
||||||
FunctionCall const& _call,
|
FunctionCall const&,
|
||||||
AbstractAssembly& _assembly,
|
AbstractAssembly&,
|
||||||
BuiltinContext&,
|
BuiltinContext&
|
||||||
std::function<void(Expression const&)> _visitExpression
|
) {}));
|
||||||
) {
|
|
||||||
visitArguments(_assembly, _call, _visitExpression);
|
|
||||||
}));
|
|
||||||
m_functions["bool_to_u256"_yulstring].parameters = {"bool"_yulstring};
|
m_functions["bool_to_u256"_yulstring].parameters = {"bool"_yulstring};
|
||||||
m_functions["bool_to_u256"_yulstring].returns = {"u256"_yulstring};
|
m_functions["bool_to_u256"_yulstring].returns = {"u256"_yulstring};
|
||||||
m_functions.insert(createFunction("u256_to_bool", 1, 1, {}, {}, [](
|
m_functions.insert(createFunction("u256_to_bool", 1, 1, {}, {}, [](
|
||||||
FunctionCall const& _call,
|
FunctionCall const&,
|
||||||
AbstractAssembly& _assembly,
|
AbstractAssembly& _assembly,
|
||||||
BuiltinContext&,
|
BuiltinContext&
|
||||||
std::function<void(Expression const&)> _visitExpression
|
|
||||||
) {
|
) {
|
||||||
// TODO this should use a Panic.
|
// TODO this should use a Panic.
|
||||||
// A value larger than 1 causes an invalid instruction.
|
// A value larger than 1 causes an invalid instruction.
|
||||||
visitArguments(_assembly, _call, _visitExpression);
|
|
||||||
_assembly.appendConstant(2);
|
_assembly.appendConstant(2);
|
||||||
_assembly.appendInstruction(evmasm::Instruction::DUP2);
|
_assembly.appendInstruction(evmasm::Instruction::DUP2);
|
||||||
_assembly.appendInstruction(evmasm::Instruction::LT);
|
_assembly.appendInstruction(evmasm::Instruction::LT);
|
||||||
|
@ -52,9 +52,10 @@ struct BuiltinFunctionForEVM: public BuiltinFunction
|
|||||||
{
|
{
|
||||||
std::optional<evmasm::Instruction> instruction;
|
std::optional<evmasm::Instruction> instruction;
|
||||||
/// Function to generate code for the given function call and append it to the abstract
|
/// Function to generate code for the given function call and append it to the abstract
|
||||||
/// assembly. The fourth parameter is called to visit (and generate code for) the given
|
/// assembly. Expects all non-literal arguments of the call to be on stack in reverse order
|
||||||
/// argument.
|
/// (i.e. right-most argument pushed first).
|
||||||
std::function<void(FunctionCall const&, AbstractAssembly&, BuiltinContext&, std::function<void(Expression const&)>)> generateCode;
|
/// Expects the caller to set the source location.
|
||||||
|
std::function<void(FunctionCall const&, AbstractAssembly&, BuiltinContext&)> generateCode;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
|
|
||||||
#include <libevmasm/Instruction.h>
|
#include <libevmasm/Instruction.h>
|
||||||
|
|
||||||
|
#include <range/v3/view/iota.hpp>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace solidity;
|
using namespace solidity;
|
||||||
@ -135,21 +136,11 @@ NoOutputEVMDialect::NoOutputEVMDialect(EVMDialect const& _copyFrom):
|
|||||||
for (auto& fun: m_functions)
|
for (auto& fun: m_functions)
|
||||||
{
|
{
|
||||||
size_t returns = fun.second.returns.size();
|
size_t returns = fun.second.returns.size();
|
||||||
fun.second.generateCode = [=](FunctionCall const& _call, AbstractAssembly& _assembly, BuiltinContext&, std::function<void(Expression const&)> _visitExpression)
|
fun.second.generateCode = [=](FunctionCall const& _call, AbstractAssembly& _assembly, BuiltinContext&)
|
||||||
{
|
{
|
||||||
size_t visited = 0;
|
for (size_t i: ranges::views::iota(0u, _call.arguments.size()))
|
||||||
for (size_t j = 0; j < _call.arguments.size(); j++)
|
|
||||||
{
|
|
||||||
size_t const i = _call.arguments.size() - j - 1;
|
|
||||||
if (!fun.second.literalArgument(i))
|
if (!fun.second.literalArgument(i))
|
||||||
{
|
_assembly.appendInstruction(evmasm::Instruction::POP);
|
||||||
_visitExpression(_call.arguments[i]);
|
|
||||||
visited++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i = 0; i < visited; i++)
|
|
||||||
_assembly.appendInstruction(evmasm::Instruction::POP);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < returns; i++)
|
for (size_t i = 0; i < returns; i++)
|
||||||
_assembly.appendConstant(u256(0));
|
_assembly.appendConstant(u256(0));
|
||||||
|
Loading…
Reference in New Issue
Block a user