Merge pull request #12239 from ethereum/preregisterfunction

Preregister functions
This commit is contained in:
chriseth 2021-11-04 14:31:12 +01:00 committed by GitHub
commit 7c8ad7a5c1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 34 additions and 23 deletions

View File

@ -176,9 +176,9 @@ StackSlot ControlFlowGraphBuilder::operator()(Expression const& _expression)
StackSlot ControlFlowGraphBuilder::operator()(FunctionCall const& _call) StackSlot ControlFlowGraphBuilder::operator()(FunctionCall const& _call)
{ {
CFG::Operation const& operation = visitFunctionCall(_call); Stack const& output = visitFunctionCall(_call);
yulAssert(operation.output.size() == 1, ""); yulAssert(output.size() == 1, "");
return operation.output.front(); return output.front();
} }
void ControlFlowGraphBuilder::operator()(VariableDeclaration const& _varDecl) void ControlFlowGraphBuilder::operator()(VariableDeclaration const& _varDecl)
@ -219,8 +219,8 @@ void ControlFlowGraphBuilder::operator()(ExpressionStatement const& _exprStmt)
yulAssert(m_currentBlock, ""); yulAssert(m_currentBlock, "");
std::visit(util::GenericVisitor{ std::visit(util::GenericVisitor{
[&](FunctionCall const& _call) { [&](FunctionCall const& _call) {
CFG::Operation const& operation = visitFunctionCall(_call); Stack const& output = visitFunctionCall(_call);
yulAssert(operation.output.empty(), ""); yulAssert(output.empty(), "");
}, },
[&](auto const&) { yulAssert(false, ""); } [&](auto const&) { yulAssert(false, ""); }
}, _exprStmt.expression); }, _exprStmt.expression);
@ -239,6 +239,9 @@ void ControlFlowGraphBuilder::operator()(ExpressionStatement const& _exprStmt)
void ControlFlowGraphBuilder::operator()(Block const& _block) void ControlFlowGraphBuilder::operator()(Block const& _block)
{ {
ScopedSaveAndRestore saveScope(m_scope, m_info.scopes.at(&_block).get()); ScopedSaveAndRestore saveScope(m_scope, m_info.scopes.at(&_block).get());
for (auto const& statement: _block.statements)
if (auto const* function = get_if<FunctionDefinition>(&statement))
registerFunction(*function);
for (auto const& statement: _block.statements) for (auto const& statement: _block.statements)
std::visit(*this, statement); std::visit(*this, statement);
} }
@ -386,11 +389,26 @@ void ControlFlowGraphBuilder::operator()(FunctionDefinition const& _function)
Scope::Function& function = std::get<Scope::Function>(m_scope->identifiers.at(_function.name)); Scope::Function& function = std::get<Scope::Function>(m_scope->identifiers.at(_function.name));
m_graph.functions.emplace_back(&function); 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<Scope::Function>(m_scope->identifiers.at(_function.name));
yulAssert(m_info.scopes.at(&_function.body), ""); yulAssert(m_info.scopes.at(&_function.body), "");
Scope* virtualFunctionScope = m_info.scopes.at(m_info.virtualBlocks.at(&_function).get()).get(); Scope* virtualFunctionScope = m_info.scopes.at(m_info.virtualBlocks.at(&_function).get()).get();
yulAssert(virtualFunctionScope, ""); 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.debugData,
function, function,
&m_graph.makeBlock(debugDataOf(_function.body)), &m_graph.makeBlock(debugDataOf(_function.body)),
@ -406,19 +424,11 @@ void ControlFlowGraphBuilder::operator()(FunctionDefinition const& _function)
_retVar.debugData _retVar.debugData
}; };
}) | ranges::to<vector> }) | ranges::to<vector>
})); })).second;
yulAssert(inserted, ""); 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};
} }
Stack const& ControlFlowGraphBuilder::visitFunctionCall(FunctionCall const& _call)
CFG::Operation const& ControlFlowGraphBuilder::visitFunctionCall(FunctionCall const& _call)
{ {
yulAssert(m_scope, ""); yulAssert(m_scope, "");
yulAssert(m_currentBlock, ""); yulAssert(m_currentBlock, "");
@ -439,7 +449,7 @@ CFG::Operation const& ControlFlowGraphBuilder::visitFunctionCall(FunctionCall co
}) | ranges::to<Stack>, }) | ranges::to<Stack>,
// operation // operation
move(builtinCall) move(builtinCall)
}); }).output;
} }
else else
{ {
@ -456,7 +466,7 @@ CFG::Operation const& ControlFlowGraphBuilder::visitFunctionCall(FunctionCall co
}) | ranges::to<Stack>, }) | ranges::to<Stack>,
// operation // operation
CFG::FunctionCall{_call.debugData, function, _call} CFG::FunctionCall{_call.debugData, function, _call}
}); }).output;
} }
} }
@ -464,9 +474,9 @@ Stack ControlFlowGraphBuilder::visitAssignmentRightHandSide(Expression const& _e
{ {
return std::visit(util::GenericVisitor{ return std::visit(util::GenericVisitor{
[&](FunctionCall const& _call) -> Stack { [&](FunctionCall const& _call) -> Stack {
CFG::Operation const& operation = visitFunctionCall(_call); Stack const& output = visitFunctionCall(_call);
yulAssert(_expectedSlotCount == operation.output.size(), ""); yulAssert(_expectedSlotCount == output.size(), "");
return operation.output; return output;
}, },
[&](auto const& _identifierOrLiteral) -> Stack { [&](auto const& _identifierOrLiteral) -> Stack {
yulAssert(_expectedSlotCount == 1, ""); yulAssert(_expectedSlotCount == 1, "");

View File

@ -57,7 +57,8 @@ private:
AsmAnalysisInfo const& _analysisInfo, AsmAnalysisInfo const& _analysisInfo,
Dialect const& _dialect 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); Stack visitAssignmentRightHandSide(Expression const& _expression, size_t _expectedSlotCount);
Scope::Function const& lookupFunction(YulString _name) const; Scope::Function const& lookupFunction(YulString _name) const;