diff --git a/libyul/backends/evm/EVMDialect.cpp b/libyul/backends/evm/EVMDialect.cpp index 69bdc8686..d89ec2b22 100644 --- a/libyul/backends/evm/EVMDialect.cpp +++ b/libyul/backends/evm/EVMDialect.cpp @@ -35,64 +35,98 @@ using namespace std; using namespace dev; using namespace yul; -EVMDialect::EVMDialect(AsmFlavour _flavour, bool _objectAccess, langutil::EVMVersion _evmVersion): - Dialect{_flavour}, m_objectAccess(_objectAccess), m_evmVersion(_evmVersion) +namespace { - // The EVM instructions will be moved to builtins at some point. - if (!m_objectAccess) - return; +pair createFunction( + string _name, + size_t _params, + size_t _returns, + bool _movable, + bool _sideEffectFree, + bool _literalArguments, + std::function)> _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, []( - FunctionCall const& _call, - AbstractAssembly& _assembly, - BuiltinContext& _context, - std::function - ) { - yulAssert(_context.currentObject, "No object available."); - yulAssert(_call.arguments.size() == 1, ""); - Expression const& arg = _call.arguments.front(); - YulString dataName = boost::get(arg).value; - if (_context.currentObject->name == dataName) - _assembly.appendAssemblySize(); - else - { - yulAssert( - _context.subIDs.count(dataName) != 0, - "Could not find assembly object <" + dataName.str() + ">." - ); - _assembly.appendDataSize(_context.subIDs.at(dataName)); - } - }); - addFunction("dataoffset", 1, 1, true, true, true, []( - FunctionCall const& _call, - AbstractAssembly& _assembly, - BuiltinContext& _context, - std::function - ) { - yulAssert(_context.currentObject, "No object available."); - yulAssert(_call.arguments.size() == 1, ""); - Expression const& arg = _call.arguments.front(); - YulString dataName = boost::get(arg).value; - if (_context.currentObject->name == dataName) - _assembly.appendConstant(0); - else - { - yulAssert( - _context.subIDs.count(dataName) != 0, - "Could not find assembly object <" + dataName.str() + ">." - ); - _assembly.appendDataOffset(_context.subIDs.at(dataName)); - } - }); - addFunction("datacopy", 3, 0, false, false, false, []( - FunctionCall const&, - AbstractAssembly& _assembly, - BuiltinContext&, - std::function _visitArguments - ) { - _visitArguments(); - _assembly.appendInstruction(dev::eth::Instruction::CODECOPY); - }); +map createBuiltins(langutil::EVMVersion, bool _objectAccess) +{ + map builtins; + if (_objectAccess) + { + builtins.emplace(createFunction("datasize", 1, 1, true, true, true, []( + FunctionCall const& _call, + AbstractAssembly& _assembly, + BuiltinContext& _context, + function + ) { + yulAssert(_context.currentObject, "No object available."); + yulAssert(_call.arguments.size() == 1, ""); + Expression const& arg = _call.arguments.front(); + YulString dataName = boost::get(arg).value; + if (_context.currentObject->name == dataName) + _assembly.appendAssemblySize(); + else + { + yulAssert( + _context.subIDs.count(dataName) != 0, + "Could not find assembly object <" + dataName.str() + ">." + ); + _assembly.appendDataSize(_context.subIDs.at(dataName)); + } + })); + builtins.emplace(createFunction("dataoffset", 1, 1, true, true, true, []( + FunctionCall const& _call, + AbstractAssembly& _assembly, + BuiltinContext& _context, + std::function + ) { + yulAssert(_context.currentObject, "No object available."); + yulAssert(_call.arguments.size() == 1, ""); + Expression const& arg = _call.arguments.front(); + YulString dataName = boost::get(arg).value; + if (_context.currentObject->name == dataName) + _assembly.appendConstant(0); + else + { + yulAssert( + _context.subIDs.count(dataName) != 0, + "Could not find assembly object <" + dataName.str() + ">." + ); + _assembly.appendDataOffset(_context.subIDs.at(dataName)); + } + })); + builtins.emplace(createFunction("datacopy", 3, 0, false, false, false, []( + FunctionCall const&, + AbstractAssembly& _assembly, + BuiltinContext&, + std::function _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 @@ -123,24 +157,3 @@ shared_ptr EVMDialect::yulForEVM(langutil::EVMVersion _version) { return make_shared(AsmFlavour::Yul, false, _version); } - -void EVMDialect::addFunction( - string _name, - size_t _params, - size_t _returns, - bool _movable, - bool _sideEffectFree, - bool _literalArguments, - std::function)> _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); -} diff --git a/libyul/backends/evm/EVMDialect.h b/libyul/backends/evm/EVMDialect.h index 1ea9abd51..4cf475866 100644 --- a/libyul/backends/evm/EVMDialect.h +++ b/libyul/backends/evm/EVMDialect.h @@ -76,18 +76,8 @@ struct EVMDialect: public Dialect bool providesObjectAccess() const { return m_objectAccess; } protected: - void addFunction( - std::string _name, - size_t _params, - size_t _returns, - bool _movable, - bool _sideEffectFree, - bool _literalArguments, - std::function)> _generateCode - ); - - bool m_objectAccess; - langutil::EVMVersion m_evmVersion; + bool const m_objectAccess; + langutil::EVMVersion const m_evmVersion; std::map m_functions; };