aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian <c@ethdev.com>2015-01-14 18:57:22 +0800
committerChristian <c@ethdev.com>2015-01-14 18:57:22 +0800
commit1ba38c9c0266ef3bf2229a18dc1953c0a954e182 (patch)
tree88a1150adc400f16576b4a2407e66f11d701e862
parentd1e05ac416c68d65112e9dd1427b8b009802afef (diff)
downloaddexon-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.cpp5
-rw-r--r--CompilerContext.h3
-rw-r--r--ExpressionCompiler.cpp17
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;