diff --git a/libyul/backends/evm/ControlFlowGraphBuilder.cpp b/libyul/backends/evm/ControlFlowGraphBuilder.cpp index 7e57b8257..df271bb8d 100644 --- a/libyul/backends/evm/ControlFlowGraphBuilder.cpp +++ b/libyul/backends/evm/ControlFlowGraphBuilder.cpp @@ -176,9 +176,9 @@ StackSlot ControlFlowGraphBuilder::operator()(Expression const& _expression) StackSlot ControlFlowGraphBuilder::operator()(FunctionCall const& _call) { - CFG::Operation const& operation = visitFunctionCall(_call); - yulAssert(operation.output.size() == 1, ""); - return operation.output.front(); + Stack const& output = visitFunctionCall(_call); + yulAssert(output.size() == 1, ""); + return output.front(); } void ControlFlowGraphBuilder::operator()(VariableDeclaration const& _varDecl) @@ -219,8 +219,8 @@ void ControlFlowGraphBuilder::operator()(ExpressionStatement const& _exprStmt) yulAssert(m_currentBlock, ""); std::visit(util::GenericVisitor{ [&](FunctionCall const& _call) { - CFG::Operation const& operation = visitFunctionCall(_call); - yulAssert(operation.output.empty(), ""); + Stack const& output = visitFunctionCall(_call); + yulAssert(output.empty(), ""); }, [&](auto const&) { yulAssert(false, ""); } }, _exprStmt.expression); @@ -239,6 +239,9 @@ void ControlFlowGraphBuilder::operator()(ExpressionStatement const& _exprStmt) void ControlFlowGraphBuilder::operator()(Block const& _block) { ScopedSaveAndRestore saveScope(m_scope, m_info.scopes.at(&_block).get()); + for (auto const& statement: _block.statements) + if (auto const* function = get_if(&statement)) + registerFunction(*function); for (auto const& statement: _block.statements) std::visit(*this, statement); } @@ -386,11 +389,26 @@ void ControlFlowGraphBuilder::operator()(FunctionDefinition const& _function) Scope::Function& function = std::get(m_scope->identifiers.at(_function.name)); m_graph.functions.emplace_back(&function); + CFG::FunctionInfo& functionInfo = m_graph.functionInfo.at(&function); + + ControlFlowGraphBuilder builder{m_graph, m_info, m_dialect}; + builder.m_currentFunction = &functionInfo; + builder.m_currentBlock = functionInfo.entry; + builder(_function.body); + builder.m_currentBlock->exit = CFG::BasicBlock::FunctionReturn{debugDataOf(_function), &functionInfo}; +} + +void ControlFlowGraphBuilder::registerFunction(FunctionDefinition const& _function) +{ + yulAssert(m_scope, ""); + yulAssert(m_scope->identifiers.count(_function.name), ""); + Scope::Function& function = std::get(m_scope->identifiers.at(_function.name)); + yulAssert(m_info.scopes.at(&_function.body), ""); Scope* virtualFunctionScope = m_info.scopes.at(m_info.virtualBlocks.at(&_function).get()).get(); yulAssert(virtualFunctionScope, ""); - auto&& [it, inserted] = m_graph.functionInfo.emplace(std::make_pair(&function, CFG::FunctionInfo{ + bool inserted = m_graph.functionInfo.emplace(std::make_pair(&function, CFG::FunctionInfo{ _function.debugData, function, &m_graph.makeBlock(debugDataOf(_function.body)), @@ -406,19 +424,11 @@ void ControlFlowGraphBuilder::operator()(FunctionDefinition const& _function) _retVar.debugData }; }) | ranges::to - })); - yulAssert(inserted, ""); - CFG::FunctionInfo& functionInfo = it->second; - - ControlFlowGraphBuilder builder{m_graph, m_info, m_dialect}; - builder.m_currentFunction = &functionInfo; - builder.m_currentBlock = functionInfo.entry; - builder(_function.body); - builder.m_currentBlock->exit = CFG::BasicBlock::FunctionReturn{debugDataOf(_function), &functionInfo}; + })).second; + yulAssert(inserted); } - -CFG::Operation const& ControlFlowGraphBuilder::visitFunctionCall(FunctionCall const& _call) +Stack const& ControlFlowGraphBuilder::visitFunctionCall(FunctionCall const& _call) { yulAssert(m_scope, ""); yulAssert(m_currentBlock, ""); @@ -439,7 +449,7 @@ CFG::Operation const& ControlFlowGraphBuilder::visitFunctionCall(FunctionCall co }) | ranges::to, // operation move(builtinCall) - }); + }).output; } else { @@ -456,7 +466,7 @@ CFG::Operation const& ControlFlowGraphBuilder::visitFunctionCall(FunctionCall co }) | ranges::to, // operation CFG::FunctionCall{_call.debugData, function, _call} - }); + }).output; } } @@ -464,9 +474,9 @@ Stack ControlFlowGraphBuilder::visitAssignmentRightHandSide(Expression const& _e { return std::visit(util::GenericVisitor{ [&](FunctionCall const& _call) -> Stack { - CFG::Operation const& operation = visitFunctionCall(_call); - yulAssert(_expectedSlotCount == operation.output.size(), ""); - return operation.output; + Stack const& output = visitFunctionCall(_call); + yulAssert(_expectedSlotCount == output.size(), ""); + return output; }, [&](auto const& _identifierOrLiteral) -> Stack { yulAssert(_expectedSlotCount == 1, ""); diff --git a/libyul/backends/evm/ControlFlowGraphBuilder.h b/libyul/backends/evm/ControlFlowGraphBuilder.h index f99a879f6..2a99cfe5b 100644 --- a/libyul/backends/evm/ControlFlowGraphBuilder.h +++ b/libyul/backends/evm/ControlFlowGraphBuilder.h @@ -57,7 +57,8 @@ private: AsmAnalysisInfo const& _analysisInfo, Dialect const& _dialect ); - CFG::Operation const& visitFunctionCall(FunctionCall const&); + void registerFunction(FunctionDefinition const& _function); + Stack const& visitFunctionCall(FunctionCall const&); Stack visitAssignmentRightHandSide(Expression const& _expression, size_t _expectedSlotCount); Scope::Function const& lookupFunction(YulString _name) const;