diff --git a/libsolidity/ast/ASTJsonExporter.cpp b/libsolidity/ast/ASTJsonExporter.cpp index 910cc257eb4a..c0b0a2914f52 100644 --- a/libsolidity/ast/ASTJsonExporter.cpp +++ b/libsolidity/ast/ASTJsonExporter.cpp @@ -665,7 +665,7 @@ bool ASTJsonExporter::visit(InlineAssembly const& _node) externalReferencesJson.emplace_back(std::move(it)); std::vector> attributes = { - std::make_pair("AST", Json(yul::AsmJsonConverter(sourceIndexFromLocation(_node.location()))(_node.operations().root()))), + std::make_pair("AST", Json(yul::AsmJsonConverter(_node.dialect(), sourceIndexFromLocation(_node.location()))(_node.operations().root()))), std::make_pair("externalReferences", std::move(externalReferencesJson)), std::make_pair("evmVersion", dynamic_cast(_node.dialect()).evmVersion().name()) }; diff --git a/libsolidity/experimental/codegen/IRGeneratorForStatements.cpp b/libsolidity/experimental/codegen/IRGeneratorForStatements.cpp index 6925a434d0a1..80d8238bf370 100644 --- a/libsolidity/experimental/codegen/IRGeneratorForStatements.cpp +++ b/libsolidity/experimental/codegen/IRGeneratorForStatements.cpp @@ -54,9 +54,8 @@ struct CopyTranslate: public yul::ASTCopier { CopyTranslate( IRGenerationContext const& _context, - yul::Dialect const& _dialect, std::map _references - ): m_context(_context), m_dialect(_dialect), m_references(std::move(_references)) {} + ): m_context(_context), m_references(std::move(_references)) {} using ASTCopier::operator(); @@ -72,10 +71,7 @@ struct CopyTranslate: public yul::ASTCopier yul::YulName translateIdentifier(yul::YulName _name) override { - if (m_dialect.builtin(_name)) - return _name; - else - return yul::YulName{"usr$" + _name.str()}; + return yul::YulName{"usr$" + _name.str()}; } yul::Identifier translate(yul::Identifier const& _identifier) override @@ -106,7 +102,6 @@ struct CopyTranslate: public yul::ASTCopier } IRGenerationContext const& m_context; - yul::Dialect const& m_dialect; std::map m_references; }; @@ -129,10 +124,10 @@ bool IRGeneratorForStatements::visit(TupleExpression const& _tupleExpression) bool IRGeneratorForStatements::visit(InlineAssembly const& _assembly) { - CopyTranslate bodyCopier{m_context, _assembly.dialect(), _assembly.annotation().externalReferences}; + CopyTranslate bodyCopier{m_context, _assembly.annotation().externalReferences}; yul::Statement modified = bodyCopier(_assembly.operations().root()); solAssert(std::holds_alternative(modified)); - m_code << yul::AsmPrinter()(std::get(modified)) << "\n"; + m_code << yul::AsmPrinter(_assembly.dialect())(std::get(modified)) << "\n"; return false; } diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index 1f432db40fca..24d97503282a 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -849,7 +849,7 @@ Json CompilerStack::generatedSources(std::string const& _contractName, bool _run yul::EVMDialect const& dialect = yul::EVMDialect::strictAssemblyForEVM(m_evmVersion); std::shared_ptr parserResult = yul::Parser{errorReporter, dialect}.parse(charStream); solAssert(parserResult, ""); - sources[0]["ast"] = yul::AsmJsonConverter{sourceIndex}(parserResult->root()); + sources[0]["ast"] = yul::AsmJsonConverter{dialect, sourceIndex}(parserResult->root()); sources[0]["name"] = sourceName; sources[0]["id"] = sourceIndex; sources[0]["language"] = "Yul"; diff --git a/libyul/Utilities.cpp b/libyul/Utilities.cpp index 049dd290e0c6..e986bddaec41 100644 --- a/libyul/Utilities.cpp +++ b/libyul/Utilities.cpp @@ -21,12 +21,15 @@ #include +#include + #include #include #include #include #include +#include #include @@ -241,12 +244,30 @@ bool SwitchCaseCompareByLiteralValue::operator()(Case const* _lhs, Case const* _ std::string_view yul::resolveFunctionName(FunctionName const& _functionName, Dialect const& _dialect) { - if (std::holds_alternative(_functionName)) - return std::get(_functionName).name.str(); - else if (std::holds_alternative(_functionName)) - return _dialect.builtinFunction(std::get(_functionName).handle).name; - else if (std::holds_alternative(_functionName)) - return _dialect.verbatimFunction(std::get(_functionName).handle).name; - yulAssert(false); + GenericVisitor visitor{ + [&](Identifier const& _identifier) { return _identifier.name.str(); }, + [&](Builtin const& _builtin) { return _dialect.builtinFunction(_builtin.handle).name; }, + [&](Verbatim const& _verbatim) { return _dialect.verbatimFunction(_verbatim.handle).name; } + }; + return std::visit(visitor, _functionName); } +BuiltinFunction const* yul::resolveBuiltinFunction(FunctionName const& _functionName, Dialect const& _dialect) +{ + GenericVisitor visitor{ + [&](Identifier const&) -> BuiltinFunction const* { return nullptr; }, + [&](Builtin const& _builtin) -> BuiltinFunction const* { return &_dialect.builtinFunction(_builtin.handle); }, + [&](Verbatim const& _verbatim) -> BuiltinFunction const* { return &_dialect.verbatimFunction(_verbatim.handle); } + }; + return std::visit(visitor, _functionName); +} + +BuiltinFunctionForEVM const* yul::resolveBuiltinFunctionForEVM(FunctionName const& _functionName, EVMDialect const& _dialect) +{ + GenericVisitor visitor{ + [&](Identifier const&) -> BuiltinFunctionForEVM const* { return nullptr; }, + [&](Builtin const& _builtin) -> BuiltinFunctionForEVM const* { return &_dialect.builtinFunction(_builtin.handle); }, + [&](Verbatim const& _verbatim) -> BuiltinFunctionForEVM const* { return &_dialect.verbatimFunction(_verbatim.handle); } + }; + return std::visit(visitor, _functionName); +} diff --git a/libyul/Utilities.h b/libyul/Utilities.h index 41c454313ca0..ff4ea687a044 100644 --- a/libyul/Utilities.h +++ b/libyul/Utilities.h @@ -31,6 +31,9 @@ namespace solidity::yul { struct Dialect; +struct EVMDialect; +struct BuiltinFunction; +struct BuiltinFunctionForEVM; std::string reindent(std::string const& _code); @@ -87,4 +90,7 @@ struct SwitchCaseCompareByLiteralValue std::string_view resolveFunctionName(FunctionName const& _functionName, Dialect const& _dialect); +BuiltinFunction const* resolveBuiltinFunction(FunctionName const& _functionName, Dialect const& _dialect); +BuiltinFunctionForEVM const* resolveBuiltinFunctionForEVM(FunctionName const& _functionName, EVMDialect const& _dialect); + } diff --git a/libyul/backends/evm/EVMDialect.cpp b/libyul/backends/evm/EVMDialect.cpp index 21d499ac3fbb..4fce51f9ba5b 100644 --- a/libyul/backends/evm/EVMDialect.cpp +++ b/libyul/backends/evm/EVMDialect.cpp @@ -397,7 +397,6 @@ EVMDialect::EVMDialect(langutil::EVMVersion _evmVersion, bool _objectAccess): std::optional EVMDialect::builtin(std::string_view _name) const { - static auto constexpr comparator = [](auto const& lhs, auto const& rhs) { return lhs.name.str() < rhs.str(); }; auto it = std::find_if(m_functions.begin(), m_functions.end(), [&_name](auto const& builtin) { return builtin && builtin.value().name == _name; }); if (it != m_functions.end() && *it && it->value().name == _name) return BuiltinHandle{static_cast(std::distance(m_functions.begin(), it))}; diff --git a/test/libsolidity/MemoryGuardTest.cpp b/test/libsolidity/MemoryGuardTest.cpp index b2e0b75d367a..967added53f9 100644 --- a/test/libsolidity/MemoryGuardTest.cpp +++ b/test/libsolidity/MemoryGuardTest.cpp @@ -59,10 +59,11 @@ TestCase::TestResult MemoryGuardTest::run(std::ostream& _stream, std::string con m_obtainedResult.clear(); for (std::string contractName: compiler().contractNames()) { + auto const& dialect = EVMDialect::strictAssemblyForEVMObjects(CommonOptions::get().evmVersion()); ErrorList errors; auto [object, analysisInfo] = yul::test::parse( compiler().yulIR(contractName), - EVMDialect::strictAssemblyForEVMObjects(CommonOptions::get().evmVersion()), + dialect, errors ); @@ -76,7 +77,8 @@ TestCase::TestResult MemoryGuardTest::run(std::ostream& _stream, std::string con auto handleObject = [&](std::string const& _kind, Object const& _object) { m_obtainedResult += contractName + "(" + _kind + ") " + (findFunctionCalls( _object.code()->root(), - "memoryguard"_yulname + "memoryguard", + dialect ).empty() ? "false" : "true") + "\n"; }; handleObject("creation", *object); diff --git a/test/libsolidity/SemanticTest.cpp b/test/libsolidity/SemanticTest.cpp index b0bdb95cb9c4..f814edb1e078 100644 --- a/test/libsolidity/SemanticTest.cpp +++ b/test/libsolidity/SemanticTest.cpp @@ -118,7 +118,7 @@ SemanticTest::SemanticTest( } } -std::map SemanticTest::makeBuiltins() +std::map SemanticTest::makeBuiltins() { return { { diff --git a/test/libsolidity/SemanticTest.h b/test/libsolidity/SemanticTest.h index efc2b59030e6..d47dc8dad6e5 100644 --- a/test/libsolidity/SemanticTest.h +++ b/test/libsolidity/SemanticTest.h @@ -104,7 +104,7 @@ class SemanticTest: public SolidityExecutionFramework, public EVMVersionRestrict bool _formatted ); bool checkGasCostExpectation(TestFunctionCall& io_test, bool _compileViaYul) const; - std::map makeBuiltins(); + std::map makeBuiltins(); std::vector makeSideEffectHooks() const; std::vector eventSideEffectHook(FunctionCall const&) const; std::optional matchEvent(util::h256 const& hash) const; diff --git a/test/libyul/Common.cpp b/test/libyul/Common.cpp index 8980adcb1821..703cc88ba56b 100644 --- a/test/libyul/Common.cpp +++ b/test/libyul/Common.cpp @@ -94,9 +94,9 @@ yul::Block yul::test::disambiguate(std::string const& _source) return std::get(Disambiguator(defaultDialect(), *result.second, {})(result.first->root())); } -std::string yul::test::format(std::string const& _source) +std::string yul::test::format(std::string const& _source, Dialect const& _dialect) { - return yul::AsmPrinter()(parse(_source).first->root()); + return yul::AsmPrinter(_dialect)(parse(_source).first->root()); } namespace diff --git a/test/libyul/Common.h b/test/libyul/Common.h index c87f1c68be17..34da85502e4b 100644 --- a/test/libyul/Common.h +++ b/test/libyul/Common.h @@ -52,7 +52,7 @@ std::pair, std::shared_ptr> parse(std::string const& _source, Dialect const& _dialect, langutil::ErrorList& _errors); Block disambiguate(std::string const& _source); -std::string format(std::string const& _source); +std::string format(std::string const& _source, Dialect const& _dialect); solidity::yul::Dialect const& dialect(std::string const& _name, langutil::EVMVersion _evmVersion); diff --git a/test/libyul/ControlFlowGraphTest.cpp b/test/libyul/ControlFlowGraphTest.cpp index 5c9bba8d41e5..019a9d3ad228 100644 --- a/test/libyul/ControlFlowGraphTest.cpp +++ b/test/libyul/ControlFlowGraphTest.cpp @@ -60,8 +60,8 @@ static std::string variableSlotToString(VariableSlot const& _slot) class ControlFlowGraphPrinter { public: - ControlFlowGraphPrinter(std::ostream& _stream): - m_stream(_stream) + ControlFlowGraphPrinter(std::ostream& _stream, Dialect const& _dialect): + m_stream(_stream), m_dialect(_dialect) { } void operator()(CFG::BasicBlock const& _block, bool _isMainEntry = true) @@ -129,8 +129,7 @@ class ControlFlowGraphPrinter m_stream << _call.function.get().name.str() << ": "; }, [&](CFG::BuiltinCall const& _call) { - m_stream << _call.functionCall.get().functionName.name.str() << ": "; - + m_stream << _call.builtin.get().name << ": "; }, [&](CFG::Assignment const& _assignment) { m_stream << "Assignment("; @@ -138,7 +137,7 @@ class ControlFlowGraphPrinter m_stream << "): "; } }, operation.operation); - m_stream << stackToString(operation.input) << " => " << stackToString(operation.output) << "\\l\\\n"; + m_stream << stackToString(operation.input, m_dialect) << " => " << stackToString(operation.output, m_dialect) << "\\l\\\n"; } m_stream << "\"];\n"; std::visit(util::GenericVisitor{ @@ -160,7 +159,7 @@ class ControlFlowGraphPrinter { m_stream << "Block" << getBlockId(_block) << " -> Block" << getBlockId(_block) << "Exit;\n"; m_stream << "Block" << getBlockId(_block) << "Exit [label=\"{ "; - m_stream << stackSlotToString(_conditionalJump.condition); + m_stream << stackSlotToString(_conditionalJump.condition, m_dialect); m_stream << "| { <0> Zero | <1> NonZero }}\" shape=Mrecord];\n"; m_stream << "Block" << getBlockId(_block); m_stream << "Exit:0 -> Block" << getBlockId(*_conditionalJump.zero) << ";\n"; @@ -189,6 +188,7 @@ class ControlFlowGraphPrinter return id; } std::ostream& m_stream; + Dialect const& m_dialect; std::map m_blockIds; size_t m_blockCount = 0; std::list m_blocksToPrint; @@ -209,7 +209,7 @@ TestCase::TestResult ControlFlowGraphTest::run(std::ostream& _stream, std::strin std::unique_ptr cfg = ControlFlowGraphBuilder::build(*analysisInfo, *m_dialect, object->code()->root()); output << "digraph CFG {\nnodesep=0.7;\nnode[shape=box];\n\n"; - ControlFlowGraphPrinter printer{output}; + ControlFlowGraphPrinter printer{output, *m_dialect}; printer(*cfg->entry); for (auto function: cfg->functions) printer(cfg->functionInfo.at(function)); diff --git a/test/libyul/FunctionSideEffects.cpp b/test/libyul/FunctionSideEffects.cpp index 9d6599f42bc1..83e1d88c9dcb 100644 --- a/test/libyul/FunctionSideEffects.cpp +++ b/test/libyul/FunctionSideEffects.cpp @@ -29,6 +29,7 @@ #include #include +#include #include @@ -88,14 +89,22 @@ TestCase::TestResult FunctionSideEffects::run(std::ostream& _stream, std::string if (!obj.hasCode()) BOOST_THROW_EXCEPTION(std::runtime_error("Parsing input failed.")); - std::map functionSideEffects = SideEffectsPropagator::sideEffects( - EVMDialect::strictAssemblyForEVMObjects(langutil::EVMVersion()), + auto const& dialect = EVMDialect::strictAssemblyForEVMObjects(langutil::EVMVersion()); + std::map functionSideEffects = SideEffectsPropagator::sideEffects( + dialect, CallGraphGenerator::callGraph(obj.code()->root()) ); std::map functionSideEffectsStr; for (auto const& fun: functionSideEffects) - functionSideEffectsStr[fun.first.str()] = toString(fun.second); + { + auto const& functionNameStr = std::visit(GenericVisitor{ + [](YulName const& _name) { return _name.str(); }, + [&](BuiltinHandle const& _builtin) { return dialect.builtinFunction(_builtin).name; }, + [&](VerbatimHandle const& _verbatim) { return dialect.verbatimFunction(_verbatim).name; } + }, fun.first); + functionSideEffectsStr[functionNameStr] = toString(fun.second); + } m_obtainedResult.clear(); for (auto const& fun: functionSideEffectsStr) diff --git a/test/libyul/StackLayoutGeneratorTest.cpp b/test/libyul/StackLayoutGeneratorTest.cpp index 9c16eaefc110..bee5236ecad9 100644 --- a/test/libyul/StackLayoutGeneratorTest.cpp +++ b/test/libyul/StackLayoutGeneratorTest.cpp @@ -64,8 +64,8 @@ static std::string variableSlotToString(VariableSlot const& _slot) class StackLayoutPrinter { public: - StackLayoutPrinter(std::ostream& _stream, StackLayout const& _stackLayout): - m_stream(_stream), m_stackLayout(_stackLayout) + StackLayoutPrinter(std::ostream& _stream, StackLayout const& _stackLayout, Dialect const& _dialect): + m_stream(_stream), m_stackLayout(_stackLayout), m_dialect(_dialect) { } void operator()(CFG::BasicBlock const& _block, bool _isMainEntry = true) @@ -99,7 +99,7 @@ class StackLayoutPrinter m_stream << "\\l\\\n"; Stack functionEntryStack = {FunctionReturnLabelSlot{_info.function}}; functionEntryStack += _info.parameters | ranges::views::reverse; - m_stream << stackToString(functionEntryStack) << "\"];\n"; + m_stream << stackToString(functionEntryStack, m_dialect) << "\"];\n"; m_stream << "FunctionEntry_" << _info.function.name.str() << " -> Block" << getBlockId(*_info.entry) << ";\n"; (*this)(*_info.entry, false); } @@ -130,17 +130,17 @@ class StackLayoutPrinter }, entry->exit); auto const& blockInfo = m_stackLayout.blockInfos.at(&_block); - m_stream << stackToString(blockInfo.entryLayout) << "\\l\\\n"; + m_stream << stackToString(blockInfo.entryLayout, m_dialect) << "\\l\\\n"; for (auto const& operation: _block.operations) { auto entryLayout = m_stackLayout.operationEntryLayout.at(&operation); - m_stream << stackToString(m_stackLayout.operationEntryLayout.at(&operation)) << "\\l\\\n"; + m_stream << stackToString(m_stackLayout.operationEntryLayout.at(&operation), m_dialect) << "\\l\\\n"; std::visit(util::GenericVisitor{ [&](CFG::FunctionCall const& _call) { m_stream << _call.function.get().name.str(); }, [&](CFG::BuiltinCall const& _call) { - m_stream << _call.functionCall.get().functionName.name.str(); + m_stream << _call.builtin.get().name; }, [&](CFG::Assignment const& _assignment) { @@ -154,9 +154,9 @@ class StackLayoutPrinter for (size_t i = 0; i < operation.input.size(); ++i) entryLayout.pop_back(); entryLayout += operation.output; - m_stream << stackToString(entryLayout) << "\\l\\\n"; + m_stream << stackToString(entryLayout, m_dialect) << "\\l\\\n"; } - m_stream << stackToString(blockInfo.exitLayout) << "\\l\\\n"; + m_stream << stackToString(blockInfo.exitLayout, m_dialect) << "\\l\\\n"; m_stream << "\"];\n"; std::visit(util::GenericVisitor{ [&](CFG::BasicBlock::MainExit const&) @@ -177,7 +177,7 @@ class StackLayoutPrinter { m_stream << "Block" << getBlockId(_block) << " -> Block" << getBlockId(_block) << "Exit;\n"; m_stream << "Block" << getBlockId(_block) << "Exit [label=\"{ "; - m_stream << stackSlotToString(_conditionalJump.condition); + m_stream << stackSlotToString(_conditionalJump.condition, m_dialect); m_stream << "| { <0> Zero | <1> NonZero }}\" shape=Mrecord];\n"; m_stream << "Block" << getBlockId(_block); m_stream << "Exit:0 -> Block" << getBlockId(*_conditionalJump.zero) << ";\n"; @@ -207,6 +207,7 @@ class StackLayoutPrinter } std::ostream& m_stream; StackLayout const& m_stackLayout; + Dialect const& m_dialect; std::map m_blockIds; size_t m_blockCount = 0; std::list m_blocksToPrint; @@ -228,7 +229,7 @@ TestCase::TestResult StackLayoutGeneratorTest::run(std::ostream& _stream, std::s StackLayout stackLayout = StackLayoutGenerator::run(*cfg); output << "digraph CFG {\nnodesep=0.7;\nnode[shape=box];\n\n"; - StackLayoutPrinter printer{output, stackLayout}; + StackLayoutPrinter printer{output, stackLayout, *m_dialect}; printer(*cfg->entry); for (auto function: cfg->functions) printer(cfg->functionInfo.at(function)); diff --git a/test/libyul/StackShufflingTest.cpp b/test/libyul/StackShufflingTest.cpp index 40fdcc5b15f4..9716edd40c79 100644 --- a/test/libyul/StackShufflingTest.cpp +++ b/test/libyul/StackShufflingTest.cpp @@ -17,9 +17,11 @@ #include +#include +#include + #include #include -#include using namespace solidity::util; using namespace solidity::langutil; @@ -149,14 +151,14 @@ TestCase::TestResult StackShufflingTest::run(std::ostream& _stream, std::string m_targetStack, [&](unsigned _swapDepth) // swap { - output << stackToString(m_sourceStack) << std::endl; + output << stackToString(m_sourceStack, EVMDialect::strictAssemblyForEVM({})) << std::endl; output << "SWAP" << _swapDepth << std::endl; }, [&](StackSlot const& _slot) // dupOrPush { - output << stackToString(m_sourceStack) << std::endl; + output << stackToString(m_sourceStack, EVMDialect::strictAssemblyForEVM({})) << std::endl; if (canBeFreelyGenerated(_slot)) - output << "PUSH " << stackSlotToString(_slot) << std::endl; + output << "PUSH " << stackSlotToString(_slot, EVMDialect::strictAssemblyForEVM({})) << std::endl; else { if (auto depth = util::findOffset(m_sourceStack | ranges::views::reverse, _slot)) @@ -166,12 +168,12 @@ TestCase::TestResult StackShufflingTest::run(std::ostream& _stream, std::string } }, [&](){ // pop - output << stackToString(m_sourceStack) << std::endl; + output << stackToString(m_sourceStack, EVMDialect::strictAssemblyForEVM({})) << std::endl; output << "POP" << std::endl; } ); - output << stackToString(m_sourceStack) << std::endl; + output << stackToString(m_sourceStack, EVMDialect::strictAssemblyForEVM({})) << std::endl; m_obtainedResult = output.str(); return checkResult(_stream, _linePrefix, _formatted); diff --git a/test/libyul/YulOptimizerTest.cpp b/test/libyul/YulOptimizerTest.cpp index 7f2f5815a675..4d2d0eb0470a 100644 --- a/test/libyul/YulOptimizerTest.cpp +++ b/test/libyul/YulOptimizerTest.cpp @@ -81,9 +81,9 @@ TestCase::TestResult YulOptimizerTest::run(std::ostream& _stream, std::string co auto optimizedObject = tester.optimizedObject(); std::string printedOptimizedObject; if (optimizedObject->subObjects.empty()) - printedOptimizedObject = AsmPrinter{}(optimizedObject->code()->root()); + printedOptimizedObject = AsmPrinter{*m_dialect}(optimizedObject->code()->root()); else - printedOptimizedObject = optimizedObject->toString(); + printedOptimizedObject = optimizedObject->toString(*m_dialect); // Re-parse new code for compilability if (!std::get<0>(parse(_stream, _linePrefix, _formatted, printedOptimizedObject))) diff --git a/test/tools/yulInterpreter/Interpreter.cpp b/test/tools/yulInterpreter/Interpreter.cpp index 21e97f0769c8..d1477bcd9e00 100644 --- a/test/tools/yulInterpreter/Interpreter.cpp +++ b/test/tools/yulInterpreter/Interpreter.cpp @@ -309,14 +309,16 @@ void ExpressionEvaluator::operator()(Identifier const& _identifier) void ExpressionEvaluator::operator()(FunctionCall const& _funCall) { std::vector> const* literalArguments = nullptr; - if (BuiltinFunction const* builtin = m_dialect.builtin(_funCall.functionName.name)) + if (isBuiltinFunctionCall(_funCall)) + + if (BuiltinFunction const* builtin = resolveBuiltinFunction(_funCall.functionName, m_dialect)) if (!builtin->literalArguments.empty()) literalArguments = &builtin->literalArguments; evaluateArgs(_funCall.arguments, literalArguments); if (EVMDialect const* dialect = dynamic_cast(&m_dialect)) { - if (BuiltinFunctionForEVM const* fun = dialect->builtin(_funCall.functionName.name)) + if (BuiltinFunctionForEVM const* fun = resolveBuiltinFunctionForEVM(_funCall.functionName, *dialect)) { EVMInstructionInterpreter interpreter(dialect->evmVersion(), m_state, m_disableMemoryTrace); @@ -335,28 +337,35 @@ void ExpressionEvaluator::operator()(FunctionCall const& _funCall) } Scope* scope = &m_scope; - for (; scope; scope = scope->parent) - if (scope->names.count(_funCall.functionName.name)) - break; - yulAssert(scope, ""); - - FunctionDefinition const* fun = scope->names.at(_funCall.functionName.name); - yulAssert(fun, "Function not found."); - yulAssert(m_values.size() == fun->parameters.size(), ""); - std::map variables; - for (size_t i = 0; i < fun->parameters.size(); ++i) - variables[fun->parameters.at(i).name] = m_values.at(i); - for (size_t i = 0; i < fun->returnVariables.size(); ++i) - variables[fun->returnVariables.at(i).name] = 0; - - m_state.controlFlowState = ControlFlowState::Default; - std::unique_ptr interpreter = makeInterpreterCopy(std::move(variables)); - (*interpreter)(fun->body); - m_state.controlFlowState = ControlFlowState::Default; + if (!isBuiltinFunctionCall(_funCall)) + { + yulAssert(std::holds_alternative(_funCall.functionName)); + for (; scope; scope = scope->parent) + if (scope->names.count(std::get(_funCall.functionName).name)) + break; + + yulAssert(scope, ""); + + FunctionDefinition const* fun = scope->names.at(std::get(_funCall.functionName).name); + yulAssert(fun, "Function not found."); + yulAssert(m_values.size() == fun->parameters.size(), ""); + std::map variables; + for (size_t i = 0; i < fun->parameters.size(); ++i) + variables[fun->parameters.at(i).name] = m_values.at(i); + for (size_t i = 0; i < fun->returnVariables.size(); ++i) + variables[fun->returnVariables.at(i).name] = 0; - m_values.clear(); - for (auto const& retVar: fun->returnVariables) - m_values.emplace_back(interpreter->valueOfVariable(retVar.name)); + m_state.controlFlowState = ControlFlowState::Default; + std::unique_ptr interpreter = makeInterpreterCopy(std::move(variables)); + (*interpreter)(fun->body); + m_state.controlFlowState = ControlFlowState::Default; + + m_values.clear(); + for (auto const& retVar: fun->returnVariables) + m_values.emplace_back(interpreter->valueOfVariable(retVar.name)); + } + else + yulAssert(false); // should not be reachable } u256 ExpressionEvaluator::value() const