From 4b92cbb283a19d3389a7f66dcd9e05c05369d197 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Tue, 23 Aug 2022 16:16:51 +0200 Subject: [PATCH] IR codegen: Extract code for appending an internal function call into a separate function --- .../codegen/ir/IRGeneratorForStatements.cpp | 93 ++++++++++++------- .../codegen/ir/IRGeneratorForStatements.h | 7 ++ 2 files changed, 65 insertions(+), 35 deletions(-) diff --git a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp index a9eb0bf15..e3eb9ef15 100644 --- a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp +++ b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp @@ -47,7 +47,10 @@ #include #include +#include +#include #include +#include using namespace std; using namespace solidity; @@ -996,42 +999,13 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall) solAssert(false, "Attempted to generate code for calling a function definition."); break; case FunctionType::Kind::Internal: - { - FunctionDefinition const* functionDef = ASTNode::resolveFunctionCall(_functionCall, &m_context.mostDerivedContract()); - - solAssert(!functionType->takesArbitraryParameters()); - - vector args; - if (functionType->hasBoundFirstArgument()) - args += IRVariable(_functionCall.expression()).part("self").stackSlots(); - - for (size_t i = 0; i < arguments.size(); ++i) - args += convert(*arguments[i], *parameterTypes[i]).stackSlots(); - - if (functionDef) - { - solAssert(functionDef->isImplemented()); - - define(_functionCall) << - m_context.enqueueFunctionForCodeGeneration(*functionDef) << - "(" << - joinHumanReadable(args) << - ")\n"; - } - else - { - YulArity arity = YulArity::fromType(*functionType); - m_context.internalFunctionCalledThroughDispatch(arity); - - define(_functionCall) << - IRNames::internalDispatch(arity) << - "(" << - IRVariable(_functionCall.expression()).part("functionIdentifier").name() << - joinHumanReadablePrefixed(args) << - ")\n"; - } + solAssert(functionType); + appendInternalFunctionCall( + _functionCall, + *functionType, + arguments | ranges::views::indirect | ranges::views::addressof | ranges::to + ); break; - } case FunctionType::Kind::External: case FunctionType::Kind::DelegateCall: appendExternalFunctionCall(_functionCall, arguments); @@ -2536,6 +2510,55 @@ void IRGeneratorForStatements::handleVariableReference( solAssert(false, "Invalid variable kind."); } +void IRGeneratorForStatements::appendInternalFunctionCall( + FunctionCall const& _functionCall, + FunctionType const& _functionType, + vector const& _arguments +) +{ + solAssert(!_functionType.takesArbitraryParameters()); + + FunctionDefinition const *functionDefinition = ASTNode::resolveFunctionCall(_functionCall, &m_context.mostDerivedContract()); + Expression const* identifierOrMemberAccess = &_functionCall.expression(); + + vector convertedArguments; + if (_functionType.hasBoundFirstArgument()) + convertedArguments += IRVariable(*identifierOrMemberAccess).part("self").stackSlots(); + + TypePointers parameterTypes = _functionType.parameterTypes(); + for (size_t i = 0; i < _arguments.size(); ++i) + convertedArguments += convert(*_arguments[i], *parameterTypes[i]).stackSlots(); + + if (functionDefinition) + { + solAssert(functionDefinition->isImplemented()); + if (_functionType.hasBoundFirstArgument()) + solAssert(_functionType == *functionDefinition->functionType(true /* _internal */)->withBoundFirstArgument()); + else + solAssert(_functionType == *functionDefinition->functionType(true /* _internal */)); + + define(_functionCall) << + m_context.enqueueFunctionForCodeGeneration(*functionDefinition) << + "(" << + joinHumanReadable(convertedArguments) << + ")\n"; + } + else + { + solAssert(identifierOrMemberAccess); + + YulArity arity = YulArity::fromType(_functionType); + m_context.internalFunctionCalledThroughDispatch(arity); + + define(_functionCall) << + IRNames::internalDispatch(arity) << + "(" << + IRVariable(*identifierOrMemberAccess).part("functionIdentifier").name() << + joinHumanReadablePrefixed(convertedArguments) << + ")\n"; + } +} + void IRGeneratorForStatements::appendExternalFunctionCall( FunctionCall const& _functionCall, vector> const& _arguments diff --git a/libsolidity/codegen/ir/IRGeneratorForStatements.h b/libsolidity/codegen/ir/IRGeneratorForStatements.h index 11f8b3c84..8e278f34a 100644 --- a/libsolidity/codegen/ir/IRGeneratorForStatements.h +++ b/libsolidity/codegen/ir/IRGeneratorForStatements.h @@ -152,6 +152,13 @@ private: Expression const& _referencingExpression ); + /// Appends code to call an internal function with the given arguments. + /// All involved expressions have already been visited. + void appendInternalFunctionCall( + FunctionCall const& _functionCall, + FunctionType const& _functionType, + std::vector const& _arguments + ); /// Appends code to call an external function with the given arguments. /// All involved expressions have already been visited. void appendExternalFunctionCall(