diff options
author | chriseth <c@ethdev.com> | 2015-03-31 01:31:57 +0800 |
---|---|---|
committer | chriseth <c@ethdev.com> | 2015-03-31 01:32:14 +0800 |
commit | d0ede6fafdd2a2e6f2498e5c9e939052a058f7c8 (patch) | |
tree | 03f3ecf42bb205cee279dafcf5bd7fb2ff805048 /ExpressionCompiler.cpp | |
parent | f728a336b1af6ae25b5cb5282119bef8f55c08b6 (diff) | |
download | dexon-solidity-d0ede6fafdd2a2e6f2498e5c9e939052a058f7c8.tar.gz dexon-solidity-d0ede6fafdd2a2e6f2498e5c9e939052a058f7c8.tar.zst dexon-solidity-d0ede6fafdd2a2e6f2498e5c9e939052a058f7c8.zip |
Refactor: Pull out array index access.
Diffstat (limited to 'ExpressionCompiler.cpp')
-rw-r--r-- | ExpressionCompiler.cpp | 107 |
1 files changed, 7 insertions, 100 deletions
diff --git a/ExpressionCompiler.cpp b/ExpressionCompiler.cpp index 90568767..daea2162 100644 --- a/ExpressionCompiler.cpp +++ b/ExpressionCompiler.cpp @@ -755,113 +755,20 @@ bool ExpressionCompiler::visit(IndexAccess const& _indexAccess) { ArrayType const& arrayType = dynamic_cast<ArrayType const&>(baseType); solAssert(_indexAccess.getIndexExpression(), "Index expression expected."); - ArrayType::Location location = arrayType.getLocation(); - eth::Instruction load = - location == ArrayType::Location::Storage ? eth::Instruction::SLOAD : - location == ArrayType::Location::Memory ? eth::Instruction::MLOAD : - eth::Instruction::CALLDATALOAD; // remove storage byte offset - if (location == ArrayType::Location::Storage) + if (arrayType.getLocation() == ArrayType::Location::Storage) m_context << eth::Instruction::POP; - // stack layout: <base_ref> [<length>] <index> _indexAccess.getIndexExpression()->accept(*this); - // retrieve length - if (!arrayType.isDynamicallySized()) - m_context << arrayType.getLength(); - else if (location == ArrayType::Location::CallData) - // length is stored on the stack - m_context << eth::Instruction::SWAP1; - else - m_context << eth::Instruction::DUP2 << load; - // stack: <base_ref> <index> <length> - // check out-of-bounds access - m_context << eth::Instruction::DUP2 << eth::Instruction::LT; - eth::AssemblyItem legalAccess = m_context.appendConditionalJump(); - // out-of-bounds access throws exception (just STOP for now) - m_context << eth::Instruction::STOP; - - m_context << legalAccess; - // stack: <base_ref> <index> - if (arrayType.isByteArray()) - switch (location) - { - 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; - CompilerUtils(m_context).computeHashStatic(); - // stack: 32 index data_ref - m_context - << eth::Instruction::DUP3 << 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; - setLValue<StorageByteArrayElement>(_indexAccess); - break; - case ArrayType::Location::CallData: - // no lvalue, just retrieve the value - m_context - << eth::Instruction::ADD << eth::Instruction::CALLDATALOAD - << ((u256(0xff) << (256 - 8))) << eth::Instruction::AND; - break; - case ArrayType::Location::Memory: - solAssert(false, "Memory lvalues not yet implemented."); - } - else + // stack layout: <base_ref> [<length>] <index> + ArrayUtils(m_context).accessIndex(arrayType); + if (arrayType.getLocation() == ArrayType::Location::Storage) { - // stack: <base_ref> <index> - m_context << eth::Instruction::SWAP1; - if (arrayType.isDynamicallySized()) - { - if (location == ArrayType::Location::Storage) - CompilerUtils(m_context).computeHashStatic(); - else if (location == ArrayType::Location::Memory) - m_context << u256(32) << eth::Instruction::ADD; - } - // stack: <index> <data_ref> - switch (location) - { - case ArrayType::Location::CallData: - m_context - << eth::Instruction::SWAP1 << arrayType.getBaseType()->getCalldataEncodedSize() - << eth::Instruction::MUL << eth::Instruction::ADD; - if (arrayType.getBaseType()->isValueType()) - CompilerUtils(m_context).loadFromMemoryDynamic(*arrayType.getBaseType(), true, true, false); - break; - case ArrayType::Location::Storage: - m_context << eth::Instruction::SWAP1; - if (arrayType.getBaseType()->getStorageBytes() <= 16) - { - // stack: <data_ref> <index> - // goal: - // <ref> <byte_number> = <base_ref + index / itemsPerSlot> <(index % itemsPerSlot) * byteSize> - unsigned byteSize = arrayType.getBaseType()->getStorageBytes(); - solAssert(byteSize != 0, ""); - unsigned itemsPerSlot = 32 / byteSize; - m_context << u256(itemsPerSlot) << eth::Instruction::SWAP2; - // stack: itemsPerSlot index data_ref - m_context - << eth::Instruction::DUP3 << eth::Instruction::DUP3 - << eth::Instruction::DIV << eth::Instruction::ADD - // stack: itemsPerSlot index (data_ref + index / itemsPerSlot) - << eth::Instruction::SWAP2 << eth::Instruction::SWAP1 - << eth::Instruction::MOD - << u256(byteSize) << eth::Instruction::MUL; - } - else - { - if (arrayType.getBaseType()->getStorageSize() != 1) - m_context << arrayType.getBaseType()->getStorageSize() << eth::Instruction::MUL; - m_context << eth::Instruction::ADD << u256(0); - } + if (arrayType.isByteArray()) + setLValue<StorageByteArrayElement>(_indexAccess); + else setLValueToStorageItem(_indexAccess); - break; - case ArrayType::Location::Memory: - solAssert(false, "Memory lvalues not yet implemented."); - } } } else |