aboutsummaryrefslogtreecommitdiffstats
path: root/ExpressionCompiler.cpp
diff options
context:
space:
mode:
authorchriseth <c@ethdev.com>2015-06-05 20:34:10 +0800
committerchriseth <c@ethdev.com>2015-06-05 23:37:16 +0800
commit5a9d01b815de437a287ac749b528a3dab1f98d9a (patch)
tree358f05c8c8f32e42a6e9fe4ce51d01c6e882572d /ExpressionCompiler.cpp
parent6667c6736483b2ff9855b9b9a9147a9703a188d2 (diff)
downloaddexon-solidity-5a9d01b815de437a287ac749b528a3dab1f98d9a.tar.gz
dexon-solidity-5a9d01b815de437a287ac749b528a3dab1f98d9a.tar.zst
dexon-solidity-5a9d01b815de437a287ac749b528a3dab1f98d9a.zip
Bare functions return success condition.
Diffstat (limited to 'ExpressionCompiler.cpp')
-rw-r--r--ExpressionCompiler.cpp35
1 files changed, 24 insertions, 11 deletions
diff --git a/ExpressionCompiler.cpp b/ExpressionCompiler.cpp
index f91839ed..11de7308 100644
--- a/ExpressionCompiler.cpp
+++ b/ExpressionCompiler.cpp
@@ -1058,10 +1058,15 @@ void ExpressionCompiler::appendExternalFunctionCall(
unsigned gasStackPos = m_context.currentToBaseStackOffset(gasValueSize);
unsigned valueStackPos = m_context.currentToBaseStackOffset(1);
+ bool returnSuccessCondition =
+ _functionType.getLocation() == FunctionType::Location::Bare ||
+ _functionType.getLocation() == FunctionType::Location::BareCallCode;
//@todo only return the first return value for now
Type const* firstType = _functionType.getReturnParameterTypes().empty() ? nullptr :
_functionType.getReturnParameterTypes().front().get();
unsigned retSize = firstType ? firstType->getCalldataEncodedSize() : 0;
+ if (returnSuccessCondition)
+ retSize = 0; // return value actually is success condition
m_context << u256(retSize) << u256(0);
if (_functionType.isBareCall())
@@ -1112,19 +1117,27 @@ void ExpressionCompiler::appendExternalFunctionCall(
else
m_context << eth::Instruction::CALL;
- //Propagate error condition (if CALL pushes 0 on stack).
- m_context << eth::Instruction::ISZERO;
- m_context.appendConditionalJumpTo(m_context.errorTag());
+ unsigned remainsSize = 1 + // contract address
+ _functionType.valueSet() +
+ _functionType.gasSet() +
+ !_functionType.isBareCall();
- if (_functionType.valueSet())
- m_context << eth::Instruction::POP;
- if (_functionType.gasSet())
- m_context << eth::Instruction::POP;
- if (!_functionType.isBareCall())
- m_context << eth::Instruction::POP;
- m_context << eth::Instruction::POP; // pop contract address
+ if (returnSuccessCondition)
+ m_context << eth::swapInstruction(remainsSize);
+ else
+ {
+ //Propagate error condition (if CALL pushes 0 on stack).
+ m_context << eth::Instruction::ISZERO;
+ m_context.appendConditionalJumpTo(m_context.errorTag());
+ }
- if (_functionType.getLocation() == FunctionType::Location::RIPEMD160)
+ CompilerUtils(m_context).popStackSlots(remainsSize);
+
+ if (returnSuccessCondition)
+ {
+ // already there
+ }
+ else if (_functionType.getLocation() == FunctionType::Location::RIPEMD160)
{
// fix: built-in contract returns right-aligned data
CompilerUtils(m_context).loadFromMemory(0, IntegerType(160), false, true);