Bare functions return success condition.

This commit is contained in:
chriseth 2015-06-05 14:34:10 +02:00
parent 6667c67364
commit 5a9d01b815
2 changed files with 27 additions and 14 deletions

View File

@ -1058,10 +1058,15 @@ void ExpressionCompiler::appendExternalFunctionCall(
unsigned gasStackPos = m_context.currentToBaseStackOffset(gasValueSize); unsigned gasStackPos = m_context.currentToBaseStackOffset(gasValueSize);
unsigned valueStackPos = m_context.currentToBaseStackOffset(1); 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 //@todo only return the first return value for now
Type const* firstType = _functionType.getReturnParameterTypes().empty() ? nullptr : Type const* firstType = _functionType.getReturnParameterTypes().empty() ? nullptr :
_functionType.getReturnParameterTypes().front().get(); _functionType.getReturnParameterTypes().front().get();
unsigned retSize = firstType ? firstType->getCalldataEncodedSize() : 0; unsigned retSize = firstType ? firstType->getCalldataEncodedSize() : 0;
if (returnSuccessCondition)
retSize = 0; // return value actually is success condition
m_context << u256(retSize) << u256(0); m_context << u256(retSize) << u256(0);
if (_functionType.isBareCall()) if (_functionType.isBareCall())
@ -1112,19 +1117,27 @@ void ExpressionCompiler::appendExternalFunctionCall(
else else
m_context << eth::Instruction::CALL; m_context << eth::Instruction::CALL;
unsigned remainsSize = 1 + // contract address
_functionType.valueSet() +
_functionType.gasSet() +
!_functionType.isBareCall();
if (returnSuccessCondition)
m_context << eth::swapInstruction(remainsSize);
else
{
//Propagate error condition (if CALL pushes 0 on stack). //Propagate error condition (if CALL pushes 0 on stack).
m_context << eth::Instruction::ISZERO; m_context << eth::Instruction::ISZERO;
m_context.appendConditionalJumpTo(m_context.errorTag()); m_context.appendConditionalJumpTo(m_context.errorTag());
}
if (_functionType.valueSet()) CompilerUtils(m_context).popStackSlots(remainsSize);
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 (_functionType.getLocation() == FunctionType::Location::RIPEMD160) if (returnSuccessCondition)
{
// already there
}
else if (_functionType.getLocation() == FunctionType::Location::RIPEMD160)
{ {
// fix: built-in contract returns right-aligned data // fix: built-in contract returns right-aligned data
CompilerUtils(m_context).loadFromMemory(0, IntegerType(160), false, true); CompilerUtils(m_context).loadFromMemory(0, IntegerType(160), false, true);

View File

@ -317,9 +317,9 @@ TypePointer IntegerType::binaryOperatorResult(Token::Value _operator, TypePointe
const MemberList IntegerType::AddressMemberList({ const MemberList IntegerType::AddressMemberList({
{"balance", make_shared<IntegerType >(256)}, {"balance", make_shared<IntegerType >(256)},
{"call", make_shared<FunctionType>(strings(), strings(), FunctionType::Location::Bare, true)}, {"call", make_shared<FunctionType>(strings(), strings{"bool"}, FunctionType::Location::Bare, true)},
{"callcode", make_shared<FunctionType>(strings(), strings(), FunctionType::Location::BareCallCode, true)}, {"callcode", make_shared<FunctionType>(strings(), strings{"bool"}, FunctionType::Location::BareCallCode, true)},
{"send", make_shared<FunctionType>(strings{"uint"}, strings{}, FunctionType::Location::Send)} {"send", make_shared<FunctionType>(strings{"uint"}, strings{"bool"}, FunctionType::Location::Send)}
}); });
IntegerConstantType::IntegerConstantType(Literal const& _literal) IntegerConstantType::IntegerConstantType(Literal const& _literal)