diff options
author | chriseth <c@ethdev.com> | 2015-03-12 01:09:35 +0800 |
---|---|---|
committer | chriseth <c@ethdev.com> | 2015-03-17 01:07:14 +0800 |
commit | fff3f98f58345d45dcf518d7dccbfa0d0a4e67b7 (patch) | |
tree | fd00609ec95fd240a8a41efcd9461b60ea15b142 /ExpressionCompiler.cpp | |
parent | c34e1da6dbc8c66dcdfcb0f09ee0cf8815473124 (diff) | |
download | dexon-solidity-fff3f98f58345d45dcf518d7dccbfa0d0a4e67b7.tar.gz dexon-solidity-fff3f98f58345d45dcf518d7dccbfa0d0a4e67b7.tar.zst dexon-solidity-fff3f98f58345d45dcf518d7dccbfa0d0a4e67b7.zip |
Enlarge storage references to two stack slots.
Diffstat (limited to 'ExpressionCompiler.cpp')
-rw-r--r-- | ExpressionCompiler.cpp | 72 |
1 files changed, 45 insertions, 27 deletions
diff --git a/ExpressionCompiler.cpp b/ExpressionCompiler.cpp index 92fd7043..6f533129 100644 --- a/ExpressionCompiler.cpp +++ b/ExpressionCompiler.cpp @@ -81,6 +81,7 @@ void ExpressionCompiler::appendStateVariableAccessor(VariableDeclaration const& returnType = dynamic_cast<MappingType const&>(*returnType).getValueType(); } + m_context << u256(0); // @todo unsigned retSizeOnStack = 0; solAssert(accessorType.getReturnParameterTypes().size() >= 1, ""); if (StructType const* structType = dynamic_cast<StructType const*>(returnType.get())) @@ -90,15 +91,18 @@ void ExpressionCompiler::appendStateVariableAccessor(VariableDeclaration const& // struct for (size_t i = 0; i < names.size(); ++i) { - m_context << eth::Instruction::DUP1 - << structType->getStorageOffsetOfMember(names[i]) - << eth::Instruction::ADD; + if (types[i]->getCategory() == Type::Category::Mapping) + continue; + m_context + << eth::Instruction::DUP2 << structType->getStorageOffsetOfMember(names[i]) + << eth::Instruction::ADD; + m_context << u256(0); //@todo StorageItem(m_context, *types[i]).retrieveValue(SourceLocation(), true); solAssert(types[i]->getSizeOnStack() == 1, "Returning struct elements with stack size != 1 not yet implemented."); - m_context << eth::Instruction::SWAP1; + m_context << eth::Instruction::SWAP2 << eth::Instruction::SWAP1; retSizeOnStack += types[i]->getSizeOnStack(); } - m_context << eth::Instruction::POP; + m_context << eth::Instruction::POP << eth::Instruction::POP; } else { @@ -280,23 +284,24 @@ bool ExpressionCompiler::visit(UnaryOperation const& _unaryOperation) case Token::Dec: // -- (pre- or postfix) solAssert(!!m_currentLValue, "LValue not retrieved."); m_currentLValue->retrieveValue(_unaryOperation.getLocation()); - solAssert(m_currentLValue->sizeOnStack() <= 1, "Not implemented."); if (!_unaryOperation.isPrefixOperation()) { - if (m_currentLValue->sizeOnStack() == 1) - m_context << eth::Instruction::SWAP1 << eth::Instruction::DUP2; - else - m_context << eth::Instruction::DUP1; + // store value for later + solAssert(_unaryOperation.getType()->getSizeOnStack() == 1, "Stack size != 1 not implemented."); + m_context << eth::Instruction::DUP1; + if (m_currentLValue->sizeOnStack() > 0) + for (unsigned i = 1 + m_currentLValue->sizeOnStack(); i > 0; --i) + m_context << eth::swapInstruction(i); } m_context << u256(1); if (_unaryOperation.getOperator() == Token::Inc) m_context << eth::Instruction::ADD; else - m_context << eth::Instruction::SWAP1 << eth::Instruction::SUB; // @todo avoid the swap - // Stack for prefix: [ref] (*ref)+-1 - // Stack for postfix: *ref [ref] (*ref)+-1 - if (m_currentLValue->sizeOnStack() == 1) - m_context << eth::Instruction::SWAP1; + m_context << eth::Instruction::SWAP1 << eth::Instruction::SUB; + // Stack for prefix: [ref...] (*ref)+-1 + // Stack for postfix: *ref [ref...] (*ref)+-1 + for (unsigned i = m_currentLValue->sizeOnStack(); i > 0; --i) + m_context << eth::swapInstruction(i); m_currentLValue->storeValue( *_unaryOperation.getType(), _unaryOperation.getLocation(), !_unaryOperation.isPrefixOperation()); @@ -661,7 +666,10 @@ void ExpressionCompiler::endVisit(MemberAccess const& _memberAccess) case Type::Category::Struct: { StructType const& type = dynamic_cast<StructType const&>(*_memberAccess.getExpression().getType()); + m_context << eth::Instruction::POP; //@todo m_context << type.getStorageOffsetOfMember(member) << eth::Instruction::ADD; + //@todo + m_context << u256(0); setLValueToStorageItem(_memberAccess); break; } @@ -729,20 +737,22 @@ bool ExpressionCompiler::visit(IndexAccess const& _indexAccess) Type const& baseType = *_indexAccess.getBaseExpression().getType(); if (baseType.getCategory() == Type::Category::Mapping) { + // storage byte offset is ignored for mappings, it should be zero. + m_context << eth::Instruction::POP; + // stack: storage_base_ref Type const& keyType = *dynamic_cast<MappingType const&>(baseType).getKeyType(); - m_context << u256(0); + m_context << u256(0); // memory position solAssert(_indexAccess.getIndexExpression(), "Index expression expected."); appendExpressionCopyToMemory(keyType, *_indexAccess.getIndexExpression()); - solAssert(baseType.getSizeOnStack() == 1, - "Unexpected: Not exactly one stack slot taken by subscriptable expression."); m_context << eth::Instruction::SWAP1; appendTypeMoveToMemory(IntegerType(256)); m_context << u256(0) << eth::Instruction::SHA3; + m_context << u256(0); setLValueToStorageItem( _indexAccess); } else if (baseType.getCategory() == Type::Category::Array) { - // stack layout: <base_ref> [<length>] <index> + // stack layout: <base_ref> [storage_byte_offset] [<length>] <index> ArrayType const& arrayType = dynamic_cast<ArrayType const&>(baseType); solAssert(_indexAccess.getIndexExpression(), "Index expression expected."); ArrayType::Location location = arrayType.getLocation(); @@ -758,9 +768,11 @@ bool ExpressionCompiler::visit(IndexAccess const& _indexAccess) else if (location == ArrayType::Location::CallData) // length is stored on the stack m_context << eth::Instruction::SWAP1; + else if (location == ArrayType::Location::Storage) + m_context << eth::Instruction::DUP3 << load; else m_context << eth::Instruction::DUP2 << load; - // stack: <base_ref> <index> <length> + // stack: <base_ref> [storage_byte_offset] <index> <length> // check out-of-bounds access m_context << eth::Instruction::DUP2 << eth::Instruction::LT; eth::AssemblyItem legalAccess = m_context.appendConditionalJump(); @@ -768,7 +780,7 @@ bool ExpressionCompiler::visit(IndexAccess const& _indexAccess) m_context << eth::Instruction::STOP; m_context << legalAccess; - // stack: <base_ref> <index> + // stack: <base_ref> [storage_byte_offset] <index> if (arrayType.isByteArray()) // byte array is packed differently, especially in storage switch (location) @@ -776,14 +788,15 @@ bool ExpressionCompiler::visit(IndexAccess const& _indexAccess) case ArrayType::Location::Storage: // byte array index storage lvalue on stack (goal): // <ref> <byte_number> = <base_ref + index / 32> <index % 32> - m_context << u256(32) << eth::Instruction::SWAP2; + m_context << u256(32) << eth::Instruction::SWAP3; CompilerUtils(m_context).computeHashStatic(); - // stack: 32 index data_ref + // stack: 32 storage_byte_offset index data_ref m_context - << eth::Instruction::DUP3 << eth::Instruction::DUP3 + << eth::Instruction::DUP4 << eth::Instruction::DUP3 << eth::Instruction::DIV << eth::Instruction::ADD - // stack: 32 index (data_ref + index / 32) - << eth::Instruction::SWAP2 << eth::Instruction::SWAP1 << eth::Instruction::MOD; + // stack: 32 storage_byte_offset index (data_ref + index / 32) + << eth::Instruction::SWAP3 << eth::Instruction::SWAP2 + << eth::Instruction::POP << eth::Instruction::MOD; setLValue<StorageByteArrayElement>(_indexAccess); break; case ArrayType::Location::CallData: @@ -797,6 +810,10 @@ bool ExpressionCompiler::visit(IndexAccess const& _indexAccess) } else { + // stack: <base_ref> [storage_byte_offset] <index> + if (location == ArrayType::Location::Storage) + //@todo use byte offset, remove it for now + m_context << eth::Instruction::SWAP1 << eth::Instruction::POP; u256 elementSize = location == ArrayType::Location::Storage ? arrayType.getBaseType()->getStorageSize() : @@ -822,6 +839,7 @@ bool ExpressionCompiler::visit(IndexAccess const& _indexAccess) CompilerUtils(m_context).loadFromMemoryDynamic(*arrayType.getBaseType(), true, true, false); break; case ArrayType::Location::Storage: + m_context << u256(0); // @todo setLValueToStorageItem(_indexAccess); break; case ArrayType::Location::Memory: @@ -1141,7 +1159,7 @@ void ExpressionCompiler::setLValueFromDeclaration(Declaration const& _declaratio if (m_context.isLocalVariable(&_declaration)) setLValue<StackVariable>(_expression, _declaration); else if (m_context.isStateVariable(&_declaration)) - setLValue<StorageItem>(_expression, _declaration); + setLValue<StorageItem>(_expression, _declaration); else BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_sourceLocation(_expression.getLocation()) |