Skip to content

Commit ebd584f

Browse files
authored
Merge pull request #12206 from ethereum/extractExternalFunctionPart
Extract external function part
2 parents e0cc2d4 + e9592c3 commit ebd584f

File tree

103 files changed

+1004
-883
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

103 files changed

+1004
-883
lines changed

libsolidity/codegen/ir/Common.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,14 @@ YulArity YulArity::fromType(FunctionType const& _functionType)
4141
};
4242
}
4343

44+
string IRNames::externalFunctionABIWrapper(Declaration const& _functionOrVarDecl)
45+
{
46+
if (auto const* function = dynamic_cast<FunctionDefinition const*>(&_functionOrVarDecl))
47+
solAssert(!function->isConstructor());
48+
49+
return "external_fun_" + _functionOrVarDecl.name() + "_" + to_string(_functionOrVarDecl.id());
50+
}
51+
4452
string IRNames::function(FunctionDefinition const& _function)
4553
{
4654
if (_function.isConstructor())

libsolidity/codegen/ir/Common.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ struct YulArity
4949

5050
struct IRNames
5151
{
52+
static std::string externalFunctionABIWrapper(Declaration const& _functionOrVardecl);
5253
static std::string function(FunctionDefinition const& _function);
5354
static std::string function(VariableDeclaration const& _varDecl);
5455
static std::string modifierInvocation(ModifierInvocation const& _modifierInvocation);

libsolidity/codegen/ir/IRGenerator.cpp

Lines changed: 40 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -735,6 +735,44 @@ string IRGenerator::generateGetter(VariableDeclaration const& _varDecl)
735735
});
736736
}
737737

738+
string IRGenerator::generateExternalFunction(ContractDefinition const& _contract, FunctionType const& _functionType)
739+
{
740+
string functionName = IRNames::externalFunctionABIWrapper(_functionType.declaration());
741+
return m_context.functionCollector().createFunction(functionName, [&](vector<string>&, vector<string>&) -> string {
742+
Whiskers t(R"X(
743+
<callValueCheck>
744+
<?+params>let <params> := </+params> <abiDecode>(4, calldatasize())
745+
<?+retParams>let <retParams> := </+retParams> <function>(<params>)
746+
let memPos := <allocateUnbounded>()
747+
let memEnd := <abiEncode>(memPos <?+retParams>,</+retParams> <retParams>)
748+
return(memPos, sub(memEnd, memPos))
749+
)X");
750+
t("callValueCheck", (_functionType.isPayable() || _contract.isLibrary()) ? "" : callValueCheck());
751+
752+
unsigned paramVars = make_shared<TupleType>(_functionType.parameterTypes())->sizeOnStack();
753+
unsigned retVars = make_shared<TupleType>(_functionType.returnParameterTypes())->sizeOnStack();
754+
755+
ABIFunctions abiFunctions(m_evmVersion, m_context.revertStrings(), m_context.functionCollector());
756+
t("abiDecode", abiFunctions.tupleDecoder(_functionType.parameterTypes()));
757+
t("params", suffixedVariableNameList("param_", 0, paramVars));
758+
t("retParams", suffixedVariableNameList("ret_", 0, retVars));
759+
760+
if (FunctionDefinition const* funDef = dynamic_cast<FunctionDefinition const*>(&_functionType.declaration()))
761+
{
762+
solAssert(!funDef->isConstructor());
763+
t("function", m_context.enqueueFunctionForCodeGeneration(*funDef));
764+
}
765+
else if (VariableDeclaration const* varDecl = dynamic_cast<VariableDeclaration const*>(&_functionType.declaration()))
766+
t("function", generateGetter(*varDecl));
767+
else
768+
solAssert(false, "Unexpected declaration for function!");
769+
770+
t("allocateUnbounded", m_utils.allocateUnboundedFunction());
771+
t("abiEncode", abiFunctions.tupleEncoder(_functionType.returnParameterTypes(), _functionType.returnParameterTypes(), _contract.isLibrary()));
772+
return t.render();
773+
});
774+
}
775+
738776
string IRGenerator::generateInitialAssignment(VariableDeclaration const& _varDecl)
739777
{
740778
IRGeneratorForStatements generator(m_context, m_utils);
@@ -976,12 +1014,7 @@ string IRGenerator::dispatchRoutine(ContractDefinition const& _contract)
9761014
{
9771015
// <functionName>
9781016
<delegatecallCheck>
979-
<callValueCheck>
980-
<?+params>let <params> := </+params> <abiDecode>(4, calldatasize())
981-
<?+retParams>let <retParams> := </+retParams> <function>(<params>)
982-
let memPos := <allocateUnbounded>()
983-
let memEnd := <abiEncode>(memPos <?+retParams>,</+retParams> <retParams>)
984-
return(memPos, sub(memEnd, memPos))
1017+
<externalFunction>()
9851018
}
9861019
</cases>
9871020
default {}
@@ -1011,25 +1044,8 @@ string IRGenerator::dispatchRoutine(ContractDefinition const& _contract)
10111044
"() }";
10121045
}
10131046
templ["delegatecallCheck"] = delegatecallCheck;
1014-
templ["callValueCheck"] = (type->isPayable() || _contract.isLibrary()) ? "" : callValueCheck();
1015-
1016-
unsigned paramVars = make_shared<TupleType>(type->parameterTypes())->sizeOnStack();
1017-
unsigned retVars = make_shared<TupleType>(type->returnParameterTypes())->sizeOnStack();
1018-
1019-
ABIFunctions abiFunctions(m_evmVersion, m_context.revertStrings(), m_context.functionCollector());
1020-
templ["abiDecode"] = abiFunctions.tupleDecoder(type->parameterTypes());
1021-
templ["params"] = suffixedVariableNameList("param_", 0, paramVars);
1022-
templ["retParams"] = suffixedVariableNameList("ret_", 0, retVars);
1023-
1024-
if (FunctionDefinition const* funDef = dynamic_cast<FunctionDefinition const*>(&type->declaration()))
1025-
templ["function"] = m_context.enqueueFunctionForCodeGeneration(*funDef);
1026-
else if (VariableDeclaration const* varDecl = dynamic_cast<VariableDeclaration const*>(&type->declaration()))
1027-
templ["function"] = generateGetter(*varDecl);
1028-
else
1029-
solAssert(false, "Unexpected declaration for function!");
10301047

1031-
templ["allocateUnbounded"] = m_utils.allocateUnboundedFunction();
1032-
templ["abiEncode"] = abiFunctions.tupleEncoder(type->returnParameterTypes(), type->returnParameterTypes(), _contract.isLibrary());
1048+
templ["externalFunction"] = generateExternalFunction(_contract, *type);
10331049
}
10341050
t("cases", functions);
10351051
FunctionDefinition const* etherReceiver = _contract.receiveFunction();

libsolidity/codegen/ir/IRGenerator.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,9 @@ class IRGenerator
102102
/// Generates a getter for the given declaration and returns its name
103103
std::string generateGetter(VariableDeclaration const& _varDecl);
104104

105+
/// Generates the external part (ABI decoding and encoding) of a function or getter.
106+
std::string generateExternalFunction(ContractDefinition const& _contract, FunctionType const& _functionType);
107+
105108
/// Generates code that assigns the initial value of the respective type.
106109
std::string generateInitialAssignment(VariableDeclaration const& _varDecl);
107110

test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_all/output

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -108,12 +108,7 @@ object "C_6" {
108108
{
109109
// f()
110110

111-
if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() }
112-
abi_decode_tuple_(4, calldatasize())
113-
fun_f_5()
114-
let memPos := allocate_unbounded()
115-
let memEnd := abi_encode_tuple__to__fromStack(memPos )
116-
return(memPos, sub(memEnd, memPos))
111+
external_fun_f_5()
117112
}
118113

119114
default {}
@@ -150,6 +145,17 @@ object "C_6" {
150145

151146
}
152147

148+
function external_fun_f_5() {
149+
150+
if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() }
151+
abi_decode_tuple_(4, calldatasize())
152+
fun_f_5()
153+
let memPos := allocate_unbounded()
154+
let memEnd := abi_encode_tuple__to__fromStack(memPos )
155+
return(memPos, sub(memEnd, memPos))
156+
157+
}
158+
153159
function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() {
154160
revert(0, 0)
155161
}

test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_location_only/output

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -108,12 +108,7 @@ object "C_6" {
108108
{
109109
// f()
110110

111-
if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() }
112-
abi_decode_tuple_(4, calldatasize())
113-
fun_f_5()
114-
let memPos := allocate_unbounded()
115-
let memEnd := abi_encode_tuple__to__fromStack(memPos )
116-
return(memPos, sub(memEnd, memPos))
111+
external_fun_f_5()
117112
}
118113

119114
default {}
@@ -150,6 +145,17 @@ object "C_6" {
150145

151146
}
152147

148+
function external_fun_f_5() {
149+
150+
if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() }
151+
abi_decode_tuple_(4, calldatasize())
152+
fun_f_5()
153+
let memPos := allocate_unbounded()
154+
let memEnd := abi_encode_tuple__to__fromStack(memPos )
155+
return(memPos, sub(memEnd, memPos))
156+
157+
}
158+
153159
function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() {
154160
revert(0, 0)
155161
}

test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_none/output

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -101,12 +101,7 @@ object "C_6" {
101101
{
102102
// f()
103103

104-
if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() }
105-
abi_decode_tuple_(4, calldatasize())
106-
fun_f_5()
107-
let memPos := allocate_unbounded()
108-
let memEnd := abi_encode_tuple__to__fromStack(memPos )
109-
return(memPos, sub(memEnd, memPos))
104+
external_fun_f_5()
110105
}
111106

112107
default {}
@@ -143,6 +138,17 @@ object "C_6" {
143138

144139
}
145140

141+
function external_fun_f_5() {
142+
143+
if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() }
144+
abi_decode_tuple_(4, calldatasize())
145+
fun_f_5()
146+
let memPos := allocate_unbounded()
147+
let memEnd := abi_encode_tuple__to__fromStack(memPos )
148+
return(memPos, sub(memEnd, memPos))
149+
150+
}
151+
146152
function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() {
147153
revert(0, 0)
148154
}

test/cmdlineTests/debug_info_in_yul_snippet_escaping/output

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -158,12 +158,7 @@ object "D_27" {
158158
{
159159
// f()
160160

161-
if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() }
162-
abi_decode_tuple_(4, calldatasize())
163-
let ret_0 := fun_f_26()
164-
let memPos := allocate_unbounded()
165-
let memEnd := abi_encode_tuple_t_string_memory_ptr__to_t_string_memory_ptr__fromStack(memPos , ret_0)
166-
return(memPos, sub(memEnd, memPos))
161+
external_fun_f_26()
167162
}
168163

169164
default {}
@@ -238,6 +233,17 @@ object "D_27" {
238233

239234
}
240235

236+
function external_fun_f_26() {
237+
238+
if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() }
239+
abi_decode_tuple_(4, calldatasize())
240+
let ret_0 := fun_f_26()
241+
let memPos := allocate_unbounded()
242+
let memEnd := abi_encode_tuple_t_string_memory_ptr__to_t_string_memory_ptr__fromStack(memPos , ret_0)
243+
return(memPos, sub(memEnd, memPos))
244+
245+
}
246+
241247
function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() {
242248
revert(0, 0)
243249
}
@@ -484,7 +490,7 @@ object "D_27" {
484490
revert(pos, returndatasize())
485491
}
486492
mstore(add(allocate_memory_array_string(), 32), "/*")
487-
let memPtr := allocate_memory_array_string_480()
493+
let memPtr := allocate_memory_array_string_546()
488494
mstore(add(memPtr, 32), 0x2f2a2a204073726320303a39363a313635202022636f6e74726163742044207b)
489495
mstore(add(memPtr, 64), shl(200, 0x2e2e2e22202a2f))
490496
let memPos := mload(64)
@@ -525,7 +531,7 @@ object "D_27" {
525531
memPtr := memPtr_1
526532
mstore(memPtr_1, 2)
527533
}
528-
function allocate_memory_array_string_480() -> memPtr
534+
function allocate_memory_array_string_546() -> memPtr
529535
{
530536
let memPtr_1 := mload(64)
531537
let newFreePtr := add(memPtr_1, 96)

test/cmdlineTests/exp_base_literal/output

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -53,12 +53,7 @@ object "C_81" {
5353
{
5454
// f(uint256,uint256,uint256,uint256)
5555

56-
if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() }
57-
let param_0, param_1, param_2, param_3 := abi_decode_tuple_t_uint256t_uint256t_uint256t_uint256(4, calldatasize())
58-
let ret_0, ret_1, ret_2, ret_3 := fun_f_80(param_0, param_1, param_2, param_3)
59-
let memPos := allocate_unbounded()
60-
let memEnd := abi_encode_tuple_t_uint256_t_int256_t_uint256_t_uint256__to_t_uint256_t_int256_t_uint256_t_uint256__fromStack(memPos , ret_0, ret_1, ret_2, ret_3)
61-
return(memPos, sub(memEnd, memPos))
56+
external_fun_f_80()
6257
}
6358

6459
default {}
@@ -160,6 +155,17 @@ object "C_81" {
160155

161156
}
162157

158+
function external_fun_f_80() {
159+
160+
if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() }
161+
let param_0, param_1, param_2, param_3 := abi_decode_tuple_t_uint256t_uint256t_uint256t_uint256(4, calldatasize())
162+
let ret_0, ret_1, ret_2, ret_3 := fun_f_80(param_0, param_1, param_2, param_3)
163+
let memPos := allocate_unbounded()
164+
let memEnd := abi_encode_tuple_t_uint256_t_int256_t_uint256_t_uint256__to_t_uint256_t_int256_t_uint256_t_uint256__fromStack(memPos , ret_0, ret_1, ret_2, ret_3)
165+
return(memPos, sub(memEnd, memPos))
166+
167+
}
168+
163169
function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() {
164170
revert(0, 0)
165171
}

0 commit comments

Comments
 (0)