@@ -735,6 +735,44 @@ string IRGenerator::generateGetter(VariableDeclaration const& _varDecl)
735
735
});
736
736
}
737
737
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
+
738
776
string IRGenerator::generateInitialAssignment (VariableDeclaration const & _varDecl)
739
777
{
740
778
IRGeneratorForStatements generator (m_context, m_utils);
@@ -976,12 +1014,7 @@ string IRGenerator::dispatchRoutine(ContractDefinition const& _contract)
976
1014
{
977
1015
// <functionName>
978
1016
<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>()
985
1018
}
986
1019
</cases>
987
1020
default {}
@@ -1011,25 +1044,8 @@ string IRGenerator::dispatchRoutine(ContractDefinition const& _contract)
1011
1044
" () }" ;
1012
1045
}
1013
1046
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!" );
1030
1047
1031
- templ[" allocateUnbounded" ] = m_utils.allocateUnboundedFunction ();
1032
- templ[" abiEncode" ] = abiFunctions.tupleEncoder (type->returnParameterTypes (), type->returnParameterTypes (), _contract.isLibrary ());
1048
+ templ[" externalFunction" ] = generateExternalFunction (_contract, *type);
1033
1049
}
1034
1050
t (" cases" , functions);
1035
1051
FunctionDefinition const * etherReceiver = _contract.receiveFunction ();
0 commit comments