[Sol->Yul] Implementing copying of calldata arrays to memory

This commit is contained in:
Djordje Mijovic 2020-11-10 17:41:52 +01:00
parent 4bff99a518
commit 53a4b4a622

View File

@ -3090,7 +3090,8 @@ string YulUtilFunctions::conversionFunction(Type const& _from, Type const& _to)
string YulUtilFunctions::arrayConversionFunction(ArrayType const& _from, ArrayType const& _to) string YulUtilFunctions::arrayConversionFunction(ArrayType const& _from, ArrayType const& _to)
{ {
solUnimplementedAssert(_to.location() != DataLocation::CallData, "Conversion of calldata types not yet implemented."); solAssert(_to.location() != DataLocation::CallData, "");
// Other cases are done explicitly in LValue::storeValue, and only possible by assignment. // Other cases are done explicitly in LValue::storeValue, and only possible by assignment.
if (_to.location() == DataLocation::Storage) if (_to.location() == DataLocation::Storage)
solAssert( solAssert(
@ -3098,12 +3099,6 @@ string YulUtilFunctions::arrayConversionFunction(ArrayType const& _from, ArrayTy
_from.location() == DataLocation::Storage, _from.location() == DataLocation::Storage,
"Invalid conversion to storage type." "Invalid conversion to storage type."
); );
if (_to.location() == DataLocation::Memory && _from.location() == DataLocation::CallData)
{
solUnimplementedAssert(_from.isDynamicallySized(), "");
solUnimplementedAssert(!_from.baseType()->isDynamicallyEncoded(), "");
solUnimplementedAssert(_from.isByteArray() && _to.isByteArray() && _to.isDynamicallySized(), "");
}
string functionName = string functionName =
"convert_array_" + "convert_array_" +
@ -3131,19 +3126,31 @@ string YulUtilFunctions::arrayConversionFunction(ArrayType const& _from, ArrayTy
"body", "body",
Whiskers(R"( Whiskers(R"(
// Copy the array to a free position in memory // Copy the array to a free position in memory
converted :=
<?fromStorage> <?fromStorage>
converted := <arrayStorageToMem>(value) <arrayStorageToMem>(value)
</fromStorage> </fromStorage>
<?fromCalldata> <?fromCalldata>
converted := <allocateMemoryArray>(length) <abiDecode>(value, <length>, calldatasize())
<copyToMemory>(value, add(converted, 0x20), length)
</fromCalldata> </fromCalldata>
)") )")
("fromStorage", _from.dataStoredIn(DataLocation::Storage)) ("fromStorage", _from.dataStoredIn(DataLocation::Storage))
("fromCalldata", _from.dataStoredIn(DataLocation::CallData)) ("fromCalldata", _from.dataStoredIn(DataLocation::CallData))
("allocateMemoryArray", _from.dataStoredIn(DataLocation::CallData) ? allocateMemoryArrayFunction(_to) : "") ("length", _from.isDynamicallySized() ? "length" : _from.length().str())
("copyToMemory", _from.dataStoredIn(DataLocation::CallData) ? copyToMemoryFunction(true) : "") (
("arrayStorageToMem", _from.dataStoredIn(DataLocation::Storage) ? copyArrayFromStorageToMemoryFunction(_from, _to) : "") "abiDecode",
_from.dataStoredIn(DataLocation::CallData) ?
ABIFunctions(
m_evmVersion,
m_revertStrings,
m_functionCollector
).abiDecodingFunctionArrayAvailableLength(_to, false) :
""
)
(
"arrayStorageToMem",
_from.dataStoredIn(DataLocation::Storage) ? copyArrayFromStorageToMemoryFunction(_from, _to) : ""
)
.render() .render()
); );
else else