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));
|
||||
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
|
||||
{
|
||||
AbstractAssembly::LabelID returnLabel = m_assembly.newLabelId();
|
||||
|
@ -26,8 +26,8 @@
|
||||
#include <libyul/Object.h>
|
||||
#include <libyul/Exceptions.h>
|
||||
#include <libyul/AsmParser.h>
|
||||
#include <libyul/Utilities.h>
|
||||
#include <libyul/backends/evm/AbstractAssembly.h>
|
||||
|
||||
#include <libevmasm/SemanticInformation.h>
|
||||
#include <libevmasm/Instruction.h>
|
||||
|
||||
@ -46,19 +46,6 @@ using namespace solidity::util;
|
||||
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(
|
||||
string const& _name,
|
||||
evmasm::Instruction _instruction
|
||||
@ -76,12 +63,10 @@ pair<YulString, BuiltinFunctionForEVM> createEVMFunction(
|
||||
f.literalArguments.clear();
|
||||
f.instruction = _instruction;
|
||||
f.generateCode = [_instruction](
|
||||
FunctionCall const& _call,
|
||||
FunctionCall const&,
|
||||
AbstractAssembly& _assembly,
|
||||
BuiltinContext&,
|
||||
std::function<void(Expression const&)> _visitExpression
|
||||
BuiltinContext&
|
||||
) {
|
||||
visitArguments(_assembly, _call, _visitExpression);
|
||||
_assembly.appendInstruction(_instruction);
|
||||
};
|
||||
|
||||
@ -94,7 +79,7 @@ pair<YulString, BuiltinFunctionForEVM> createFunction(
|
||||
size_t _returns,
|
||||
SideEffects _sideEffects,
|
||||
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(), "");
|
||||
@ -166,12 +151,10 @@ map<YulString, BuiltinFunctionForEVM> createBuiltins(langutil::EVMVersion _evmVe
|
||||
builtins.emplace(createFunction("linkersymbol", 1, 1, SideEffects{}, {LiteralKind::String}, [](
|
||||
FunctionCall const& _call,
|
||||
AbstractAssembly& _assembly,
|
||||
BuiltinContext&,
|
||||
function<void(Expression const&)>
|
||||
BuiltinContext&
|
||||
) {
|
||||
yulAssert(_call.arguments.size() == 1, "");
|
||||
Expression const& arg = _call.arguments.front();
|
||||
_assembly.setSourceLocation(_call.debugData->location);
|
||||
_assembly.appendLinkerSymbol(std::get<Literal>(arg).value.str());
|
||||
}));
|
||||
|
||||
@ -184,24 +167,24 @@ map<YulString, BuiltinFunctionForEVM> createBuiltins(langutil::EVMVersion _evmVe
|
||||
[](
|
||||
FunctionCall const& _call,
|
||||
AbstractAssembly& _assembly,
|
||||
BuiltinContext&,
|
||||
function<void(Expression const&)> _visitExpression
|
||||
BuiltinContext&
|
||||
) {
|
||||
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}, [](
|
||||
FunctionCall const& _call,
|
||||
AbstractAssembly& _assembly,
|
||||
BuiltinContext& _context,
|
||||
std::function<void(Expression const&)> const&
|
||||
BuiltinContext& _context
|
||||
) {
|
||||
yulAssert(_context.currentObject, "No object available.");
|
||||
yulAssert(_call.arguments.size() == 1, "");
|
||||
Expression const& arg = _call.arguments.front();
|
||||
YulString dataName = std::get<Literal>(arg).value;
|
||||
_assembly.setSourceLocation(_call.debugData->location);
|
||||
if (_context.currentObject->name == dataName)
|
||||
_assembly.appendAssemblySize();
|
||||
else
|
||||
@ -217,14 +200,12 @@ map<YulString, BuiltinFunctionForEVM> createBuiltins(langutil::EVMVersion _evmVe
|
||||
builtins.emplace(createFunction("dataoffset", 1, 1, SideEffects{}, {LiteralKind::String}, [](
|
||||
FunctionCall const& _call,
|
||||
AbstractAssembly& _assembly,
|
||||
BuiltinContext& _context,
|
||||
std::function<void(Expression const&)> const&
|
||||
BuiltinContext& _context
|
||||
) {
|
||||
yulAssert(_context.currentObject, "No object available.");
|
||||
yulAssert(_call.arguments.size() == 1, "");
|
||||
Expression const& arg = _call.arguments.front();
|
||||
YulString dataName = std::get<Literal>(arg).value;
|
||||
_assembly.setSourceLocation(_call.debugData->location);
|
||||
if (_context.currentObject->name == dataName)
|
||||
_assembly.appendConstant(0);
|
||||
else
|
||||
@ -244,12 +225,10 @@ map<YulString, BuiltinFunctionForEVM> createBuiltins(langutil::EVMVersion _evmVe
|
||||
SideEffects{false, true, false, false, true, SideEffects::None, SideEffects::None, SideEffects::Write},
|
||||
{},
|
||||
[](
|
||||
FunctionCall const& _call,
|
||||
FunctionCall const&,
|
||||
AbstractAssembly& _assembly,
|
||||
BuiltinContext&,
|
||||
std::function<void(Expression const&)> _visitExpression
|
||||
BuiltinContext&
|
||||
) {
|
||||
visitArguments(_assembly, _call, _visitExpression);
|
||||
_assembly.appendInstruction(evmasm::Instruction::CODECOPY);
|
||||
}
|
||||
));
|
||||
@ -262,15 +241,10 @@ map<YulString, BuiltinFunctionForEVM> createBuiltins(langutil::EVMVersion _evmVe
|
||||
[](
|
||||
FunctionCall const& _call,
|
||||
AbstractAssembly& _assembly,
|
||||
BuiltinContext&,
|
||||
std::function<void(Expression const&)> _visitExpression
|
||||
BuiltinContext&
|
||||
) {
|
||||
yulAssert(_call.arguments.size() == 3, "");
|
||||
|
||||
_visitExpression(_call.arguments[2]);
|
||||
YulString identifier = std::get<Literal>(_call.arguments[1]).value;
|
||||
_visitExpression(_call.arguments[0]);
|
||||
_assembly.setSourceLocation(_call.debugData->location);
|
||||
_assembly.appendImmutableAssignment(identifier.str());
|
||||
}
|
||||
));
|
||||
@ -283,11 +257,9 @@ map<YulString, BuiltinFunctionForEVM> createBuiltins(langutil::EVMVersion _evmVe
|
||||
[](
|
||||
FunctionCall const& _call,
|
||||
AbstractAssembly& _assembly,
|
||||
BuiltinContext&,
|
||||
std::function<void(Expression const&)>
|
||||
BuiltinContext&
|
||||
) {
|
||||
yulAssert(_call.arguments.size() == 1, "");
|
||||
_assembly.setSourceLocation(_call.debugData->location);
|
||||
_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,
|
||||
AbstractAssembly& _assembly,
|
||||
BuiltinContext&,
|
||||
std::function<void(Expression const&)> _visitExpression
|
||||
BuiltinContext&
|
||||
) {
|
||||
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();
|
||||
|
||||
_assembly.setSourceLocation(_call.debugData->location);
|
||||
_assembly.appendVerbatim(
|
||||
asBytes(std::get<Literal>(bytecode).value.str()),
|
||||
_arguments,
|
||||
@ -456,24 +424,19 @@ EVMDialectTyped::EVMDialectTyped(langutil::EVMVersion _evmVersion, bool _objectA
|
||||
m_functions["popbool"_yulstring].name = "popbool"_yulstring;
|
||||
m_functions["popbool"_yulstring].parameters = {"bool"_yulstring};
|
||||
m_functions.insert(createFunction("bool_to_u256", 1, 1, {}, {}, [](
|
||||
FunctionCall const& _call,
|
||||
AbstractAssembly& _assembly,
|
||||
BuiltinContext&,
|
||||
std::function<void(Expression const&)> _visitExpression
|
||||
) {
|
||||
visitArguments(_assembly, _call, _visitExpression);
|
||||
}));
|
||||
FunctionCall const&,
|
||||
AbstractAssembly&,
|
||||
BuiltinContext&
|
||||
) {}));
|
||||
m_functions["bool_to_u256"_yulstring].parameters = {"bool"_yulstring};
|
||||
m_functions["bool_to_u256"_yulstring].returns = {"u256"_yulstring};
|
||||
m_functions.insert(createFunction("u256_to_bool", 1, 1, {}, {}, [](
|
||||
FunctionCall const& _call,
|
||||
FunctionCall const&,
|
||||
AbstractAssembly& _assembly,
|
||||
BuiltinContext&,
|
||||
std::function<void(Expression const&)> _visitExpression
|
||||
BuiltinContext&
|
||||
) {
|
||||
// TODO this should use a Panic.
|
||||
// A value larger than 1 causes an invalid instruction.
|
||||
visitArguments(_assembly, _call, _visitExpression);
|
||||
_assembly.appendConstant(2);
|
||||
_assembly.appendInstruction(evmasm::Instruction::DUP2);
|
||||
_assembly.appendInstruction(evmasm::Instruction::LT);
|
||||
|
@ -52,9 +52,10 @@ struct BuiltinFunctionForEVM: public BuiltinFunction
|
||||
{
|
||||
std::optional<evmasm::Instruction> instruction;
|
||||
/// 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
|
||||
/// argument.
|
||||
std::function<void(FunctionCall const&, AbstractAssembly&, BuiltinContext&, std::function<void(Expression const&)>)> generateCode;
|
||||
/// assembly. Expects all non-literal arguments of the call to be on stack in reverse order
|
||||
/// (i.e. right-most argument pushed first).
|
||||
/// 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 <range/v3/view/iota.hpp>
|
||||
|
||||
using namespace std;
|
||||
using namespace solidity;
|
||||
@ -135,21 +136,11 @@ NoOutputEVMDialect::NoOutputEVMDialect(EVMDialect const& _copyFrom):
|
||||
for (auto& fun: m_functions)
|
||||
{
|
||||
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 j = 0; j < _call.arguments.size(); j++)
|
||||
{
|
||||
size_t const i = _call.arguments.size() - j - 1;
|
||||
for (size_t i: ranges::views::iota(0u, _call.arguments.size()))
|
||||
if (!fun.second.literalArgument(i))
|
||||
{
|
||||
_visitExpression(_call.arguments[i]);
|
||||
visited++;
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < visited; i++)
|
||||
_assembly.appendInstruction(evmasm::Instruction::POP);
|
||||
_assembly.appendInstruction(evmasm::Instruction::POP);
|
||||
|
||||
for (size_t i = 0; i < returns; i++)
|
||||
_assembly.appendConstant(u256(0));
|
||||
|
Loading…
Reference in New Issue
Block a user