| 756 | } |
| 757 | |
| 758 | std::string IRGenerator::generateExternalFunction(ContractDefinition const& _contract, FunctionType const& _functionType) |
| 759 | { |
| 760 | std::string functionName = IRNames::externalFunctionABIWrapper(_functionType.declaration()); |
| 761 | return m_context.functionCollector().createFunction(functionName, [&](std::vector<std::string>&, std::vector<std::string>&) -> std::string { |
| 762 | Whiskers t(R"X( |
| 763 | <callValueCheck> |
| 764 | <?+params>let <params> := </+params> <abiDecode>(4, calldatasize()) |
| 765 | <?+retParams>let <retParams> := </+retParams> <function>(<params>) |
| 766 | let memPos := <allocateUnbounded>() |
| 767 | let memEnd := <abiEncode>(memPos <?+retParams>,</+retParams> <retParams>) |
| 768 | return(memPos, sub(memEnd, memPos)) |
| 769 | )X"); |
| 770 | t("callValueCheck", (_functionType.isPayable() || _contract.isLibrary()) ? "" : callValueCheck()); |
| 771 | |
| 772 | unsigned paramVars = std::make_shared<TupleType>(_functionType.parameterTypes())->sizeOnStack(); |
| 773 | unsigned retVars = std::make_shared<TupleType>(_functionType.returnParameterTypes())->sizeOnStack(); |
| 774 | |
| 775 | ABIFunctions abiFunctions(m_evmVersion, m_eofVersion, m_context.revertStrings(), m_context.functionCollector()); |
| 776 | t("abiDecode", abiFunctions.tupleDecoder(_functionType.parameterTypes())); |
| 777 | t("params", suffixedVariableNameList("param_", 0, paramVars)); |
| 778 | t("retParams", suffixedVariableNameList("ret_", 0, retVars)); |
| 779 | |
| 780 | if (FunctionDefinition const* funDef = dynamic_cast<FunctionDefinition const*>(&_functionType.declaration())) |
| 781 | { |
| 782 | solAssert(!funDef->isConstructor()); |
| 783 | t("function", m_context.enqueueFunctionForCodeGeneration(*funDef)); |
| 784 | } |
| 785 | else if (VariableDeclaration const* varDecl = dynamic_cast<VariableDeclaration const*>(&_functionType.declaration())) |
| 786 | t("function", generateGetter(*varDecl)); |
| 787 | else |
| 788 | solAssert(false, "Unexpected declaration for function!"); |
| 789 | |
| 790 | t("allocateUnbounded", m_utils.allocateUnboundedFunction()); |
| 791 | t("abiEncode", abiFunctions.tupleEncoder(_functionType.returnParameterTypes(), _functionType.returnParameterTypes(), _contract.isLibrary())); |
| 792 | return t.render(); |
| 793 | }); |
| 794 | } |
| 795 | |
| 796 | std::string IRGenerator::generateInitialAssignment(VariableDeclaration const& _varDecl) |
| 797 | { |
nothing calls this directly
no test coverage detected