Browse Source

More flexible access to stack during external function call.

cl-refactor
Christian 10 years ago
parent
commit
9da6bb3629
  1. 5
      libsolidity/CompilerContext.cpp
  2. 3
      libsolidity/CompilerContext.h
  3. 17
      libsolidity/ExpressionCompiler.cpp

5
libsolidity/CompilerContext.cpp

@ -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);

3
libsolidity/CompilerContext.h

@ -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

17
libsolidity/ExpressionCompiler.cpp

@ -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…
Cancel
Save