mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #12239 from ethereum/preregisterfunction
Preregister functions
This commit is contained in:
commit
7c8ad7a5c1
@ -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, "");
|
||||||
|
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user