aboutsummaryrefslogtreecommitdiffstats
path: root/ExpressionCompiler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'ExpressionCompiler.cpp')
-rw-r--r--ExpressionCompiler.cpp40
1 files changed, 24 insertions, 16 deletions
diff --git a/ExpressionCompiler.cpp b/ExpressionCompiler.cpp
index a19c9cfd..3beb423d 100644
--- a/ExpressionCompiler.cpp
+++ b/ExpressionCompiler.cpp
@@ -239,14 +239,14 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
BOOST_THROW_EXCEPTION(CompilerError()
<< errinfo_sourceLocation(arguments[i]->getLocation())
<< errinfo_comment("Type " + type.toString() + " not yet supported."));
- if (numBytes != 32)
- m_context << (u256(1) << ((32 - numBytes) * 8)) << eth::Instruction::MUL;
- m_context << u256(dataOffset) << eth::Instruction::MSTORE;
+ bool const leftAligned = type.getCategory() == Type::Category::STRING;
+ CompilerUtils(m_context).storeInMemory(dataOffset, numBytes, leftAligned);
dataOffset += numBytes;
}
//@todo only return the first return value for now
- unsigned retSize = function.getReturnParameterTypes().empty() ? 0
- : function.getReturnParameterTypes().front()->getCalldataEncodedSize();
+ Type const* firstType = function.getReturnParameterTypes().empty() ? nullptr :
+ function.getReturnParameterTypes().front().get();
+ unsigned retSize = firstType ? firstType->getCalldataEncodedSize() : 0;
// CALL arguments: outSize, outOff, inSize, inOff, value, addr, gas (stack top)
m_context << u256(retSize) << u256(0) << u256(dataOffset) << u256(0) << u256(0);
_functionCall.getExpression().accept(*this); // pushes addr and function index
@@ -254,11 +254,11 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
<< u256(25) << eth::Instruction::GAS << eth::Instruction::SUB
<< eth::Instruction::CALL
<< eth::Instruction::POP; // @todo do not ignore failure indicator
- if (retSize == 32)
- m_context << u256(0) << eth::Instruction::MLOAD;
- else if (retSize > 0)
- m_context << (u256(1) << ((32 - retSize) * 8))
- << u256(0) << eth::Instruction::MLOAD << eth::Instruction::DIV;
+ if (retSize > 0)
+ {
+ bool const leftAligned = firstType->getCategory() == Type::Category::STRING;
+ CompilerUtils(m_context).loadFromMemory(0, retSize, leftAligned);
+ }
break;
}
case Location::SEND:
@@ -281,7 +281,8 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
arguments.front()->accept(*this);
appendTypeConversion(*arguments.front()->getType(), *function.getParameterTypes().front(), true);
// @todo move this once we actually use memory
- m_context << u256(0) << eth::Instruction::MSTORE << u256(32) << u256(0) << eth::Instruction::SHA3;
+ CompilerUtils(m_context).storeInMemory(0);
+ m_context << u256(32) << u256(0) << eth::Instruction::SHA3;
break;
case Location::ECRECOVER:
case Location::SHA256:
@@ -297,13 +298,13 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
arguments[i]->accept(*this);
appendTypeConversion(*arguments[i]->getType(), *function.getParameterTypes()[i], true);
// @todo move this once we actually use memory
- m_context << u256(i * 32) << eth::Instruction::MSTORE;
+ CompilerUtils(m_context).storeInMemory(i * 32);
}
m_context << u256(32) << u256(0) << u256(arguments.size() * 32) << u256(0) << u256(0)
<< contractAddress << u256(500) //@todo determine actual gas requirement
<< eth::Instruction::CALL
- << eth::Instruction::POP
- << u256(0) << eth::Instruction::MLOAD;
+ << eth::Instruction::POP;
+ CompilerUtils(m_context).loadFromMemory(0);
break;
}
default:
@@ -387,7 +388,8 @@ bool ExpressionCompiler::visit(IndexAccess const& _indexAccess)
*dynamic_cast<MappingType const&>(*_indexAccess.getBaseExpression().getType()).getKeyType(),
true);
// @todo move this once we actually use memory
- m_context << u256(32) << eth::Instruction::MSTORE << u256(0) << eth::Instruction::MSTORE;
+ CompilerUtils(m_context).storeInMemory(0);
+ CompilerUtils(m_context).storeInMemory(32);
m_context << u256(64) << u256(0) << eth::Instruction::SHA3;
m_currentLValue = LValue(m_context, LValue::STORAGE, *_indexAccess.getType());
@@ -425,10 +427,11 @@ void ExpressionCompiler::endVisit(Literal const& _literal)
{
case Type::Category::INTEGER:
case Type::Category::BOOL:
+ case Type::Category::STRING:
m_context << _literal.getType()->literalValue(_literal);
break;
default:
- BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Only integer and boolean literals implemented for now."));
+ BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Only integer, boolean and string literals implemented for now."));
}
}
@@ -564,6 +567,11 @@ void ExpressionCompiler::appendTypeConversion(Type const& _typeOnStack, Type con
return;
if (_typeOnStack.getCategory() == Type::Category::INTEGER)
appendHighBitsCleanup(dynamic_cast<IntegerType const&>(_typeOnStack));
+ else if (_typeOnStack.getCategory() == Type::Category::STRING)
+ {
+ // nothing to do, strings are high-order-bit-aligned
+ //@todo clear lower-order bytes if we allow explicit conversion to shorter strings
+ }
else if (_typeOnStack != _targetType)
// All other types should not be convertible to non-equal types.
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Invalid type conversion requested."));