Move code that access calldata array element to separate function

This commit is contained in:
mingchuan 2019-06-19 17:22:11 +08:00
parent 492f945973
commit ae273ff3bd
No known key found for this signature in database
GPG Key ID: 607CD25FA2D03651
3 changed files with 49 additions and 39 deletions

View File

@ -1131,6 +1131,50 @@ void ArrayUtils::accessIndex(ArrayType const& _arrayType, bool _doBoundsCheck, b
}
}
void ArrayUtils::accessCallDataArrayElement(ArrayType const& _arrayType, bool _doBoundsCheck) const
{
solAssert(_arrayType.location() == DataLocation::CallData, "");
if (_arrayType.baseType()->isDynamicallyEncoded())
{
// stack layout: <base_ref> <length> <index>
ArrayUtils(m_context).accessIndex(_arrayType, _doBoundsCheck, true);
// stack layout: <base_ref> <ptr_to_tail>
CompilerUtils(m_context).accessCalldataTail(*_arrayType.baseType());
// stack layout: <tail_ref> [length]
}
else
{
ArrayUtils(m_context).accessIndex(_arrayType, _doBoundsCheck);
if (_arrayType.baseType()->isValueType())
{
solAssert(_arrayType.baseType()->storageBytes() <= 32, "");
if (
!_arrayType.isByteArray() &&
_arrayType.baseType()->storageBytes() < 32 &&
m_context.experimentalFeatureActive(ExperimentalFeature::ABIEncoderV2)
)
{
m_context << u256(32);
CompilerUtils(m_context).abiDecodeV2({_arrayType.baseType()}, false);
}
else
CompilerUtils(m_context).loadFromMemoryDynamic(
*_arrayType.baseType(),
true,
!_arrayType.isByteArray(),
false
);
}
else
solAssert(
_arrayType.baseType()->category() == Type::Category::Struct ||
_arrayType.baseType()->category() == Type::Category::Array,
"Invalid statically sized non-value base type on array access."
);
}
}
void ArrayUtils::incrementByteOffset(unsigned _byteSize, unsigned _byteOffsetPosition, unsigned _storageOffsetPosition) const
{
solAssert(_byteSize < 32, "");

View File

@ -104,6 +104,10 @@ public:
/// Stack post (storage): [reference] storage_slot byte_offset
/// Stack post: [reference] memory/calldata_offset
void accessIndex(ArrayType const& _arrayType, bool _doBoundsCheck = true, bool _keepReference = false) const;
/// Access calldata array's element and put it on stack.
/// Stack pre: reference [length] index
/// Stack post: value
void accessCallDataArrayElement(ArrayType const& _arrayType, bool _doBoundsCheck = true) const;
private:
/// Adds the given number of bytes to a storage byte offset counter and also increments

View File

@ -1588,45 +1588,7 @@ bool ExpressionCompiler::visit(IndexAccess const& _indexAccess)
setLValue<MemoryItem>(_indexAccess, *_indexAccess.annotation().type, !arrayType.isByteArray());
break;
case DataLocation::CallData:
if (arrayType.baseType()->isDynamicallyEncoded())
{
// stack layout: <base_ref> <length> <index>
ArrayUtils(m_context).accessIndex(arrayType, true, true);
// stack layout: <base_ref> <ptr_to_tail>
CompilerUtils(m_context).accessCalldataTail(*arrayType.baseType());
// stack layout: <tail_ref> [length]
}
else
{
ArrayUtils(m_context).accessIndex(arrayType, true);
if (arrayType.baseType()->isValueType())
{
solAssert(arrayType.baseType()->storageBytes() <= 32, "");
if (
!arrayType.isByteArray() &&
arrayType.baseType()->storageBytes() < 32 &&
m_context.experimentalFeatureActive(ExperimentalFeature::ABIEncoderV2)
)
{
m_context << u256(32);
CompilerUtils(m_context).abiDecodeV2({arrayType.baseType()}, false);
}
else
CompilerUtils(m_context).loadFromMemoryDynamic(
*arrayType.baseType(),
true,
!arrayType.isByteArray(),
false
);
}
else
solAssert(
arrayType.baseType()->category() == Type::Category::Struct ||
arrayType.baseType()->category() == Type::Category::Array,
"Invalid statically sized non-value base type on array access."
);
}
ArrayUtils(m_context).accessCallDataArrayElement(arrayType);
break;
}
}