mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #8951 from ethereum/sol-yul-refactor-split-internal-dispatch
[Sol->Yul] Split internal dispatch into separate enumeration and code generation (refactor)
This commit is contained in:
commit
29405c223b
@ -53,6 +53,13 @@ string IRNames::runtimeObject(ContractDefinition const& _contract)
|
|||||||
return _contract.name() + "_" + toString(_contract.id()) + "_deployed";
|
return _contract.name() + "_" + toString(_contract.id()) + "_deployed";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string IRNames::internalDispatch(YulArity const& _arity)
|
||||||
|
{
|
||||||
|
return "dispatch_internal"
|
||||||
|
"_in_" + to_string(_arity.in) +
|
||||||
|
"_out_" + to_string(_arity.out);
|
||||||
|
}
|
||||||
|
|
||||||
string IRNames::implicitConstructor(ContractDefinition const& _contract)
|
string IRNames::implicitConstructor(ContractDefinition const& _contract)
|
||||||
{
|
{
|
||||||
return "constructor_" + _contract.name() + "_" + to_string(_contract.id());
|
return "constructor_" + _contract.name() + "_" + to_string(_contract.id());
|
||||||
|
@ -50,6 +50,7 @@ struct IRNames
|
|||||||
static std::string function(VariableDeclaration const& _varDecl);
|
static std::string function(VariableDeclaration const& _varDecl);
|
||||||
static std::string creationObject(ContractDefinition const& _contract);
|
static std::string creationObject(ContractDefinition const& _contract);
|
||||||
static std::string runtimeObject(ContractDefinition const& _contract);
|
static std::string runtimeObject(ContractDefinition const& _contract);
|
||||||
|
static std::string internalDispatch(YulArity const& _arity);
|
||||||
static std::string implicitConstructor(ContractDefinition const& _contract);
|
static std::string implicitConstructor(ContractDefinition const& _contract);
|
||||||
static std::string constantValueFunction(VariableDeclaration const& _constant);
|
static std::string constantValueFunction(VariableDeclaration const& _constant);
|
||||||
static std::string localVariable(VariableDeclaration const& _declaration);
|
static std::string localVariable(VariableDeclaration const& _declaration);
|
||||||
|
@ -121,9 +121,9 @@ string IRGenerationContext::newYulVariable()
|
|||||||
return "_" + to_string(++m_varCounter);
|
return "_" + to_string(++m_varCounter);
|
||||||
}
|
}
|
||||||
|
|
||||||
string IRGenerationContext::internalDispatch(YulArity const& _arity)
|
string IRGenerationContext::generateInternalDispatchFunction(YulArity const& _arity)
|
||||||
{
|
{
|
||||||
string funName = "dispatch_internal_in_" + to_string(_arity.in) + "_out_" + to_string(_arity.out);
|
string funName = IRNames::internalDispatch(_arity);
|
||||||
return m_functions.createFunction(funName, [&]() {
|
return m_functions.createFunction(funName, [&]() {
|
||||||
Whiskers templ(R"(
|
Whiskers templ(R"(
|
||||||
function <functionName>(fun <comma> <in>) <arrow> <out> {
|
function <functionName>(fun <comma> <in>) <arrow> <out> {
|
||||||
@ -139,35 +139,32 @@ string IRGenerationContext::internalDispatch(YulArity const& _arity)
|
|||||||
)");
|
)");
|
||||||
templ("functionName", funName);
|
templ("functionName", funName);
|
||||||
templ("comma", _arity.in > 0 ? "," : "");
|
templ("comma", _arity.in > 0 ? "," : "");
|
||||||
YulUtilFunctions utils(m_evmVersion, m_revertStrings, m_functions);
|
|
||||||
templ("in", suffixedVariableNameList("in_", 0, _arity.in));
|
templ("in", suffixedVariableNameList("in_", 0, _arity.in));
|
||||||
templ("arrow", _arity.out > 0 ? "->" : "");
|
templ("arrow", _arity.out > 0 ? "->" : "");
|
||||||
templ("assignment_op", _arity.out > 0 ? ":=" : "");
|
templ("assignment_op", _arity.out > 0 ? ":=" : "");
|
||||||
templ("out", suffixedVariableNameList("out_", 0, _arity.out));
|
templ("out", suffixedVariableNameList("out_", 0, _arity.out));
|
||||||
|
|
||||||
// UNIMPLEMENTED: Internal library calls via pointers are not implemented yet.
|
vector<map<string, string>> cases;
|
||||||
// We're not generating code for internal library functions here even though it's possible
|
for (FunctionDefinition const* function: collectFunctionsOfArity(_arity))
|
||||||
// to call them via pointers. Right now such calls end up triggering the `default` case in
|
{
|
||||||
// the switch above.
|
solAssert(function, "");
|
||||||
vector<map<string, string>> functions;
|
solAssert(
|
||||||
for (auto const& contract: mostDerivedContract().annotation().linearizedBaseContracts)
|
YulArity::fromType(*TypeProvider::function(*function, FunctionType::Kind::Internal)) == _arity,
|
||||||
for (FunctionDefinition const* function: contract->definedFunctions())
|
"A single dispatch function can only handle functions of one arity"
|
||||||
if (
|
);
|
||||||
!function->isConstructor() &&
|
solAssert(!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");
|
||||||
{
|
|
||||||
// 0 is reserved for uninitialized function pointers
|
|
||||||
solAssert(function->id() != 0, "Unexpected function ID: 0");
|
|
||||||
|
|
||||||
functions.emplace_back(map<string, string> {
|
cases.emplace_back(map<string, string>{
|
||||||
{ "funID", to_string(function->id()) },
|
{"funID", to_string(function->id())},
|
||||||
{ "name", IRNames::function(*function)}
|
{"name", IRNames::function(*function)}
|
||||||
});
|
});
|
||||||
|
|
||||||
enqueueFunctionForCodeGeneration(*function);
|
enqueueFunctionForCodeGeneration(*function);
|
||||||
}
|
}
|
||||||
templ("cases", move(functions));
|
|
||||||
|
templ("cases", move(cases));
|
||||||
return templ.render();
|
return templ.render();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -187,3 +184,20 @@ std::string IRGenerationContext::revertReasonIfDebug(std::string const& _message
|
|||||||
return YulUtilFunctions::revertReasonIfDebug(m_revertStrings, _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;
|
||||||
|
}
|
||||||
|
@ -102,7 +102,7 @@ public:
|
|||||||
|
|
||||||
std::string newYulVariable();
|
std::string newYulVariable();
|
||||||
|
|
||||||
std::string internalDispatch(YulArity const& _arity);
|
std::string generateInternalDispatchFunction(YulArity const& _arity);
|
||||||
|
|
||||||
/// @returns a new copy of the utility function generator (but using the same function set).
|
/// @returns a new copy of the utility function generator (but using the same function set).
|
||||||
YulUtilFunctions utils();
|
YulUtilFunctions utils();
|
||||||
@ -120,6 +120,8 @@ public:
|
|||||||
std::set<ContractDefinition const*, ASTNode::CompareByID>& subObjectsCreated() { return m_subObjects; }
|
std::set<ContractDefinition const*, ASTNode::CompareByID>& subObjectsCreated() { return m_subObjects; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
std::set<FunctionDefinition const*> collectFunctionsOfArity(YulArity const& _arity);
|
||||||
|
|
||||||
langutil::EVMVersion m_evmVersion;
|
langutil::EVMVersion m_evmVersion;
|
||||||
RevertStrings m_revertStrings;
|
RevertStrings m_revertStrings;
|
||||||
OptimiserSettings m_optimiserSettings;
|
OptimiserSettings m_optimiserSettings;
|
||||||
|
@ -695,8 +695,8 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
|
|||||||
{
|
{
|
||||||
YulArity arity = YulArity::fromType(*functionType);
|
YulArity arity = YulArity::fromType(*functionType);
|
||||||
define(_functionCall) <<
|
define(_functionCall) <<
|
||||||
// NOTE: internalDispatch() takes care of adding the function to function generation queue
|
// NOTE: generateInternalDispatchFunction() takes care of adding the function to function generation queue
|
||||||
m_context.internalDispatch(arity) <<
|
m_context.generateInternalDispatchFunction(arity) <<
|
||||||
"(" <<
|
"(" <<
|
||||||
IRVariable(_functionCall.expression()).part("functionIdentifier").name() <<
|
IRVariable(_functionCall.expression()).part("functionIdentifier").name() <<
|
||||||
joinHumanReadablePrefixed(args) <<
|
joinHumanReadablePrefixed(args) <<
|
||||||
|
Loading…
Reference in New Issue
Block a user