diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp index 1c02b281c..3ac5eafe8 100644 --- a/libsolidity/codegen/ExpressionCompiler.cpp +++ b/libsolidity/codegen/ExpressionCompiler.cpp @@ -40,6 +40,11 @@ #include #include + +#include +#include +#include + #include #include @@ -693,36 +698,11 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) break; case FunctionType::Kind::Internal: { - // Calling convention: Caller pushes return address and arguments - // Callee removes them and pushes return values - - evmasm::AssemblyItem returnLabel = m_context.pushNewTag(); - for (unsigned i = 0; i < arguments.size(); ++i) - acceptAndConvert(*arguments[i], *function.parameterTypes()[i]); - _functionCall.expression().accept(*this); - - unsigned parameterSize = CompilerUtils::sizeOnStack(function.parameterTypes()); - if (function.hasBoundFirstArgument()) - { - // stack: arg2, ..., argn, label, arg1 - unsigned depth = parameterSize + 1; - utils().moveIntoStack(depth, function.selfType()->sizeOnStack()); - parameterSize += function.selfType()->sizeOnStack(); - } - - if (m_context.runtimeContext()) - // We have a runtime context, so we need the creation part. - utils().rightShiftNumberOnStack(32); - else - // Extract the runtime part. - m_context << ((u256(1) << 32) - 1) << Instruction::AND; - - m_context.appendJump(evmasm::AssemblyItem::JumpType::IntoFunction); - m_context << returnLabel; - - unsigned returnParametersSize = CompilerUtils::sizeOnStack(function.returnParameterTypes()); - // callee adds return parameters, but removes arguments and return label - m_context.adjustStackOffset(static_cast(returnParametersSize - parameterSize) - 1); + appendInternalFunctionCall( + function, + _functionCall.expression(), + arguments | ranges::views::indirect | ranges::views::addressof | ranges::to() + ); break; } case FunctionType::Kind::BareCall: @@ -2614,6 +2594,46 @@ void ExpressionCompiler::appendExpOperatorCode(Type const& _valueType, Type cons m_context << Instruction::EXP; } +void ExpressionCompiler::appendInternalFunctionCall( + FunctionType const& _functionType, + Expression const& _callExpression, + vector const& _arguments +) +{ + solAssert(_functionType.kind() == FunctionType::Kind::Internal); + + // Calling convention: Caller pushes return address and arguments + // Callee removes them and pushes return values + + evmasm::AssemblyItem returnLabel = m_context.pushNewTag(); + for (unsigned i = 0; i < _arguments.size(); ++i) + acceptAndConvert(*_arguments[i], *_functionType.parameterTypes()[i]); + _callExpression.accept(*this); + + unsigned parameterSize = CompilerUtils::sizeOnStack(_functionType.parameterTypes()); + if (_functionType.hasBoundFirstArgument()) + { + // stack: arg2, ..., argn, label, arg1 + unsigned depth = parameterSize + 1; + utils().moveIntoStack(depth, _functionType.selfType()->sizeOnStack()); + parameterSize += _functionType.selfType()->sizeOnStack(); + } + + if (m_context.runtimeContext()) + // We have a runtime context, so we need the creation part. + utils().rightShiftNumberOnStack(32); + else + // Extract the runtime part. + m_context << ((u256(1) << 32) - 1) << Instruction::AND; + + m_context.appendJump(evmasm::AssemblyItem::JumpType::IntoFunction); + m_context << returnLabel; + + unsigned returnParametersSize = CompilerUtils::sizeOnStack(_functionType.returnParameterTypes()); + // callee adds return parameters, but removes arguments and return label + m_context.adjustStackOffset(static_cast(returnParametersSize - parameterSize) - 1); +} + void ExpressionCompiler::appendExternalFunctionCall( FunctionType const& _functionType, vector> const& _arguments, diff --git a/libsolidity/codegen/ExpressionCompiler.h b/libsolidity/codegen/ExpressionCompiler.h index 13e1e3106..31670a841 100644 --- a/libsolidity/codegen/ExpressionCompiler.h +++ b/libsolidity/codegen/ExpressionCompiler.h @@ -104,6 +104,12 @@ private: void appendExpOperatorCode(Type const& _valueType, Type const& _exponentType); /// @} + /// Appends code to call an internal function of the given type with the given arguments. + void appendInternalFunctionCall( + FunctionType const& _functionType, + Expression const& _callExpression, + std::vector const& _arguments + ); /// Appends code to call a function of the given type with the given arguments. /// @param _tryCall if true, this is the external call of a try statement. In that case, /// returns success flag on top of stack and does not revert on failure.