aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CompilerContext.h1
-rw-r--r--ExpressionCompiler.cpp46
-rw-r--r--Types.cpp22
3 files changed, 41 insertions, 28 deletions
diff --git a/CompilerContext.h b/CompilerContext.h
index 87f90d4c..e752d59b 100644
--- a/CompilerContext.h
+++ b/CompilerContext.h
@@ -83,6 +83,7 @@ public:
/// 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;
+ /// @returns pair of slot and byte offset of the value inside this slot.
std::pair<u256, unsigned> 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 59781f82..30cc3c6f 100644
--- a/ExpressionCompiler.cpp
+++ b/ExpressionCompiler.cpp
@@ -62,8 +62,19 @@ void ExpressionCompiler::appendStateVariableAccessor(VariableDeclaration const&
unsigned length = 0;
TypePointers const& paramTypes = accessorType.getParameterTypes();
- // move arguments to memory
- for (TypePointer const& paramType: boost::adaptors::reverse(paramTypes))
+
+ // to exclude the last key if it is an array
+ TypePointer finalMappingValueType = _varDecl.getType();
+ while (finalMappingValueType->getCategory() == Type::Category::Mapping)
+ finalMappingValueType = dynamic_cast<MappingType const&>(*finalMappingValueType).getValueType();
+
+ bool finalIsArrayType = finalMappingValueType->getCategory() == Type::Category::Array;
+ TypePointers mappingKeys(paramTypes);
+ if (finalIsArrayType)
+ mappingKeys.pop_back();
+
+ // move mapping arguments to memory
+ for (TypePointer const& paramType: boost::adaptors::reverse(mappingKeys))
length += CompilerUtils(m_context).storeInMemory(length, *paramType, true);
// retrieve the position of the variable
@@ -71,20 +82,21 @@ void ExpressionCompiler::appendStateVariableAccessor(VariableDeclaration const&
m_context << location.first;
TypePointer returnType = _varDecl.getType();
- if (ArrayType const* arrayType = dynamic_cast<ArrayType const*>(returnType.get()))
+
+ for (TypePointer const& paramType: mappingKeys)
{
- (void)arrayType;
- } else
- for (TypePointer const& paramType: paramTypes)
- {
- // move offset to memory
- CompilerUtils(m_context).storeInMemory(length);
- unsigned argLen = paramType->getCalldataEncodedSize();
- length -= argLen;
- m_context << u256(argLen + 32) << u256(length) << eth::Instruction::SHA3;
+ // move offset to memory
+ CompilerUtils(m_context).storeInMemory(length);
+ unsigned argLen = paramType->getCalldataEncodedSize();
+ length -= argLen;
+ m_context << u256(argLen + 32) << u256(length) << eth::Instruction::SHA3;
- returnType = dynamic_cast<MappingType const&>(*returnType).getValueType();
- }
+ returnType = dynamic_cast<MappingType const&>(*returnType).getValueType();
+ }
+ if (finalMappingValueType->isDynamicallySized())
+ {
+
+ }
unsigned retSizeOnStack = 0;
solAssert(accessorType.getReturnParameterTypes().size() >= 1, "");
@@ -100,7 +112,7 @@ void ExpressionCompiler::appendStateVariableAccessor(VariableDeclaration const&
pair<u256, unsigned> const& offsets = structType->getStorageOffsetsOfMember(names[i]);
m_context << eth::Instruction::DUP1 << u256(offsets.first) << eth::Instruction::ADD << u256(offsets.second);
StorageItem(m_context, *types[i]).retrieveValue(SourceLocation(), true);
- solAssert(types[i]->getSizeOnStack() == 1, "Returning struct elements with stack size != 1 not yet implemented.");
+ solAssert(types[i]->getSizeOnStack() == 1, "Returning struct elements with stack size != 1 is not yet implemented.");
m_context << eth::Instruction::SWAP1;
retSizeOnStack += types[i]->getSizeOnStack();
}
@@ -114,7 +126,7 @@ void ExpressionCompiler::appendStateVariableAccessor(VariableDeclaration const&
StorageItem(m_context, *returnType).retrieveValue(SourceLocation(), true);
retSizeOnStack = returnType->getSizeOnStack();
}
- solAssert(retSizeOnStack <= 15, "Stack too deep.");
+ solAssert(retSizeOnStack <= 15, "Stack is too deep.");
m_context << eth::dupInstruction(retSizeOnStack + 1);
m_context.appendJump(eth::AssemblyItem::JumpType::OutOfFunction);
}
@@ -753,7 +765,7 @@ bool ExpressionCompiler::visit(IndexAccess const& _indexAccess)
appendTypeMoveToMemory(IntegerType(256));
m_context << u256(0) << eth::Instruction::SHA3;
m_context << u256(0);
- setLValueToStorageItem( _indexAccess);
+ setLValueToStorageItem(_indexAccess);
}
else if (baseType.getCategory() == Type::Category::Array)
{
diff --git a/Types.cpp b/Types.cpp
index 0c80a0f7..9a5b120b 100644
--- a/Types.cpp
+++ b/Types.cpp
@@ -1002,17 +1002,17 @@ FunctionType::FunctionType(VariableDeclaration const& _varDecl):
retParamNames.push_back(member.first);
retParams.push_back(member.second);
}
- } else
- if (auto arrayType = dynamic_cast<ArrayType const*>(returnType.get()))
- {
- params.push_back(make_shared<IntegerType>(256));
- paramNames.push_back("");
- returnType = arrayType->getBaseType();
- } else
- {
- retParams.push_back(returnType);
- retParamNames.push_back("");
- }
+ } else if (auto arrayType = dynamic_cast<ArrayType const*>(returnType.get()))
+ {
+ params.push_back(make_shared<IntegerType>(256));
+ paramNames.push_back("");
+ returnType = arrayType->getBaseType();
+ }
+ else
+ {
+ retParams.push_back(returnType);
+ retParamNames.push_back("");
+ }
swap(params, m_parameterTypes);
swap(paramNames, m_parameterNames);