aboutsummaryrefslogtreecommitdiffstats
path: root/ExpressionCompiler.cpp
diff options
context:
space:
mode:
authorchriseth <c@ethdev.com>2015-03-31 01:31:57 +0800
committerchriseth <c@ethdev.com>2015-03-31 01:32:14 +0800
commitd0ede6fafdd2a2e6f2498e5c9e939052a058f7c8 (patch)
tree03f3ecf42bb205cee279dafcf5bd7fb2ff805048 /ExpressionCompiler.cpp
parentf728a336b1af6ae25b5cb5282119bef8f55c08b6 (diff)
downloaddexon-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.cpp107
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