diff --git a/CompilerUtils.cpp b/CompilerUtils.cpp index 511254fa5..454951147 100644 --- a/CompilerUtils.cpp +++ b/CompilerUtils.cpp @@ -157,8 +157,12 @@ void CompilerUtils::copyToStackTop(unsigned _stackDepth, unsigned _itemSize) void CompilerUtils::popStackElement(Type const& _type) { - unsigned const size = _type.getSizeOnStack(); - for (unsigned i = 0; i < size; ++i) + popStackSlots(_type.getSizeOnStack()); +} + +void CompilerUtils::popStackSlots(size_t _amount) +{ + for (size_t i = 0; i < _amount; ++i) m_context << eth::Instruction::POP; } diff --git a/CompilerUtils.h b/CompilerUtils.h index 043de41dd..5b809beac 100644 --- a/CompilerUtils.h +++ b/CompilerUtils.h @@ -79,6 +79,8 @@ public: void copyToStackTop(unsigned _stackDepth, unsigned _itemSize); /// Removes the current value from the top of the stack. void popStackElement(Type const& _type); + /// Removes element from the top of the stack _amount times. + void popStackSlots(size_t _amount); template static unsigned getSizeOnStack(std::vector const& _variables); diff --git a/ExpressionCompiler.cpp b/ExpressionCompiler.cpp index 30cc3c6f8..92fca636e 100644 --- a/ExpressionCompiler.cpp +++ b/ExpressionCompiler.cpp @@ -60,43 +60,37 @@ void ExpressionCompiler::appendStateVariableAccessor(VariableDeclaration const& CompilerContext::LocationSetter locationSetter(m_context, _varDecl); FunctionType accessorType(_varDecl); - unsigned length = 0; TypePointers const& paramTypes = accessorType.getParameterTypes(); - // to exclude the last key if it is an array - TypePointer finalMappingValueType = _varDecl.getType(); - while (finalMappingValueType->getCategory() == Type::Category::Mapping) - finalMappingValueType = dynamic_cast(*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 auto const& location = m_context.getStorageLocationOfVariable(_varDecl); m_context << location.first; TypePointer returnType = _varDecl.getType(); - for (TypePointer const& paramType: mappingKeys) + for (size_t i = 0; i < paramTypes.size(); ++i) { - // 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(*returnType).getValueType(); - } - if (finalMappingValueType->isDynamicallySized()) - { - + if (auto mappingType = dynamic_cast(returnType.get())) + { + // move storage offset to memory. + CompilerUtils(m_context).storeInMemory(32); + //move key to memory. + CompilerUtils(m_context).copyToStackTop(paramTypes.size() - i, 1); + CompilerUtils(m_context).storeInMemory(0); + m_context << u256(64) << u256(0) << eth::Instruction::SHA3; + returnType = mappingType->getValueType(); + } + else if (auto arrayType = dynamic_cast(returnType.get())) + { + CompilerUtils(m_context).copyToStackTop(paramTypes.size() - i + 1, 1); + ArrayUtils(m_context).accessIndex(*arrayType); + returnType = arrayType->getBaseType(); + } + else + solAssert(false, "Index access is allowed only for \"mapping\" and \"array\" types."); } + //remove index arguments. + CompilerUtils(m_context).popStackSlots(paramTypes.size()); unsigned retSizeOnStack = 0; solAssert(accessorType.getReturnParameterTypes().size() >= 1, ""); diff --git a/Types.cpp b/Types.cpp index 9a5b120b6..9ac909daf 100644 --- a/Types.cpp +++ b/Types.cpp @@ -985,11 +985,23 @@ FunctionType::FunctionType(VariableDeclaration const& _varDecl): vector paramNames; auto returnType = _varDecl.getType(); - while (auto mappingType = dynamic_cast(returnType.get())) + while (true) { - params.push_back(mappingType->getKeyType()); - paramNames.push_back(""); - returnType = mappingType->getValueType(); + auto mappingType = dynamic_cast(returnType.get()); + auto arrayType = dynamic_cast(returnType.get()); + if (mappingType) + { + params.push_back(mappingType->getKeyType()); + paramNames.push_back(""); + returnType = mappingType->getValueType(); + } + else if (arrayType) + { + returnType = arrayType->getBaseType(); + params.push_back(make_shared(256)); + } + else + break; } TypePointers retParams; @@ -1002,11 +1014,6 @@ FunctionType::FunctionType(VariableDeclaration const& _varDecl): retParamNames.push_back(member.first); retParams.push_back(member.second); } - } else if (auto arrayType = dynamic_cast(returnType.get())) - { - params.push_back(make_shared(256)); - paramNames.push_back(""); - returnType = arrayType->getBaseType(); } else {