Add stride helpers to ArrayType.

This commit is contained in:
Daniel Kirchner 2019-02-14 10:50:13 +01:00
parent f003696d7e
commit 32190dac48
3 changed files with 12 additions and 6 deletions

View File

@ -736,6 +736,13 @@ public:
TypePointer copyForLocation(DataLocation _location, bool _isPointer) const override;
/// The offset to advance in calldata to move from one array element to the next.
unsigned calldataStride() const { return isByteArray() ? 1 : m_baseType->calldataEncodedSize(); }
/// The offset to advance in memory to move from one array element to the next.
unsigned memoryStride() const { return isByteArray() ? 1 : m_baseType->memoryHeadSize(); }
/// The offset to advance in storage to move from one array element to the next.
unsigned storageStride() const { return isByteArray() ? 1 : m_baseType->storageBytes(); }
private:
/// String is interpreted as a subtype of Bytes.
enum class ArrayKind { Ordinary, Bytes, String };

View File

@ -623,7 +623,7 @@ void ArrayUtils::clearDynamicArray(ArrayType const& _type) const
m_context << Instruction::SWAP1 << Instruction::DUP2 << Instruction::ADD
<< Instruction::SWAP1;
// stack: data_pos_end data_pos
if (_type.isByteArray() || _type.baseType()->storageBytes() < 32)
if (_type.storageStride() < 32)
clearStorageLoop(make_shared<IntegerType>(256));
else
clearStorageLoop(_type.baseType());
@ -769,7 +769,7 @@ void ArrayUtils::resizeDynamicArray(ArrayType const& _typeIn) const
// stack: ref new_length data_pos new_size delete_end
_context << Instruction::SWAP2 << Instruction::ADD;
// stack: ref new_length delete_end delete_start
if (_type.isByteArray() || _type.baseType()->storageBytes() < 32)
if (_type.storageStride() < 32)
ArrayUtils(_context).clearStorageLoop(make_shared<IntegerType>(256));
else
ArrayUtils(_context).clearStorageLoop(_type.baseType());

View File

@ -243,7 +243,7 @@ void CompilerUtils::abiDecode(TypePointers const& _typeParameters, bool _fromMem
gt(add(array_data_start, mul(array_length, <item_size>)), input_end)
) { revert(0, 0) }
})");
templ("item_size", to_string(arrayType.isByteArray() ? 1 : arrayType.baseType()->calldataEncodedSize(true)));
templ("item_size", to_string(arrayType.calldataStride()));
m_context.appendInlineAssembly(templ.render(), {"input_end", "base_offset", "offset", "ptr"});
// stack: v1 v2 ... v(k-1) input_end base_offset current_offset v(k)
moveIntoStack(3);
@ -279,11 +279,10 @@ void CompilerUtils::abiDecode(TypePointers const& _typeParameters, bool _fromMem
// stack: input_end base_offset next_pointer array_length data_pointer
m_context << Instruction::SWAP2;
// stack: input_end base_offset data_pointer array_length next_pointer
unsigned itemSize = arrayType.isByteArray() ? 1 : arrayType.baseType()->calldataEncodedSize(true);
m_context.appendInlineAssembly(R"({
if or(
gt(array_length, 0x100000000),
gt(add(data_ptr, mul(array_length, )" + to_string(itemSize) + R"()), input_end)
gt(add(data_ptr, mul(array_length, )" + to_string(arrayType.calldataStride()) + R"()), input_end)
) { revert(0, 0) }
})", {"input_end", "base_offset", "data_ptr", "array_length", "next_ptr"});
}
@ -517,7 +516,7 @@ void CompilerUtils::zeroInitialiseMemoryArray(ArrayType const& _type)
codecopy(memptr, codesize(), size)
memptr := add(memptr, size)
})");
templ("element_size", to_string(_type.isByteArray() ? 1 : _type.baseType()->memoryHeadSize()));
templ("element_size", to_string(_type.memoryStride()));
m_context.appendInlineAssembly(templ.render(), {"length", "memptr"});
}
else