Move generation of builtin functions to helper.

This commit is contained in:
chriseth 2019-05-16 10:18:08 +02:00
parent 7de150924c
commit 9a387380b3
2 changed files with 92 additions and 89 deletions

View File

@ -35,64 +35,98 @@ using namespace std;
using namespace dev; using namespace dev;
using namespace yul; using namespace yul;
EVMDialect::EVMDialect(AsmFlavour _flavour, bool _objectAccess, langutil::EVMVersion _evmVersion): namespace
Dialect{_flavour}, m_objectAccess(_objectAccess), m_evmVersion(_evmVersion)
{ {
// The EVM instructions will be moved to builtins at some point. pair<YulString, BuiltinFunctionForEVM> createFunction(
if (!m_objectAccess) string _name,
return; size_t _params,
size_t _returns,
bool _movable,
bool _sideEffectFree,
bool _literalArguments,
std::function<void(FunctionCall const&, AbstractAssembly&, BuiltinContext&, std::function<void()>)> _generateCode
)
{
YulString name{std::move(_name)};
BuiltinFunctionForEVM f;
f.name = name;
f.parameters.resize(_params);
f.returns.resize(_returns);
f.movable = _movable;
f.literalArguments = _literalArguments;
f.sideEffectFree = _sideEffectFree;
f.generateCode = std::move(_generateCode);
return {name, f};
}
addFunction("datasize", 1, 1, true, true, true, []( map<YulString, BuiltinFunctionForEVM> createBuiltins(langutil::EVMVersion, bool _objectAccess)
FunctionCall const& _call, {
AbstractAssembly& _assembly, map<YulString, BuiltinFunctionForEVM> builtins;
BuiltinContext& _context, if (_objectAccess)
std::function<void()> {
) { builtins.emplace(createFunction("datasize", 1, 1, true, true, true, [](
yulAssert(_context.currentObject, "No object available."); FunctionCall const& _call,
yulAssert(_call.arguments.size() == 1, ""); AbstractAssembly& _assembly,
Expression const& arg = _call.arguments.front(); BuiltinContext& _context,
YulString dataName = boost::get<Literal>(arg).value; function<void()>
if (_context.currentObject->name == dataName) ) {
_assembly.appendAssemblySize(); yulAssert(_context.currentObject, "No object available.");
else yulAssert(_call.arguments.size() == 1, "");
{ Expression const& arg = _call.arguments.front();
yulAssert( YulString dataName = boost::get<Literal>(arg).value;
_context.subIDs.count(dataName) != 0, if (_context.currentObject->name == dataName)
"Could not find assembly object <" + dataName.str() + ">." _assembly.appendAssemblySize();
); else
_assembly.appendDataSize(_context.subIDs.at(dataName)); {
} yulAssert(
}); _context.subIDs.count(dataName) != 0,
addFunction("dataoffset", 1, 1, true, true, true, []( "Could not find assembly object <" + dataName.str() + ">."
FunctionCall const& _call, );
AbstractAssembly& _assembly, _assembly.appendDataSize(_context.subIDs.at(dataName));
BuiltinContext& _context, }
std::function<void()> }));
) { builtins.emplace(createFunction("dataoffset", 1, 1, true, true, true, [](
yulAssert(_context.currentObject, "No object available."); FunctionCall const& _call,
yulAssert(_call.arguments.size() == 1, ""); AbstractAssembly& _assembly,
Expression const& arg = _call.arguments.front(); BuiltinContext& _context,
YulString dataName = boost::get<Literal>(arg).value; std::function<void()>
if (_context.currentObject->name == dataName) ) {
_assembly.appendConstant(0); yulAssert(_context.currentObject, "No object available.");
else yulAssert(_call.arguments.size() == 1, "");
{ Expression const& arg = _call.arguments.front();
yulAssert( YulString dataName = boost::get<Literal>(arg).value;
_context.subIDs.count(dataName) != 0, if (_context.currentObject->name == dataName)
"Could not find assembly object <" + dataName.str() + ">." _assembly.appendConstant(0);
); else
_assembly.appendDataOffset(_context.subIDs.at(dataName)); {
} yulAssert(
}); _context.subIDs.count(dataName) != 0,
addFunction("datacopy", 3, 0, false, false, false, []( "Could not find assembly object <" + dataName.str() + ">."
FunctionCall const&, );
AbstractAssembly& _assembly, _assembly.appendDataOffset(_context.subIDs.at(dataName));
BuiltinContext&, }
std::function<void()> _visitArguments }));
) { builtins.emplace(createFunction("datacopy", 3, 0, false, false, false, [](
_visitArguments(); FunctionCall const&,
_assembly.appendInstruction(dev::eth::Instruction::CODECOPY); AbstractAssembly& _assembly,
}); BuiltinContext&,
std::function<void()> _visitArguments
) {
_visitArguments();
_assembly.appendInstruction(dev::eth::Instruction::CODECOPY);
}));
}
return builtins;
}
}
EVMDialect::EVMDialect(AsmFlavour _flavour, bool _objectAccess, langutil::EVMVersion _evmVersion):
Dialect{_flavour},
m_objectAccess(_objectAccess),
m_evmVersion(_evmVersion),
m_functions(createBuiltins(_evmVersion, _objectAccess))
{
} }
BuiltinFunctionForEVM const* EVMDialect::builtin(YulString _name) const BuiltinFunctionForEVM const* EVMDialect::builtin(YulString _name) const
@ -123,24 +157,3 @@ shared_ptr<yul::EVMDialect> EVMDialect::yulForEVM(langutil::EVMVersion _version)
{ {
return make_shared<EVMDialect>(AsmFlavour::Yul, false, _version); return make_shared<EVMDialect>(AsmFlavour::Yul, false, _version);
} }
void EVMDialect::addFunction(
string _name,
size_t _params,
size_t _returns,
bool _movable,
bool _sideEffectFree,
bool _literalArguments,
std::function<void(FunctionCall const&, AbstractAssembly&, BuiltinContext&, std::function<void()>)> _generateCode
)
{
YulString name{std::move(_name)};
BuiltinFunctionForEVM& f = m_functions[name];
f.name = name;
f.parameters.resize(_params);
f.returns.resize(_returns);
f.movable = _movable;
f.sideEffectFree = _sideEffectFree;
f.literalArguments = _literalArguments;
f.generateCode = std::move(_generateCode);
}

View File

@ -76,18 +76,8 @@ struct EVMDialect: public Dialect
bool providesObjectAccess() const { return m_objectAccess; } bool providesObjectAccess() const { return m_objectAccess; }
protected: protected:
void addFunction( bool const m_objectAccess;
std::string _name, langutil::EVMVersion const m_evmVersion;
size_t _params,
size_t _returns,
bool _movable,
bool _sideEffectFree,
bool _literalArguments,
std::function<void(FunctionCall const&, AbstractAssembly&, BuiltinContext&, std::function<void()>)> _generateCode
);
bool m_objectAccess;
langutil::EVMVersion m_evmVersion;
std::map<YulString, BuiltinFunctionForEVM> m_functions; std::map<YulString, BuiltinFunctionForEVM> m_functions;
}; };