diff options
Diffstat (limited to 'LValue.cpp')
-rw-r--r-- | LValue.cpp | 59 |
1 files changed, 58 insertions, 1 deletions
@@ -232,6 +232,64 @@ void StorageItem::setToZero(SourceLocation const&, bool _removeReference) const } } +/// Used in StorageByteArrayElement +static IntegerType byteType(8, IntegerType::Modifier::Hash); + +StorageByteArrayElement::StorageByteArrayElement(CompilerContext& _compilerContext): + LValue(_compilerContext, byteType) +{ +} + +void StorageByteArrayElement::retrieveValue(SourceLocation const&, bool _remove) const +{ + // stack: ref bytenr + if (_remove) + m_context << eth::Instruction::SWAP1 << eth::Instruction::SLOAD + << eth::Instruction::SWAP1 << eth::Instruction::BYTE; + else + m_context << eth::Instruction::DUP2 << eth::Instruction::SLOAD + << eth::Instruction::DUP2 << eth::Instruction::BYTE; +} + +void StorageByteArrayElement::storeValue(Type const&, SourceLocation const&, bool _move) const +{ + //@todo optimize this + + // stack: value ref bytenr + m_context << u256(31) << eth::Instruction::SUB << u256(0x100) << eth::Instruction::EXP; + // stack: value ref (1<<(8*(31-bytenr))) + m_context << eth::Instruction::DUP2 << eth::Instruction::SLOAD; + // stack: value ref (1<<(8*(31-bytenr))) old_full_value + // clear byte in old value + m_context << eth::Instruction::DUP2 << u256(0xff) << eth::Instruction::MUL + << eth::Instruction::NOT << eth::Instruction::AND; + // stack: value ref (1<<(32-bytenr)) old_full_value_with_cleared_byte + m_context << eth::Instruction::SWAP1 << eth::Instruction::DUP4 << eth::Instruction::MUL + << eth::Instruction::OR; + // stack: value ref new_full_value + m_context << eth::Instruction::SWAP1 << eth::Instruction::SSTORE; + if (_move) + m_context << eth::Instruction::POP; +} + +void StorageByteArrayElement::setToZero(SourceLocation const&, bool _removeReference) const +{ + // stack: ref bytenr + if (!_removeReference) + m_context << eth::Instruction::SWAP1 << eth::Instruction::DUP2; + m_context << u256(31) << eth::Instruction::SUB << u256(0x100) << eth::Instruction::EXP; + // stack: ref (1<<(8*(31-bytenr))) + m_context << eth::Instruction::DUP2 << eth::Instruction::SLOAD; + // stack: ref (1<<(8*(31-bytenr))) old_full_value + // clear byte in old value + m_context << eth::Instruction::SWAP1 << u256(0xff) << eth::Instruction::MUL << eth::Instruction::AND; + // stack: ref old_full_value_with_cleared_byte + m_context << eth::Instruction::SWAP1 << eth::Instruction::SSTORE; + if (!_removeReference) + m_context << eth::Instruction::SWAP1; + else + m_context << eth::Instruction::POP; +} StorageArrayLength::StorageArrayLength(CompilerContext& _compilerContext, const ArrayType& _arrayType): LValue(_compilerContext, *_arrayType.getMemberType("length")), @@ -262,4 +320,3 @@ void StorageArrayLength::setToZero(SourceLocation const&, bool _removeReference) m_context << eth::Instruction::DUP1; ArrayUtils(m_context).clearDynamicArray(m_arrayType); } - |