IRGenerationContext: Extract code for enumerating dispatchable functions from generateInternalDispatch() into a separate function

This commit is contained in:
Kamil Śliwak 2020-05-14 20:34:59 +02:00
parent bd75543900
commit 6c6a8a74e8
2 changed files with 38 additions and 21 deletions

View File

@ -144,29 +144,27 @@ string IRGenerationContext::generateInternalDispatchFunction(YulArity const& _ar
templ("assignment_op", _arity.out > 0 ? ":=" : "");
templ("out", suffixedVariableNameList("out_", 0, _arity.out));
// UNIMPLEMENTED: Internal library calls via pointers are not implemented yet.
// We're not generating code for internal library functions here even though it's possible
// to call them via pointers. Right now such calls end up triggering the `default` case in
// the switch above.
vector<map<string, string>> functions;
for (auto const& contract: mostDerivedContract().annotation().linearizedBaseContracts)
for (FunctionDefinition const* function: contract->definedFunctions())
if (
!function->isConstructor() &&
YulArity::fromType(*TypeProvider::function(*function, FunctionType::Kind::Internal)) == _arity
)
{
// 0 is reserved for uninitialized function pointers
solAssert(function->id() != 0, "Unexpected function ID: 0");
vector<map<string, string>> cases;
for (FunctionDefinition const* function: collectFunctionsOfArity(_arity))
{
solAssert(function, "");
solAssert(
YulArity::fromType(*TypeProvider::function(*function, FunctionType::Kind::Internal)) == _arity,
"A single dispatch function can only handle functions of one arity"
);
solAssert(!function->isConstructor(), "");
// 0 is reserved for uninitialized function pointers
solAssert(function->id() != 0, "Unexpected function ID: 0");
functions.emplace_back(map<string, string> {
{ "funID", to_string(function->id()) },
{ "name", IRNames::function(*function)}
});
cases.emplace_back(map<string, string>{
{"funID", to_string(function->id())},
{"name", IRNames::function(*function)}
});
enqueueFunctionForCodeGeneration(*function);
}
templ("cases", move(functions));
enqueueFunctionForCodeGeneration(*function);
}
templ("cases", move(cases));
return templ.render();
});
}
@ -186,3 +184,20 @@ std::string IRGenerationContext::revertReasonIfDebug(std::string const& _message
return YulUtilFunctions::revertReasonIfDebug(m_revertStrings, _message);
}
set<FunctionDefinition const*> IRGenerationContext::collectFunctionsOfArity(YulArity const& _arity)
{
// UNIMPLEMENTED: Internal library calls via pointers are not implemented yet.
// We're not returning any internal library functions here even though it's possible
// to call them via pointers. Right now such calls end will up triggering the `default` case in
// the switch in the generated dispatch function.
set<FunctionDefinition const*> functions;
for (auto const& contract: mostDerivedContract().annotation().linearizedBaseContracts)
for (FunctionDefinition const* function: contract->definedFunctions())
if (
!function->isConstructor() &&
YulArity::fromType(*TypeProvider::function(*function, FunctionType::Kind::Internal)) == _arity
)
functions.insert(function);
return functions;
}

View File

@ -120,6 +120,8 @@ public:
std::set<ContractDefinition const*, ASTNode::CompareByID>& subObjectsCreated() { return m_subObjects; }
private:
std::set<FunctionDefinition const*> collectFunctionsOfArity(YulArity const& _arity);
langutil::EVMVersion m_evmVersion;
RevertStrings m_revertStrings;
OptimiserSettings m_optimiserSettings;