diff --git a/libsolidity/codegen/YulUtilFunctions.cpp b/libsolidity/codegen/YulUtilFunctions.cpp index 791e8b5b9..2407fa548 100644 --- a/libsolidity/codegen/YulUtilFunctions.cpp +++ b/libsolidity/codegen/YulUtilFunctions.cpp @@ -1000,10 +1000,9 @@ string YulUtilFunctions::arrayLengthFunction(ArrayType const& _type) }); } -std::string YulUtilFunctions::resizeDynamicArrayFunction(ArrayType const& _type) +std::string YulUtilFunctions::resizeArrayFunction(ArrayType const& _type) { solAssert(_type.location() == DataLocation::Storage, ""); - solAssert(_type.isDynamicallySized(), ""); solUnimplementedAssert(_type.baseType()->storageBytes() <= 32, "..."); if (_type.isByteArray()) @@ -1019,8 +1018,10 @@ std::string YulUtilFunctions::resizeDynamicArrayFunction(ArrayType const& _type) let oldLen := (array) - // Store new length - sstore(array, newLen) + + // Store new length + sstore(array, newLen) + // Size was reduced, clear end of array if lt(newLen, oldLen) { @@ -1041,6 +1042,7 @@ std::string YulUtilFunctions::resizeDynamicArrayFunction(ArrayType const& _type) ("functionName", functionName) ("panic", panicFunction()) ("fetchLength", arrayLengthFunction(_type)) + ("isDynamic", _type.isDynamicallySized()) ("convertToSize", arrayConvertLengthToSize(_type)) ("dataPosition", arrayDataAreaFunction(_type)) ("clearStorageRange", clearStorageRangeFunction(*_type.baseType())) @@ -1425,7 +1427,7 @@ string YulUtilFunctions::clearStorageArrayFunction(ArrayType const& _type) )") ("functionName", functionName) ("dynamic", _type.isDynamicallySized()) - ("resizeArray", _type.isDynamicallySized() ? resizeDynamicArrayFunction(_type) : "") + ("resizeArray", _type.isDynamicallySized() ? resizeArrayFunction(_type) : "") ( "clearRange", clearStorageRangeFunction( @@ -1497,6 +1499,9 @@ string YulUtilFunctions::copyArrayToStorageFunction(ArrayType const& _fromType, *_fromType.copyForLocation(_toType.location(), _toType.isPointer()) == dynamic_cast(_toType), "" ); + if (!_toType.isDynamicallySized()) + solAssert(!_fromType.isDynamicallySized() && _fromType.length() <= _toType.length(), ""); + if (_fromType.isByteArray()) return copyByteArrayToStorageFunction(_fromType, _toType); if (_fromType.dataStoredIn(DataLocation::Storage) && _toType.baseType()->isValueType()) @@ -1508,9 +1513,8 @@ string YulUtilFunctions::copyArrayToStorageFunction(ArrayType const& _fromType, function (slot, value, len) { if eq(slot, value) { leave } let length := (value, len) - - (slot, length) - + + (slot, length) let srcPtr := (value) @@ -1564,7 +1568,6 @@ string YulUtilFunctions::copyArrayToStorageFunction(ArrayType const& _fromType, bool fromMemory = _fromType.dataStoredIn(DataLocation::Memory); templ("fromMemory", fromMemory); templ("fromCalldata", fromCalldata); - templ("isToDynamic", _toType.isDynamicallySized()); templ("srcDataLocation", arrayDataAreaFunction(_fromType)); if (fromCalldata) { @@ -1573,8 +1576,7 @@ string YulUtilFunctions::copyArrayToStorageFunction(ArrayType const& _fromType, if (_fromType.baseType()->isDynamicallyEncoded()) templ("accessCalldataTail", accessCalldataTailFunction(*_fromType.baseType())); } - if (_toType.isDynamicallySized()) - templ("resizeArray", resizeDynamicArrayFunction(_toType)); + templ("resizeArray", resizeArrayFunction(_toType)); templ("arrayLength",arrayLengthFunction(_fromType)); templ("isValueType", _fromType.baseType()->isValueType()); templ("dstDataLocation", arrayDataAreaFunction(_toType)); @@ -1693,6 +1695,8 @@ string YulUtilFunctions::copyValueArrayStorageToStorageFunction(ArrayType const& solAssert(_fromType.dataStoredIn(DataLocation::Storage) && _toType.baseType()->isValueType(), ""); solAssert(_toType.dataStoredIn(DataLocation::Storage), ""); + solUnimplementedAssert(_fromType.storageStride() == _toType.storageStride(), ""); + string functionName = "copy_array_to_storage_from_" + _fromType.identifier() + "_to_" + _toType.identifier(); return m_functionCollector.createFunction(functionName, [&](){ Whiskers templ(R"( @@ -1701,9 +1705,7 @@ string YulUtilFunctions::copyValueArrayStorageToStorageFunction(ArrayType const& let length := (src) // Make sure array length is sane if gt(length, 0xffffffffffffffff) { () } - - (dst, length) - + (dst, length) let srcPtr := (src) @@ -1723,9 +1725,7 @@ string YulUtilFunctions::copyValueArrayStorageToStorageFunction(ArrayType const& if (_fromType.dataStoredIn(DataLocation::Storage)) solAssert(!_fromType.isValueType(), ""); templ("functionName", functionName); - templ("isToDynamic", _toType.isDynamicallySized()); - if (_toType.isDynamicallySized()) - templ("resizeArray", resizeDynamicArrayFunction(_toType)); + templ("resizeArray", resizeArrayFunction(_toType)); templ("arrayLength",arrayLengthFunction(_fromType)); templ("panic", panicFunction()); templ("srcDataLocation", arrayDataAreaFunction(_fromType)); diff --git a/libsolidity/codegen/YulUtilFunctions.h b/libsolidity/codegen/YulUtilFunctions.h index af34c3535..1c2bc9332 100644 --- a/libsolidity/codegen/YulUtilFunctions.h +++ b/libsolidity/codegen/YulUtilFunctions.h @@ -171,8 +171,9 @@ public: std::string arrayLengthFunction(ArrayType const& _type); /// @returns the name of a function that resizes a storage array + /// for statically sized arrays, it will just clean-up elements of array starting from newLen until the end /// signature: (array, newLen) - std::string resizeDynamicArrayFunction(ArrayType const& _type); + std::string resizeArrayFunction(ArrayType const& _type); /// @returns the name of a function that reduces the size of a storage array by one element /// signature: (array) diff --git a/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_static_static.sol b/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_static_static.sol index 71601d477..98642c9e1 100644 --- a/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_static_static.sol +++ b/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_static_static.sol @@ -13,5 +13,7 @@ contract c { } } +// ==== +// compileViaYul: also // ---- // test() -> 8, 0