mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
More flexible access to stack during external function call.
This commit is contained in:
parent
d1e05ac416
commit
1ba38c9c02
@ -95,6 +95,11 @@ unsigned CompilerContext::baseToCurrentStackOffset(unsigned _baseOffset) const
|
|||||||
return _baseOffset + m_asm.deposit();
|
return _baseOffset + m_asm.deposit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned CompilerContext::currentToBaseStackOffset(unsigned _offset) const
|
||||||
|
{
|
||||||
|
return -baseToCurrentStackOffset(-_offset);
|
||||||
|
}
|
||||||
|
|
||||||
u256 CompilerContext::getStorageLocationOfVariable(const Declaration& _declaration) const
|
u256 CompilerContext::getStorageLocationOfVariable(const Declaration& _declaration) const
|
||||||
{
|
{
|
||||||
auto it = m_stateVariables.find(&_declaration);
|
auto it = m_stateVariables.find(&_declaration);
|
||||||
|
@ -62,6 +62,9 @@ public:
|
|||||||
/// If supplied by a value returned by @ref getBaseStackOffsetOfVariable(variable), returns
|
/// If supplied by a value returned by @ref getBaseStackOffsetOfVariable(variable), returns
|
||||||
/// the distance of that variable from the current top of the stack.
|
/// the distance of that variable from the current top of the stack.
|
||||||
unsigned baseToCurrentStackOffset(unsigned _baseOffset) const;
|
unsigned baseToCurrentStackOffset(unsigned _baseOffset) const;
|
||||||
|
/// Converts an offset relative to the current stack height to a value that can be used later
|
||||||
|
/// with baseToCurrentStackOffset to point to the same stack element.
|
||||||
|
unsigned currentToBaseStackOffset(unsigned _offset) const;
|
||||||
u256 getStorageLocationOfVariable(Declaration const& _declaration) const;
|
u256 getStorageLocationOfVariable(Declaration const& _declaration) const;
|
||||||
|
|
||||||
/// Appends a JUMPI instruction to a new tag and @returns the tag
|
/// Appends a JUMPI instruction to a new tag and @returns the tag
|
||||||
|
@ -669,17 +669,24 @@ void ExpressionCompiler::appendExternalFunctionCall(FunctionType const& _functio
|
|||||||
// <stack top>
|
// <stack top>
|
||||||
// value [if _functionType.valueSet()]
|
// value [if _functionType.valueSet()]
|
||||||
// gas [if _functionType.gasSet()]
|
// gas [if _functionType.gasSet()]
|
||||||
// function identifier [unless options.bare]
|
// function identifier [unless bare]
|
||||||
// contract address
|
// contract address
|
||||||
|
|
||||||
unsigned gasValueSize = (_functionType.gasSet() ? 1 : 0) + (_functionType.valueSet() ? 1 : 0);
|
unsigned gasValueSize = (_functionType.gasSet() ? 1 : 0) + (_functionType.valueSet() ? 1 : 0);
|
||||||
|
|
||||||
|
unsigned contractStackPos = m_context.currentToBaseStackOffset(1 + gasValueSize + (bare ? 0 : 1));
|
||||||
|
unsigned gasStackPos = m_context.currentToBaseStackOffset(gasValueSize);
|
||||||
|
unsigned valueStackPos = m_context.currentToBaseStackOffset(1);
|
||||||
|
|
||||||
if (!bare)
|
if (!bare)
|
||||||
{
|
{
|
||||||
|
// copy function identifier
|
||||||
m_context << eth::dupInstruction(gasValueSize + 1);
|
m_context << eth::dupInstruction(gasValueSize + 1);
|
||||||
CompilerUtils(m_context).storeInMemory(0, CompilerUtils::dataStartOffset);
|
CompilerUtils(m_context).storeInMemory(0, CompilerUtils::dataStartOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned dataOffset = bare ? 0 : CompilerUtils::dataStartOffset; // reserve 4 bytes for the function's hash identifier
|
// reserve space for the function identifier
|
||||||
|
unsigned dataOffset = bare ? 0 : CompilerUtils::dataStartOffset;
|
||||||
dataOffset += appendArgumentCopyToMemory(_functionType.getParameterTypes(), _arguments, dataOffset);
|
dataOffset += appendArgumentCopyToMemory(_functionType.getParameterTypes(), _arguments, dataOffset);
|
||||||
|
|
||||||
//@todo only return the first return value for now
|
//@todo only return the first return value for now
|
||||||
@ -689,13 +696,13 @@ void ExpressionCompiler::appendExternalFunctionCall(FunctionType const& _functio
|
|||||||
// CALL arguments: outSize, outOff, inSize, inOff, value, addr, gas (stack top)
|
// CALL arguments: outSize, outOff, inSize, inOff, value, addr, gas (stack top)
|
||||||
m_context << u256(retSize) << u256(0) << u256(dataOffset) << u256(0);
|
m_context << u256(retSize) << u256(0) << u256(dataOffset) << u256(0);
|
||||||
if (_functionType.valueSet())
|
if (_functionType.valueSet())
|
||||||
m_context << eth::dupInstruction(5);
|
m_context << eth::dupInstruction(m_context.baseToCurrentStackOffset(valueStackPos));
|
||||||
else
|
else
|
||||||
m_context << u256(0);
|
m_context << u256(0);
|
||||||
m_context << eth::dupInstruction(6 + gasValueSize + (bare ? 0 : 1)); //copy contract address
|
m_context << eth::dupInstruction(m_context.baseToCurrentStackOffset(contractStackPos));
|
||||||
|
|
||||||
if (_functionType.gasSet())
|
if (_functionType.gasSet())
|
||||||
m_context << eth::dupInstruction(7 + (_functionType.valueSet() ? 1 : 0));
|
m_context << eth::dupInstruction(m_context.baseToCurrentStackOffset(gasStackPos));
|
||||||
else
|
else
|
||||||
// send all gas except for the 21 needed to execute "SUB" and "CALL"
|
// send all gas except for the 21 needed to execute "SUB" and "CALL"
|
||||||
m_context << u256(21) << eth::Instruction::GAS << eth::Instruction::SUB;
|
m_context << u256(21) << eth::Instruction::GAS << eth::Instruction::SUB;
|
||||||
|
Loading…
Reference in New Issue
Block a user