mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
ExpressionCompiler: Extract internal function handling into a separate function
This commit is contained in:
parent
4b92cbb283
commit
da47f25df2
@ -40,6 +40,11 @@
|
|||||||
#include <libsolutil/StackTooDeepString.h>
|
#include <libsolutil/StackTooDeepString.h>
|
||||||
|
|
||||||
#include <boost/algorithm/string/replace.hpp>
|
#include <boost/algorithm/string/replace.hpp>
|
||||||
|
|
||||||
|
#include <range/v3/view/indirect.hpp>
|
||||||
|
#include <range/v3/view/addressof.hpp>
|
||||||
|
#include <range/v3/range/conversion.hpp>
|
||||||
|
|
||||||
#include <numeric>
|
#include <numeric>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
@ -693,36 +698,11 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
|
|||||||
break;
|
break;
|
||||||
case FunctionType::Kind::Internal:
|
case FunctionType::Kind::Internal:
|
||||||
{
|
{
|
||||||
// Calling convention: Caller pushes return address and arguments
|
appendInternalFunctionCall(
|
||||||
// Callee removes them and pushes return values
|
function,
|
||||||
|
_functionCall.expression(),
|
||||||
evmasm::AssemblyItem returnLabel = m_context.pushNewTag();
|
arguments | ranges::views::indirect | ranges::views::addressof | ranges::to<vector>()
|
||||||
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<int>(returnParametersSize - parameterSize) - 1);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case FunctionType::Kind::BareCall:
|
case FunctionType::Kind::BareCall:
|
||||||
@ -2614,6 +2594,46 @@ void ExpressionCompiler::appendExpOperatorCode(Type const& _valueType, Type cons
|
|||||||
m_context << Instruction::EXP;
|
m_context << Instruction::EXP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ExpressionCompiler::appendInternalFunctionCall(
|
||||||
|
FunctionType const& _functionType,
|
||||||
|
Expression const& _callExpression,
|
||||||
|
vector<Expression const*> 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<int>(returnParametersSize - parameterSize) - 1);
|
||||||
|
}
|
||||||
|
|
||||||
void ExpressionCompiler::appendExternalFunctionCall(
|
void ExpressionCompiler::appendExternalFunctionCall(
|
||||||
FunctionType const& _functionType,
|
FunctionType const& _functionType,
|
||||||
vector<ASTPointer<Expression const>> const& _arguments,
|
vector<ASTPointer<Expression const>> const& _arguments,
|
||||||
|
@ -104,6 +104,12 @@ private:
|
|||||||
void appendExpOperatorCode(Type const& _valueType, Type const& _exponentType);
|
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<Expression const*> const& _arguments
|
||||||
|
);
|
||||||
/// Appends code to call a function of the given type with the given 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,
|
/// @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.
|
/// returns success flag on top of stack and does not revert on failure.
|
||||||
|
Loading…
Reference in New Issue
Block a user