Skip to content

Unoptimized IR output has different ordering of functions on different platforms and produces different bytecode #14361

Closed
@cameel

Description

@cameel

Discovered in the via IR bytecode comparison PR (#14355). The PR revealed that unoptimized via IR produces slightly different bytecode on some platforms (specifically emscripten and macOS).

I investigated 288_conditional_with_all_types_sol and in this case the differences are caused by functions being ordered differently in the generated IR.

Repro

Input

input.json
{
    "language": "Solidity",
    "sources": {
        "A": {"content": "
            contract C {
                function f2() public {
                    bytes1[2] memory k;
                    k[0] = bytes1(0);
                }
            }"
        }
    },
    "settings": {
        "optimizer": {"enabled": false},
        "viaIR": true,
        "outputSelection": {
            "*": {"*": [
                "ir",
                "evm.assembly",
                "evm.bytecode.object"
            ]}
        }
    }
}
Script
npm install solc

emscripten_output=$(cat input.json | npx --no -- solcjs --standard-json)
linux_output=$(cat input.json | solc --standard-json)

emscripten_bytecode=$(echo "$emscripten_output" | jq --raw-output .contracts.A.C.evm.bytecode.object | fold --width 80)
emscripten_ir=$(echo "$emscripten_output" | jq --raw-output .contracts.A.C.ir)
emscripten_asm=$(echo "$emscripten_output" | jq --raw-output .contracts.A.C.evm.assembly)

linux_bytecode=$(echo "$linux_output" | jq --raw-output .contracts.A.C.evm.bytecode.object | fold --width 80)
linux_ir=$(echo "$linux_output" | jq --raw-output .contracts.A.C.ir)
linux_asm=$(echo "$linux_output" | jq --raw-output .contracts.A.C.evm.assembly)

echo "=== BYTECODE DIFF ==="
diff --color --unified <(echo "$emscripten_bytecode") <(echo "$linux_bytecode")
echo "=== IR DIFF ==="
diff --color --unified <(echo "$emscripten_ir") <(echo "$linux_ir")
echo "=== ASM DIFF ==="
diff --color --unified <(echo "$emscripten_asm") <(echo "$linux_asm")

Output

Versions
0.8.20+commit.a1b79de6.Emscripten.clang
solc, the solidity compiler commandline interface
Version: 0.8.20+commit.a1b79de6.Linux.g++
Bytecode diff
@@ -13,11 +13,11 @@
 01a7818361017f565b5050919050565b5f6101b96002610187565b905090565b5f81905091905056
 5b5f7fff000000000000000000000000000000000000000000000000000000000000008216905091
 9050565b5f8160f81b9050919050565b5f61021861021361020e846101be565b6101f2565b6101c7
-565b9050919050565b7f4e487b710000000000000000000000000000000000000000000000000000
-00005f52603260045260245ffd5b5f60029050919050565b5f6102608261024c565b831061026f57
-61026e61021f565b5b6020830280830191505092915050565b5f819050919050565b5f8190509190
-50565b5f6102ab6102a66102a1846101be565b610288565b61027f565b9050919050565b6102bb82
+565b9050919050565b5f819050919050565b5f819050919050565b5f61024b610246610241846101
+be565b610228565b61021f565b9050919050565b7f4e487b71000000000000000000000000000000
+000000000000000000000000005f52603260045260245ffd5b5f60029050919050565b5f61029382
+61027f565b83106102a2576102a1610252565b5b6020830280830191505092915050565b6102bb82
 6101c7565b81525050565b60025f6102cc6101ae565b8091505f6102d9816101fe565b83805f8361
-02f8816102f36102ed85610291565b86610256565b6102b2565b505050505050505050565bfea264
+02f8816102f36102ed85610231565b86610289565b6102b2565b505050505050505050565bfea264
 6970667358221220a48f1dac064e7879796321b58551b9e9892676c3ba4d848e77dd46134e985a74
 64736f6c63430008140033
IR diff
@@ -168,6 +168,18 @@
                 converted := cleanup_t_bytes1(shift_left_248(cleanup_t_rational_0_by_1(value)))
             }

+            function cleanup_t_uint256(value) -> cleaned {
+                cleaned := value
+            }
+
+            function identity(value) -> ret {
+                ret := value
+            }
+
+            function convert_t_rational_0_by_1_to_t_uint256(value) -> converted {
+                converted := cleanup_t_uint256(identity(cleanup_t_rational_0_by_1(value)))
+            }
+
             function panic_error_0x32() {
                 mstore(0, 35408467139433450592217433187231851964531694900788300625387963629091585785856)
                 mstore(4, 0x32)
@@ -190,18 +202,6 @@
                 addr := add(baseRef, offset)
             }

-            function cleanup_t_uint256(value) -> cleaned {
-                cleaned := value
-            }
-
-            function identity(value) -> ret {
-                ret := value
-            }
-
-            function convert_t_rational_0_by_1_to_t_uint256(value) -> converted {
-                converted := cleanup_t_uint256(identity(cleanup_t_rational_0_by_1(value)))
-            }
-
             function write_to_memory_t_bytes1(memPtr, value) {
                 mstore(memPtr, cleanup_t_bytes1(value))
             }
Assembly diff
@@ -358,12 +358,17 @@
       pop
       jump     // out
     tag_22:
-      mstore(0x00, 0x4e487b7100000000000000000000000000000000000000000000000000000000)
-      mstore(0x04, 0x32)
-      revert(0x00, 0x24)
+      0x00
+      dup2
+      swap1
+      pop
+      swap2
+      swap1
+      pop
+      jump     // out
     tag_23:
       0x00
-      0x02
+      dup2
       swap1
       pop
       swap2
@@ -373,45 +378,31 @@
     tag_24:
       0x00
       tag_85
-      dup3
-      tag_23
-      jump     // in
-    tag_85:
-      dup4
-      lt
       tag_86
-      jumpi
       tag_87
-      tag_22
+      dup5
+      tag_18
       jump     // in
     tag_87:
+      tag_23
+      jump     // in
     tag_86:
-      0x20
-      dup4
-      mul
-      dup1
-      dup4
-      add
-      swap2
-      pop
-      pop
-      swap3
-      swap2
-      pop
-      pop
-      jump     // out
-    tag_25:
-      0x00
-      dup2
+      tag_22
+      jump     // in
+    tag_85:
       swap1
       pop
       swap2
       swap1
       pop
       jump     // out
+    tag_25:
+      mstore(0x00, 0x4e487b7100000000000000000000000000000000000000000000000000000000)
+      mstore(0x04, 0x32)
+      revert(0x00, 0x24)
     tag_26:
       0x00
-      dup2
+      0x02
       swap1
       pop
       swap2
@@ -421,22 +412,31 @@
     tag_27:
       0x00
       tag_91
+      dup3
+      tag_26
+      jump     // in
+    tag_91:
+      dup4
+      lt
       tag_92
+      jumpi
       tag_93
-      dup5
-      tag_18
+      tag_25
       jump     // in
     tag_93:
-      tag_26
-      jump     // in
     tag_92:
-      tag_25
-      jump     // in
-    tag_91:
-      swap1
+      0x20
+      dup4
+      mul
+      dup1
+      dup4
+      add
+      swap2
+      pop
       pop
+      swap3
       swap2
-      swap1
+      pop
       pop
       jump     // out
     tag_28:
@@ -483,11 +483,11 @@
       tag_100
       tag_101
       dup6
-      tag_27
+      tag_24
       jump     // in
     tag_101:
       dup7
-      tag_24
+      tag_27
       jump     // in
     tag_100:
       tag_28

Metadata

Metadata

Assignees

Type

No type

Projects

Status

Done

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions