From b84cf62d6bd3a9caa8a9a7f1dcd427418170aed9 Mon Sep 17 00:00:00 2001 From: Christian Date: Tue, 3 Mar 2015 17:55:28 +0100 Subject: Index access for calldata arrays. --- LValue.cpp | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 58 insertions(+), 1 deletion(-) (limited to 'LValue.cpp') diff --git a/LValue.cpp b/LValue.cpp index 452ca1c7..f5730020 100644 --- a/LValue.cpp +++ b/LValue.cpp @@ -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); } - -- cgit v1.2.3