mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Extract external function part into its own function.
This commit is contained in:
parent
daad9a42c1
commit
106921c278
@ -41,6 +41,14 @@ YulArity YulArity::fromType(FunctionType const& _functionType)
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string IRNames::externalFunctionABIWrapper(Declaration const& _functionOrVarDecl)
|
||||||
|
{
|
||||||
|
if (auto const* function = dynamic_cast<FunctionDefinition const*>(&_functionOrVarDecl))
|
||||||
|
solAssert(!function->isConstructor());
|
||||||
|
|
||||||
|
return "external_fun_" + _functionOrVarDecl.name() + "_" + to_string(_functionOrVarDecl.id());
|
||||||
|
}
|
||||||
|
|
||||||
string IRNames::function(FunctionDefinition const& _function)
|
string IRNames::function(FunctionDefinition const& _function)
|
||||||
{
|
{
|
||||||
if (_function.isConstructor())
|
if (_function.isConstructor())
|
||||||
|
@ -49,6 +49,7 @@ struct YulArity
|
|||||||
|
|
||||||
struct IRNames
|
struct IRNames
|
||||||
{
|
{
|
||||||
|
static std::string externalFunctionABIWrapper(Declaration const& _functionOrVardecl);
|
||||||
static std::string function(FunctionDefinition const& _function);
|
static std::string function(FunctionDefinition const& _function);
|
||||||
static std::string function(VariableDeclaration const& _varDecl);
|
static std::string function(VariableDeclaration const& _varDecl);
|
||||||
static std::string modifierInvocation(ModifierInvocation const& _modifierInvocation);
|
static std::string modifierInvocation(ModifierInvocation const& _modifierInvocation);
|
||||||
|
@ -735,6 +735,44 @@ string IRGenerator::generateGetter(VariableDeclaration const& _varDecl)
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string IRGenerator::generateExternalFunction(ContractDefinition const& _contract, FunctionType const& _functionType)
|
||||||
|
{
|
||||||
|
string functionName = IRNames::externalFunctionABIWrapper(_functionType.declaration());
|
||||||
|
return m_context.functionCollector().createFunction(functionName, [&](vector<string>&, vector<string>&) -> string {
|
||||||
|
Whiskers t(R"X(
|
||||||
|
<callValueCheck>
|
||||||
|
<?+params>let <params> := </+params> <abiDecode>(4, calldatasize())
|
||||||
|
<?+retParams>let <retParams> := </+retParams> <function>(<params>)
|
||||||
|
let memPos := <allocateUnbounded>()
|
||||||
|
let memEnd := <abiEncode>(memPos <?+retParams>,</+retParams> <retParams>)
|
||||||
|
return(memPos, sub(memEnd, memPos))
|
||||||
|
)X");
|
||||||
|
t("callValueCheck", (_functionType.isPayable() || _contract.isLibrary()) ? "" : callValueCheck());
|
||||||
|
|
||||||
|
unsigned paramVars = make_shared<TupleType>(_functionType.parameterTypes())->sizeOnStack();
|
||||||
|
unsigned retVars = make_shared<TupleType>(_functionType.returnParameterTypes())->sizeOnStack();
|
||||||
|
|
||||||
|
ABIFunctions abiFunctions(m_evmVersion, m_context.revertStrings(), m_context.functionCollector());
|
||||||
|
t("abiDecode", abiFunctions.tupleDecoder(_functionType.parameterTypes()));
|
||||||
|
t("params", suffixedVariableNameList("param_", 0, paramVars));
|
||||||
|
t("retParams", suffixedVariableNameList("ret_", 0, retVars));
|
||||||
|
|
||||||
|
if (FunctionDefinition const* funDef = dynamic_cast<FunctionDefinition const*>(&_functionType.declaration()))
|
||||||
|
{
|
||||||
|
solAssert(!funDef->isConstructor());
|
||||||
|
t("function", m_context.enqueueFunctionForCodeGeneration(*funDef));
|
||||||
|
}
|
||||||
|
else if (VariableDeclaration const* varDecl = dynamic_cast<VariableDeclaration const*>(&_functionType.declaration()))
|
||||||
|
t("function", generateGetter(*varDecl));
|
||||||
|
else
|
||||||
|
solAssert(false, "Unexpected declaration for function!");
|
||||||
|
|
||||||
|
t("allocateUnbounded", m_utils.allocateUnboundedFunction());
|
||||||
|
t("abiEncode", abiFunctions.tupleEncoder(_functionType.returnParameterTypes(), _functionType.returnParameterTypes(), _contract.isLibrary()));
|
||||||
|
return t.render();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
string IRGenerator::generateInitialAssignment(VariableDeclaration const& _varDecl)
|
string IRGenerator::generateInitialAssignment(VariableDeclaration const& _varDecl)
|
||||||
{
|
{
|
||||||
IRGeneratorForStatements generator(m_context, m_utils);
|
IRGeneratorForStatements generator(m_context, m_utils);
|
||||||
@ -976,12 +1014,7 @@ string IRGenerator::dispatchRoutine(ContractDefinition const& _contract)
|
|||||||
{
|
{
|
||||||
// <functionName>
|
// <functionName>
|
||||||
<delegatecallCheck>
|
<delegatecallCheck>
|
||||||
<callValueCheck>
|
<externalFunction>()
|
||||||
<?+params>let <params> := </+params> <abiDecode>(4, calldatasize())
|
|
||||||
<?+retParams>let <retParams> := </+retParams> <function>(<params>)
|
|
||||||
let memPos := <allocateUnbounded>()
|
|
||||||
let memEnd := <abiEncode>(memPos <?+retParams>,</+retParams> <retParams>)
|
|
||||||
return(memPos, sub(memEnd, memPos))
|
|
||||||
}
|
}
|
||||||
</cases>
|
</cases>
|
||||||
default {}
|
default {}
|
||||||
@ -1011,25 +1044,8 @@ string IRGenerator::dispatchRoutine(ContractDefinition const& _contract)
|
|||||||
"() }";
|
"() }";
|
||||||
}
|
}
|
||||||
templ["delegatecallCheck"] = delegatecallCheck;
|
templ["delegatecallCheck"] = delegatecallCheck;
|
||||||
templ["callValueCheck"] = (type->isPayable() || _contract.isLibrary()) ? "" : callValueCheck();
|
|
||||||
|
|
||||||
unsigned paramVars = make_shared<TupleType>(type->parameterTypes())->sizeOnStack();
|
templ["externalFunction"] = generateExternalFunction(_contract, *type);
|
||||||
unsigned retVars = make_shared<TupleType>(type->returnParameterTypes())->sizeOnStack();
|
|
||||||
|
|
||||||
ABIFunctions abiFunctions(m_evmVersion, m_context.revertStrings(), m_context.functionCollector());
|
|
||||||
templ["abiDecode"] = abiFunctions.tupleDecoder(type->parameterTypes());
|
|
||||||
templ["params"] = suffixedVariableNameList("param_", 0, paramVars);
|
|
||||||
templ["retParams"] = suffixedVariableNameList("ret_", 0, retVars);
|
|
||||||
|
|
||||||
if (FunctionDefinition const* funDef = dynamic_cast<FunctionDefinition const*>(&type->declaration()))
|
|
||||||
templ["function"] = m_context.enqueueFunctionForCodeGeneration(*funDef);
|
|
||||||
else if (VariableDeclaration const* varDecl = dynamic_cast<VariableDeclaration const*>(&type->declaration()))
|
|
||||||
templ["function"] = generateGetter(*varDecl);
|
|
||||||
else
|
|
||||||
solAssert(false, "Unexpected declaration for function!");
|
|
||||||
|
|
||||||
templ["allocateUnbounded"] = m_utils.allocateUnboundedFunction();
|
|
||||||
templ["abiEncode"] = abiFunctions.tupleEncoder(type->returnParameterTypes(), type->returnParameterTypes(), _contract.isLibrary());
|
|
||||||
}
|
}
|
||||||
t("cases", functions);
|
t("cases", functions);
|
||||||
FunctionDefinition const* etherReceiver = _contract.receiveFunction();
|
FunctionDefinition const* etherReceiver = _contract.receiveFunction();
|
||||||
|
@ -102,6 +102,9 @@ private:
|
|||||||
/// Generates a getter for the given declaration and returns its name
|
/// Generates a getter for the given declaration and returns its name
|
||||||
std::string generateGetter(VariableDeclaration const& _varDecl);
|
std::string generateGetter(VariableDeclaration const& _varDecl);
|
||||||
|
|
||||||
|
/// Generates the external part (ABI decoding and encoding) of a function or getter.
|
||||||
|
std::string generateExternalFunction(ContractDefinition const& _contract, FunctionType const& _functionType);
|
||||||
|
|
||||||
/// Generates code that assigns the initial value of the respective type.
|
/// Generates code that assigns the initial value of the respective type.
|
||||||
std::string generateInitialAssignment(VariableDeclaration const& _varDecl);
|
std::string generateInitialAssignment(VariableDeclaration const& _varDecl);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user