mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Allow ABI encoding for array slices without explicit casts.
This commit is contained in:
@@ -279,31 +279,47 @@ string ABIFunctions::abiEncodingFunction(
|
||||
return abiEncodingFunctionStringLiteral(_from, to, _options);
|
||||
else if (auto toArray = dynamic_cast<ArrayType const*>(&to))
|
||||
{
|
||||
solAssert(_from.category() == Type::Category::Array, "");
|
||||
solAssert(to.dataStoredIn(DataLocation::Memory), "");
|
||||
ArrayType const& fromArray = dynamic_cast<ArrayType const&>(_from);
|
||||
ArrayType const* fromArray = nullptr;
|
||||
switch (_from.category())
|
||||
{
|
||||
case Type::Category::Array:
|
||||
fromArray = dynamic_cast<ArrayType const*>(&_from);
|
||||
break;
|
||||
case Type::Category::ArraySlice:
|
||||
fromArray = &dynamic_cast<ArraySliceType const*>(&_from)->arrayType();
|
||||
solAssert(
|
||||
fromArray->dataStoredIn(DataLocation::CallData) &&
|
||||
fromArray->isDynamicallySized() &&
|
||||
!fromArray->baseType()->isDynamicallyEncoded(),
|
||||
""
|
||||
);
|
||||
break;
|
||||
default:
|
||||
solAssert(false, "");
|
||||
break;
|
||||
}
|
||||
|
||||
switch (fromArray.location())
|
||||
switch (fromArray->location())
|
||||
{
|
||||
case DataLocation::CallData:
|
||||
if (
|
||||
fromArray.isByteArray() ||
|
||||
*fromArray.baseType() == *TypeProvider::uint256() ||
|
||||
*fromArray.baseType() == FixedBytesType(32)
|
||||
fromArray->isByteArray() ||
|
||||
*fromArray->baseType() == *TypeProvider::uint256() ||
|
||||
*fromArray->baseType() == FixedBytesType(32)
|
||||
)
|
||||
return abiEncodingFunctionCalldataArrayWithoutCleanup(fromArray, *toArray, _options);
|
||||
return abiEncodingFunctionCalldataArrayWithoutCleanup(*fromArray, *toArray, _options);
|
||||
else
|
||||
return abiEncodingFunctionSimpleArray(fromArray, *toArray, _options);
|
||||
return abiEncodingFunctionSimpleArray(*fromArray, *toArray, _options);
|
||||
case DataLocation::Memory:
|
||||
if (fromArray.isByteArray())
|
||||
return abiEncodingFunctionMemoryByteArray(fromArray, *toArray, _options);
|
||||
if (fromArray->isByteArray())
|
||||
return abiEncodingFunctionMemoryByteArray(*fromArray, *toArray, _options);
|
||||
else
|
||||
return abiEncodingFunctionSimpleArray(fromArray, *toArray, _options);
|
||||
return abiEncodingFunctionSimpleArray(*fromArray, *toArray, _options);
|
||||
case DataLocation::Storage:
|
||||
if (fromArray.baseType()->storageBytes() <= 16)
|
||||
return abiEncodingFunctionCompactStorageArray(fromArray, *toArray, _options);
|
||||
if (fromArray->baseType()->storageBytes() <= 16)
|
||||
return abiEncodingFunctionCompactStorageArray(*fromArray, *toArray, _options);
|
||||
else
|
||||
return abiEncodingFunctionSimpleArray(fromArray, *toArray, _options);
|
||||
return abiEncodingFunctionSimpleArray(*fromArray, *toArray, _options);
|
||||
default:
|
||||
solAssert(false, "");
|
||||
}
|
||||
|
||||
@@ -480,6 +480,16 @@ void CompilerUtils::encodeToMemory(
|
||||
convertType(*_givenTypes[i], *targetType, true);
|
||||
if (auto arrayType = dynamic_cast<ArrayType const*>(type))
|
||||
ArrayUtils(m_context).copyArrayToMemory(*arrayType, _padToWordBoundaries);
|
||||
else if (auto arraySliceType = dynamic_cast<ArraySliceType const*>(type))
|
||||
{
|
||||
solAssert(
|
||||
arraySliceType->dataStoredIn(DataLocation::CallData) &&
|
||||
arraySliceType->isDynamicallySized() &&
|
||||
!arraySliceType->arrayType().baseType()->isDynamicallyEncoded(),
|
||||
""
|
||||
);
|
||||
ArrayUtils(m_context).copyArrayToMemory(arraySliceType->arrayType(), _padToWordBoundaries);
|
||||
}
|
||||
else
|
||||
storeInMemoryDynamic(*type, _padToWordBoundaries);
|
||||
}
|
||||
@@ -516,22 +526,39 @@ void CompilerUtils::encodeToMemory(
|
||||
}
|
||||
else
|
||||
{
|
||||
solAssert(_givenTypes[i]->category() == Type::Category::Array, "Unknown dynamic type.");
|
||||
auto const& arrayType = dynamic_cast<ArrayType const&>(*_givenTypes[i]);
|
||||
ArrayType const* arrayType = nullptr;
|
||||
switch (_givenTypes[i]->category())
|
||||
{
|
||||
case Type::Category::Array:
|
||||
arrayType = dynamic_cast<ArrayType const*>(_givenTypes[i]);
|
||||
break;
|
||||
case Type::Category::ArraySlice:
|
||||
arrayType = &dynamic_cast<ArraySliceType const*>(_givenTypes[i])->arrayType();
|
||||
solAssert(
|
||||
arrayType->isDynamicallySized() &&
|
||||
arrayType->dataStoredIn(DataLocation::CallData) &&
|
||||
!arrayType->baseType()->isDynamicallyEncoded(),
|
||||
""
|
||||
);
|
||||
break;
|
||||
default:
|
||||
solAssert(false, "Unknown dynamic type.");
|
||||
break;
|
||||
}
|
||||
// now copy the array
|
||||
copyToStackTop(argSize - stackPos + dynPointers + 2, arrayType.sizeOnStack());
|
||||
copyToStackTop(argSize - stackPos + dynPointers + 2, arrayType->sizeOnStack());
|
||||
// stack: ... <end_of_mem> <value...>
|
||||
// copy length to memory
|
||||
m_context << dupInstruction(1 + arrayType.sizeOnStack());
|
||||
ArrayUtils(m_context).retrieveLength(arrayType, 1);
|
||||
m_context << dupInstruction(1 + arrayType->sizeOnStack());
|
||||
ArrayUtils(m_context).retrieveLength(*arrayType, 1);
|
||||
// stack: ... <end_of_mem> <value...> <end_of_mem'> <length>
|
||||
storeInMemoryDynamic(*TypeProvider::uint256(), true);
|
||||
// stack: ... <end_of_mem> <value...> <end_of_mem''>
|
||||
// copy the new memory pointer
|
||||
m_context << swapInstruction(arrayType.sizeOnStack() + 1) << Instruction::POP;
|
||||
m_context << swapInstruction(arrayType->sizeOnStack() + 1) << Instruction::POP;
|
||||
// stack: ... <end_of_mem''> <value...>
|
||||
// copy data part
|
||||
ArrayUtils(m_context).copyArrayToMemory(arrayType, _padToWordBoundaries);
|
||||
ArrayUtils(m_context).copyArrayToMemory(*arrayType, _padToWordBoundaries);
|
||||
// stack: ... <end_of_mem'''>
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user