diff --git a/libsolidity/codegen/YulUtilFunctions.cpp b/libsolidity/codegen/YulUtilFunctions.cpp index 8786ff6c2..f61a76d32 100644 --- a/libsolidity/codegen/YulUtilFunctions.cpp +++ b/libsolidity/codegen/YulUtilFunctions.cpp @@ -35,6 +35,16 @@ using namespace solidity; using namespace solidity::util; using namespace solidity::frontend; +string YulUtilFunctions::identityFunction() +{ + string functionName = "identity"; + return m_functionCollector.createFunction("identity", [&](vector& _args, vector& _rets) { + _args.push_back("value"); + _rets.push_back("ret"); + return "ret := value"; + }); +} + string YulUtilFunctions::combineExternalFunctionIdFunction() { string functionName = "combine_external_function_id"; @@ -3272,48 +3282,38 @@ string YulUtilFunctions::conversionFunction(Type const& _from, Type const& _to) if (rational->isFractional()) solAssert(toCategory == Type::Category::FixedPoint, ""); - if (toCategory == Type::Category::FixedBytes) - { - FixedBytesType const& toBytesType = dynamic_cast(_to); - body = - Whiskers("converted := ((value))") - ("shiftLeft", shiftLeftFunction(256 - toBytesType.numBytes() * 8)) - ("clean", cleanupFunction(_from)) - .render(); - } - else if (toCategory == Type::Category::Enum) - body = - Whiskers("converted := ((value))") - ("cleanEnum", cleanupFunction(_to)) - ("cleanInt", cleanupFunction(_from)) - .render(); - else if (toCategory == Type::Category::FixedPoint) - solUnimplemented("Not yet implemented - FixedPointType."); - else if (toCategory == Type::Category::Address || toCategory == Type::Category::Contract) + if (toCategory == Type::Category::Address || toCategory == Type::Category::Contract) body = Whiskers("converted := (value)") ("convert", conversionFunction(_from, IntegerType(160))) .render(); - else if (toCategory == Type::Category::Integer) - { - IntegerType const& to = dynamic_cast(_to); - - // Clean according to the "to" type, except if this is - // a widening conversion. - IntegerType const* cleanupType = &to; - if (fromCategory == Type::Category::Integer) - { - IntegerType const& from = dynamic_cast(_from); - if (to.numBits() > from.numBits()) - cleanupType = &from; - } - body = - Whiskers("converted := (value)") - ("cleanInt", cleanupFunction(*cleanupType)) - .render(); - } else - solAssert(false, ""); + { + Whiskers bodyTemplate("converted := (((value)))"); + bodyTemplate("cleanInput", cleanupFunction(_from)); + bodyTemplate("cleanOutput", cleanupFunction(_to)); + string convert; + + if (auto const* toFixedBytes = dynamic_cast(&_to)) + convert = shiftLeftFunction(256 - toFixedBytes->numBytes() * 8); + else if (dynamic_cast(&_to)) + solUnimplementedAssert(false, ""); + else if (dynamic_cast(&_to)) + { + solUnimplementedAssert(fromCategory != Type::Category::FixedPoint, ""); + convert = identityFunction(); + } + else if (toCategory == Type::Category::Enum) + { + solAssert(fromCategory != Type::Category::FixedPoint, ""); + convert = identityFunction(); + } + else + solAssert(false, ""); + solAssert(!convert.empty(), ""); + bodyTemplate("convert", convert); + body = bodyTemplate.render(); + } break; } case Type::Category::Bool: diff --git a/libsolidity/codegen/YulUtilFunctions.h b/libsolidity/codegen/YulUtilFunctions.h index 6b7aa1545..a03ee75c2 100644 --- a/libsolidity/codegen/YulUtilFunctions.h +++ b/libsolidity/codegen/YulUtilFunctions.h @@ -59,6 +59,10 @@ public: m_functionCollector(_functionCollector) {} + /// @returns the name of a function that returns its argument. + /// Sometimes needed to satisfy templates. + std::string identityFunction(); + /// @returns a function that combines the address and selector to a single value /// for use in the ABI. std::string combineExternalFunctionIdFunction(); diff --git a/test/cmdlineTests/exp_base_literal/output b/test/cmdlineTests/exp_base_literal/output index b7aaea4ba..1872afbe4 100644 --- a/test/cmdlineTests/exp_base_literal/output +++ b/test/cmdlineTests/exp_base_literal/output @@ -182,36 +182,64 @@ object "C_81" { cleaned := value } + function cleanup_t_rational_0_by_1(value) -> cleaned { + cleaned := value + } + + function cleanup_t_rational_10_by_1(value) -> cleaned { + cleaned := value + } + + function cleanup_t_rational_115792089237316195423570985008687907853269984665640564039457584007913129639935_by_1(value) -> cleaned { + cleaned := value + } + + function cleanup_t_rational_1_by_1(value) -> cleaned { + cleaned := value + } + + function cleanup_t_rational_2_by_1(value) -> cleaned { + cleaned := value + } + + function cleanup_t_rational_minus_1_by_1(value) -> cleaned { + cleaned := value + } + + function cleanup_t_rational_minus_2_by_1(value) -> cleaned { + cleaned := value + } + function cleanup_t_uint256(value) -> cleaned { cleaned := value } function convert_t_rational_0_by_1_to_t_uint256(value) -> converted { - converted := cleanup_t_uint256(value) + converted := cleanup_t_uint256(identity(cleanup_t_rational_0_by_1(value))) } function convert_t_rational_10_by_1_to_t_uint256(value) -> converted { - converted := cleanup_t_uint256(value) + converted := cleanup_t_uint256(identity(cleanup_t_rational_10_by_1(value))) } function convert_t_rational_115792089237316195423570985008687907853269984665640564039457584007913129639935_by_1_to_t_uint256(value) -> converted { - converted := cleanup_t_uint256(value) + converted := cleanup_t_uint256(identity(cleanup_t_rational_115792089237316195423570985008687907853269984665640564039457584007913129639935_by_1(value))) } function convert_t_rational_1_by_1_to_t_uint256(value) -> converted { - converted := cleanup_t_uint256(value) + converted := cleanup_t_uint256(identity(cleanup_t_rational_1_by_1(value))) } function convert_t_rational_2_by_1_to_t_uint256(value) -> converted { - converted := cleanup_t_uint256(value) + converted := cleanup_t_uint256(identity(cleanup_t_rational_2_by_1(value))) } function convert_t_rational_minus_1_by_1_to_t_int256(value) -> converted { - converted := cleanup_t_int256(value) + converted := cleanup_t_int256(identity(cleanup_t_rational_minus_1_by_1(value))) } function convert_t_rational_minus_2_by_1_to_t_int256(value) -> converted { - converted := cleanup_t_int256(value) + converted := cleanup_t_int256(identity(cleanup_t_rational_minus_2_by_1(value))) } /// @src 0:96:368 @@ -340,6 +368,10 @@ object "C_81" { } /// @src 0:82:370 + function identity(value) -> ret { + ret := value + } + function panic_error_0x11() { mstore(0, 35408467139433450592217433187231851964531694900788300625387963629091585785856) mstore(4, 0x11) diff --git a/test/cmdlineTests/name_simplifier/output b/test/cmdlineTests/name_simplifier/output index 7d0fba09f..be3cb3780 100644 --- a/test/cmdlineTests/name_simplifier/output +++ b/test/cmdlineTests/name_simplifier/output @@ -48,7 +48,7 @@ object "C_59" { for { } lt(i, _4) { i := add(i, 1) } { if slt(sub(calldatasize(), src), _2) { revert(_1, _1) } - let value := allocate_memory_1228() + let value := allocate_memory_1236() mstore(value, calldataload(src)) mstore(dst, value) dst := add(dst, _2) @@ -79,7 +79,7 @@ object "C_59" { } tail := add(add(headStart, and(add(length, 31), not(31))), 96) } - function allocate_memory_1228() -> memPtr + function allocate_memory_1236() -> memPtr { memPtr := mload(64) let newFreePtr := add(memPtr, 32) diff --git a/test/cmdlineTests/yul_source_locations/output.json b/test/cmdlineTests/yul_source_locations/output.json index ae7d70556..100249924 100644 --- a/test/cmdlineTests/yul_source_locations/output.json +++ b/test/cmdlineTests/yul_source_locations/output.json @@ -53,6 +53,10 @@ object \"C_54\" { cleaned := value } + function cleanup_t_rational_42_by_1(value) -> cleaned { + cleaned := value + } + /// @src 0:175:223 function constructor_C_54(var__init_12) { @@ -74,11 +78,11 @@ object \"C_54\" { /// @src 0:79:428 function convert_t_int256_to_t_int256(value) -> converted { - converted := cleanup_t_int256(value) + converted := cleanup_t_int256(identity(cleanup_t_int256(value))) } function convert_t_rational_42_by_1_to_t_int256(value) -> converted { - converted := cleanup_t_int256(value) + converted := cleanup_t_int256(identity(cleanup_t_rational_42_by_1(value))) } function copy_arguments_for_constructor_20_object_C_54() -> ret_param_0 { @@ -98,6 +102,10 @@ object \"C_54\" { mstore(64, newFreePtr) } + function identity(value) -> ret { + ret := value + } + function panic_error_0x41() { mstore(0, 35408467139433450592217433187231851964531694900788300625387963629091585785856) mstore(4, 0x41) @@ -261,6 +269,10 @@ object \"C_54\" { cleaned := value } + function cleanup_t_rational_41_by_1(value) -> cleaned { + cleaned := value + } + function cleanup_t_uint160(value) -> cleaned { cleaned := and(value, 0xffffffffffffffffffffffffffffffffffffffff) } @@ -279,11 +291,11 @@ object \"C_54\" { } function convert_t_int256_to_t_int256(value) -> converted { - converted := cleanup_t_int256(value) + converted := cleanup_t_int256(identity(cleanup_t_int256(value))) } function convert_t_rational_41_by_1_to_t_int256(value) -> converted { - converted := cleanup_t_int256(value) + converted := cleanup_t_int256(identity(cleanup_t_rational_41_by_1(value))) } function convert_t_uint160_to_t_address(value) -> converted { @@ -291,7 +303,7 @@ object \"C_54\" { } function convert_t_uint160_to_t_uint160(value) -> converted { - converted := cleanup_t_uint160(value) + converted := cleanup_t_uint160(identity(cleanup_t_uint160(value))) } function extract_from_storage_value_dynamict_int256(slot_value, offset) -> value { @@ -400,6 +412,10 @@ object \"C_54\" { } /// @src 0:79:428 + function identity(value) -> ret { + ret := value + } + function increment_t_int256(value) -> ret { value := cleanup_t_int256(value) if eq(value, 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) { panic_error_0x11() } @@ -610,6 +626,14 @@ object \"D_72\" { cleaned := value } + function cleanup_t_rational_3_by_1(value) -> cleaned { + cleaned := value + } + + function cleanup_t_rational_42_by_1(value) -> cleaned { + cleaned := value + } + /// @src 0:175:223 function constructor_C_54(var__init_12) { @@ -652,15 +676,15 @@ object \"D_72\" { /// @src 1:91:166 function convert_t_int256_to_t_int256(value) -> converted { - converted := cleanup_t_int256(value) + converted := cleanup_t_int256(identity(cleanup_t_int256(value))) } function convert_t_rational_3_by_1_to_t_int256(value) -> converted { - converted := cleanup_t_int256(value) + converted := cleanup_t_int256(identity(cleanup_t_rational_3_by_1(value))) } function convert_t_rational_42_by_1_to_t_int256(value) -> converted { - converted := cleanup_t_int256(value) + converted := cleanup_t_int256(identity(cleanup_t_rational_42_by_1(value))) } function copy_arguments_for_constructor_71_object_D_72() -> ret_param_0 { @@ -684,6 +708,10 @@ object \"D_72\" { mstore(64, newFreePtr) } + function identity(value) -> ret { + ret := value + } + function panic_error_0x11() { mstore(0, 35408467139433450592217433187231851964531694900788300625387963629091585785856) mstore(4, 0x11) @@ -865,6 +893,10 @@ object \"D_72\" { cleaned := value } + function cleanup_t_rational_41_by_1(value) -> cleaned { + cleaned := value + } + function cleanup_t_uint160(value) -> cleaned { cleaned := and(value, 0xffffffffffffffffffffffffffffffffffffffff) } @@ -883,11 +915,11 @@ object \"D_72\" { } function convert_t_int256_to_t_int256(value) -> converted { - converted := cleanup_t_int256(value) + converted := cleanup_t_int256(identity(cleanup_t_int256(value))) } function convert_t_rational_41_by_1_to_t_int256(value) -> converted { - converted := cleanup_t_int256(value) + converted := cleanup_t_int256(identity(cleanup_t_rational_41_by_1(value))) } function convert_t_uint160_to_t_address(value) -> converted { @@ -895,7 +927,7 @@ object \"D_72\" { } function convert_t_uint160_to_t_uint160(value) -> converted { - converted := cleanup_t_uint160(value) + converted := cleanup_t_uint160(identity(cleanup_t_uint160(value))) } function extract_from_storage_value_dynamict_int256(slot_value, offset) -> value { @@ -1004,6 +1036,10 @@ object \"D_72\" { } /// @src 1:91:166 + function identity(value) -> ret { + ret := value + } + function increment_t_int256(value) -> ret { value := cleanup_t_int256(value) if eq(value, 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) { panic_error_0x11() } diff --git a/test/cmdlineTests/yul_string_format_ascii_bytes32_from_number/output.json b/test/cmdlineTests/yul_string_format_ascii_bytes32_from_number/output.json index 09e81312b..e02016c0e 100644 --- a/test/cmdlineTests/yul_string_format_ascii_bytes32_from_number/output.json +++ b/test/cmdlineTests/yul_string_format_ascii_bytes32_from_number/output.json @@ -93,7 +93,7 @@ object \"C_11\" { } function convert_t_rational_1633837924_by_1_to_t_bytes4(value) -> converted { - converted := shift_left_224(cleanup_t_rational_1633837924_by_1(value)) + converted := cleanup_t_bytes4(shift_left_224(cleanup_t_rational_1633837924_by_1(value))) } /// @src 0:91:157 diff --git a/test/cmdlineTests/yul_string_format_hex/output.json b/test/cmdlineTests/yul_string_format_hex/output.json index e944cf5e1..0bce08e79 100644 --- a/test/cmdlineTests/yul_string_format_hex/output.json +++ b/test/cmdlineTests/yul_string_format_hex/output.json @@ -93,7 +93,7 @@ object \"C_11\" { } function convert_t_rational_2864434397_by_1_to_t_bytes4(value) -> converted { - converted := shift_left_224(cleanup_t_rational_2864434397_by_1(value)) + converted := cleanup_t_bytes4(shift_left_224(cleanup_t_rational_2864434397_by_1(value))) } /// @src 0:91:157 diff --git a/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_v2.sol b/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_v2.sol index 52a57fdd0..d475ffa19 100644 --- a/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_v2.sol +++ b/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_v2.sol @@ -54,5 +54,5 @@ contract C { // f3() -> 0x20, 0xa0, 0x1, 0x60, 0x2, 0x3, "abc" // f4() -> 0x20, 0x160, 0x1, 0x80, 0xc0, 0x2, 0x3, "abc", 0x7, 0x40, 0x2, 0x2, 0x3 // gas irOptimized: 113296 -// gas legacy: 114728 +// gas legacy: 114900 // gas legacyOptimized: 112606 diff --git a/test/libsolidity/semanticTests/array/copying/copy_byte_array_to_storage.sol b/test/libsolidity/semanticTests/array/copying/copy_byte_array_to_storage.sol index e48d23e94..26332e6f2 100644 --- a/test/libsolidity/semanticTests/array/copying/copy_byte_array_to_storage.sol +++ b/test/libsolidity/semanticTests/array/copying/copy_byte_array_to_storage.sol @@ -49,5 +49,5 @@ contract C { // ---- // f() -> 0xff // gas irOptimized: 121438 -// gas legacy: 126745 +// gas legacy: 128035 // gas legacyOptimized: 123476 diff --git a/test/libsolidity/semanticTests/array/fixed_arrays_as_return_type.sol b/test/libsolidity/semanticTests/array/fixed_arrays_as_return_type.sol index 03410a6fe..a4c808b57 100644 --- a/test/libsolidity/semanticTests/array/fixed_arrays_as_return_type.sol +++ b/test/libsolidity/semanticTests/array/fixed_arrays_as_return_type.sol @@ -22,5 +22,5 @@ contract B { // ---- // f() -> 2, 3, 4, 5, 6, 1000, 1001, 1002, 1003, 1004 // gas irOptimized: 121038 -// gas legacy: 235167 +// gas legacy: 235339 // gas legacyOptimized: 133299 diff --git a/test/libsolidity/semanticTests/array/push/array_push_struct.sol b/test/libsolidity/semanticTests/array/push/array_push_struct.sol index 4b80a6e03..03a2c53b3 100644 --- a/test/libsolidity/semanticTests/array/push/array_push_struct.sol +++ b/test/libsolidity/semanticTests/array/push/array_push_struct.sol @@ -22,6 +22,6 @@ contract c { // compileViaYul: also // ---- // test() -> 2, 3, 4, 5 -// gas irOptimized: 137059 +// gas irOptimized: 137074 // gas legacy: 147484 // gas legacyOptimized: 146456 diff --git a/test/libsolidity/semanticTests/array/push/array_push_struct_from_calldata.sol b/test/libsolidity/semanticTests/array/push/array_push_struct_from_calldata.sol index b6788c076..272b179e9 100644 --- a/test/libsolidity/semanticTests/array/push/array_push_struct_from_calldata.sol +++ b/test/libsolidity/semanticTests/array/push/array_push_struct_from_calldata.sol @@ -19,5 +19,5 @@ contract c { // ---- // test((uint16,uint16,uint16[3],uint16[])): 0x20, 2, 3, 0, 0, 4, 0xC0, 4, 0, 0, 5, 0, 0 -> 2, 3, 4, 5 // gas irOptimized: 139100 -// gas legacy: 144322 +// gas legacy: 145150 // gas legacyOptimized: 139171 diff --git a/test/libsolidity/semanticTests/events/event_indexed_mixed.sol b/test/libsolidity/semanticTests/events/event_indexed_mixed.sol index e816a4961..d3971c1e9 100644 --- a/test/libsolidity/semanticTests/events/event_indexed_mixed.sol +++ b/test/libsolidity/semanticTests/events/event_indexed_mixed.sol @@ -14,5 +14,5 @@ contract C { // deposit() -> // ~ emit E(uint256,uint256,uint256,bytes): #0x02, 0x01, 0x03, 0x60, 0x03, "def" // gas irOptimized: 23685 -// gas legacy: 24170 +// gas legacy: 24342 // gas legacyOptimized: 23753 diff --git a/test/libsolidity/semanticTests/externalContracts/ramanujan_pi.sol b/test/libsolidity/semanticTests/externalContracts/ramanujan_pi.sol index a2ff8bd75..98eb25470 100644 --- a/test/libsolidity/semanticTests/externalContracts/ramanujan_pi.sol +++ b/test/libsolidity/semanticTests/externalContracts/ramanujan_pi.sol @@ -35,10 +35,10 @@ contract test { // compileViaYul: also // ---- // constructor() -// gas irOptimized: 500656 +// gas irOptimized: 526745 // gas legacy: 733634 // gas legacyOptimized: 478742 // prb_pi() -> 3141592656369545286 -// gas irOptimized: 63037 +// gas irOptimized: 62867 // gas legacy: 98903 // gas legacyOptimized: 75735 diff --git a/test/libsolidity/semanticTests/functionTypes/store_function.sol b/test/libsolidity/semanticTests/functionTypes/store_function.sol index 26f90dd89..9537fda7f 100644 --- a/test/libsolidity/semanticTests/functionTypes/store_function.sol +++ b/test/libsolidity/semanticTests/functionTypes/store_function.sol @@ -29,5 +29,5 @@ contract C { // ---- // t() -> 9 // gas irOptimized: 99004 -// gas legacy: 158997 +// gas legacy: 159083 // gas legacyOptimized: 108916 diff --git a/test/libsolidity/semanticTests/inheritance/address_overload_resolution.sol b/test/libsolidity/semanticTests/inheritance/address_overload_resolution.sol index ca6bd0ca6..651ac994e 100644 --- a/test/libsolidity/semanticTests/inheritance/address_overload_resolution.sol +++ b/test/libsolidity/semanticTests/inheritance/address_overload_resolution.sol @@ -27,4 +27,4 @@ contract D { // gas legacy: 115012 // g() -> 5 // gas irOptimized: 78811 -// gas legacy: 115472 +// gas legacy: 115558 diff --git a/test/libsolidity/semanticTests/salted_create/salted_create_with_value.sol b/test/libsolidity/semanticTests/salted_create/salted_create_with_value.sol index fefd988d7..2e386ee45 100644 --- a/test/libsolidity/semanticTests/salted_create/salted_create_with_value.sol +++ b/test/libsolidity/semanticTests/salted_create/salted_create_with_value.sol @@ -23,5 +23,5 @@ contract A { // ---- // f(), 10 ether -> 3007, 3008, 3009 // gas irOptimized: 270255 -// gas legacy: 422627 +// gas legacy: 422885 // gas legacyOptimized: 287856 diff --git a/test/libsolidity/semanticTests/structs/calldata/calldata_struct_with_nested_array_to_storage.sol b/test/libsolidity/semanticTests/structs/calldata/calldata_struct_with_nested_array_to_storage.sol index 96dd48904..3587d8e17 100644 --- a/test/libsolidity/semanticTests/structs/calldata/calldata_struct_with_nested_array_to_storage.sol +++ b/test/libsolidity/semanticTests/structs/calldata/calldata_struct_with_nested_array_to_storage.sol @@ -19,5 +19,5 @@ contract C { // ---- // f(uint32,(uint128,uint256[][2],uint32)): 55, 0x40, 77, 0x60, 88, 0x40, 0x40, 2, 1, 2 -> 55, 77, 1, 2, 88 // gas irOptimized: 203716 -// gas legacy: 208666 +// gas legacy: 209194 // gas legacyOptimized: 203583 diff --git a/test/libsolidity/semanticTests/various/external_types_in_calls.sol b/test/libsolidity/semanticTests/various/external_types_in_calls.sol index 4aee63b93..229e93fc1 100644 --- a/test/libsolidity/semanticTests/various/external_types_in_calls.sol +++ b/test/libsolidity/semanticTests/various/external_types_in_calls.sol @@ -27,5 +27,5 @@ contract C { // compileViaYul: also // ---- // test() -> 9, 7 -// gas legacy: 125064 +// gas legacy: 130016 // t2() -> 9