More flexible access to stack during external function call.

This commit is contained in:
Christian 2015-01-14 11:57:22 +01:00
parent d1e05ac416
commit 1ba38c9c02
3 changed files with 20 additions and 5 deletions

View File

@ -95,6 +95,11 @@ unsigned CompilerContext::baseToCurrentStackOffset(unsigned _baseOffset) const
return _baseOffset + m_asm.deposit();
}
unsigned CompilerContext::currentToBaseStackOffset(unsigned _offset) const
{
return -baseToCurrentStackOffset(-_offset);
}
u256 CompilerContext::getStorageLocationOfVariable(const Declaration& _declaration) const
{
auto it = m_stateVariables.find(&_declaration);

View File

@ -62,6 +62,9 @@ public:
/// If supplied by a value returned by @ref getBaseStackOffsetOfVariable(variable), returns
/// the distance of that variable from the current top of the stack.
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;
/// Appends a JUMPI instruction to a new tag and @returns the tag

View File

@ -669,17 +669,24 @@ void ExpressionCompiler::appendExternalFunctionCall(FunctionType const& _functio
// <stack top>
// value [if _functionType.valueSet()]
// gas [if _functionType.gasSet()]
// function identifier [unless options.bare]
// function identifier [unless bare]
// contract address
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)
{
// copy function identifier
m_context << eth::dupInstruction(gasValueSize + 1);
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);
//@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)
m_context << u256(retSize) << u256(0) << u256(dataOffset) << u256(0);
if (_functionType.valueSet())
m_context << eth::dupInstruction(5);
m_context << eth::dupInstruction(m_context.baseToCurrentStackOffset(valueStackPos));
else
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())
m_context << eth::dupInstruction(7 + (_functionType.valueSet() ? 1 : 0));
m_context << eth::dupInstruction(m_context.baseToCurrentStackOffset(gasStackPos));
else
// send all gas except for the 21 needed to execute "SUB" and "CALL"
m_context << u256(21) << eth::Instruction::GAS << eth::Instruction::SUB;