diff --git a/libsolidity/codegen/YulUtilFunctions.cpp b/libsolidity/codegen/YulUtilFunctions.cpp index 31feffc47..03a99bef5 100644 --- a/libsolidity/codegen/YulUtilFunctions.cpp +++ b/libsolidity/codegen/YulUtilFunctions.cpp @@ -1348,6 +1348,24 @@ string YulUtilFunctions::shortByteArrayEncodeUsedAreaSetLengthFunction() }); } +string YulUtilFunctions::longByteArrayStorageIndexAccessNoCheckFunction() +{ + return m_functionCollector.createFunction( + "long_byte_array_index_access_no_checks", + [&](vector& _args, vector& _returnParams) { + _args = {"array", "index"}; + _returnParams = {"slot", "offset"}; + return Whiskers(R"( + offset := sub(31, mod(index, 0x20)) + let dataArea := (array) + slot := add(dataArea, div(index, 0x20)) + )") + ("dataAreaFunc", arrayDataAreaFunction(*TypeProvider::bytesStorage())) + .render(); + } + ); +} + string YulUtilFunctions::storageArrayPopFunction(ArrayType const& _type) { solAssert(_type.location() == DataLocation::Storage, ""); @@ -1406,7 +1424,7 @@ string YulUtilFunctions::storageByteArrayPopFunction(ArrayType const& _type) sstore(array, (data, newLen)) } default { - let slot, offset := (array, newLen) + let slot, offset := (array, newLen) (slot, offset) sstore(array, sub(data, 2)) } @@ -1417,7 +1435,7 @@ string YulUtilFunctions::storageByteArrayPopFunction(ArrayType const& _type) ("extractByteArrayLength", extractByteArrayLengthFunction()) ("transitLongToShort", byteArrayTransitLongToShortFunction(_type)) ("encodeUsedSetLen", shortByteArrayEncodeUsedAreaSetLengthFunction()) - ("indexAccess", storageArrayIndexAccessFunction(_type)) + ("indexAccessNoChecks", longByteArrayStorageIndexAccessNoCheckFunction()) ("setToZero", storageSetToZeroFunction(*_type.baseType())) .render(); }); @@ -2112,13 +2130,12 @@ string YulUtilFunctions::storageArrayIndexAccessFunction(ArrayType const& _type) - offset := sub(31, mod(index, 0x20)) switch lt(arrayLength, 0x20) case 0 { - let dataArea := (array) - slot := add(dataArea, div(index, 0x20)) + slot, offset := (array, index) } default { + offset := sub(31, mod(index, 0x20)) slot := array } @@ -2137,6 +2154,7 @@ string YulUtilFunctions::storageArrayIndexAccessFunction(ArrayType const& _type) ("panic", panicFunction(PanicCode::ArrayOutOfBounds)) ("arrayLen", arrayLengthFunction(_type)) ("dataAreaFunc", arrayDataAreaFunction(_type)) + ("indexAccessNoChecks", longByteArrayStorageIndexAccessNoCheckFunction()) ("multipleItemsPerSlot", _type.baseType()->storageBytes() <= 16) ("isBytesArray", _type.isByteArray()) ("storageSize", _type.baseType()->storageSize().str()) diff --git a/libsolidity/codegen/YulUtilFunctions.h b/libsolidity/codegen/YulUtilFunctions.h index 13fa173a4..c39b2d507 100644 --- a/libsolidity/codegen/YulUtilFunctions.h +++ b/libsolidity/codegen/YulUtilFunctions.h @@ -552,6 +552,11 @@ private: /// signature: (data, len) -> data std::string shortByteArrayEncodeUsedAreaSetLengthFunction(); + /// @returns the name of a function that calculates slot and offset for index + /// Doesn't perform length checks, assumes that index is in bounds + /// signature: (array, index) + std::string longByteArrayStorageIndexAccessNoCheckFunction(); + langutil::EVMVersion m_evmVersion; RevertStrings m_revertStrings; MultiUseYulFunctionCollector& m_functionCollector; diff --git a/test/cmdlineTests/name_simplifier/output b/test/cmdlineTests/name_simplifier/output index 5120b3b86..89b171a46 100644 --- a/test/cmdlineTests/name_simplifier/output +++ b/test/cmdlineTests/name_simplifier/output @@ -139,14 +139,14 @@ object "C_59" { } function storage_array_index_access_struct_S_1252() -> slot, offset { - if iszero(lt(slot, 0x02)) { panic_error_0x32() } - slot := add(slot, slot) + if iszero(lt(offset, 0x02)) { panic_error_0x32() } + slot := add(offset, offset) offset := offset } function storage_array_index_access_struct_S() -> slot, offset { - if iszero(lt(slot, 0x02)) { panic_error_0x32() } - slot := add(0x02, slot) + if iszero(lt(offset, 0x02)) { panic_error_0x32() } + slot := add(0x02, offset) offset := offset } } diff --git a/test/libsolidity/semanticTests/array/byte_array_transitional_2.sol b/test/libsolidity/semanticTests/array/byte_array_transitional_2.sol index 653085278..737116c20 100644 --- a/test/libsolidity/semanticTests/array/byte_array_transitional_2.sol +++ b/test/libsolidity/semanticTests/array/byte_array_transitional_2.sol @@ -19,6 +19,6 @@ contract c { // compileViaYul: also // ---- // test() -> 0 -// gas irOptimized: 311472 +// gas irOptimized: 310460 // gas legacy: 483915 // gas legacyOptimized: 478672 diff --git a/test/libsolidity/semanticTests/array/dynamic_arrays_in_storage.sol b/test/libsolidity/semanticTests/array/dynamic_arrays_in_storage.sol index bcd034c67..2a90ea0c9 100644 --- a/test/libsolidity/semanticTests/array/dynamic_arrays_in_storage.sol +++ b/test/libsolidity/semanticTests/array/dynamic_arrays_in_storage.sol @@ -44,7 +44,7 @@ contract c { // ---- // getLengths() -> 0, 0 // setLengths(uint256,uint256): 48, 49 -> -// gas irOptimized: 275838 +// gas irOptimized: 276212 // gas legacy: 308271 // gas legacyOptimized: 300117 // getLengths() -> 48, 49 diff --git a/test/libsolidity/semanticTests/array/pop/byte_array_pop_copy_long.sol b/test/libsolidity/semanticTests/array/pop/byte_array_pop_copy_long.sol index 59f73d124..ed21c0c4d 100644 --- a/test/libsolidity/semanticTests/array/pop/byte_array_pop_copy_long.sol +++ b/test/libsolidity/semanticTests/array/pop/byte_array_pop_copy_long.sol @@ -12,6 +12,6 @@ contract c { // compileViaYul: also // ---- // test() -> 0x20, 29, 0x0303030303030303030303030303030303030303030303030303030303000000 -// gas irOptimized: 163572 +// gas irOptimized: 162649 // gas legacy: 245809 // gas legacyOptimized: 242636 diff --git a/test/libsolidity/semanticTests/array/pop/byte_array_pop_long_storage_empty.sol b/test/libsolidity/semanticTests/array/pop/byte_array_pop_long_storage_empty.sol index 0a6f802c6..54a4949e9 100644 --- a/test/libsolidity/semanticTests/array/pop/byte_array_pop_long_storage_empty.sol +++ b/test/libsolidity/semanticTests/array/pop/byte_array_pop_long_storage_empty.sol @@ -18,7 +18,7 @@ contract c { // compileViaYul: also // ---- // test() -> true -// gas irOptimized: 455893 +// gas irOptimized: 447028 // gas legacy: 552064 // gas legacyOptimized: 533164 // storage: empty diff --git a/test/libsolidity/semanticTests/array/pop/byte_array_pop_long_storage_empty_garbage_ref.sol b/test/libsolidity/semanticTests/array/pop/byte_array_pop_long_storage_empty_garbage_ref.sol index a8119434e..61720d0aa 100644 --- a/test/libsolidity/semanticTests/array/pop/byte_array_pop_long_storage_empty_garbage_ref.sol +++ b/test/libsolidity/semanticTests/array/pop/byte_array_pop_long_storage_empty_garbage_ref.sol @@ -17,7 +17,7 @@ contract c { // compileViaYul: also // ---- // test() -> -// gas irOptimized: 300849 +// gas irOptimized: 291984 // gas legacy: 372763 // gas legacyOptimized: 366846 // storage: empty diff --git a/test/libsolidity/semanticTests/array/pop/byte_array_pop_masking_long.sol b/test/libsolidity/semanticTests/array/pop/byte_array_pop_masking_long.sol index cd59188d9..8b3694cdb 100644 --- a/test/libsolidity/semanticTests/array/pop/byte_array_pop_masking_long.sol +++ b/test/libsolidity/semanticTests/array/pop/byte_array_pop_masking_long.sol @@ -12,6 +12,6 @@ contract c { // compileViaYul: also // ---- // test() -> 0x20, 33, 0x303030303030303030303030303030303030303030303030303030303030303, 0x0300000000000000000000000000000000000000000000000000000000000000 -// gas irOptimized: 160904 +// gas irOptimized: 160043 // gas legacy: 243287 // gas legacyOptimized: 240361 diff --git a/test/libsolidity/semanticTests/array/push/push_no_args_bytes.sol b/test/libsolidity/semanticTests/array/push/push_no_args_bytes.sol index 1ce7f5141..fb859941d 100644 --- a/test/libsolidity/semanticTests/array/push/push_no_args_bytes.sol +++ b/test/libsolidity/semanticTests/array/push/push_no_args_bytes.sol @@ -23,7 +23,7 @@ contract C { // ---- // l() -> 0 // g(uint256): 70 -> -// gas irOptimized: 428769 +// gas irOptimized: 429679 // gas legacy: 419791 // gas legacyOptimized: 415408 // l() -> 70 diff --git a/test/libsolidity/semanticTests/constructor/bytes_in_constructors_packer.sol b/test/libsolidity/semanticTests/constructor/bytes_in_constructors_packer.sol index 26b9e7da3..21fad1600 100644 --- a/test/libsolidity/semanticTests/constructor/bytes_in_constructors_packer.sol +++ b/test/libsolidity/semanticTests/constructor/bytes_in_constructors_packer.sol @@ -26,6 +26,6 @@ contract Creator { // compileViaYul: also // ---- // f(uint256,bytes): 7, 0x40, 78, "abcdefghijklmnopqrstuvwxyzabcdef", "ghijklmnopqrstuvwxyzabcdefghijkl", "mnopqrstuvwxyz" -> 7, "h" -// gas irOptimized: 323391 +// gas irOptimized: 322968 // gas legacy: 414850 // gas legacyOptimized: 290278