aboutsummaryrefslogtreecommitdiffstats
path: root/ExpressionCompiler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'ExpressionCompiler.cpp')
-rw-r--r--ExpressionCompiler.cpp49
1 files changed, 41 insertions, 8 deletions
diff --git a/ExpressionCompiler.cpp b/ExpressionCompiler.cpp
index 7d58ea2e..45e0e80b 100644
--- a/ExpressionCompiler.cpp
+++ b/ExpressionCompiler.cpp
@@ -22,6 +22,7 @@
#include <utility>
#include <numeric>
+#include <boost/range/adaptor/reversed.hpp>
#include <libdevcore/Common.h>
#include <libdevcrypto/SHA3.h>
#include <libsolidity/AST.h>
@@ -823,26 +824,58 @@ unsigned ExpressionCompiler::appendArgumentCopyToMemory(TypePointers const& _typ
return length;
}
-unsigned ExpressionCompiler::appendExpressionCopyToMemory(Type const& _expectedType,
- Expression const& _expression, unsigned _memoryOffset)
+unsigned ExpressionCompiler::appendTypeConversionAndMoveToMemory(Type const& _expectedType, Type const& _type,
+ Location const& _location, unsigned _memoryOffset)
{
- _expression.accept(*this);
- appendTypeConversion(*_expression.getType(), _expectedType, true);
+ appendTypeConversion(_type, _expectedType, true);
unsigned const c_numBytes = CompilerUtils::getPaddedSize(_expectedType.getCalldataEncodedSize());
if (c_numBytes == 0 || c_numBytes > 32)
BOOST_THROW_EXCEPTION(CompilerError()
- << errinfo_sourceLocation(_expression.getLocation())
+ << errinfo_sourceLocation(_location)
<< errinfo_comment("Type " + _expectedType.toString() + " not yet supported."));
bool const c_leftAligned = _expectedType.getCategory() == Type::Category::STRING;
bool const c_padToWords = true;
return CompilerUtils(m_context).storeInMemory(_memoryOffset, c_numBytes, c_leftAligned, c_padToWords);
}
+unsigned ExpressionCompiler::appendExpressionCopyToMemory(Type const& _expectedType,
+ Expression const& _expression,
+ unsigned _memoryOffset)
+{
+ _expression.accept(*this);
+ return appendTypeConversionAndMoveToMemory(_expectedType, *_expression.getType(), _expression.getLocation(), _memoryOffset);
+}
+
void ExpressionCompiler::appendStateVariableAccessor(VariableDeclaration const& _varDecl)
{
- m_currentLValue.fromStateVariable(_varDecl, _varDecl.getType());
- solAssert(m_currentLValue.isInStorage(), "");
- m_currentLValue.retrieveValue(_varDecl.getType(), Location(), true);
+ FunctionType thisType(_varDecl);
+ solAssert(thisType.getReturnParameterTypes().size() == 1, "");
+ TypePointer const& resultType = thisType.getReturnParameterTypes().front();
+ unsigned sizeOnStack;
+
+ unsigned length = 0;
+ TypePointers const& params = thisType.getParameterTypes();
+ // move arguments to memory
+ for (TypePointer const& param: boost::adaptors::reverse(params))
+ length += appendTypeConversionAndMoveToMemory(*param, *param, Location(), length);
+
+ // retrieve the position of the mapping
+ m_context << m_context.getStorageLocationOfVariable(_varDecl);
+
+ for (TypePointer const& param: params)
+ {
+ // move offset to memory
+ CompilerUtils(m_context).storeInMemory(length);
+ unsigned argLen = CompilerUtils::getPaddedSize(param->getCalldataEncodedSize());
+ length -= argLen;
+ m_context << u256(argLen + 32) << u256(length) << eth::Instruction::SHA3;
+ }
+
+ m_currentLValue = LValue(m_context, LValue::STORAGE, *resultType);
+ m_currentLValue.retrieveValue(resultType, Location(), true);
+ sizeOnStack = resultType->getSizeOnStack();
+ solAssert(sizeOnStack <= 15, "Stack too deep.");
+ m_context << eth::dupInstruction(sizeOnStack + 1) << eth::Instruction::JUMP;
}
ExpressionCompiler::LValue::LValue(CompilerContext& _compilerContext, LValueType _type, Type const& _dataType,