diff options
author | Christian <c@ethdev.com> | 2015-01-14 18:57:22 +0800 |
---|---|---|
committer | Christian <c@ethdev.com> | 2015-01-14 18:57:22 +0800 |
commit | 1ba38c9c0266ef3bf2229a18dc1953c0a954e182 (patch) | |
tree | 88a1150adc400f16576b4a2407e66f11d701e862 | |
parent | d1e05ac416c68d65112e9dd1427b8b009802afef (diff) | |
download | dexon-solidity-1ba38c9c0266ef3bf2229a18dc1953c0a954e182.tar.gz dexon-solidity-1ba38c9c0266ef3bf2229a18dc1953c0a954e182.tar.zst dexon-solidity-1ba38c9c0266ef3bf2229a18dc1953c0a954e182.zip |
More flexible access to stack during external function call.
-rw-r--r-- | CompilerContext.cpp | 5 | ||||
-rw-r--r-- | CompilerContext.h | 3 | ||||
-rw-r--r-- | ExpressionCompiler.cpp | 17 |
3 files changed, 20 insertions, 5 deletions
diff --git a/CompilerContext.cpp b/CompilerContext.cpp index 5d10a5f9..29e98eab 100644 --- a/CompilerContext.cpp +++ b/CompilerContext.cpp @@ -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); diff --git a/CompilerContext.h b/CompilerContext.h index 14672c95..cf505d65 100644 --- a/CompilerContext.h +++ b/CompilerContext.h @@ -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 diff --git a/ExpressionCompiler.cpp b/ExpressionCompiler.cpp index 93645187..5c81b7c2 100644 --- a/ExpressionCompiler.cpp +++ b/ExpressionCompiler.cpp @@ -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; |