diff --git a/crates/codegen/tests/fixtures/sonatina_ir/by_ref_trait_provider_storage_bug.snap b/crates/codegen/tests/fixtures/sonatina_ir/by_ref_trait_provider_storage_bug.snap index 7e75da1383..3731809185 100644 --- a/crates/codegen/tests/fixtures/sonatina_ir/by_ref_trait_provider_storage_bug.snap +++ b/crates/codegen/tests/fixtures/sonatina_ir/by_ref_trait_provider_storage_bug.snap @@ -1,28 +1,27 @@ --- source: crates/codegen/tests/sonatina_ir.rs +assertion_line: 402 expression: output input_file: crates/codegen/tests/fixtures/by_ref_trait_provider_storage_bug.fe --- target = "evm-ethereum-osaka" type @layout_0 = {i256, i256}; -type @layout_1 = {i256, i256}; +type @layout_1 = {@layout_0, i256}; type @layout_2 = {@layout_1, i256}; -type @layout_3 = {@layout_2, i256}; -type @layout_4 = {i256, i256}; -type @layout_5 = {i256, i256}; +type @layout_3 = {i256, i256}; func private %__ByRefTraitProviderStorageBug_init(v0.i256) { block0: jump block1; block1: - v3.objref<@layout_5> = obj.alloc @layout_5; + v3.objref<@layout_3> = obj.alloc @layout_3; v5.objref = obj.proj v3 0.i256; obj.store v5 40.i256; v7.objref = obj.proj v3 1.i256; obj.store v7 2.i256; - v8.@layout_5 = obj.load v3; + v8.@layout_3 = obj.load v3; v10.i256 = extract_value v8 0.i256; evm_sstore v0 v10; v11.i256 = extract_value v8 1.i256; @@ -40,58 +39,6 @@ func private %__ByRefTraitProviderStorageBug_recv_0_0(v0.i256) -> i256 { return v2; } -func private %abi_field_size(v0.i256) -> i256 { - block0: - v1.*i256 = alloca i256; - mstore v1 v0 i256; - jump block1; - - block1: - v2.i256 = mload v1 i256; - v3.i256 = call %core__lib__abi__trait_AbiSize__payload_size__ge513_83d5_0 v2; - br 0.i1 block2 block3; - - block2: - (v7.i256, v8.i1) = uaddo 32.i256 v3; - br v8 block5 block6; - - block3: - jump block4; - - block4: - return v3; - - block5: - mstore 0.i256 35408467139433450592217433187231851964531694900788300625387963629091585785856.i256 i256; - mstore 4.i256 17.i256 i256; - evm_revert 0.i256 36.i256; - - block6: - return v7; -} - -func private %abi_single_root_size(v0.i256) -> i256 { - block0: - v1.*i256 = alloca i256; - mstore v1 v0 i256; - jump block1; - - block1: - v2.i256 = mload v1 i256; - v3.i256 = call %abi_field_size v2; - return v3; -} - -func private %base(v0.objref<@layout_0>) -> i256 { - block0: - jump block1; - - block1: - v3.objref = obj.proj v0 0.i256; - v4.i256 = obj.load v3; - return v4; -} - func private %contract_init_abi_ByRefTraitProviderStorageBug() { block0: jump block1; @@ -124,8 +71,8 @@ func private %contract_init_root_ByRefTraitProviderStorageBug() { func private %contract_recv_abi_ByRefTraitProviderStorageBug_1() { block0: - v0.objref<@layout_1> = obj.alloc @layout_1; - v1.objref<@layout_3> = obj.alloc @layout_3; + v0.objref<@layout_0> = obj.alloc @layout_0; + v1.objref<@layout_2> = obj.alloc @layout_2; jump block1; block1: @@ -155,12 +102,12 @@ func private %contract_recv_abi_ByRefTraitProviderStorageBug_1() { obj.store v19 v16; v21.objref = obj.proj v0 1.i256; obj.store v21 v10; - v22.@layout_1 = obj.load v0; - v23.@layout_3 = call %decoder_new v22; - v24.objref<@layout_2> = obj.proj v1 0.i256; - v25.@layout_2 = extract_value v23 0.i256; - v26.objref<@layout_1> = obj.proj v24 0.i256; - v27.@layout_1 = extract_value v25 0.i256; + v22.@layout_0 = obj.load v0; + v23.@layout_2 = call %decoder_new v22; + v24.objref<@layout_1> = obj.proj v1 0.i256; + v25.@layout_1 = extract_value v23 0.i256; + v26.objref<@layout_0> = obj.proj v24 0.i256; + v27.@layout_0 = extract_value v25 0.i256; v28.objref = obj.proj v26 0.i256; v29.i256 = extract_value v27 0.i256; obj.store v28 v29; @@ -175,19 +122,8 @@ func private %contract_recv_abi_ByRefTraitProviderStorageBug_1() { obj.store v34 v35; call %decode_payload v1; v37.i256 = call %__ByRefTraitProviderStorageBug_recv_0_0 0.i256; - v38.@layout_4 = call %encode_single_root_alloc v37; - v39.objref<@layout_4> = obj.alloc @layout_4; - v40.objref = obj.proj v39 0.i256; - v41.i256 = extract_value v38 0.i256; - obj.store v40 v41; - v42.objref = obj.proj v39 1.i256; - v43.i256 = extract_value v38 1.i256; - obj.store v42 v43; - v44.objref = obj.proj v39 0.i256; - v45.i256 = obj.load v44; - v46.objref = obj.proj v39 1.i256; - v47.i256 = obj.load v46; - evm_return v45 v47; + mstore 0.i256 v37 i256; + evm_return 0.i256 32.i256; } func private %contract_runtime_root_ByRefTraitProviderStorageBug() { @@ -208,7 +144,7 @@ func private %contract_runtime_root_ByRefTraitProviderStorageBug() { unreachable; } -func private %decode_payload(v0.objref<@layout_3>) { +func private %decode_payload(v0.objref<@layout_2>) { block0: jump block1; @@ -216,144 +152,25 @@ func private %decode_payload(v0.objref<@layout_3>) { return; } -func private %decoder_new(v0.@layout_1) -> @layout_3 { +func private %decoder_new(v0.@layout_0) -> @layout_2 { block0: jump block1; block1: - v2.@layout_3 = call %impl_SolDecoder__new__g463e v0; + v2.@layout_2 = call %impl_SolDecoder__new__g463e v0; return v2; } -func private %encode(v0.i256, v1.objref<@layout_0>) { - block0: - jump block1; - - block1: - call %std__lib__abi__sol__impl_trait_SolEncoder_19ce__write_word_e918 v1 v0; - return; -} - -func private %encode_field(v0.i256, v1.objref<@layout_0>, v2.i256) { - block0: - jump block1; - - block1: - br 0.i1 block2 block3; - - block2: - v5.i256 = call %base v1; - v8.i256 = call %core__lib__abi__trait_AbiSize__payload_size__ge513_83d5 v0; - v9.i256 = mload v2 i256; - v10.i256 = sub v9 v5; - call %std__lib__abi__sol__impl_trait_SolEncoder_19ce__write_word_7682 v1 v10; - v12.i256 = call %pos v1; - v13.i256 = mload v2 i256; - call %set_base v1 v13; - v15.i256 = mload v2 i256; - call %set_pos v1 v15; - call %encode v0 v1; - call %set_base v1 v5; - call %set_pos v1 v12; - v20.i256 = mload v2 i256; - v21.i256 = add v20 v8; - mstore v2 v21 i256; - return; - - block3: - jump block4; - - block4: - br 1.i1 block5 block6; - - block5: - v24.i256 = call %pos v1; - call %encode_to_ptr v0 v24; - v28.i256 = add v24 32.i256; - call %set_pos v1 v28; - return; - - block6: - jump block7; - - block7: - call %encode v0 v1; - return; -} - -func private %encode_single_root(v0.i256, v1.objref<@layout_0>) { - block0: - v2.*i256 = alloca i256; - jump block1; - - block1: - v4.i256 = call %base v1; - v6.i256 = add v4 32.i256; - mstore v2 v6 i256; - v7.i256 = ptr_to_int v2 i256; - call %encode_field v0 v1 v7; - return; -} - -func private %encode_single_root_alloc(v0.i256) -> @layout_4 { - block0: - jump block1; - - block1: - v2.i256 = call %abi_single_root_size v0; - v3.@layout_0 = call %encoder_new v2; - v4.objref<@layout_0> = obj.alloc @layout_0; - v6.objref = obj.proj v4 0.i256; - v7.i256 = extract_value v3 0.i256; - obj.store v6 v7; - v9.objref = obj.proj v4 1.i256; - v10.i256 = extract_value v3 1.i256; - obj.store v9 v10; - v11.i256 = call %base v4; - call %encode_single_root v0 v4; - v13.objref<@layout_4> = obj.alloc @layout_4; - v14.objref = obj.proj v13 0.i256; - obj.store v14 v11; - v15.objref = obj.proj v13 1.i256; - obj.store v15 v2; - v16.@layout_4 = obj.load v13; - return v16; -} - -func private %encode_to_ptr(v0.i256, v1.i256) { - block0: - v2.*i256 = alloca i256; - mstore v2 v1 i256; - jump block1; - - block1: - v3.i256 = mload v2 i256; - call %store_word v3 v0; - return; -} - -func private %encoder_new(v0.i256) -> @layout_0 { - block0: - v1.*i256 = alloca i256; - mstore v1 v0 i256; - jump block1; - - block1: - v2.i256 = mload v1 i256; - v3.@layout_0 = call %impl_SolEncoder__new v2; - return v3; -} - -func private %impl_SolDecoder__new__g463e(v0.@layout_1) -> @layout_3 { +func private %impl_SolDecoder__new__g463e(v0.@layout_0) -> @layout_2 { block0: jump block1; block1: - v2.@layout_2 = call %impl_Cursor__new__g463e v0; - v4.objref<@layout_3> = obj.alloc @layout_3; - v5.objref<@layout_2> = obj.proj v4 0.i256; - v6.objref<@layout_1> = obj.proj v5 0.i256; - v7.@layout_1 = extract_value v2 0.i256; + v2.@layout_1 = call %impl_Cursor__new__g463e v0; + v4.objref<@layout_2> = obj.alloc @layout_2; + v5.objref<@layout_1> = obj.proj v4 0.i256; + v6.objref<@layout_0> = obj.proj v5 0.i256; + v7.@layout_0 = extract_value v2 0.i256; v8.objref = obj.proj v6 0.i256; v9.i256 = extract_value v7 0.i256; obj.store v8 v9; @@ -365,17 +182,17 @@ func private %impl_SolDecoder__new__g463e(v0.@layout_1) -> @layout_3 { obj.store v13 v14; v15.objref = obj.proj v4 1.i256; obj.store v15 0.i256; - v16.@layout_3 = obj.load v4; + v16.@layout_2 = obj.load v4; return v16; } -func private %impl_Cursor__new__g463e(v0.@layout_1) -> @layout_2 { +func private %impl_Cursor__new__g463e(v0.@layout_0) -> @layout_1 { block0: jump block1; block1: - v2.objref<@layout_2> = obj.alloc @layout_2; - v4.objref<@layout_1> = obj.proj v2 0.i256; + v2.objref<@layout_1> = obj.alloc @layout_1; + v4.objref<@layout_0> = obj.proj v2 0.i256; v5.objref = obj.proj v4 0.i256; v6.i256 = extract_value v0 0.i256; obj.store v5 v6; @@ -384,112 +201,10 @@ func private %impl_Cursor__new__g463e(v0.@layout_1) -> @layout_2 { obj.store v8 v9; v10.objref = obj.proj v2 1.i256; obj.store v10 0.i256; - v11.@layout_2 = obj.load v2; + v11.@layout_1 = obj.load v2; return v11; } -func private %impl_SolEncoder__new(v0.i256) -> @layout_0 { - block0: - v1.*i256 = alloca i256; - mstore v1 v0 i256; - jump block1; - - block1: - v2.i256 = mload v1 i256; - v4.i1 = eq v2 0.i256; - br v4 block2 block3; - - block2: - jump block4; - - block3: - v5.i256 = mload v1 i256; - v6.*i8 = evm_malloc v5; - v7.i256 = ptr_to_int v6 i256; - jump block4; - - block4: - v8.i256 = phi (0.i256 block2) (v7 block3); - v9.objref<@layout_0> = obj.alloc @layout_0; - v10.objref = obj.proj v9 0.i256; - obj.store v10 v8; - v12.objref = obj.proj v9 1.i256; - obj.store v12 v8; - v13.@layout_0 = obj.load v9; - return v13; -} - -func private %core__lib__abi__trait_AbiSize__payload_size__ge513_83d5(v0.i256) -> i256 { - block0: - v1.*i256 = alloca i256; - mstore v1 v0 i256; - jump block1; - - block1: - return 32.i256; -} - -func private %core__lib__abi__trait_AbiSize__payload_size__ge513_83d5_0(v0.i256) -> i256 { - block0: - v1.*i256 = alloca i256; - mstore v1 v0 i256; - jump block1; - - block1: - return 32.i256; -} - -func private %pos(v0.objref<@layout_0>) -> i256 { - block0: - jump block1; - - block1: - v3.objref = obj.proj v0 1.i256; - v4.i256 = obj.load v3; - return v4; -} - -func private %set_base(v0.objref<@layout_0>, v1.i256) { - block0: - v2.*i256 = alloca i256; - mstore v2 v1 i256; - jump block1; - - block1: - v3.i256 = mload v2 i256; - v6.objref = obj.proj v0 0.i256; - obj.store v6 v3; - return; -} - -func private %set_pos(v0.objref<@layout_0>, v1.i256) { - block0: - v2.*i256 = alloca i256; - mstore v2 v1 i256; - jump block1; - - block1: - v3.i256 = mload v2 i256; - v6.objref = obj.proj v0 1.i256; - obj.store v6 v3; - return; -} - -func private %store_word(v0.i256, v1.i256) { - block0: - v2.*i256 = alloca i256; - v3.*i256 = alloca i256; - mstore v2 v0 i256; - mstore v3 v1 i256; - jump block1; - - block1: - v4.i256 = mload v2 i256; - v5.i256 = mload v3 i256; - mstore v4 v5 i256; - return; -} - func private %sum(v0.i256) -> i256 { block0: jump block1; @@ -519,40 +234,6 @@ func private %use_ctx(v0.i256) -> i256 { return v2; } -func private %std__lib__abi__sol__impl_trait_SolEncoder_19ce__write_word_7682(v0.objref<@layout_0>, v1.i256) { - block0: - v2.*i256 = alloca i256; - mstore v2 v1 i256; - jump block1; - - block1: - v5.objref = obj.proj v0 1.i256; - v6.i256 = obj.load v5; - v7.i256 = mload v2 i256; - mstore v6 v7 i256; - v10.i256 = add v6 32.i256; - v11.objref = obj.proj v0 1.i256; - obj.store v11 v10; - return; -} - -func private %std__lib__abi__sol__impl_trait_SolEncoder_19ce__write_word_e918(v0.objref<@layout_0>, v1.i256) { - block0: - v2.*i256 = alloca i256; - mstore v2 v1 i256; - jump block1; - - block1: - v5.objref = obj.proj v0 1.i256; - v6.i256 = obj.load v5; - v7.i256 = mload v2 i256; - mstore v6 v7 i256; - v10.i256 = add v6 32.i256; - v11.objref = obj.proj v0 1.i256; - obj.store v11 v10; - return; -} - object @ByRefTraitProviderStorageBug { section init { diff --git a/crates/codegen/tests/fixtures/sonatina_ir/create_contract.snap b/crates/codegen/tests/fixtures/sonatina_ir/create_contract.snap index 821cf6c6c3..1134fee33a 100644 --- a/crates/codegen/tests/fixtures/sonatina_ir/create_contract.snap +++ b/crates/codegen/tests/fixtures/sonatina_ir/create_contract.snap @@ -1,5 +1,6 @@ --- source: crates/codegen/tests/sonatina_ir.rs +assertion_line: 402 expression: output input_file: crates/codegen/tests/fixtures/create_contract.fe --- @@ -13,8 +14,6 @@ type @layout_4 = {i256, i256}; type @layout_5 = {i256, i256}; type @layout_6 = {@layout_5, i256}; type @layout_7 = {@layout_6, i256}; -type @layout_8 = {i256, i256}; -type @layout_9 = {i256, i256, i256}; func private %__Child_init(v0.i256, v1.i256, v2.i256) { block0: @@ -166,27 +165,7 @@ func private %std__lib__abi__sol__impl_trait_SolEncoder_19ce__base_5cdf(v0.objre return v4; } -func private %std__lib__abi__sol__impl_trait_SolDecoder_68ab__base__g463e_a76a(v0.objref<@layout_7>) -> i256 { - block0: - jump block1; - - block1: - v3.objref = obj.proj v0 1.i256; - v4.i256 = obj.load v3; - return v4; -} - -func private %std__lib__abi__sol__impl_trait_SolDecoder_68ab__base__g463e_c677(v0.objref<@layout_7>) -> i256 { - block0: - jump block1; - - block1: - v3.objref = obj.proj v0 1.i256; - v4.i256 = obj.load v3; - return v4; -} - -func private %std__lib__abi__sol__impl_trait_SolDecoder_68ab__base__g463e_d017(v0.objref<@layout_7>) -> i256 { +func private %base__g463e(v0.objref<@layout_7>) -> i256 { block0: jump block1; @@ -238,7 +217,7 @@ func private %contract_init_abi_Child() { v25.objref = obj.proj v0 1.i256; obj.store v25 v13; v26.@layout_5 = obj.load v0; - v27.@layout_7 = call %std__lib__abi__sol__impl_trait_Sol_1f5f__decoder_new__g463e_badd_0 v26; + v27.@layout_7 = call %decoder_new v26; v28.objref<@layout_6> = obj.proj v1 0.i256; v29.@layout_6 = extract_value v27 0.i256; v30.objref<@layout_5> = obj.proj v28 0.i256; @@ -314,167 +293,69 @@ func private %contract_init_root_Factory() { func private %contract_recv_abi_Factory_1() { block0: - v0.objref<@layout_5> = obj.alloc @layout_5; - v1.objref<@layout_7> = obj.alloc @layout_7; jump block1; block1: - v4.i256 = evm_call_value; - v5.i1 = eq v4 0.i256; - v6.i1 = is_zero v5; - br v6 block2 block3; + v2.i256 = evm_call_value; + v3.i1 = eq v2 0.i256; + v4.i1 = is_zero v3; + br v4 block2 block3; block2: evm_revert 0.i256 0.i256; block3: - v8.i256 = evm_calldata_size; - (v10.i256, v11.i1) = usubo v8 4.i256; - br v11 block4 block5; - - block4: - mstore 0.i256 35408467139433450592217433187231851964531694900788300625387963629091585785856.i256 i256; - mstore 4.i256 17.i256 i256; - evm_revert 0.i256 36.i256; - - block5: - v15.*i8 = evm_malloc v10; - v16.i256 = ptr_to_int v15 i256; - evm_calldata_copy v16 4.i256 v10; - v19.objref = obj.proj v0 0.i256; - obj.store v19 v16; - v21.objref = obj.proj v0 1.i256; - obj.store v21 v10; - v22.@layout_5 = obj.load v0; - v23.@layout_7 = call %std__lib__abi__sol__impl_trait_Sol_1f5f__decoder_new__g463e_badd v22; - v24.objref<@layout_6> = obj.proj v1 0.i256; - v25.@layout_6 = extract_value v23 0.i256; - v26.objref<@layout_5> = obj.proj v24 0.i256; - v27.@layout_5 = extract_value v25 0.i256; - v28.objref = obj.proj v26 0.i256; - v29.i256 = extract_value v27 0.i256; - obj.store v28 v29; - v30.objref = obj.proj v26 1.i256; - v31.i256 = extract_value v27 1.i256; - obj.store v30 v31; - v32.objref = obj.proj v24 1.i256; - v33.i256 = extract_value v25 1.i256; - obj.store v32 v33; - v34.objref = obj.proj v1 1.i256; - v35.i256 = extract_value v23 1.i256; - obj.store v34 v35; - v36.@layout_8 = call %impl_trait_Deploy__decode_payload__gf196 v1; - v37.objref<@layout_8> = obj.alloc @layout_8; - v38.objref = obj.proj v37 0.i256; - v39.i256 = extract_value v36 0.i256; - obj.store v38 v39; - v40.objref = obj.proj v37 1.i256; - v41.i256 = extract_value v36 1.i256; - obj.store v40 v41; - v42.objref = obj.proj v37 0.i256; - v43.i256 = obj.load v42; - v44.objref = obj.proj v37 1.i256; - v45.i256 = obj.load v44; - v46.objref<@layout_1> = obj.alloc @layout_1; - v47.@layout_2 = call %__Factory_recv_0_0 v43 v45 v46; - v48.@layout_3 = call %encode_single_root_alloc v47; - v49.objref<@layout_3> = obj.alloc @layout_3; - v50.objref = obj.proj v49 0.i256; - v51.i256 = extract_value v48 0.i256; - obj.store v50 v51; - v52.objref = obj.proj v49 1.i256; - v53.i256 = extract_value v48 1.i256; - obj.store v52 v53; - v54.objref = obj.proj v49 0.i256; - v55.i256 = obj.load v54; - v56.objref = obj.proj v49 1.i256; - v57.i256 = obj.load v56; - evm_return v55 v57; + v6.i256 = evm_calldata_load 4.i256; + v8.i256 = evm_calldata_load 36.i256; + v9.objref<@layout_1> = obj.alloc @layout_1; + v10.@layout_2 = call %__Factory_recv_0_0 v6 v8 v9; + v11.@layout_3 = call %encode_single_root_alloc v10; + v12.objref<@layout_3> = obj.alloc @layout_3; + v13.objref = obj.proj v12 0.i256; + v14.i256 = extract_value v11 0.i256; + obj.store v13 v14; + v16.objref = obj.proj v12 1.i256; + v17.i256 = extract_value v11 1.i256; + obj.store v16 v17; + v18.objref = obj.proj v12 0.i256; + v19.i256 = obj.load v18; + v20.objref = obj.proj v12 1.i256; + v21.i256 = obj.load v20; + evm_return v19 v21; } func private %contract_recv_abi_Factory_2() { block0: - v0.objref<@layout_5> = obj.alloc @layout_5; - v1.objref<@layout_7> = obj.alloc @layout_7; jump block1; block1: - v4.i256 = evm_call_value; - v5.i1 = eq v4 0.i256; - v6.i1 = is_zero v5; - br v6 block2 block3; + v2.i256 = evm_call_value; + v3.i1 = eq v2 0.i256; + v4.i1 = is_zero v3; + br v4 block2 block3; block2: evm_revert 0.i256 0.i256; block3: - v8.i256 = evm_calldata_size; - (v10.i256, v11.i1) = usubo v8 4.i256; - br v11 block4 block5; - - block4: - mstore 0.i256 35408467139433450592217433187231851964531694900788300625387963629091585785856.i256 i256; - mstore 4.i256 17.i256 i256; - evm_revert 0.i256 36.i256; - - block5: - v15.*i8 = evm_malloc v10; - v16.i256 = ptr_to_int v15 i256; - evm_calldata_copy v16 4.i256 v10; - v19.objref = obj.proj v0 0.i256; - obj.store v19 v16; - v21.objref = obj.proj v0 1.i256; - obj.store v21 v10; - v22.@layout_5 = obj.load v0; - v23.@layout_7 = call %std__lib__abi__sol__impl_trait_Sol_1f5f__decoder_new__g463e_badd v22; - v24.objref<@layout_6> = obj.proj v1 0.i256; - v25.@layout_6 = extract_value v23 0.i256; - v26.objref<@layout_5> = obj.proj v24 0.i256; - v27.@layout_5 = extract_value v25 0.i256; - v28.objref = obj.proj v26 0.i256; - v29.i256 = extract_value v27 0.i256; - obj.store v28 v29; - v30.objref = obj.proj v26 1.i256; - v31.i256 = extract_value v27 1.i256; - obj.store v30 v31; - v32.objref = obj.proj v24 1.i256; - v33.i256 = extract_value v25 1.i256; - obj.store v32 v33; - v34.objref = obj.proj v1 1.i256; - v35.i256 = extract_value v23 1.i256; - obj.store v34 v35; - v36.@layout_9 = call %impl_trait_Deploy2__decode_payload__gf196 v1; - v37.objref<@layout_9> = obj.alloc @layout_9; - v38.objref = obj.proj v37 0.i256; - v39.i256 = extract_value v36 0.i256; - obj.store v38 v39; - v40.objref = obj.proj v37 1.i256; - v41.i256 = extract_value v36 1.i256; - obj.store v40 v41; - v43.objref = obj.proj v37 2.i256; - v44.i256 = extract_value v36 2.i256; - obj.store v43 v44; - v45.objref = obj.proj v37 0.i256; - v46.i256 = obj.load v45; - v47.objref = obj.proj v37 1.i256; - v48.i256 = obj.load v47; - v49.objref = obj.proj v37 2.i256; - v50.i256 = obj.load v49; - v51.objref<@layout_1> = obj.alloc @layout_1; - v52.@layout_2 = call %__Factory_recv_0_1 v46 v48 v50 v51; - v53.@layout_3 = call %encode_single_root_alloc v52; - v54.objref<@layout_3> = obj.alloc @layout_3; - v55.objref = obj.proj v54 0.i256; - v56.i256 = extract_value v53 0.i256; - obj.store v55 v56; - v57.objref = obj.proj v54 1.i256; - v58.i256 = extract_value v53 1.i256; - obj.store v57 v58; - v59.objref = obj.proj v54 0.i256; - v60.i256 = obj.load v59; - v61.objref = obj.proj v54 1.i256; - v62.i256 = obj.load v61; - evm_return v60 v62; + v6.i256 = evm_calldata_load 4.i256; + v8.i256 = evm_calldata_load 36.i256; + v10.i256 = evm_calldata_load 68.i256; + v11.objref<@layout_1> = obj.alloc @layout_1; + v12.@layout_2 = call %__Factory_recv_0_1 v6 v8 v10 v11; + v13.@layout_3 = call %encode_single_root_alloc v12; + v14.objref<@layout_3> = obj.alloc @layout_3; + v15.objref = obj.proj v14 0.i256; + v16.i256 = extract_value v13 0.i256; + obj.store v15 v16; + v18.objref = obj.proj v14 1.i256; + v19.i256 = extract_value v13 1.i256; + obj.store v18 v19; + v20.objref = obj.proj v14 0.i256; + v21.i256 = obj.load v20; + v22.objref = obj.proj v14 1.i256; + v23.i256 = obj.load v22; + evm_return v21 v23; } func private %contract_runtime_root_Child() { @@ -826,79 +707,7 @@ func private %create_raw(v0.objref<@layout_1>, v1.i256, v2.i256, v3.i256) -> @la return v14; } -func private %core__lib__abi__decode_field__g3854_7ff1(v0.objref<@layout_7>) -> i256 { - block0: - jump block1; - - block1: - br 0.i1 block2 block3; - - block2: - v3.i256 = call %std__lib__abi__sol__impl_trait_SolDecoder_68ab__read_word__g463e_3bfc v0; - v4.i256 = call %std__lib__abi__sol__impl_trait_SolDecoder_68ab__base__g463e_a76a v0; - v5.i256 = call %std__lib__abi__sol__impl_trait_SolDecoder_68ab__pos__g463e_ad58 v0; - (v6.i256, v7.i1) = uaddo v4 v3; - br v7 block5 block6; - - block3: - jump block4; - - block4: - v23.i256 = call %core__lib__abi__impl_trait_u256_85b6__decode_payload__g407e_a2fc v0; - return v23; - - block5: - mstore 0.i256 35408467139433450592217433187231851964531694900788300625387963629091585785856.i256 i256; - mstore 4.i256 17.i256 i256; - evm_revert 0.i256 36.i256; - - block6: - call %std__lib__abi__sol__impl_trait_SolDecoder_68ab__set_base__g463e_c080 v0 v6; - v15.i256 = call %std__lib__abi__sol__impl_trait_SolDecoder_68ab__base__g463e_a76a v0; - call %std__lib__abi__sol__impl_trait_SolDecoder_68ab__set_pos__g463e_7f62 v0 v15; - v17.i256 = call %core__lib__abi__impl_trait_u256_85b6__decode_payload__g407e_a2fc v0; - call %std__lib__abi__sol__impl_trait_SolDecoder_68ab__set_base__g463e_c080 v0 v4; - call %std__lib__abi__sol__impl_trait_SolDecoder_68ab__set_pos__g463e_7f62 v0 v5; - return v17; -} - -func private %core__lib__abi__decode_field__g3854_ae51(v0.objref<@layout_7>) -> i256 { - block0: - jump block1; - - block1: - br 0.i1 block2 block3; - - block2: - v3.i256 = call %std__lib__abi__sol__impl_trait_SolDecoder_68ab__read_word__g463e_bdd2 v0; - v4.i256 = call %std__lib__abi__sol__impl_trait_SolDecoder_68ab__base__g463e_d017 v0; - v5.i256 = call %std__lib__abi__sol__impl_trait_SolDecoder_68ab__pos__g463e_6e96 v0; - (v6.i256, v7.i1) = uaddo v4 v3; - br v7 block5 block6; - - block3: - jump block4; - - block4: - v23.i256 = call %core__lib__abi__impl_trait_u256_85b6__decode_payload__g407e_6da3 v0; - return v23; - - block5: - mstore 0.i256 35408467139433450592217433187231851964531694900788300625387963629091585785856.i256 i256; - mstore 4.i256 17.i256 i256; - evm_revert 0.i256 36.i256; - - block6: - call %std__lib__abi__sol__impl_trait_SolDecoder_68ab__set_base__g463e_8106 v0 v6; - v15.i256 = call %std__lib__abi__sol__impl_trait_SolDecoder_68ab__base__g463e_d017 v0; - call %std__lib__abi__sol__impl_trait_SolDecoder_68ab__set_pos__g463e_010d v0 v15; - v17.i256 = call %core__lib__abi__impl_trait_u256_85b6__decode_payload__g407e_6da3 v0; - call %std__lib__abi__sol__impl_trait_SolDecoder_68ab__set_base__g463e_8106 v0 v4; - call %std__lib__abi__sol__impl_trait_SolDecoder_68ab__set_pos__g463e_010d v0 v5; - return v17; -} - -func private %core__lib__abi__decode_field__g3854_f9bf(v0.objref<@layout_7>) -> i256 { +func private %decode_field(v0.objref<@layout_7>) -> i256 { block0: jump block1; @@ -907,8 +716,8 @@ func private %core__lib__abi__decode_field__g3854_f9bf(v0.objref<@layout_7>) -> block2: v3.i256 = call %std__lib__abi__sol__impl_trait_SolDecoder_68ab__read_word__g463e_0984 v0; - v4.i256 = call %std__lib__abi__sol__impl_trait_SolDecoder_68ab__base__g463e_c677 v0; - v5.i256 = call %std__lib__abi__sol__impl_trait_SolDecoder_68ab__pos__g463e_8da8 v0; + v4.i256 = call %base__g463e v0; + v5.i256 = call %pos__g463e v0; (v6.i256, v7.i1) = uaddo v4 v3; br v7 block5 block6; @@ -916,7 +725,7 @@ func private %core__lib__abi__decode_field__g3854_f9bf(v0.objref<@layout_7>) -> jump block4; block4: - v23.i256 = call %core__lib__abi__impl_trait_u256_85b6__decode_payload__g407e_fcef v0; + v23.i256 = call %decode_payload__g407e v0; return v23; block5: @@ -925,75 +734,22 @@ func private %core__lib__abi__decode_field__g3854_f9bf(v0.objref<@layout_7>) -> evm_revert 0.i256 36.i256; block6: - call %std__lib__abi__sol__impl_trait_SolDecoder_68ab__set_base__g463e_504e v0 v6; - v15.i256 = call %std__lib__abi__sol__impl_trait_SolDecoder_68ab__base__g463e_c677 v0; - call %std__lib__abi__sol__impl_trait_SolDecoder_68ab__set_pos__g463e_7f12 v0 v15; - v17.i256 = call %core__lib__abi__impl_trait_u256_85b6__decode_payload__g407e_fcef v0; - call %std__lib__abi__sol__impl_trait_SolDecoder_68ab__set_base__g463e_504e v0 v4; - call %std__lib__abi__sol__impl_trait_SolDecoder_68ab__set_pos__g463e_7f12 v0 v5; + call %set_base__g463e v0 v6; + v15.i256 = call %base__g463e v0; + call %set_pos__g463e v0 v15; + v17.i256 = call %decode_payload__g407e v0; + call %set_base__g463e v0 v4; + call %set_pos__g463e v0 v5; return v17; } -func private %impl_trait_Deploy__decode_payload__gf196(v0.objref<@layout_7>) -> @layout_8 { - block0: - jump block1; - - block1: - v2.i256 = call %core__lib__abi__decode_field__g3854_ae51 v0; - v3.i256 = call %core__lib__abi__decode_field__g3854_ae51 v0; - v4.objref<@layout_8> = obj.alloc @layout_8; - v6.objref = obj.proj v4 0.i256; - obj.store v6 v2; - v8.objref = obj.proj v4 1.i256; - obj.store v8 v3; - v9.@layout_8 = obj.load v4; - return v9; -} - -func private %core__lib__abi__impl_trait_u256_85b6__decode_payload__g407e_6da3(v0.objref<@layout_7>) -> i256 { - block0: - jump block1; - - block1: - v2.i256 = call %std__lib__abi__sol__impl_trait_SolDecoder_68ab__read_word__g463e_e372 v0; - return v2; -} - -func private %core__lib__abi__impl_trait_u256_85b6__decode_payload__g407e_a2fc(v0.objref<@layout_7>) -> i256 { - block0: - jump block1; - - block1: - v2.i256 = call %std__lib__abi__sol__impl_trait_SolDecoder_68ab__read_word__g463e_be19 v0; - return v2; -} - -func private %impl_trait_Deploy2__decode_payload__gf196(v0.objref<@layout_7>) -> @layout_9 { - block0: - jump block1; - - block1: - v2.i256 = call %core__lib__abi__decode_field__g3854_7ff1 v0; - v3.i256 = call %core__lib__abi__decode_field__g3854_7ff1 v0; - v4.i256 = call %core__lib__abi__decode_field__g3854_7ff1 v0; - v5.objref<@layout_9> = obj.alloc @layout_9; - v7.objref = obj.proj v5 0.i256; - obj.store v7 v2; - v9.objref = obj.proj v5 1.i256; - obj.store v9 v3; - v11.objref = obj.proj v5 2.i256; - obj.store v11 v4; - v12.@layout_9 = obj.load v5; - return v12; -} - func private %decode_payload__g4770(v0.objref<@layout_7>) -> @layout_3 { block0: jump block1; block1: - v2.i256 = call %core__lib__abi__decode_field__g3854_f9bf v0; - v3.i256 = call %core__lib__abi__decode_field__g3854_f9bf v0; + v2.i256 = call %decode_field v0; + v3.i256 = call %decode_field v0; v4.objref<@layout_3> = obj.alloc @layout_3; v6.objref = obj.proj v4 0.i256; obj.store v6 v2; @@ -1003,7 +759,7 @@ func private %decode_payload__g4770(v0.objref<@layout_7>) -> @layout_3 { return v9; } -func private %core__lib__abi__impl_trait_u256_85b6__decode_payload__g407e_fcef(v0.objref<@layout_7>) -> i256 { +func private %decode_payload__g407e(v0.objref<@layout_7>) -> i256 { block0: jump block1; @@ -1012,21 +768,12 @@ func private %core__lib__abi__impl_trait_u256_85b6__decode_payload__g407e_fcef(v return v2; } -func private %std__lib__abi__sol__impl_trait_Sol_1f5f__decoder_new__g463e_badd(v0.@layout_5) -> @layout_7 { - block0: - jump block1; - - block1: - v2.@layout_7 = call %std__lib__abi__sol__impl_SolDecoder_113c__new__g463e_ff02_0 v0; - return v2; -} - -func private %std__lib__abi__sol__impl_trait_Sol_1f5f__decoder_new__g463e_badd_0(v0.@layout_5) -> @layout_7 { +func private %decoder_new(v0.@layout_5) -> @layout_7 { block0: jump block1; block1: - v2.@layout_7 = call %std__lib__abi__sol__impl_SolDecoder_113c__new__g463e_ff02 v0; + v2.@layout_7 = call %impl_SolDecoder__new__g463e v0; return v2; } @@ -1331,57 +1078,6 @@ func private %std__lib__abi__sol__impl_trait_Sol_1f5f__encoder_new_c533(v0.i256) return v3; } -func private %std__lib__evm__memory_input__impl_trait_MemoryBytes_c1cd__len_3a5b(v0.@layout_5) -> i256 { - block0: - v1.objref<@layout_5> = obj.alloc @layout_5; - v3.objref = obj.proj v1 0.i256; - v4.i256 = extract_value v0 0.i256; - obj.store v3 v4; - v6.objref = obj.proj v1 1.i256; - v7.i256 = extract_value v0 1.i256; - obj.store v6 v7; - jump block1; - - block1: - v8.objref = obj.proj v1 1.i256; - v9.i256 = obj.load v8; - return v9; -} - -func private %std__lib__evm__memory_input__impl_trait_MemoryBytes_c1cd__len_7357(v0.@layout_5) -> i256 { - block0: - v1.objref<@layout_5> = obj.alloc @layout_5; - v3.objref = obj.proj v1 0.i256; - v4.i256 = extract_value v0 0.i256; - obj.store v3 v4; - v6.objref = obj.proj v1 1.i256; - v7.i256 = extract_value v0 1.i256; - obj.store v6 v7; - jump block1; - - block1: - v8.objref = obj.proj v1 1.i256; - v9.i256 = obj.load v8; - return v9; -} - -func private %std__lib__evm__memory_input__impl_trait_MemoryBytes_c1cd__len_7ae6(v0.@layout_5) -> i256 { - block0: - v1.objref<@layout_5> = obj.alloc @layout_5; - v3.objref = obj.proj v1 0.i256; - v4.i256 = extract_value v0 0.i256; - obj.store v3 v4; - v6.objref = obj.proj v1 1.i256; - v7.i256 = extract_value v0 1.i256; - obj.store v6 v7; - jump block1; - - block1: - v8.objref = obj.proj v1 1.i256; - v9.i256 = obj.load v8; - return v9; -} - func private %std__lib__evm__memory_input__impl_trait_MemoryBytes_c1cd__len_afea(v0.@layout_5) -> i256 { block0: v1.objref<@layout_5> = obj.alloc @layout_5; @@ -1399,23 +1095,6 @@ func private %std__lib__evm__memory_input__impl_trait_MemoryBytes_c1cd__len_afea return v9; } -func private %std__lib__evm__memory_input__impl_trait_MemoryBytes_c1cd__len_f2e9(v0.@layout_5) -> i256 { - block0: - v1.objref<@layout_5> = obj.alloc @layout_5; - v3.objref = obj.proj v1 0.i256; - v4.i256 = extract_value v0 0.i256; - obj.store v3 v4; - v6.objref = obj.proj v1 1.i256; - v7.i256 = extract_value v0 1.i256; - obj.store v6 v7; - jump block1; - - block1: - v8.objref = obj.proj v1 1.i256; - v9.i256 = obj.load v8; - return v9; -} - func private %std__lib__evm__memory_input__impl_trait_MemoryBytes_c1cd__len_f8f2(v0.@layout_5) -> i256 { block0: v1.objref<@layout_5> = obj.alloc @layout_5; @@ -1433,26 +1112,7 @@ func private %std__lib__evm__memory_input__impl_trait_MemoryBytes_c1cd__len_f8f2 return v9; } -func private %core__lib__abi__impl_Cursor_1a04__new__g463e_15c7(v0.@layout_5) -> @layout_6 { - block0: - jump block1; - - block1: - v2.objref<@layout_6> = obj.alloc @layout_6; - v4.objref<@layout_5> = obj.proj v2 0.i256; - v5.objref = obj.proj v4 0.i256; - v6.i256 = extract_value v0 0.i256; - obj.store v5 v6; - v8.objref = obj.proj v4 1.i256; - v9.i256 = extract_value v0 1.i256; - obj.store v8 v9; - v10.objref = obj.proj v2 1.i256; - obj.store v10 0.i256; - v11.@layout_6 = obj.load v2; - return v11; -} - -func private %core__lib__abi__impl_Cursor_1a04__new__g463e_15c7_0(v0.@layout_5) -> @layout_6 { +func private %impl_Cursor__new__g463e(v0.@layout_5) -> @layout_6 { block0: jump block1; @@ -1533,37 +1193,12 @@ func private %std__lib__abi__sol__impl_SolEncoder_ce34__new_aa27(v0.i256) -> @la return v13; } -func private %std__lib__abi__sol__impl_SolDecoder_113c__new__g463e_ff02(v0.@layout_5) -> @layout_7 { - block0: - jump block1; - - block1: - v2.@layout_6 = call %core__lib__abi__impl_Cursor_1a04__new__g463e_15c7 v0; - v4.objref<@layout_7> = obj.alloc @layout_7; - v5.objref<@layout_6> = obj.proj v4 0.i256; - v6.objref<@layout_5> = obj.proj v5 0.i256; - v7.@layout_5 = extract_value v2 0.i256; - v8.objref = obj.proj v6 0.i256; - v9.i256 = extract_value v7 0.i256; - obj.store v8 v9; - v11.objref = obj.proj v6 1.i256; - v12.i256 = extract_value v7 1.i256; - obj.store v11 v12; - v13.objref = obj.proj v5 1.i256; - v14.i256 = extract_value v2 1.i256; - obj.store v13 v14; - v15.objref = obj.proj v4 1.i256; - obj.store v15 0.i256; - v16.@layout_7 = obj.load v4; - return v16; -} - -func private %std__lib__abi__sol__impl_SolDecoder_113c__new__g463e_ff02_0(v0.@layout_5) -> @layout_7 { +func private %impl_SolDecoder__new__g463e(v0.@layout_5) -> @layout_7 { block0: jump block1; block1: - v2.@layout_6 = call %core__lib__abi__impl_Cursor_1a04__new__g463e_15c7_0 v0; + v2.@layout_6 = call %impl_Cursor__new__g463e v0; v4.objref<@layout_7> = obj.alloc @layout_7; v5.objref<@layout_6> = obj.proj v4 0.i256; v6.objref<@layout_5> = obj.proj v5 0.i256; @@ -1671,7 +1306,7 @@ func private %std__lib__abi__sol__impl_trait_SolEncoder_19ce__pos_65f2(v0.objref return v4; } -func private %std__lib__abi__sol__impl_trait_SolDecoder_68ab__pos__g463e_6e96(v0.objref<@layout_7>) -> i256 { +func private %pos__g463e(v0.objref<@layout_7>) -> i256 { block0: jump block1; @@ -1682,29 +1317,7 @@ func private %std__lib__abi__sol__impl_trait_SolDecoder_68ab__pos__g463e_6e96(v0 return v6; } -func private %std__lib__abi__sol__impl_trait_SolDecoder_68ab__pos__g463e_8da8(v0.objref<@layout_7>) -> i256 { - block0: - jump block1; - - block1: - v3.objref<@layout_6> = obj.proj v0 0.i256; - v5.objref = obj.proj v3 1.i256; - v6.i256 = obj.load v5; - return v6; -} - -func private %std__lib__abi__sol__impl_trait_SolDecoder_68ab__pos__g463e_ad58(v0.objref<@layout_7>) -> i256 { - block0: - jump block1; - - block1: - v3.objref<@layout_6> = obj.proj v0 0.i256; - v5.objref = obj.proj v3 1.i256; - v6.i256 = obj.load v5; - return v6; -} - -func private %std__lib__abi__sol__impl_trait_SolEncoder_19ce__pos_de88(v0.objref<@layout_4>) -> i256 { +func private %std__lib__abi__sol__impl_trait_SolEncoder_19ce__pos_de88(v0.objref<@layout_4>) -> i256 { block0: jump block1; @@ -1771,63 +1384,6 @@ func private %std__lib__abi__sol__impl_trait_SolDecoder_68ab__read_word__g463e_0 br v24 block2 block5; } -func private %std__lib__abi__sol__impl_trait_SolDecoder_68ab__read_word__g463e_3bfc(v0.objref<@layout_7>) -> i256 { - block0: - v1.*i256 = alloca i256; - v2.*i256 = alloca i256; - jump block1; - - block1: - v5.objref<@layout_6> = obj.proj v0 0.i256; - v6.objref<@layout_5> = obj.proj v5 0.i256; - v7.@layout_5 = obj.load v6; - v8.i256 = call %std__lib__evm__memory_input__impl_trait_MemoryBytes_c1cd__len_3a5b v7; - mstore v1 v8 i256; - v9.objref<@layout_6> = obj.proj v0 0.i256; - v11.objref = obj.proj v9 1.i256; - v12.i256 = obj.load v11; - (v14.i256, v15.i1) = uaddo v12 32.i256; - br v15 block6 block7; - - block2: - evm_revert 0.i256 0.i256; - - block3: - jump block4; - - block4: - v26.objref<@layout_6> = obj.proj v0 0.i256; - v27.objref<@layout_5> = obj.proj v26 0.i256; - v28.@layout_5 = obj.load v27; - v29.objref<@layout_6> = obj.proj v0 0.i256; - v30.objref = obj.proj v29 1.i256; - v31.i256 = obj.load v30; - v32.i256 = call %std__lib__evm__memory_input__impl_trait_MemoryBytes_c1cd__word_at_a9cc v28 v31; - v34.objref<@layout_6> = obj.proj v0 0.i256; - v35.objref = obj.proj v34 1.i256; - obj.store v35 v14; - return v32; - - block5: - v36.i256 = mload v1 i256; - mstore v2 v36 i256; - v38.i256 = mload v2 i256; - v39.i1 = gt v14 v38; - br v39 block2 block3; - - block6: - mstore 0.i256 35408467139433450592217433187231851964531694900788300625387963629091585785856.i256 i256; - mstore 4.i256 17.i256 i256; - evm_revert 0.i256 36.i256; - - block7: - v21.objref<@layout_6> = obj.proj v0 0.i256; - v22.objref = obj.proj v21 1.i256; - v23.i256 = obj.load v22; - v24.i1 = lt v14 v23; - br v24 block2 block5; -} - func private %std__lib__abi__sol__impl_trait_SolDecoder_68ab__read_word__g463e_8dbd(v0.objref<@layout_7>) -> i256 { block0: v1.*i256 = alloca i256; @@ -1885,177 +1441,6 @@ func private %std__lib__abi__sol__impl_trait_SolDecoder_68ab__read_word__g463e_8 br v24 block2 block5; } -func private %std__lib__abi__sol__impl_trait_SolDecoder_68ab__read_word__g463e_bdd2(v0.objref<@layout_7>) -> i256 { - block0: - v1.*i256 = alloca i256; - v2.*i256 = alloca i256; - jump block1; - - block1: - v5.objref<@layout_6> = obj.proj v0 0.i256; - v6.objref<@layout_5> = obj.proj v5 0.i256; - v7.@layout_5 = obj.load v6; - v8.i256 = call %std__lib__evm__memory_input__impl_trait_MemoryBytes_c1cd__len_7357 v7; - mstore v1 v8 i256; - v9.objref<@layout_6> = obj.proj v0 0.i256; - v11.objref = obj.proj v9 1.i256; - v12.i256 = obj.load v11; - (v14.i256, v15.i1) = uaddo v12 32.i256; - br v15 block6 block7; - - block2: - evm_revert 0.i256 0.i256; - - block3: - jump block4; - - block4: - v26.objref<@layout_6> = obj.proj v0 0.i256; - v27.objref<@layout_5> = obj.proj v26 0.i256; - v28.@layout_5 = obj.load v27; - v29.objref<@layout_6> = obj.proj v0 0.i256; - v30.objref = obj.proj v29 1.i256; - v31.i256 = obj.load v30; - v32.i256 = call %std__lib__evm__memory_input__impl_trait_MemoryBytes_c1cd__word_at_9d90 v28 v31; - v34.objref<@layout_6> = obj.proj v0 0.i256; - v35.objref = obj.proj v34 1.i256; - obj.store v35 v14; - return v32; - - block5: - v36.i256 = mload v1 i256; - mstore v2 v36 i256; - v38.i256 = mload v2 i256; - v39.i1 = gt v14 v38; - br v39 block2 block3; - - block6: - mstore 0.i256 35408467139433450592217433187231851964531694900788300625387963629091585785856.i256 i256; - mstore 4.i256 17.i256 i256; - evm_revert 0.i256 36.i256; - - block7: - v21.objref<@layout_6> = obj.proj v0 0.i256; - v22.objref = obj.proj v21 1.i256; - v23.i256 = obj.load v22; - v24.i1 = lt v14 v23; - br v24 block2 block5; -} - -func private %std__lib__abi__sol__impl_trait_SolDecoder_68ab__read_word__g463e_be19(v0.objref<@layout_7>) -> i256 { - block0: - v1.*i256 = alloca i256; - v2.*i256 = alloca i256; - jump block1; - - block1: - v5.objref<@layout_6> = obj.proj v0 0.i256; - v6.objref<@layout_5> = obj.proj v5 0.i256; - v7.@layout_5 = obj.load v6; - v8.i256 = call %std__lib__evm__memory_input__impl_trait_MemoryBytes_c1cd__len_f2e9 v7; - mstore v1 v8 i256; - v9.objref<@layout_6> = obj.proj v0 0.i256; - v11.objref = obj.proj v9 1.i256; - v12.i256 = obj.load v11; - (v14.i256, v15.i1) = uaddo v12 32.i256; - br v15 block6 block7; - - block2: - evm_revert 0.i256 0.i256; - - block3: - jump block4; - - block4: - v26.objref<@layout_6> = obj.proj v0 0.i256; - v27.objref<@layout_5> = obj.proj v26 0.i256; - v28.@layout_5 = obj.load v27; - v29.objref<@layout_6> = obj.proj v0 0.i256; - v30.objref = obj.proj v29 1.i256; - v31.i256 = obj.load v30; - v32.i256 = call %std__lib__evm__memory_input__impl_trait_MemoryBytes_c1cd__word_at_3b13 v28 v31; - v34.objref<@layout_6> = obj.proj v0 0.i256; - v35.objref = obj.proj v34 1.i256; - obj.store v35 v14; - return v32; - - block5: - v36.i256 = mload v1 i256; - mstore v2 v36 i256; - v38.i256 = mload v2 i256; - v39.i1 = gt v14 v38; - br v39 block2 block3; - - block6: - mstore 0.i256 35408467139433450592217433187231851964531694900788300625387963629091585785856.i256 i256; - mstore 4.i256 17.i256 i256; - evm_revert 0.i256 36.i256; - - block7: - v21.objref<@layout_6> = obj.proj v0 0.i256; - v22.objref = obj.proj v21 1.i256; - v23.i256 = obj.load v22; - v24.i1 = lt v14 v23; - br v24 block2 block5; -} - -func private %std__lib__abi__sol__impl_trait_SolDecoder_68ab__read_word__g463e_e372(v0.objref<@layout_7>) -> i256 { - block0: - v1.*i256 = alloca i256; - v2.*i256 = alloca i256; - jump block1; - - block1: - v5.objref<@layout_6> = obj.proj v0 0.i256; - v6.objref<@layout_5> = obj.proj v5 0.i256; - v7.@layout_5 = obj.load v6; - v8.i256 = call %std__lib__evm__memory_input__impl_trait_MemoryBytes_c1cd__len_7ae6 v7; - mstore v1 v8 i256; - v9.objref<@layout_6> = obj.proj v0 0.i256; - v11.objref = obj.proj v9 1.i256; - v12.i256 = obj.load v11; - (v14.i256, v15.i1) = uaddo v12 32.i256; - br v15 block6 block7; - - block2: - evm_revert 0.i256 0.i256; - - block3: - jump block4; - - block4: - v26.objref<@layout_6> = obj.proj v0 0.i256; - v27.objref<@layout_5> = obj.proj v26 0.i256; - v28.@layout_5 = obj.load v27; - v29.objref<@layout_6> = obj.proj v0 0.i256; - v30.objref = obj.proj v29 1.i256; - v31.i256 = obj.load v30; - v32.i256 = call %std__lib__evm__memory_input__impl_trait_MemoryBytes_c1cd__word_at_9b8c v28 v31; - v34.objref<@layout_6> = obj.proj v0 0.i256; - v35.objref = obj.proj v34 1.i256; - obj.store v35 v14; - return v32; - - block5: - v36.i256 = mload v1 i256; - mstore v2 v36 i256; - v38.i256 = mload v2 i256; - v39.i1 = gt v14 v38; - br v39 block2 block3; - - block6: - mstore 0.i256 35408467139433450592217433187231851964531694900788300625387963629091585785856.i256 i256; - mstore 4.i256 17.i256 i256; - evm_revert 0.i256 36.i256; - - block7: - v21.objref<@layout_6> = obj.proj v0 0.i256; - v22.objref = obj.proj v21 1.i256; - v23.i256 = obj.load v22; - v24.i1 = lt v14 v23; - br v24 block2 block5; -} - func private %std__lib__abi__sol__impl_trait_SolEncoder_19ce__set_base_3f4d(v0.objref<@layout_4>, v1.i256) { block0: v2.*i256 = alloca i256; @@ -2069,20 +1454,7 @@ func private %std__lib__abi__sol__impl_trait_SolEncoder_19ce__set_base_3f4d(v0.o return; } -func private %std__lib__abi__sol__impl_trait_SolDecoder_68ab__set_base__g463e_504e(v0.objref<@layout_7>, v1.i256) { - block0: - v2.*i256 = alloca i256; - mstore v2 v1 i256; - jump block1; - - block1: - v3.i256 = mload v2 i256; - v6.objref = obj.proj v0 1.i256; - obj.store v6 v3; - return; -} - -func private %std__lib__abi__sol__impl_trait_SolDecoder_68ab__set_base__g463e_8106(v0.objref<@layout_7>, v1.i256) { +func private %set_base__g463e(v0.objref<@layout_7>, v1.i256) { block0: v2.*i256 = alloca i256; mstore v2 v1 i256; @@ -2108,48 +1480,7 @@ func private %std__lib__abi__sol__impl_trait_SolEncoder_19ce__set_base_b006(v0.o return; } -func private %std__lib__abi__sol__impl_trait_SolDecoder_68ab__set_base__g463e_c080(v0.objref<@layout_7>, v1.i256) { - block0: - v2.*i256 = alloca i256; - mstore v2 v1 i256; - jump block1; - - block1: - v3.i256 = mload v2 i256; - v6.objref = obj.proj v0 1.i256; - obj.store v6 v3; - return; -} - -func private %std__lib__abi__sol__impl_trait_SolDecoder_68ab__set_pos__g463e_010d(v0.objref<@layout_7>, v1.i256) { - block0: - v2.*i256 = alloca i256; - mstore v2 v1 i256; - jump block1; - - block1: - v3.i256 = mload v2 i256; - v6.objref<@layout_6> = obj.proj v0 0.i256; - v8.objref = obj.proj v6 1.i256; - obj.store v8 v3; - return; -} - -func private %std__lib__abi__sol__impl_trait_SolDecoder_68ab__set_pos__g463e_7f12(v0.objref<@layout_7>, v1.i256) { - block0: - v2.*i256 = alloca i256; - mstore v2 v1 i256; - jump block1; - - block1: - v3.i256 = mload v2 i256; - v6.objref<@layout_6> = obj.proj v0 0.i256; - v8.objref = obj.proj v6 1.i256; - obj.store v8 v3; - return; -} - -func private %std__lib__abi__sol__impl_trait_SolDecoder_68ab__set_pos__g463e_7f62(v0.objref<@layout_7>, v1.i256) { +func private %set_pos__g463e(v0.objref<@layout_7>, v1.i256) { block0: v2.*i256 = alloca i256; mstore v2 v1 i256; @@ -2241,28 +1572,6 @@ func private %std__lib__evm__memory_input__impl_trait_MemoryBytes_c1cd__word_at_ return v14; } -func private %std__lib__evm__memory_input__impl_trait_MemoryBytes_c1cd__word_at_3b13(v0.@layout_5, v1.i256) -> i256 { - block0: - v2.objref<@layout_5> = obj.alloc @layout_5; - v3.*i256 = alloca i256; - v5.objref = obj.proj v2 0.i256; - v6.i256 = extract_value v0 0.i256; - obj.store v5 v6; - v8.objref = obj.proj v2 1.i256; - v9.i256 = extract_value v0 1.i256; - obj.store v8 v9; - mstore v3 v1 i256; - jump block1; - - block1: - v10.objref = obj.proj v2 0.i256; - v11.i256 = obj.load v10; - v12.i256 = mload v3 i256; - v13.i256 = add v11 v12; - v14.i256 = mload v13 i256; - return v14; -} - func private %std__lib__evm__memory_input__impl_trait_MemoryBytes_c1cd__word_at_90b8(v0.@layout_5, v1.i256) -> i256 { block0: v2.objref<@layout_5> = obj.alloc @layout_5; @@ -2285,72 +1594,6 @@ func private %std__lib__evm__memory_input__impl_trait_MemoryBytes_c1cd__word_at_ return v14; } -func private %std__lib__evm__memory_input__impl_trait_MemoryBytes_c1cd__word_at_9b8c(v0.@layout_5, v1.i256) -> i256 { - block0: - v2.objref<@layout_5> = obj.alloc @layout_5; - v3.*i256 = alloca i256; - v5.objref = obj.proj v2 0.i256; - v6.i256 = extract_value v0 0.i256; - obj.store v5 v6; - v8.objref = obj.proj v2 1.i256; - v9.i256 = extract_value v0 1.i256; - obj.store v8 v9; - mstore v3 v1 i256; - jump block1; - - block1: - v10.objref = obj.proj v2 0.i256; - v11.i256 = obj.load v10; - v12.i256 = mload v3 i256; - v13.i256 = add v11 v12; - v14.i256 = mload v13 i256; - return v14; -} - -func private %std__lib__evm__memory_input__impl_trait_MemoryBytes_c1cd__word_at_9d90(v0.@layout_5, v1.i256) -> i256 { - block0: - v2.objref<@layout_5> = obj.alloc @layout_5; - v3.*i256 = alloca i256; - v5.objref = obj.proj v2 0.i256; - v6.i256 = extract_value v0 0.i256; - obj.store v5 v6; - v8.objref = obj.proj v2 1.i256; - v9.i256 = extract_value v0 1.i256; - obj.store v8 v9; - mstore v3 v1 i256; - jump block1; - - block1: - v10.objref = obj.proj v2 0.i256; - v11.i256 = obj.load v10; - v12.i256 = mload v3 i256; - v13.i256 = add v11 v12; - v14.i256 = mload v13 i256; - return v14; -} - -func private %std__lib__evm__memory_input__impl_trait_MemoryBytes_c1cd__word_at_a9cc(v0.@layout_5, v1.i256) -> i256 { - block0: - v2.objref<@layout_5> = obj.alloc @layout_5; - v3.*i256 = alloca i256; - v5.objref = obj.proj v2 0.i256; - v6.i256 = extract_value v0 0.i256; - obj.store v5 v6; - v8.objref = obj.proj v2 1.i256; - v9.i256 = extract_value v0 1.i256; - obj.store v8 v9; - mstore v3 v1 i256; - jump block1; - - block1: - v10.objref = obj.proj v2 0.i256; - v11.i256 = obj.load v10; - v12.i256 = mload v3 i256; - v13.i256 = add v11 v12; - v14.i256 = mload v13 i256; - return v14; -} - func private %std__lib__abi__sol__impl_trait_SolEncoder_19ce__write_word_1f5e(v0.objref<@layout_4>, v1.i256) { block0: v2.*i256 = alloca i256; diff --git a/crates/codegen/tests/fixtures/sonatina_ir/effect_handle_field_deref.snap b/crates/codegen/tests/fixtures/sonatina_ir/effect_handle_field_deref.snap index d2fe3a2e50..591e7043e6 100644 --- a/crates/codegen/tests/fixtures/sonatina_ir/effect_handle_field_deref.snap +++ b/crates/codegen/tests/fixtures/sonatina_ir/effect_handle_field_deref.snap @@ -1,5 +1,6 @@ --- source: crates/codegen/tests/sonatina_ir.rs +assertion_line: 402 expression: output input_file: crates/codegen/tests/fixtures/effect_handle_field_deref.fe --- @@ -7,16 +8,8 @@ target = "evm-ethereum-osaka" type @layout_0 = {}; type @layout_1 = {@layout_0}; -type @layout_2 = {i256, i256}; +type @layout_2 = {i256}; type @layout_3 = {i256, i256}; -type @layout_4 = {@layout_3, i256}; -type @layout_5 = {@layout_4, i256}; -type @layout_6 = {i256}; -type @layout_7 = {i256}; -type @layout_8 = {i256}; -type @layout_9 = {i256, i256}; -type @layout_10 = {i256, i256}; -type @layout_11 = {i256, i256}; func private %__EffectHandleFieldDeref_init(v0.i256) { block0: @@ -43,12 +36,12 @@ func private %__EffectHandleFieldDeref_recv_0_1(v0.i256, v1.objref<@layout_1>) - block1: v3.i256 = call %stor_ptr v0; - v5.objref<@layout_11> = obj.alloc @layout_11; + v5.objref<@layout_3> = obj.alloc @layout_3; v7.objref = obj.proj v5 0.i256; obj.store v7 v3; v8.objref = obj.proj v5 1.i256; obj.store v8 1.i256; - v9.@layout_11 = obj.load v5; + v9.@layout_3 = obj.load v5; v10.i256 = call %extract_ptr v9; v11.i256 = call %read_cell v10; return v11; @@ -59,11 +52,11 @@ func private %__EffectHandleFieldDeref_recv_0_2(v0.i256, v1.i256) -> i256 { jump block1; block1: - v3.objref<@layout_6> = obj.alloc @layout_6; + v3.objref<@layout_2> = obj.alloc @layout_2; v5.objref = obj.proj v3 0.i256; obj.store v5 v1; - v6.@layout_6 = obj.load v3; - v7.objref<@layout_6> = obj.alloc @layout_6; + v6.@layout_2 = obj.load v3; + v7.objref<@layout_2> = obj.alloc @layout_2; v8.objref = obj.proj v7 0.i256; v9.i256 = extract_value v6 0.i256; obj.store v8 v9; @@ -71,89 +64,7 @@ func private %__EffectHandleFieldDeref_recv_0_2(v0.i256, v1.i256) -> i256 { return v11; } -func private %abi_field_size(v0.i256) -> i256 { - block0: - v1.*i256 = alloca i256; - mstore v1 v0 i256; - jump block1; - - block1: - v2.i256 = mload v1 i256; - v3.i256 = call %core__lib__abi__trait_AbiSize__payload_size__ge513_a8bc_0 v2; - br 0.i1 block2 block3; - - block2: - (v7.i256, v8.i1) = uaddo 32.i256 v3; - br v8 block5 block6; - - block3: - jump block4; - - block4: - return v3; - - block5: - mstore 0.i256 35408467139433450592217433187231851964531694900788300625387963629091585785856.i256 i256; - mstore 4.i256 17.i256 i256; - evm_revert 0.i256 36.i256; - - block6: - return v7; -} - -func private %abi_single_root_size(v0.i256) -> i256 { - block0: - v1.*i256 = alloca i256; - mstore v1 v0 i256; - jump block1; - - block1: - v2.i256 = mload v1 i256; - v3.i256 = call %abi_field_size v2; - return v3; -} - -func private %impl_trait_SolEncoder__base(v0.objref<@layout_2>) -> i256 { - block0: - jump block1; - - block1: - v3.objref = obj.proj v0 0.i256; - v4.i256 = obj.load v3; - return v4; -} - -func private %std__lib__abi__sol__impl_trait_SolDecoder_68ab__base__g463e_8cc3(v0.objref<@layout_5>) -> i256 { - block0: - jump block1; - - block1: - v3.objref = obj.proj v0 1.i256; - v4.i256 = obj.load v3; - return v4; -} - -func private %std__lib__abi__sol__impl_trait_SolDecoder_68ab__base__g463e_8edd(v0.objref<@layout_5>) -> i256 { - block0: - jump block1; - - block1: - v3.objref = obj.proj v0 1.i256; - v4.i256 = obj.load v3; - return v4; -} - -func private %std__lib__abi__sol__impl_trait_SolDecoder_68ab__base__g463e_cedc(v0.objref<@layout_5>) -> i256 { - block0: - jump block1; - - block1: - v3.objref = obj.proj v0 1.i256; - v4.i256 = obj.load v3; - return v4; -} - -func private %bump(v0.objref<@layout_6>, v1.i256) -> i256 { +func private %bump(v0.objref<@layout_2>, v1.i256) -> i256 { block0: v2.*i256 = alloca i256; mstore v2 v1 i256; @@ -212,231 +123,65 @@ func private %contract_init_root_EffectHandleFieldDeref() { func private %contract_recv_abi_EffectHandleFieldDeref_1() { block0: - v0.objref<@layout_3> = obj.alloc @layout_3; - v1.objref<@layout_5> = obj.alloc @layout_5; jump block1; block1: - v4.i256 = evm_call_value; - v5.i1 = eq v4 0.i256; - v6.i1 = is_zero v5; - br v6 block2 block3; + v2.i256 = evm_call_value; + v3.i1 = eq v2 0.i256; + v4.i1 = is_zero v3; + br v4 block2 block3; block2: evm_revert 0.i256 0.i256; block3: - v8.i256 = evm_calldata_size; - (v10.i256, v11.i1) = usubo v8 4.i256; - br v11 block4 block5; - - block4: - mstore 0.i256 35408467139433450592217433187231851964531694900788300625387963629091585785856.i256 i256; - mstore 4.i256 17.i256 i256; - evm_revert 0.i256 36.i256; - - block5: - v15.*i8 = evm_malloc v10; - v16.i256 = ptr_to_int v15 i256; - evm_calldata_copy v16 4.i256 v10; - v19.objref = obj.proj v0 0.i256; - obj.store v19 v16; - v21.objref = obj.proj v0 1.i256; - obj.store v21 v10; - v22.@layout_3 = obj.load v0; - v23.@layout_5 = call %decoder_new v22; - v24.objref<@layout_4> = obj.proj v1 0.i256; - v25.@layout_4 = extract_value v23 0.i256; - v26.objref<@layout_3> = obj.proj v24 0.i256; - v27.@layout_3 = extract_value v25 0.i256; - v28.objref = obj.proj v26 0.i256; - v29.i256 = extract_value v27 0.i256; - obj.store v28 v29; - v30.objref = obj.proj v26 1.i256; - v31.i256 = extract_value v27 1.i256; - obj.store v30 v31; - v32.objref = obj.proj v24 1.i256; - v33.i256 = extract_value v25 1.i256; - obj.store v32 v33; - v34.objref = obj.proj v1 1.i256; - v35.i256 = extract_value v23 1.i256; - obj.store v34 v35; - v36.@layout_9 = call %impl_trait_SeedSlot__decode_payload__gf196 v1; - v37.objref<@layout_9> = obj.alloc @layout_9; - v38.objref = obj.proj v37 0.i256; - v39.i256 = extract_value v36 0.i256; - obj.store v38 v39; - v40.objref = obj.proj v37 1.i256; - v41.i256 = extract_value v36 1.i256; - obj.store v40 v41; - v42.objref = obj.proj v37 0.i256; - v43.i256 = obj.load v42; - v44.objref = obj.proj v37 1.i256; - v45.i256 = obj.load v44; - v46.objref<@layout_1> = obj.alloc @layout_1; - v47.i256 = call %__EffectHandleFieldDeref_recv_0_0 v43 v45 v46; - v48.@layout_10 = call %encode_single_root_alloc v47; - v49.objref<@layout_10> = obj.alloc @layout_10; - v50.objref = obj.proj v49 0.i256; - v51.i256 = extract_value v48 0.i256; - obj.store v50 v51; - v52.objref = obj.proj v49 1.i256; - v53.i256 = extract_value v48 1.i256; - obj.store v52 v53; - v54.objref = obj.proj v49 0.i256; - v55.i256 = obj.load v54; - v56.objref = obj.proj v49 1.i256; - v57.i256 = obj.load v56; - evm_return v55 v57; + v6.i256 = evm_calldata_load 4.i256; + v8.i256 = evm_calldata_load 36.i256; + v9.objref<@layout_1> = obj.alloc @layout_1; + v10.i256 = call %__EffectHandleFieldDeref_recv_0_0 v6 v8 v9; + mstore 0.i256 v10 i256; + evm_return 0.i256 32.i256; } func private %contract_recv_abi_EffectHandleFieldDeref_2() { block0: - v0.objref<@layout_3> = obj.alloc @layout_3; - v1.objref<@layout_5> = obj.alloc @layout_5; jump block1; block1: - v4.i256 = evm_call_value; - v5.i1 = eq v4 0.i256; - v6.i1 = is_zero v5; - br v6 block2 block3; + v2.i256 = evm_call_value; + v3.i1 = eq v2 0.i256; + v4.i1 = is_zero v3; + br v4 block2 block3; block2: evm_revert 0.i256 0.i256; block3: - v8.i256 = evm_calldata_size; - (v10.i256, v11.i1) = usubo v8 4.i256; - br v11 block4 block5; - - block4: - mstore 0.i256 35408467139433450592217433187231851964531694900788300625387963629091585785856.i256 i256; - mstore 4.i256 17.i256 i256; - evm_revert 0.i256 36.i256; - - block5: - v15.*i8 = evm_malloc v10; - v16.i256 = ptr_to_int v15 i256; - evm_calldata_copy v16 4.i256 v10; - v19.objref = obj.proj v0 0.i256; - obj.store v19 v16; - v21.objref = obj.proj v0 1.i256; - obj.store v21 v10; - v22.@layout_3 = obj.load v0; - v23.@layout_5 = call %decoder_new v22; - v24.objref<@layout_4> = obj.proj v1 0.i256; - v25.@layout_4 = extract_value v23 0.i256; - v26.objref<@layout_3> = obj.proj v24 0.i256; - v27.@layout_3 = extract_value v25 0.i256; - v28.objref = obj.proj v26 0.i256; - v29.i256 = extract_value v27 0.i256; - obj.store v28 v29; - v30.objref = obj.proj v26 1.i256; - v31.i256 = extract_value v27 1.i256; - obj.store v30 v31; - v32.objref = obj.proj v24 1.i256; - v33.i256 = extract_value v25 1.i256; - obj.store v32 v33; - v34.objref = obj.proj v1 1.i256; - v35.i256 = extract_value v23 1.i256; - obj.store v34 v35; - v36.@layout_8 = call %impl_trait_ReadViaHolder__decode_payload__gf196 v1; - v37.objref<@layout_8> = obj.alloc @layout_8; - v38.objref = obj.proj v37 0.i256; - v39.i256 = extract_value v36 0.i256; - obj.store v38 v39; - v40.objref = obj.proj v37 0.i256; - v41.i256 = obj.load v40; - v42.objref<@layout_1> = obj.alloc @layout_1; - v43.i256 = call %__EffectHandleFieldDeref_recv_0_1 v41 v42; - v44.@layout_10 = call %encode_single_root_alloc v43; - v45.objref<@layout_10> = obj.alloc @layout_10; - v46.objref = obj.proj v45 0.i256; - v47.i256 = extract_value v44 0.i256; - obj.store v46 v47; - v48.objref = obj.proj v45 1.i256; - v49.i256 = extract_value v44 1.i256; - obj.store v48 v49; - v50.objref = obj.proj v45 0.i256; - v51.i256 = obj.load v50; - v52.objref = obj.proj v45 1.i256; - v53.i256 = obj.load v52; - evm_return v51 v53; + v6.i256 = evm_calldata_load 4.i256; + v7.objref<@layout_1> = obj.alloc @layout_1; + v8.i256 = call %__EffectHandleFieldDeref_recv_0_1 v6 v7; + mstore 0.i256 v8 i256; + evm_return 0.i256 32.i256; } func private %contract_recv_abi_EffectHandleFieldDeref_3() { block0: - v0.objref<@layout_3> = obj.alloc @layout_3; - v1.objref<@layout_5> = obj.alloc @layout_5; jump block1; block1: - v4.i256 = evm_call_value; - v5.i1 = eq v4 0.i256; - v6.i1 = is_zero v5; - br v6 block2 block3; + v2.i256 = evm_call_value; + v3.i1 = eq v2 0.i256; + v4.i1 = is_zero v3; + br v4 block2 block3; block2: evm_revert 0.i256 0.i256; block3: - v8.i256 = evm_calldata_size; - (v10.i256, v11.i1) = usubo v8 4.i256; - br v11 block4 block5; - - block4: - mstore 0.i256 35408467139433450592217433187231851964531694900788300625387963629091585785856.i256 i256; - mstore 4.i256 17.i256 i256; - evm_revert 0.i256 36.i256; - - block5: - v15.*i8 = evm_malloc v10; - v16.i256 = ptr_to_int v15 i256; - evm_calldata_copy v16 4.i256 v10; - v19.objref = obj.proj v0 0.i256; - obj.store v19 v16; - v21.objref = obj.proj v0 1.i256; - obj.store v21 v10; - v22.@layout_3 = obj.load v0; - v23.@layout_5 = call %decoder_new v22; - v24.objref<@layout_4> = obj.proj v1 0.i256; - v25.@layout_4 = extract_value v23 0.i256; - v26.objref<@layout_3> = obj.proj v24 0.i256; - v27.@layout_3 = extract_value v25 0.i256; - v28.objref = obj.proj v26 0.i256; - v29.i256 = extract_value v27 0.i256; - obj.store v28 v29; - v30.objref = obj.proj v26 1.i256; - v31.i256 = extract_value v27 1.i256; - obj.store v30 v31; - v32.objref = obj.proj v24 1.i256; - v33.i256 = extract_value v25 1.i256; - obj.store v32 v33; - v34.objref = obj.proj v1 1.i256; - v35.i256 = extract_value v23 1.i256; - obj.store v34 v35; - v36.@layout_7 = call %impl_trait_BumpMover__decode_payload__gf196 v1; - v37.objref<@layout_7> = obj.alloc @layout_7; - v38.objref = obj.proj v37 0.i256; - v39.i256 = extract_value v36 0.i256; - obj.store v38 v39; - v40.objref = obj.proj v37 0.i256; - v41.i256 = obj.load v40; - v42.i256 = call %__EffectHandleFieldDeref_recv_0_2 v41 0.i256; - v43.@layout_10 = call %encode_single_root_alloc v42; - v44.objref<@layout_10> = obj.alloc @layout_10; - v45.objref = obj.proj v44 0.i256; - v46.i256 = extract_value v43 0.i256; - obj.store v45 v46; - v47.objref = obj.proj v44 1.i256; - v48.i256 = extract_value v43 1.i256; - obj.store v47 v48; - v49.objref = obj.proj v44 0.i256; - v50.i256 = obj.load v49; - v51.objref = obj.proj v44 1.i256; - v52.i256 = obj.load v51; - evm_return v50 v52; + v6.i256 = evm_calldata_load 4.i256; + v7.i256 = call %__EffectHandleFieldDeref_recv_0_2 v6 0.i256; + mstore 0.i256 v7 i256; + evm_return 0.i256 32.i256; } func private %contract_runtime_root_EffectHandleFieldDeref() { @@ -465,300 +210,44 @@ func private %contract_runtime_root_EffectHandleFieldDeref() { unreachable; } -func private %core__lib__abi__decode_field__g3854_89ba(v0.objref<@layout_5>) -> i256 { - block0: - jump block1; - - block1: - br 0.i1 block2 block3; - - block2: - v3.i256 = call %std__lib__abi__sol__impl_trait_SolDecoder_68ab__read_word__g463e_d39e v0; - v4.i256 = call %std__lib__abi__sol__impl_trait_SolDecoder_68ab__base__g463e_8edd v0; - v5.i256 = call %std__lib__abi__sol__impl_trait_SolDecoder_68ab__pos__g463e_047d v0; - (v6.i256, v7.i1) = uaddo v4 v3; - br v7 block5 block6; - - block3: - jump block4; - - block4: - v23.i256 = call %core__lib__abi__impl_trait_u256_85b6__decode_payload__g407e_e618 v0; - return v23; - - block5: - mstore 0.i256 35408467139433450592217433187231851964531694900788300625387963629091585785856.i256 i256; - mstore 4.i256 17.i256 i256; - evm_revert 0.i256 36.i256; - - block6: - call %std__lib__abi__sol__impl_trait_SolDecoder_68ab__set_base__g463e_b155 v0 v6; - v15.i256 = call %std__lib__abi__sol__impl_trait_SolDecoder_68ab__base__g463e_8edd v0; - call %std__lib__abi__sol__impl_trait_SolDecoder_68ab__set_pos__g463e_ec19 v0 v15; - v17.i256 = call %core__lib__abi__impl_trait_u256_85b6__decode_payload__g407e_e618 v0; - call %std__lib__abi__sol__impl_trait_SolDecoder_68ab__set_base__g463e_b155 v0 v4; - call %std__lib__abi__sol__impl_trait_SolDecoder_68ab__set_pos__g463e_ec19 v0 v5; - return v17; -} - -func private %core__lib__abi__decode_field__g3854_bc76(v0.objref<@layout_5>) -> i256 { - block0: - jump block1; - - block1: - br 0.i1 block2 block3; - - block2: - v3.i256 = call %std__lib__abi__sol__impl_trait_SolDecoder_68ab__read_word__g463e_3646 v0; - v4.i256 = call %std__lib__abi__sol__impl_trait_SolDecoder_68ab__base__g463e_8cc3 v0; - v5.i256 = call %std__lib__abi__sol__impl_trait_SolDecoder_68ab__pos__g463e_c53e v0; - (v6.i256, v7.i1) = uaddo v4 v3; - br v7 block5 block6; - - block3: - jump block4; - - block4: - v23.i256 = call %core__lib__abi__impl_trait_u256_85b6__decode_payload__g407e_e250 v0; - return v23; - - block5: - mstore 0.i256 35408467139433450592217433187231851964531694900788300625387963629091585785856.i256 i256; - mstore 4.i256 17.i256 i256; - evm_revert 0.i256 36.i256; - - block6: - call %std__lib__abi__sol__impl_trait_SolDecoder_68ab__set_base__g463e_6a44 v0 v6; - v15.i256 = call %std__lib__abi__sol__impl_trait_SolDecoder_68ab__base__g463e_8cc3 v0; - call %std__lib__abi__sol__impl_trait_SolDecoder_68ab__set_pos__g463e_135d v0 v15; - v17.i256 = call %core__lib__abi__impl_trait_u256_85b6__decode_payload__g407e_e250 v0; - call %std__lib__abi__sol__impl_trait_SolDecoder_68ab__set_base__g463e_6a44 v0 v4; - call %std__lib__abi__sol__impl_trait_SolDecoder_68ab__set_pos__g463e_135d v0 v5; - return v17; -} - -func private %core__lib__abi__decode_field__g3854_fcf7(v0.objref<@layout_5>) -> i256 { - block0: - jump block1; - - block1: - br 0.i1 block2 block3; - - block2: - v3.i256 = call %std__lib__abi__sol__impl_trait_SolDecoder_68ab__read_word__g463e_c929 v0; - v4.i256 = call %std__lib__abi__sol__impl_trait_SolDecoder_68ab__base__g463e_cedc v0; - v5.i256 = call %std__lib__abi__sol__impl_trait_SolDecoder_68ab__pos__g463e_ebe7 v0; - (v6.i256, v7.i1) = uaddo v4 v3; - br v7 block5 block6; - - block3: - jump block4; - - block4: - v23.i256 = call %core__lib__abi__impl_trait_u256_85b6__decode_payload__g407e_8d5d v0; - return v23; - - block5: - mstore 0.i256 35408467139433450592217433187231851964531694900788300625387963629091585785856.i256 i256; - mstore 4.i256 17.i256 i256; - evm_revert 0.i256 36.i256; - - block6: - call %std__lib__abi__sol__impl_trait_SolDecoder_68ab__set_base__g463e_8d49 v0 v6; - v15.i256 = call %std__lib__abi__sol__impl_trait_SolDecoder_68ab__base__g463e_cedc v0; - call %std__lib__abi__sol__impl_trait_SolDecoder_68ab__set_pos__g463e_6579 v0 v15; - v17.i256 = call %core__lib__abi__impl_trait_u256_85b6__decode_payload__g407e_8d5d v0; - call %std__lib__abi__sol__impl_trait_SolDecoder_68ab__set_base__g463e_8d49 v0 v4; - call %std__lib__abi__sol__impl_trait_SolDecoder_68ab__set_pos__g463e_6579 v0 v5; - return v17; -} - -func private %impl_trait_BumpMover__decode_payload__gf196(v0.objref<@layout_5>) -> @layout_7 { - block0: - jump block1; - - block1: - v2.i256 = call %core__lib__abi__decode_field__g3854_bc76 v0; - v3.objref<@layout_7> = obj.alloc @layout_7; - v5.objref = obj.proj v3 0.i256; - obj.store v5 v2; - v6.@layout_7 = obj.load v3; - return v6; -} - -func private %impl_trait_ReadViaHolder__decode_payload__gf196(v0.objref<@layout_5>) -> @layout_8 { - block0: - jump block1; - - block1: - v2.i256 = call %core__lib__abi__decode_field__g3854_fcf7 v0; - v3.objref<@layout_8> = obj.alloc @layout_8; - v5.objref = obj.proj v3 0.i256; - obj.store v5 v2; - v6.@layout_8 = obj.load v3; - return v6; -} - -func private %impl_trait_SeedSlot__decode_payload__gf196(v0.objref<@layout_5>) -> @layout_9 { +func private %extract_ptr(v0.@layout_3) -> i256 { block0: + v1.objref<@layout_3> = obj.alloc @layout_3; + v3.objref = obj.proj v1 0.i256; + v4.i256 = extract_value v0 0.i256; + obj.store v3 v4; + v6.objref = obj.proj v1 1.i256; + v7.i256 = extract_value v0 1.i256; + obj.store v6 v7; jump block1; block1: - v2.i256 = call %core__lib__abi__decode_field__g3854_89ba v0; - v3.i256 = call %core__lib__abi__decode_field__g3854_89ba v0; - v4.objref<@layout_9> = obj.alloc @layout_9; - v6.objref = obj.proj v4 0.i256; - obj.store v6 v2; - v8.objref = obj.proj v4 1.i256; - obj.store v8 v3; - v9.@layout_9 = obj.load v4; + v8.objref = obj.proj v1 0.i256; + v9.i256 = obj.load v8; return v9; } -func private %core__lib__abi__impl_trait_u256_85b6__decode_payload__g407e_8d5d(v0.objref<@layout_5>) -> i256 { - block0: - jump block1; - - block1: - v2.i256 = call %std__lib__abi__sol__impl_trait_SolDecoder_68ab__read_word__g463e_77a7 v0; - return v2; -} - -func private %core__lib__abi__impl_trait_u256_85b6__decode_payload__g407e_e250(v0.objref<@layout_5>) -> i256 { - block0: - jump block1; - - block1: - v2.i256 = call %std__lib__abi__sol__impl_trait_SolDecoder_68ab__read_word__g463e_b6e9 v0; - return v2; -} - -func private %core__lib__abi__impl_trait_u256_85b6__decode_payload__g407e_e618(v0.objref<@layout_5>) -> i256 { +func private %from_raw(v0.i256) -> i256 { block0: + v1.*i256 = alloca i256; + mstore v1 v0 i256; jump block1; block1: - v2.i256 = call %std__lib__abi__sol__impl_trait_SolDecoder_68ab__read_word__g463e_ebbf v0; + v2.i256 = mload v1 i256; return v2; } -func private %decoder_new(v0.@layout_3) -> @layout_5 { +func private %read_cell(v0.i256) -> i256 { block0: jump block1; block1: - v2.@layout_5 = call %impl_SolDecoder__new__g463e v0; + v2.i256 = evm_sload v0; return v2; } -func private %encode(v0.i256, v1.objref<@layout_2>) { - block0: - jump block1; - - block1: - call %std__lib__abi__sol__impl_trait_SolEncoder_19ce__write_word_2aa5 v1 v0; - return; -} - -func private %encode_field(v0.i256, v1.objref<@layout_2>, v2.i256) { - block0: - jump block1; - - block1: - br 0.i1 block2 block3; - - block2: - v5.i256 = call %impl_trait_SolEncoder__base v1; - v8.i256 = call %core__lib__abi__trait_AbiSize__payload_size__ge513_a8bc v0; - v9.i256 = mload v2 i256; - v10.i256 = sub v9 v5; - call %std__lib__abi__sol__impl_trait_SolEncoder_19ce__write_word_8a50 v1 v10; - v12.i256 = call %impl_trait_SolEncoder__pos v1; - v13.i256 = mload v2 i256; - call %impl_trait_SolEncoder__set_base v1 v13; - v15.i256 = mload v2 i256; - call %impl_trait_SolEncoder__set_pos v1 v15; - call %encode v0 v1; - call %impl_trait_SolEncoder__set_base v1 v5; - call %impl_trait_SolEncoder__set_pos v1 v12; - v20.i256 = mload v2 i256; - v21.i256 = add v20 v8; - mstore v2 v21 i256; - return; - - block3: - jump block4; - - block4: - br 1.i1 block5 block6; - - block5: - v24.i256 = call %impl_trait_SolEncoder__pos v1; - call %encode_to_ptr v0 v24; - v28.i256 = add v24 32.i256; - call %impl_trait_SolEncoder__set_pos v1 v28; - return; - - block6: - jump block7; - - block7: - call %encode v0 v1; - return; -} - -func private %encode_single_root(v0.i256, v1.objref<@layout_2>) { - block0: - v2.*i256 = alloca i256; - jump block1; - - block1: - v4.i256 = call %impl_trait_SolEncoder__base v1; - v6.i256 = add v4 32.i256; - mstore v2 v6 i256; - v7.i256 = ptr_to_int v2 i256; - call %encode_field v0 v1 v7; - return; -} - -func private %encode_single_root_alloc(v0.i256) -> @layout_10 { - block0: - jump block1; - - block1: - v2.i256 = call %abi_single_root_size v0; - v3.@layout_2 = call %encoder_new v2; - v4.objref<@layout_2> = obj.alloc @layout_2; - v6.objref = obj.proj v4 0.i256; - v7.i256 = extract_value v3 0.i256; - obj.store v6 v7; - v9.objref = obj.proj v4 1.i256; - v10.i256 = extract_value v3 1.i256; - obj.store v9 v10; - v11.i256 = call %impl_trait_SolEncoder__base v4; - call %encode_single_root v0 v4; - v13.objref<@layout_10> = obj.alloc @layout_10; - v14.objref = obj.proj v13 0.i256; - obj.store v14 v11; - v15.objref = obj.proj v13 1.i256; - obj.store v15 v2; - v16.@layout_10 = obj.load v13; - return v16; -} - -func private %encode_to_ptr(v0.i256, v1.i256) { - block0: - v2.*i256 = alloca i256; - mstore v2 v1 i256; - jump block1; - - block1: - v3.i256 = mload v2 i256; - call %store_word v3 v0; - return; -} - -func private %encoder_new(v0.i256) -> @layout_2 { +func private %stor_ptr(v0.i256) -> i256 { block0: v1.*i256 = alloca i256; mstore v1 v0 i256; @@ -766,899 +255,14 @@ func private %encoder_new(v0.i256) -> @layout_2 { block1: v2.i256 = mload v1 i256; - v3.@layout_2 = call %impl_SolEncoder__new v2; + v3.i256 = call %from_raw v2; return v3; } -func private %extract_ptr(v0.@layout_11) -> i256 { - block0: - v1.objref<@layout_11> = obj.alloc @layout_11; - v3.objref = obj.proj v1 0.i256; - v4.i256 = extract_value v0 0.i256; - obj.store v3 v4; - v6.objref = obj.proj v1 1.i256; - v7.i256 = extract_value v0 1.i256; - obj.store v6 v7; - jump block1; - - block1: - v8.objref = obj.proj v1 0.i256; - v9.i256 = obj.load v8; - return v9; -} - -func private %from_raw(v0.i256) -> i256 { +func private %write_cell(v0.i256, v1.i256) -> i256 { block0: - v1.*i256 = alloca i256; - mstore v1 v0 i256; - jump block1; - - block1: - v2.i256 = mload v1 i256; - return v2; -} - -func private %std__lib__evm__memory_input__impl_trait_MemoryBytes_c1cd__len_0a8e(v0.@layout_3) -> i256 { - block0: - v1.objref<@layout_3> = obj.alloc @layout_3; - v3.objref = obj.proj v1 0.i256; - v4.i256 = extract_value v0 0.i256; - obj.store v3 v4; - v6.objref = obj.proj v1 1.i256; - v7.i256 = extract_value v0 1.i256; - obj.store v6 v7; - jump block1; - - block1: - v8.objref = obj.proj v1 1.i256; - v9.i256 = obj.load v8; - return v9; -} - -func private %std__lib__evm__memory_input__impl_trait_MemoryBytes_c1cd__len_2605(v0.@layout_3) -> i256 { - block0: - v1.objref<@layout_3> = obj.alloc @layout_3; - v3.objref = obj.proj v1 0.i256; - v4.i256 = extract_value v0 0.i256; - obj.store v3 v4; - v6.objref = obj.proj v1 1.i256; - v7.i256 = extract_value v0 1.i256; - obj.store v6 v7; - jump block1; - - block1: - v8.objref = obj.proj v1 1.i256; - v9.i256 = obj.load v8; - return v9; -} - -func private %std__lib__evm__memory_input__impl_trait_MemoryBytes_c1cd__len_7233(v0.@layout_3) -> i256 { - block0: - v1.objref<@layout_3> = obj.alloc @layout_3; - v3.objref = obj.proj v1 0.i256; - v4.i256 = extract_value v0 0.i256; - obj.store v3 v4; - v6.objref = obj.proj v1 1.i256; - v7.i256 = extract_value v0 1.i256; - obj.store v6 v7; - jump block1; - - block1: - v8.objref = obj.proj v1 1.i256; - v9.i256 = obj.load v8; - return v9; -} - -func private %std__lib__evm__memory_input__impl_trait_MemoryBytes_c1cd__len_9b08(v0.@layout_3) -> i256 { - block0: - v1.objref<@layout_3> = obj.alloc @layout_3; - v3.objref = obj.proj v1 0.i256; - v4.i256 = extract_value v0 0.i256; - obj.store v3 v4; - v6.objref = obj.proj v1 1.i256; - v7.i256 = extract_value v0 1.i256; - obj.store v6 v7; - jump block1; - - block1: - v8.objref = obj.proj v1 1.i256; - v9.i256 = obj.load v8; - return v9; -} - -func private %std__lib__evm__memory_input__impl_trait_MemoryBytes_c1cd__len_b143(v0.@layout_3) -> i256 { - block0: - v1.objref<@layout_3> = obj.alloc @layout_3; - v3.objref = obj.proj v1 0.i256; - v4.i256 = extract_value v0 0.i256; - obj.store v3 v4; - v6.objref = obj.proj v1 1.i256; - v7.i256 = extract_value v0 1.i256; - obj.store v6 v7; - jump block1; - - block1: - v8.objref = obj.proj v1 1.i256; - v9.i256 = obj.load v8; - return v9; -} - -func private %std__lib__evm__memory_input__impl_trait_MemoryBytes_c1cd__len_c8fa(v0.@layout_3) -> i256 { - block0: - v1.objref<@layout_3> = obj.alloc @layout_3; - v3.objref = obj.proj v1 0.i256; - v4.i256 = extract_value v0 0.i256; - obj.store v3 v4; - v6.objref = obj.proj v1 1.i256; - v7.i256 = extract_value v0 1.i256; - obj.store v6 v7; - jump block1; - - block1: - v8.objref = obj.proj v1 1.i256; - v9.i256 = obj.load v8; - return v9; -} - -func private %impl_SolEncoder__new(v0.i256) -> @layout_2 { - block0: - v1.*i256 = alloca i256; - mstore v1 v0 i256; - jump block1; - - block1: - v2.i256 = mload v1 i256; - v4.i1 = eq v2 0.i256; - br v4 block2 block3; - - block2: - jump block4; - - block3: - v5.i256 = mload v1 i256; - v6.*i8 = evm_malloc v5; - v7.i256 = ptr_to_int v6 i256; - jump block4; - - block4: - v8.i256 = phi (0.i256 block2) (v7 block3); - v9.objref<@layout_2> = obj.alloc @layout_2; - v10.objref = obj.proj v9 0.i256; - obj.store v10 v8; - v12.objref = obj.proj v9 1.i256; - obj.store v12 v8; - v13.@layout_2 = obj.load v9; - return v13; -} - -func private %impl_SolDecoder__new__g463e(v0.@layout_3) -> @layout_5 { - block0: - jump block1; - - block1: - v2.@layout_4 = call %impl_Cursor__new__g463e v0; - v4.objref<@layout_5> = obj.alloc @layout_5; - v5.objref<@layout_4> = obj.proj v4 0.i256; - v6.objref<@layout_3> = obj.proj v5 0.i256; - v7.@layout_3 = extract_value v2 0.i256; - v8.objref = obj.proj v6 0.i256; - v9.i256 = extract_value v7 0.i256; - obj.store v8 v9; - v11.objref = obj.proj v6 1.i256; - v12.i256 = extract_value v7 1.i256; - obj.store v11 v12; - v13.objref = obj.proj v5 1.i256; - v14.i256 = extract_value v2 1.i256; - obj.store v13 v14; - v15.objref = obj.proj v4 1.i256; - obj.store v15 0.i256; - v16.@layout_5 = obj.load v4; - return v16; -} - -func private %impl_Cursor__new__g463e(v0.@layout_3) -> @layout_4 { - block0: - jump block1; - - block1: - v2.objref<@layout_4> = obj.alloc @layout_4; - v4.objref<@layout_3> = obj.proj v2 0.i256; - v5.objref = obj.proj v4 0.i256; - v6.i256 = extract_value v0 0.i256; - obj.store v5 v6; - v8.objref = obj.proj v4 1.i256; - v9.i256 = extract_value v0 1.i256; - obj.store v8 v9; - v10.objref = obj.proj v2 1.i256; - obj.store v10 0.i256; - v11.@layout_4 = obj.load v2; - return v11; -} - -func private %core__lib__abi__trait_AbiSize__payload_size__ge513_a8bc(v0.i256) -> i256 { - block0: - v1.*i256 = alloca i256; - mstore v1 v0 i256; - jump block1; - - block1: - return 32.i256; -} - -func private %core__lib__abi__trait_AbiSize__payload_size__ge513_a8bc_0(v0.i256) -> i256 { - block0: - v1.*i256 = alloca i256; - mstore v1 v0 i256; - jump block1; - - block1: - return 32.i256; -} - -func private %std__lib__abi__sol__impl_trait_SolDecoder_68ab__pos__g463e_047d(v0.objref<@layout_5>) -> i256 { - block0: - jump block1; - - block1: - v3.objref<@layout_4> = obj.proj v0 0.i256; - v5.objref = obj.proj v3 1.i256; - v6.i256 = obj.load v5; - return v6; -} - -func private %impl_trait_SolEncoder__pos(v0.objref<@layout_2>) -> i256 { - block0: - jump block1; - - block1: - v3.objref = obj.proj v0 1.i256; - v4.i256 = obj.load v3; - return v4; -} - -func private %std__lib__abi__sol__impl_trait_SolDecoder_68ab__pos__g463e_c53e(v0.objref<@layout_5>) -> i256 { - block0: - jump block1; - - block1: - v3.objref<@layout_4> = obj.proj v0 0.i256; - v5.objref = obj.proj v3 1.i256; - v6.i256 = obj.load v5; - return v6; -} - -func private %std__lib__abi__sol__impl_trait_SolDecoder_68ab__pos__g463e_ebe7(v0.objref<@layout_5>) -> i256 { - block0: - jump block1; - - block1: - v3.objref<@layout_4> = obj.proj v0 0.i256; - v5.objref = obj.proj v3 1.i256; - v6.i256 = obj.load v5; - return v6; -} - -func private %read_cell(v0.i256) -> i256 { - block0: - jump block1; - - block1: - v2.i256 = evm_sload v0; - return v2; -} - -func private %std__lib__abi__sol__impl_trait_SolDecoder_68ab__read_word__g463e_3646(v0.objref<@layout_5>) -> i256 { - block0: - v1.*i256 = alloca i256; - v2.*i256 = alloca i256; - jump block1; - - block1: - v5.objref<@layout_4> = obj.proj v0 0.i256; - v6.objref<@layout_3> = obj.proj v5 0.i256; - v7.@layout_3 = obj.load v6; - v8.i256 = call %std__lib__evm__memory_input__impl_trait_MemoryBytes_c1cd__len_b143 v7; - mstore v1 v8 i256; - v9.objref<@layout_4> = obj.proj v0 0.i256; - v11.objref = obj.proj v9 1.i256; - v12.i256 = obj.load v11; - (v14.i256, v15.i1) = uaddo v12 32.i256; - br v15 block6 block7; - - block2: - evm_revert 0.i256 0.i256; - - block3: - jump block4; - - block4: - v26.objref<@layout_4> = obj.proj v0 0.i256; - v27.objref<@layout_3> = obj.proj v26 0.i256; - v28.@layout_3 = obj.load v27; - v29.objref<@layout_4> = obj.proj v0 0.i256; - v30.objref = obj.proj v29 1.i256; - v31.i256 = obj.load v30; - v32.i256 = call %std__lib__evm__memory_input__impl_trait_MemoryBytes_c1cd__word_at_ca68 v28 v31; - v34.objref<@layout_4> = obj.proj v0 0.i256; - v35.objref = obj.proj v34 1.i256; - obj.store v35 v14; - return v32; - - block5: - v36.i256 = mload v1 i256; - mstore v2 v36 i256; - v38.i256 = mload v2 i256; - v39.i1 = gt v14 v38; - br v39 block2 block3; - - block6: - mstore 0.i256 35408467139433450592217433187231851964531694900788300625387963629091585785856.i256 i256; - mstore 4.i256 17.i256 i256; - evm_revert 0.i256 36.i256; - - block7: - v21.objref<@layout_4> = obj.proj v0 0.i256; - v22.objref = obj.proj v21 1.i256; - v23.i256 = obj.load v22; - v24.i1 = lt v14 v23; - br v24 block2 block5; -} - -func private %std__lib__abi__sol__impl_trait_SolDecoder_68ab__read_word__g463e_77a7(v0.objref<@layout_5>) -> i256 { - block0: - v1.*i256 = alloca i256; - v2.*i256 = alloca i256; - jump block1; - - block1: - v5.objref<@layout_4> = obj.proj v0 0.i256; - v6.objref<@layout_3> = obj.proj v5 0.i256; - v7.@layout_3 = obj.load v6; - v8.i256 = call %std__lib__evm__memory_input__impl_trait_MemoryBytes_c1cd__len_7233 v7; - mstore v1 v8 i256; - v9.objref<@layout_4> = obj.proj v0 0.i256; - v11.objref = obj.proj v9 1.i256; - v12.i256 = obj.load v11; - (v14.i256, v15.i1) = uaddo v12 32.i256; - br v15 block6 block7; - - block2: - evm_revert 0.i256 0.i256; - - block3: - jump block4; - - block4: - v26.objref<@layout_4> = obj.proj v0 0.i256; - v27.objref<@layout_3> = obj.proj v26 0.i256; - v28.@layout_3 = obj.load v27; - v29.objref<@layout_4> = obj.proj v0 0.i256; - v30.objref = obj.proj v29 1.i256; - v31.i256 = obj.load v30; - v32.i256 = call %std__lib__evm__memory_input__impl_trait_MemoryBytes_c1cd__word_at_caf8 v28 v31; - v34.objref<@layout_4> = obj.proj v0 0.i256; - v35.objref = obj.proj v34 1.i256; - obj.store v35 v14; - return v32; - - block5: - v36.i256 = mload v1 i256; - mstore v2 v36 i256; - v38.i256 = mload v2 i256; - v39.i1 = gt v14 v38; - br v39 block2 block3; - - block6: - mstore 0.i256 35408467139433450592217433187231851964531694900788300625387963629091585785856.i256 i256; - mstore 4.i256 17.i256 i256; - evm_revert 0.i256 36.i256; - - block7: - v21.objref<@layout_4> = obj.proj v0 0.i256; - v22.objref = obj.proj v21 1.i256; - v23.i256 = obj.load v22; - v24.i1 = lt v14 v23; - br v24 block2 block5; -} - -func private %std__lib__abi__sol__impl_trait_SolDecoder_68ab__read_word__g463e_b6e9(v0.objref<@layout_5>) -> i256 { - block0: - v1.*i256 = alloca i256; - v2.*i256 = alloca i256; - jump block1; - - block1: - v5.objref<@layout_4> = obj.proj v0 0.i256; - v6.objref<@layout_3> = obj.proj v5 0.i256; - v7.@layout_3 = obj.load v6; - v8.i256 = call %std__lib__evm__memory_input__impl_trait_MemoryBytes_c1cd__len_0a8e v7; - mstore v1 v8 i256; - v9.objref<@layout_4> = obj.proj v0 0.i256; - v11.objref = obj.proj v9 1.i256; - v12.i256 = obj.load v11; - (v14.i256, v15.i1) = uaddo v12 32.i256; - br v15 block6 block7; - - block2: - evm_revert 0.i256 0.i256; - - block3: - jump block4; - - block4: - v26.objref<@layout_4> = obj.proj v0 0.i256; - v27.objref<@layout_3> = obj.proj v26 0.i256; - v28.@layout_3 = obj.load v27; - v29.objref<@layout_4> = obj.proj v0 0.i256; - v30.objref = obj.proj v29 1.i256; - v31.i256 = obj.load v30; - v32.i256 = call %std__lib__evm__memory_input__impl_trait_MemoryBytes_c1cd__word_at_d0f7 v28 v31; - v34.objref<@layout_4> = obj.proj v0 0.i256; - v35.objref = obj.proj v34 1.i256; - obj.store v35 v14; - return v32; - - block5: - v36.i256 = mload v1 i256; - mstore v2 v36 i256; - v38.i256 = mload v2 i256; - v39.i1 = gt v14 v38; - br v39 block2 block3; - - block6: - mstore 0.i256 35408467139433450592217433187231851964531694900788300625387963629091585785856.i256 i256; - mstore 4.i256 17.i256 i256; - evm_revert 0.i256 36.i256; - - block7: - v21.objref<@layout_4> = obj.proj v0 0.i256; - v22.objref = obj.proj v21 1.i256; - v23.i256 = obj.load v22; - v24.i1 = lt v14 v23; - br v24 block2 block5; -} - -func private %std__lib__abi__sol__impl_trait_SolDecoder_68ab__read_word__g463e_c929(v0.objref<@layout_5>) -> i256 { - block0: - v1.*i256 = alloca i256; - v2.*i256 = alloca i256; - jump block1; - - block1: - v5.objref<@layout_4> = obj.proj v0 0.i256; - v6.objref<@layout_3> = obj.proj v5 0.i256; - v7.@layout_3 = obj.load v6; - v8.i256 = call %std__lib__evm__memory_input__impl_trait_MemoryBytes_c1cd__len_2605 v7; - mstore v1 v8 i256; - v9.objref<@layout_4> = obj.proj v0 0.i256; - v11.objref = obj.proj v9 1.i256; - v12.i256 = obj.load v11; - (v14.i256, v15.i1) = uaddo v12 32.i256; - br v15 block6 block7; - - block2: - evm_revert 0.i256 0.i256; - - block3: - jump block4; - - block4: - v26.objref<@layout_4> = obj.proj v0 0.i256; - v27.objref<@layout_3> = obj.proj v26 0.i256; - v28.@layout_3 = obj.load v27; - v29.objref<@layout_4> = obj.proj v0 0.i256; - v30.objref = obj.proj v29 1.i256; - v31.i256 = obj.load v30; - v32.i256 = call %std__lib__evm__memory_input__impl_trait_MemoryBytes_c1cd__word_at_a18e v28 v31; - v34.objref<@layout_4> = obj.proj v0 0.i256; - v35.objref = obj.proj v34 1.i256; - obj.store v35 v14; - return v32; - - block5: - v36.i256 = mload v1 i256; - mstore v2 v36 i256; - v38.i256 = mload v2 i256; - v39.i1 = gt v14 v38; - br v39 block2 block3; - - block6: - mstore 0.i256 35408467139433450592217433187231851964531694900788300625387963629091585785856.i256 i256; - mstore 4.i256 17.i256 i256; - evm_revert 0.i256 36.i256; - - block7: - v21.objref<@layout_4> = obj.proj v0 0.i256; - v22.objref = obj.proj v21 1.i256; - v23.i256 = obj.load v22; - v24.i1 = lt v14 v23; - br v24 block2 block5; -} - -func private %std__lib__abi__sol__impl_trait_SolDecoder_68ab__read_word__g463e_d39e(v0.objref<@layout_5>) -> i256 { - block0: - v1.*i256 = alloca i256; - v2.*i256 = alloca i256; - jump block1; - - block1: - v5.objref<@layout_4> = obj.proj v0 0.i256; - v6.objref<@layout_3> = obj.proj v5 0.i256; - v7.@layout_3 = obj.load v6; - v8.i256 = call %std__lib__evm__memory_input__impl_trait_MemoryBytes_c1cd__len_c8fa v7; - mstore v1 v8 i256; - v9.objref<@layout_4> = obj.proj v0 0.i256; - v11.objref = obj.proj v9 1.i256; - v12.i256 = obj.load v11; - (v14.i256, v15.i1) = uaddo v12 32.i256; - br v15 block6 block7; - - block2: - evm_revert 0.i256 0.i256; - - block3: - jump block4; - - block4: - v26.objref<@layout_4> = obj.proj v0 0.i256; - v27.objref<@layout_3> = obj.proj v26 0.i256; - v28.@layout_3 = obj.load v27; - v29.objref<@layout_4> = obj.proj v0 0.i256; - v30.objref = obj.proj v29 1.i256; - v31.i256 = obj.load v30; - v32.i256 = call %std__lib__evm__memory_input__impl_trait_MemoryBytes_c1cd__word_at_bd46 v28 v31; - v34.objref<@layout_4> = obj.proj v0 0.i256; - v35.objref = obj.proj v34 1.i256; - obj.store v35 v14; - return v32; - - block5: - v36.i256 = mload v1 i256; - mstore v2 v36 i256; - v38.i256 = mload v2 i256; - v39.i1 = gt v14 v38; - br v39 block2 block3; - - block6: - mstore 0.i256 35408467139433450592217433187231851964531694900788300625387963629091585785856.i256 i256; - mstore 4.i256 17.i256 i256; - evm_revert 0.i256 36.i256; - - block7: - v21.objref<@layout_4> = obj.proj v0 0.i256; - v22.objref = obj.proj v21 1.i256; - v23.i256 = obj.load v22; - v24.i1 = lt v14 v23; - br v24 block2 block5; -} - -func private %std__lib__abi__sol__impl_trait_SolDecoder_68ab__read_word__g463e_ebbf(v0.objref<@layout_5>) -> i256 { - block0: - v1.*i256 = alloca i256; - v2.*i256 = alloca i256; - jump block1; - - block1: - v5.objref<@layout_4> = obj.proj v0 0.i256; - v6.objref<@layout_3> = obj.proj v5 0.i256; - v7.@layout_3 = obj.load v6; - v8.i256 = call %std__lib__evm__memory_input__impl_trait_MemoryBytes_c1cd__len_9b08 v7; - mstore v1 v8 i256; - v9.objref<@layout_4> = obj.proj v0 0.i256; - v11.objref = obj.proj v9 1.i256; - v12.i256 = obj.load v11; - (v14.i256, v15.i1) = uaddo v12 32.i256; - br v15 block6 block7; - - block2: - evm_revert 0.i256 0.i256; - - block3: - jump block4; - - block4: - v26.objref<@layout_4> = obj.proj v0 0.i256; - v27.objref<@layout_3> = obj.proj v26 0.i256; - v28.@layout_3 = obj.load v27; - v29.objref<@layout_4> = obj.proj v0 0.i256; - v30.objref = obj.proj v29 1.i256; - v31.i256 = obj.load v30; - v32.i256 = call %std__lib__evm__memory_input__impl_trait_MemoryBytes_c1cd__word_at_731b v28 v31; - v34.objref<@layout_4> = obj.proj v0 0.i256; - v35.objref = obj.proj v34 1.i256; - obj.store v35 v14; - return v32; - - block5: - v36.i256 = mload v1 i256; - mstore v2 v36 i256; - v38.i256 = mload v2 i256; - v39.i1 = gt v14 v38; - br v39 block2 block3; - - block6: - mstore 0.i256 35408467139433450592217433187231851964531694900788300625387963629091585785856.i256 i256; - mstore 4.i256 17.i256 i256; - evm_revert 0.i256 36.i256; - - block7: - v21.objref<@layout_4> = obj.proj v0 0.i256; - v22.objref = obj.proj v21 1.i256; - v23.i256 = obj.load v22; - v24.i1 = lt v14 v23; - br v24 block2 block5; -} - -func private %std__lib__abi__sol__impl_trait_SolDecoder_68ab__set_base__g463e_6a44(v0.objref<@layout_5>, v1.i256) { - block0: - v2.*i256 = alloca i256; - mstore v2 v1 i256; - jump block1; - - block1: - v3.i256 = mload v2 i256; - v6.objref = obj.proj v0 1.i256; - obj.store v6 v3; - return; -} - -func private %std__lib__abi__sol__impl_trait_SolDecoder_68ab__set_base__g463e_8d49(v0.objref<@layout_5>, v1.i256) { - block0: - v2.*i256 = alloca i256; - mstore v2 v1 i256; - jump block1; - - block1: - v3.i256 = mload v2 i256; - v6.objref = obj.proj v0 1.i256; - obj.store v6 v3; - return; -} - -func private %impl_trait_SolEncoder__set_base(v0.objref<@layout_2>, v1.i256) { - block0: - v2.*i256 = alloca i256; - mstore v2 v1 i256; - jump block1; - - block1: - v3.i256 = mload v2 i256; - v6.objref = obj.proj v0 0.i256; - obj.store v6 v3; - return; -} - -func private %std__lib__abi__sol__impl_trait_SolDecoder_68ab__set_base__g463e_b155(v0.objref<@layout_5>, v1.i256) { - block0: - v2.*i256 = alloca i256; - mstore v2 v1 i256; - jump block1; - - block1: - v3.i256 = mload v2 i256; - v6.objref = obj.proj v0 1.i256; - obj.store v6 v3; - return; -} - -func private %std__lib__abi__sol__impl_trait_SolDecoder_68ab__set_pos__g463e_135d(v0.objref<@layout_5>, v1.i256) { - block0: - v2.*i256 = alloca i256; - mstore v2 v1 i256; - jump block1; - - block1: - v3.i256 = mload v2 i256; - v6.objref<@layout_4> = obj.proj v0 0.i256; - v8.objref = obj.proj v6 1.i256; - obj.store v8 v3; - return; -} - -func private %impl_trait_SolEncoder__set_pos(v0.objref<@layout_2>, v1.i256) { - block0: - v2.*i256 = alloca i256; - mstore v2 v1 i256; - jump block1; - - block1: - v3.i256 = mload v2 i256; - v6.objref = obj.proj v0 1.i256; - obj.store v6 v3; - return; -} - -func private %std__lib__abi__sol__impl_trait_SolDecoder_68ab__set_pos__g463e_6579(v0.objref<@layout_5>, v1.i256) { - block0: - v2.*i256 = alloca i256; - mstore v2 v1 i256; - jump block1; - - block1: - v3.i256 = mload v2 i256; - v6.objref<@layout_4> = obj.proj v0 0.i256; - v8.objref = obj.proj v6 1.i256; - obj.store v8 v3; - return; -} - -func private %std__lib__abi__sol__impl_trait_SolDecoder_68ab__set_pos__g463e_ec19(v0.objref<@layout_5>, v1.i256) { - block0: - v2.*i256 = alloca i256; - mstore v2 v1 i256; - jump block1; - - block1: - v3.i256 = mload v2 i256; - v6.objref<@layout_4> = obj.proj v0 0.i256; - v8.objref = obj.proj v6 1.i256; - obj.store v8 v3; - return; -} - -func private %stor_ptr(v0.i256) -> i256 { - block0: - v1.*i256 = alloca i256; - mstore v1 v0 i256; - jump block1; - - block1: - v2.i256 = mload v1 i256; - v3.i256 = call %from_raw v2; - return v3; -} - -func private %store_word(v0.i256, v1.i256) { - block0: - v2.*i256 = alloca i256; - v3.*i256 = alloca i256; - mstore v2 v0 i256; - mstore v3 v1 i256; - jump block1; - - block1: - v4.i256 = mload v2 i256; - v5.i256 = mload v3 i256; - mstore v4 v5 i256; - return; -} - -func private %std__lib__evm__memory_input__impl_trait_MemoryBytes_c1cd__word_at_731b(v0.@layout_3, v1.i256) -> i256 { - block0: - v2.objref<@layout_3> = obj.alloc @layout_3; - v3.*i256 = alloca i256; - v5.objref = obj.proj v2 0.i256; - v6.i256 = extract_value v0 0.i256; - obj.store v5 v6; - v8.objref = obj.proj v2 1.i256; - v9.i256 = extract_value v0 1.i256; - obj.store v8 v9; - mstore v3 v1 i256; - jump block1; - - block1: - v10.objref = obj.proj v2 0.i256; - v11.i256 = obj.load v10; - v12.i256 = mload v3 i256; - v13.i256 = add v11 v12; - v14.i256 = mload v13 i256; - return v14; -} - -func private %std__lib__evm__memory_input__impl_trait_MemoryBytes_c1cd__word_at_a18e(v0.@layout_3, v1.i256) -> i256 { - block0: - v2.objref<@layout_3> = obj.alloc @layout_3; - v3.*i256 = alloca i256; - v5.objref = obj.proj v2 0.i256; - v6.i256 = extract_value v0 0.i256; - obj.store v5 v6; - v8.objref = obj.proj v2 1.i256; - v9.i256 = extract_value v0 1.i256; - obj.store v8 v9; - mstore v3 v1 i256; - jump block1; - - block1: - v10.objref = obj.proj v2 0.i256; - v11.i256 = obj.load v10; - v12.i256 = mload v3 i256; - v13.i256 = add v11 v12; - v14.i256 = mload v13 i256; - return v14; -} - -func private %std__lib__evm__memory_input__impl_trait_MemoryBytes_c1cd__word_at_bd46(v0.@layout_3, v1.i256) -> i256 { - block0: - v2.objref<@layout_3> = obj.alloc @layout_3; - v3.*i256 = alloca i256; - v5.objref = obj.proj v2 0.i256; - v6.i256 = extract_value v0 0.i256; - obj.store v5 v6; - v8.objref = obj.proj v2 1.i256; - v9.i256 = extract_value v0 1.i256; - obj.store v8 v9; - mstore v3 v1 i256; - jump block1; - - block1: - v10.objref = obj.proj v2 0.i256; - v11.i256 = obj.load v10; - v12.i256 = mload v3 i256; - v13.i256 = add v11 v12; - v14.i256 = mload v13 i256; - return v14; -} - -func private %std__lib__evm__memory_input__impl_trait_MemoryBytes_c1cd__word_at_ca68(v0.@layout_3, v1.i256) -> i256 { - block0: - v2.objref<@layout_3> = obj.alloc @layout_3; - v3.*i256 = alloca i256; - v5.objref = obj.proj v2 0.i256; - v6.i256 = extract_value v0 0.i256; - obj.store v5 v6; - v8.objref = obj.proj v2 1.i256; - v9.i256 = extract_value v0 1.i256; - obj.store v8 v9; - mstore v3 v1 i256; - jump block1; - - block1: - v10.objref = obj.proj v2 0.i256; - v11.i256 = obj.load v10; - v12.i256 = mload v3 i256; - v13.i256 = add v11 v12; - v14.i256 = mload v13 i256; - return v14; -} - -func private %std__lib__evm__memory_input__impl_trait_MemoryBytes_c1cd__word_at_caf8(v0.@layout_3, v1.i256) -> i256 { - block0: - v2.objref<@layout_3> = obj.alloc @layout_3; - v3.*i256 = alloca i256; - v5.objref = obj.proj v2 0.i256; - v6.i256 = extract_value v0 0.i256; - obj.store v5 v6; - v8.objref = obj.proj v2 1.i256; - v9.i256 = extract_value v0 1.i256; - obj.store v8 v9; - mstore v3 v1 i256; - jump block1; - - block1: - v10.objref = obj.proj v2 0.i256; - v11.i256 = obj.load v10; - v12.i256 = mload v3 i256; - v13.i256 = add v11 v12; - v14.i256 = mload v13 i256; - return v14; -} - -func private %std__lib__evm__memory_input__impl_trait_MemoryBytes_c1cd__word_at_d0f7(v0.@layout_3, v1.i256) -> i256 { - block0: - v2.objref<@layout_3> = obj.alloc @layout_3; - v3.*i256 = alloca i256; - v5.objref = obj.proj v2 0.i256; - v6.i256 = extract_value v0 0.i256; - obj.store v5 v6; - v8.objref = obj.proj v2 1.i256; - v9.i256 = extract_value v0 1.i256; - obj.store v8 v9; - mstore v3 v1 i256; - jump block1; - - block1: - v10.objref = obj.proj v2 0.i256; - v11.i256 = obj.load v10; - v12.i256 = mload v3 i256; - v13.i256 = add v11 v12; - v14.i256 = mload v13 i256; - return v14; -} - -func private %write_cell(v0.i256, v1.i256) -> i256 { - block0: - v2.*i256 = alloca i256; - mstore v2 v0 i256; + v2.*i256 = alloca i256; + mstore v2 v0 i256; jump block1; block1: @@ -1668,40 +272,6 @@ func private %write_cell(v0.i256, v1.i256) -> i256 { return v5; } -func private %std__lib__abi__sol__impl_trait_SolEncoder_19ce__write_word_2aa5(v0.objref<@layout_2>, v1.i256) { - block0: - v2.*i256 = alloca i256; - mstore v2 v1 i256; - jump block1; - - block1: - v5.objref = obj.proj v0 1.i256; - v6.i256 = obj.load v5; - v7.i256 = mload v2 i256; - mstore v6 v7 i256; - v10.i256 = add v6 32.i256; - v11.objref = obj.proj v0 1.i256; - obj.store v11 v10; - return; -} - -func private %std__lib__abi__sol__impl_trait_SolEncoder_19ce__write_word_8a50(v0.objref<@layout_2>, v1.i256) { - block0: - v2.*i256 = alloca i256; - mstore v2 v1 i256; - jump block1; - - block1: - v5.objref = obj.proj v0 1.i256; - v6.i256 = obj.load v5; - v7.i256 = mload v2 i256; - mstore v6 v7 i256; - v10.i256 = add v6 32.i256; - v11.objref = obj.proj v0 1.i256; - obj.store v11 v10; - return; -} - object @EffectHandleFieldDeref { section init { diff --git a/crates/codegen/tests/fixtures/sonatina_ir/erc20.snap b/crates/codegen/tests/fixtures/sonatina_ir/erc20.snap index 7f26facb89..980ca6f064 100644 --- a/crates/codegen/tests/fixtures/sonatina_ir/erc20.snap +++ b/crates/codegen/tests/fixtures/sonatina_ir/erc20.snap @@ -1,5 +1,6 @@ --- source: crates/codegen/tests/sonatina_ir.rs +assertion_line: 402 expression: output input_file: crates/codegen/tests/fixtures/erc20.fe --- @@ -23,15 +24,14 @@ type @layout_14 = {@layout_0}; type @layout_15 = {i256, @layout_0}; type @layout_16 = {@layout_0, i256}; type @layout_17 = {@layout_0, i256}; -type @layout_18 = {i256}; +type @layout_18 = {@layout_0, @layout_0, i256}; type @layout_19 = {@layout_0, @layout_0, i256}; -type @layout_20 = {@layout_0, @layout_0, i256}; -type @layout_21 = {i256, i256}; -type @layout_22 = {@layout_0, @layout_0}; +type @layout_20 = {i256, i256}; +type @layout_21 = {@layout_0, @layout_0}; +type @layout_22 = {}; type @layout_23 = {}; type @layout_24 = {}; -type @layout_25 = {}; -type @layout_26 = {@layout_25}; +type @layout_25 = {@layout_24}; func private %__CoolCoin_init(v0.i256, v1.@layout_0, v2.i256, v3.i256, v4.objref<@layout_2>, v5.objref<@layout_2>) { block0: @@ -110,7 +110,7 @@ func private %__CoolCoin_recv_0_4(v0.@layout_0, v1.@layout_0, v2.i256) -> i256 { jump block1; block1: - v3.objref<@layout_22> = obj.alloc @layout_22; + v3.objref<@layout_21> = obj.alloc @layout_21; v6.objref<@layout_0> = obj.proj v3 0.i256; v7.objref = obj.proj v6 0.i256; v8.i256 = extract_value v0 0.i256; @@ -119,7 +119,7 @@ func private %__CoolCoin_recv_0_4(v0.@layout_0, v1.@layout_0, v2.i256) -> i256 { v12.objref = obj.proj v11 0.i256; v13.i256 = extract_value v1 0.i256; obj.store v12 v13; - v14.@layout_22 = obj.load v3; + v14.@layout_21 = obj.load v3; v15.i256 = call %std__lib__evm__storage_map__impl_StorageMap_9f54__get__ga15b_cf04 v14; return v15; } @@ -196,7 +196,7 @@ func private %__CoolCoin_recv_1_3(v0.@layout_0, v1.i256, v2.objref<@layout_2>, v block1: v5.@layout_0 = call %caller; - v6.objref<@layout_22> = obj.alloc @layout_22; + v6.objref<@layout_21> = obj.alloc @layout_21; v8.objref<@layout_0> = obj.proj v6 0.i256; v9.objref = obj.proj v8 0.i256; v10.i256 = extract_value v5 0.i256; @@ -205,7 +205,7 @@ func private %__CoolCoin_recv_1_3(v0.@layout_0, v1.i256, v2.objref<@layout_2>, v v14.objref = obj.proj v13 0.i256; v15.i256 = extract_value v0 0.i256; obj.store v14 v15; - v16.@layout_22 = obj.load v6; + v16.@layout_21 = obj.load v6; v17.i256 = call %std__lib__evm__storage_map__impl_StorageMap_9f54__get__ga15b_b5d5_0 v16; (v19.i256, v20.i1) = uaddo v17 v1; br v20 block2 block3; @@ -229,7 +229,7 @@ func private %__CoolCoin_recv_1_4(v0.@layout_0, v1.i256, v2.objref<@layout_2>, v block1: v7.@layout_0 = call %caller; - v8.objref<@layout_22> = obj.alloc @layout_22; + v8.objref<@layout_21> = obj.alloc @layout_21; v10.objref<@layout_0> = obj.proj v8 0.i256; v11.objref = obj.proj v10 0.i256; v12.i256 = extract_value v7 0.i256; @@ -238,7 +238,7 @@ func private %__CoolCoin_recv_1_4(v0.@layout_0, v1.i256, v2.objref<@layout_2>, v v16.objref = obj.proj v15 0.i256; v17.i256 = extract_value v0 0.i256; obj.store v16 v17; - v18.@layout_22 = obj.load v8; + v18.@layout_21 = obj.load v8; v19.i256 = call %std__lib__evm__storage_map__impl_StorageMap_9f54__get__ga15b_b5d5_0 v18; v20.i256 = mload v5 i256; mstore v6 v20 i256; @@ -380,36 +380,6 @@ func private %abi_field_size__g79ff(v0.i8) -> i256 { return v7; } -func private %abi_field_size__ge513(v0.i256) -> i256 { - block0: - v1.*i256 = alloca i256; - mstore v1 v0 i256; - jump block1; - - block1: - v2.i256 = mload v1 i256; - v3.i256 = call %core__lib__abi__trait_AbiSize__payload_size__ge513_77e5_0 v2; - br 0.i1 block2 block3; - - block2: - (v7.i256, v8.i1) = uaddo 32.i256 v3; - br v8 block5 block6; - - block3: - jump block4; - - block4: - return v3; - - block5: - mstore 0.i256 35408467139433450592217433187231851964531694900788300625387963629091585785856.i256 i256; - mstore 4.i256 17.i256 i256; - evm_revert 0.i256 36.i256; - - block6: - return v7; -} - func private %core__lib__abi__abi_payload_size__ge513_b9e3(v0.i256) -> i256 { block0: v1.*i256 = alloca i256; @@ -509,18 +479,6 @@ func private %abi_single_root_size__g79ff(v0.i8) -> i256 { return v3; } -func private %abi_single_root_size__ge513(v0.i256) -> i256 { - block0: - v1.*i256 = alloca i256; - mstore v1 v0 i256; - jump block1; - - block1: - v2.i256 = mload v1 i256; - v3.i256 = call %abi_field_size__ge513 v2; - return v3; -} - func private %standalone_erc20__erc20__approve__g5c3f_26fb(v0.@layout_0, v1.@layout_0, v2.i256, v3.i256, v4.objref<@layout_2>) { block0: v5.objref<@layout_0> = obj.alloc @layout_0; @@ -556,7 +514,7 @@ func private %standalone_erc20__erc20__approve__g5c3f_26fb(v0.@layout_0, v1.@lay call %std__lib__evm__effects__assert_d98e_0 v27; v29.@layout_0 = obj.load v5; v30.@layout_0 = obj.load v6; - v31.objref<@layout_22> = obj.alloc @layout_22; + v31.objref<@layout_21> = obj.alloc @layout_21; v32.objref<@layout_0> = obj.proj v31 0.i256; v33.objref = obj.proj v32 0.i256; v34.i256 = extract_value v29 0.i256; @@ -565,13 +523,13 @@ func private %standalone_erc20__erc20__approve__g5c3f_26fb(v0.@layout_0, v1.@lay v37.objref = obj.proj v36 0.i256; v38.i256 = extract_value v30 0.i256; obj.store v37 v38; - v39.@layout_22 = obj.load v31; + v39.@layout_21 = obj.load v31; v40.i256 = mload v7 i256; call %std__lib__evm__storage_map__impl_StorageMap_9f54__set__ga15b_f7f7_0 v39 v40; v43.@layout_0 = obj.load v5; v44.@layout_0 = obj.load v6; v45.i256 = mload v7 i256; - v46.objref<@layout_19> = obj.alloc @layout_19; + v46.objref<@layout_18> = obj.alloc @layout_18; v47.objref<@layout_0> = obj.proj v46 0.i256; v48.objref = obj.proj v47 0.i256; v49.i256 = extract_value v43 0.i256; @@ -582,7 +540,7 @@ func private %standalone_erc20__erc20__approve__g5c3f_26fb(v0.@layout_0, v1.@lay obj.store v51 v52; v54.objref = obj.proj v46 2.i256; obj.store v54 v45; - v55.@layout_19 = obj.load v46; + v55.@layout_18 = obj.load v46; call %emit__g9cd0 v4 v55; return; } @@ -622,7 +580,7 @@ func private %standalone_erc20__erc20__approve__g5c3f_6e4c(v0.@layout_0, v1.@lay call %std__lib__evm__effects__assert_d98e_0 v27; v29.@layout_0 = obj.load v5; v30.@layout_0 = obj.load v6; - v31.objref<@layout_22> = obj.alloc @layout_22; + v31.objref<@layout_21> = obj.alloc @layout_21; v32.objref<@layout_0> = obj.proj v31 0.i256; v33.objref = obj.proj v32 0.i256; v34.i256 = extract_value v29 0.i256; @@ -631,13 +589,13 @@ func private %standalone_erc20__erc20__approve__g5c3f_6e4c(v0.@layout_0, v1.@lay v37.objref = obj.proj v36 0.i256; v38.i256 = extract_value v30 0.i256; obj.store v37 v38; - v39.@layout_22 = obj.load v31; + v39.@layout_21 = obj.load v31; v40.i256 = mload v7 i256; call %std__lib__evm__storage_map__impl_StorageMap_9f54__set__ga15b_f7f7_0 v39 v40; v43.@layout_0 = obj.load v5; v44.@layout_0 = obj.load v6; v45.i256 = mload v7 i256; - v46.objref<@layout_19> = obj.alloc @layout_19; + v46.objref<@layout_18> = obj.alloc @layout_18; v47.objref<@layout_0> = obj.proj v46 0.i256; v48.objref = obj.proj v47 0.i256; v49.i256 = extract_value v43 0.i256; @@ -648,7 +606,7 @@ func private %standalone_erc20__erc20__approve__g5c3f_6e4c(v0.@layout_0, v1.@lay obj.store v51 v52; v54.objref = obj.proj v46 2.i256; obj.store v54 v45; - v55.@layout_19 = obj.load v46; + v55.@layout_18 = obj.load v46; call %emit__g9cd0 v4 v55; return; } @@ -688,7 +646,7 @@ func private %standalone_erc20__erc20__approve__g5c3f_948a(v0.@layout_0, v1.@lay call %std__lib__evm__effects__assert_d98e_0 v27; v29.@layout_0 = obj.load v5; v30.@layout_0 = obj.load v6; - v31.objref<@layout_22> = obj.alloc @layout_22; + v31.objref<@layout_21> = obj.alloc @layout_21; v32.objref<@layout_0> = obj.proj v31 0.i256; v33.objref = obj.proj v32 0.i256; v34.i256 = extract_value v29 0.i256; @@ -697,13 +655,13 @@ func private %standalone_erc20__erc20__approve__g5c3f_948a(v0.@layout_0, v1.@lay v37.objref = obj.proj v36 0.i256; v38.i256 = extract_value v30 0.i256; obj.store v37 v38; - v39.@layout_22 = obj.load v31; + v39.@layout_21 = obj.load v31; v40.i256 = mload v7 i256; call %std__lib__evm__storage_map__impl_StorageMap_9f54__set__ga15b_f7f7_0 v39 v40; v43.@layout_0 = obj.load v5; v44.@layout_0 = obj.load v6; v45.i256 = mload v7 i256; - v46.objref<@layout_19> = obj.alloc @layout_19; + v46.objref<@layout_18> = obj.alloc @layout_18; v47.objref<@layout_0> = obj.proj v46 0.i256; v48.objref = obj.proj v47 0.i256; v49.i256 = extract_value v43 0.i256; @@ -714,7 +672,7 @@ func private %standalone_erc20__erc20__approve__g5c3f_948a(v0.@layout_0, v1.@lay obj.store v51 v52; v54.objref = obj.proj v46 2.i256; obj.store v54 v45; - v55.@layout_19 = obj.load v46; + v55.@layout_18 = obj.load v46; call %emit__g9cd0 v4 v55; return; } @@ -1076,16 +1034,6 @@ func private %std__lib__abi__sol__impl_trait_SolEncoder_19ce__base_a9a0(v0.objre return v4; } -func private %std__lib__abi__sol__impl_trait_SolDecoder_68ab__base__g463e_b56a(v0.objref<@layout_7>) -> i256 { - block0: - jump block1; - - block1: - v3.objref = obj.proj v0 1.i256; - v4.i256 = obj.load v3; - return v4; -} - func private %std__lib__abi__sol__impl_trait_SolEncoder_19ce__base_bb09(v0.objref<@layout_4>) -> i256 { block0: jump block1; @@ -1176,16 +1124,6 @@ func private %std__lib__abi__sol__impl_trait_SolEncoder_19ce__base_deb4_1(v0.obj return v4; } -func private %std__lib__abi__sol__impl_trait_SolEncoder_19ce__base_fd6f(v0.objref<@layout_4>) -> i256 { - block0: - jump block1; - - block1: - v3.objref = obj.proj v0 0.i256; - v4.i256 = obj.load v3; - return v4; -} - func private %standalone_erc20__erc20__burn__g5c3f_533f(v0.@layout_0, v1.i256, v2.i256, v3.objref<@layout_2>) { block0: v4.objref<@layout_0> = obj.alloc @layout_0; @@ -1234,7 +1172,7 @@ func private %standalone_erc20__erc20__burn__g5c3f_533f(v0.@layout_0, v1.i256, v v40.@layout_0 = obj.load v4; v41.@layout_0 = call %zero; v42.i256 = mload v5 i256; - v43.objref<@layout_20> = obj.alloc @layout_20; + v43.objref<@layout_19> = obj.alloc @layout_19; v44.objref<@layout_0> = obj.proj v43 0.i256; v45.objref = obj.proj v44 0.i256; v46.i256 = extract_value v40 0.i256; @@ -1245,7 +1183,7 @@ func private %standalone_erc20__erc20__burn__g5c3f_533f(v0.@layout_0, v1.i256, v obj.store v49 v50; v52.objref = obj.proj v43 2.i256; obj.store v52 v42; - v53.@layout_20 = obj.load v43; + v53.@layout_19 = obj.load v43; call %emit__g4c3d v3 v53; return; } @@ -1298,7 +1236,7 @@ func private %standalone_erc20__erc20__burn__g5c3f_6ec4(v0.@layout_0, v1.i256, v v40.@layout_0 = obj.load v4; v41.@layout_0 = call %zero; v42.i256 = mload v5 i256; - v43.objref<@layout_20> = obj.alloc @layout_20; + v43.objref<@layout_19> = obj.alloc @layout_19; v44.objref<@layout_0> = obj.proj v43 0.i256; v45.objref = obj.proj v44 0.i256; v46.i256 = extract_value v40 0.i256; @@ -1309,7 +1247,7 @@ func private %standalone_erc20__erc20__burn__g5c3f_6ec4(v0.@layout_0, v1.i256, v obj.store v49 v50; v52.objref = obj.proj v43 2.i256; obj.store v52 v42; - v53.@layout_20 = obj.load v43; + v53.@layout_19 = obj.load v43; call %emit__g4c3d v3 v53; return; } @@ -1434,9 +1372,10 @@ func private %contract_recv_abi_CoolCoin_1086394137() { evm_revert 0.i256 0.i256; block3: - v8.i256 = evm_calldata_size; - (v10.i256, v11.i1) = usubo v8 4.i256; - br v11 block4 block5; + v9.i256 = evm_calldata_load 36.i256; + v10.i256 = evm_calldata_size; + (v12.i256, v13.i1) = usubo v10 4.i256; + br v13 block4 block5; block4: mstore 0.i256 35408467139433450592217433187231851964531694900788300625387963629091585785856.i256 i256; @@ -1444,50 +1383,48 @@ func private %contract_recv_abi_CoolCoin_1086394137() { evm_revert 0.i256 36.i256; block5: - v15.*i8 = evm_malloc v10; - v16.i256 = ptr_to_int v15 i256; - evm_calldata_copy v16 4.i256 v10; - v19.objref = obj.proj v0 0.i256; - obj.store v19 v16; - v21.objref = obj.proj v0 1.i256; - obj.store v21 v10; - v22.@layout_5 = obj.load v0; - v23.@layout_7 = call %decoder_new v22; - v24.objref<@layout_6> = obj.proj v1 0.i256; - v25.@layout_6 = extract_value v23 0.i256; - v26.objref<@layout_5> = obj.proj v24 0.i256; - v27.@layout_5 = extract_value v25 0.i256; - v28.objref = obj.proj v26 0.i256; - v29.i256 = extract_value v27 0.i256; - obj.store v28 v29; - v30.objref = obj.proj v26 1.i256; - v31.i256 = extract_value v27 1.i256; - obj.store v30 v31; - v32.objref = obj.proj v24 1.i256; - v33.i256 = extract_value v25 1.i256; - obj.store v32 v33; - v34.objref = obj.proj v1 1.i256; - v35.i256 = extract_value v23 1.i256; - obj.store v34 v35; - v36.@layout_13 = call %impl_trait_Mint__decode_payload__gf196 v1; - v37.objref<@layout_13> = obj.alloc @layout_13; - v38.objref<@layout_0> = obj.proj v37 0.i256; - v39.@layout_0 = extract_value v36 0.i256; - v40.objref = obj.proj v38 0.i256; - v41.i256 = extract_value v39 0.i256; - obj.store v40 v41; - v42.objref = obj.proj v37 1.i256; - v43.i256 = extract_value v36 1.i256; - obj.store v42 v43; - v44.objref<@layout_0> = obj.proj v37 0.i256; - v45.@layout_0 = obj.load v44; - v46.objref = obj.proj v37 1.i256; - v47.i256 = obj.load v46; + v16.*i8 = evm_malloc v12; + v17.i256 = ptr_to_int v16 i256; + evm_calldata_copy v17 4.i256 v12; + v20.objref = obj.proj v0 0.i256; + obj.store v20 v17; + v22.objref = obj.proj v0 1.i256; + obj.store v22 v12; + v23.@layout_5 = obj.load v0; + v24.@layout_7 = call %decoder_new v23; + v25.objref<@layout_6> = obj.proj v1 0.i256; + v26.@layout_6 = extract_value v24 0.i256; + v27.objref<@layout_5> = obj.proj v25 0.i256; + v28.@layout_5 = extract_value v26 0.i256; + v29.objref = obj.proj v27 0.i256; + v30.i256 = extract_value v28 0.i256; + obj.store v29 v30; + v31.objref = obj.proj v27 1.i256; + v32.i256 = extract_value v28 1.i256; + obj.store v31 v32; + v33.objref = obj.proj v25 1.i256; + v34.i256 = extract_value v26 1.i256; + obj.store v33 v34; + v35.objref = obj.proj v1 1.i256; + v36.i256 = extract_value v24 1.i256; + obj.store v35 v36; + v37.@layout_13 = call %impl_trait_Mint__decode_payload__gf196 v1; + v38.objref<@layout_13> = obj.alloc @layout_13; + v39.objref<@layout_0> = obj.proj v38 0.i256; + v40.@layout_0 = extract_value v37 0.i256; + v41.objref = obj.proj v39 0.i256; + v42.i256 = extract_value v40 0.i256; + obj.store v41 v42; + v43.objref = obj.proj v38 1.i256; + v44.i256 = extract_value v37 1.i256; + obj.store v43 v44; + v45.objref<@layout_0> = obj.proj v38 0.i256; + v46.@layout_0 = obj.load v45; + v47.objref<@layout_2> = obj.alloc @layout_2; v48.objref<@layout_2> = obj.alloc @layout_2; - v49.objref<@layout_2> = obj.alloc @layout_2; - v51.i1 = call %__CoolCoin_recv_1_0 v45 v47 v48 0.i256 v49 3.i256; - v52.@layout_21 = call %encode_single_root_alloc__g09ca v51; - v53.objref<@layout_21> = obj.alloc @layout_21; + v51.i1 = call %__CoolCoin_recv_1_0 v46 v9 v47 0.i256 v48 3.i256; + v52.@layout_20 = call %encode_single_root_alloc__g09ca v51; + v53.objref<@layout_20> = obj.alloc @layout_20; v54.objref = obj.proj v53 0.i256; v55.i256 = extract_value v52 0.i256; obj.store v54 v55; @@ -1503,78 +1440,35 @@ func private %contract_recv_abi_CoolCoin_1086394137() { func private %contract_recv_abi_CoolCoin_1117154408() { block0: - v0.objref<@layout_5> = obj.alloc @layout_5; - v1.objref<@layout_7> = obj.alloc @layout_7; jump block1; block1: - v4.i256 = evm_call_value; - v5.i1 = eq v4 0.i256; - v6.i1 = is_zero v5; - br v6 block2 block3; + v2.i256 = evm_call_value; + v3.i1 = eq v2 0.i256; + v4.i1 = is_zero v3; + br v4 block2 block3; block2: evm_revert 0.i256 0.i256; block3: - v8.i256 = evm_calldata_size; - (v10.i256, v11.i1) = usubo v8 4.i256; - br v11 block4 block5; - - block4: - mstore 0.i256 35408467139433450592217433187231851964531694900788300625387963629091585785856.i256 i256; - mstore 4.i256 17.i256 i256; - evm_revert 0.i256 36.i256; - - block5: - v15.*i8 = evm_malloc v10; - v16.i256 = ptr_to_int v15 i256; - evm_calldata_copy v16 4.i256 v10; - v19.objref = obj.proj v0 0.i256; - obj.store v19 v16; - v21.objref = obj.proj v0 1.i256; - obj.store v21 v10; - v22.@layout_5 = obj.load v0; - v23.@layout_7 = call %decoder_new v22; - v24.objref<@layout_6> = obj.proj v1 0.i256; - v25.@layout_6 = extract_value v23 0.i256; - v26.objref<@layout_5> = obj.proj v24 0.i256; - v27.@layout_5 = extract_value v25 0.i256; - v28.objref = obj.proj v26 0.i256; - v29.i256 = extract_value v27 0.i256; - obj.store v28 v29; - v30.objref = obj.proj v26 1.i256; - v31.i256 = extract_value v27 1.i256; - obj.store v30 v31; - v32.objref = obj.proj v24 1.i256; - v33.i256 = extract_value v25 1.i256; - obj.store v32 v33; - v34.objref = obj.proj v1 1.i256; - v35.i256 = extract_value v23 1.i256; - obj.store v34 v35; - v36.@layout_18 = call %impl_trait_Burn__decode_payload__gf196 v1; - v37.objref<@layout_18> = obj.alloc @layout_18; - v38.objref = obj.proj v37 0.i256; - v39.i256 = extract_value v36 0.i256; - obj.store v38 v39; - v40.objref = obj.proj v37 0.i256; - v41.i256 = obj.load v40; - v42.objref<@layout_2> = obj.alloc @layout_2; - v43.objref<@layout_2> = obj.alloc @layout_2; - v44.i1 = call %__CoolCoin_recv_1_1 v41 v42 0.i256 v43; - v45.@layout_21 = call %encode_single_root_alloc__g09ca v44; - v46.objref<@layout_21> = obj.alloc @layout_21; - v47.objref = obj.proj v46 0.i256; - v48.i256 = extract_value v45 0.i256; - obj.store v47 v48; - v49.objref = obj.proj v46 1.i256; - v50.i256 = extract_value v45 1.i256; - obj.store v49 v50; - v51.objref = obj.proj v46 0.i256; - v52.i256 = obj.load v51; - v53.objref = obj.proj v46 1.i256; - v54.i256 = obj.load v53; - evm_return v52 v54; + v6.i256 = evm_calldata_load 4.i256; + v7.objref<@layout_2> = obj.alloc @layout_2; + v8.objref<@layout_2> = obj.alloc @layout_2; + v9.i1 = call %__CoolCoin_recv_1_1 v6 v7 0.i256 v8; + v10.@layout_20 = call %encode_single_root_alloc__g09ca v9; + v11.objref<@layout_20> = obj.alloc @layout_20; + v12.objref = obj.proj v11 0.i256; + v13.i256 = extract_value v10 0.i256; + obj.store v12 v13; + v15.objref = obj.proj v11 1.i256; + v16.i256 = extract_value v10 1.i256; + obj.store v15 v16; + v17.objref = obj.proj v11 0.i256; + v18.i256 = obj.load v17; + v19.objref = obj.proj v11 1.i256; + v20.i256 = obj.load v19; + evm_return v18 v20; } func private %contract_recv_abi_CoolCoin_117300739() { @@ -1630,8 +1524,8 @@ func private %contract_recv_abi_CoolCoin_117300739() { obj.store v34 v35; call %impl_trait_Name__decode_payload__gf196 v1; v37.i256 = call %__CoolCoin_recv_0_6; - v38.@layout_21 = call %encode_single_root_alloc__g472d v37; - v39.objref<@layout_21> = obj.alloc @layout_21; + v38.@layout_20 = call %encode_single_root_alloc__g472d v37; + v39.objref<@layout_20> = obj.alloc @layout_20; v40.objref = obj.proj v39 0.i256; v41.i256 = extract_value v38 0.i256; obj.store v40 v41; @@ -1661,9 +1555,10 @@ func private %contract_recv_abi_CoolCoin_157198259() { evm_revert 0.i256 0.i256; block3: - v8.i256 = evm_calldata_size; - (v10.i256, v11.i1) = usubo v8 4.i256; - br v11 block4 block5; + v9.i256 = evm_calldata_load 36.i256; + v10.i256 = evm_calldata_size; + (v12.i256, v13.i1) = usubo v10 4.i256; + br v13 block4 block5; block4: mstore 0.i256 35408467139433450592217433187231851964531694900788300625387963629091585785856.i256 i256; @@ -1671,50 +1566,48 @@ func private %contract_recv_abi_CoolCoin_157198259() { evm_revert 0.i256 36.i256; block5: - v15.*i8 = evm_malloc v10; - v16.i256 = ptr_to_int v15 i256; - evm_calldata_copy v16 4.i256 v10; - v19.objref = obj.proj v0 0.i256; - obj.store v19 v16; - v21.objref = obj.proj v0 1.i256; - obj.store v21 v10; - v22.@layout_5 = obj.load v0; - v23.@layout_7 = call %decoder_new v22; - v24.objref<@layout_6> = obj.proj v1 0.i256; - v25.@layout_6 = extract_value v23 0.i256; - v26.objref<@layout_5> = obj.proj v24 0.i256; - v27.@layout_5 = extract_value v25 0.i256; - v28.objref = obj.proj v26 0.i256; - v29.i256 = extract_value v27 0.i256; - obj.store v28 v29; - v30.objref = obj.proj v26 1.i256; - v31.i256 = extract_value v27 1.i256; - obj.store v30 v31; - v32.objref = obj.proj v24 1.i256; - v33.i256 = extract_value v25 1.i256; - obj.store v32 v33; - v34.objref = obj.proj v1 1.i256; - v35.i256 = extract_value v23 1.i256; - obj.store v34 v35; - v36.@layout_17 = call %impl_trait_Approve__decode_payload__gf196 v1; - v37.objref<@layout_17> = obj.alloc @layout_17; - v38.objref<@layout_0> = obj.proj v37 0.i256; - v39.@layout_0 = extract_value v36 0.i256; - v40.objref = obj.proj v38 0.i256; - v41.i256 = extract_value v39 0.i256; - obj.store v40 v41; - v42.objref = obj.proj v37 1.i256; - v43.i256 = extract_value v36 1.i256; - obj.store v42 v43; - v44.objref<@layout_0> = obj.proj v37 0.i256; - v45.@layout_0 = obj.load v44; - v46.objref = obj.proj v37 1.i256; - v47.i256 = obj.load v46; + v16.*i8 = evm_malloc v12; + v17.i256 = ptr_to_int v16 i256; + evm_calldata_copy v17 4.i256 v12; + v20.objref = obj.proj v0 0.i256; + obj.store v20 v17; + v22.objref = obj.proj v0 1.i256; + obj.store v22 v12; + v23.@layout_5 = obj.load v0; + v24.@layout_7 = call %decoder_new v23; + v25.objref<@layout_6> = obj.proj v1 0.i256; + v26.@layout_6 = extract_value v24 0.i256; + v27.objref<@layout_5> = obj.proj v25 0.i256; + v28.@layout_5 = extract_value v26 0.i256; + v29.objref = obj.proj v27 0.i256; + v30.i256 = extract_value v28 0.i256; + obj.store v29 v30; + v31.objref = obj.proj v27 1.i256; + v32.i256 = extract_value v28 1.i256; + obj.store v31 v32; + v33.objref = obj.proj v25 1.i256; + v34.i256 = extract_value v26 1.i256; + obj.store v33 v34; + v35.objref = obj.proj v1 1.i256; + v36.i256 = extract_value v24 1.i256; + obj.store v35 v36; + v37.@layout_17 = call %impl_trait_Approve__decode_payload__gf196 v1; + v38.objref<@layout_17> = obj.alloc @layout_17; + v39.objref<@layout_0> = obj.proj v38 0.i256; + v40.@layout_0 = extract_value v37 0.i256; + v41.objref = obj.proj v39 0.i256; + v42.i256 = extract_value v40 0.i256; + obj.store v41 v42; + v43.objref = obj.proj v38 1.i256; + v44.i256 = extract_value v37 1.i256; + obj.store v43 v44; + v45.objref<@layout_0> = obj.proj v38 0.i256; + v46.@layout_0 = obj.load v45; + v47.objref<@layout_2> = obj.alloc @layout_2; v48.objref<@layout_2> = obj.alloc @layout_2; - v49.objref<@layout_2> = obj.alloc @layout_2; - v50.i1 = call %__CoolCoin_recv_0_1 v45 v47 v48 0.i256 v49; - v51.@layout_21 = call %encode_single_root_alloc__g09ca v50; - v52.objref<@layout_21> = obj.alloc @layout_21; + v50.i1 = call %__CoolCoin_recv_0_1 v46 v9 v47 0.i256 v48; + v51.@layout_20 = call %encode_single_root_alloc__g09ca v50; + v52.objref<@layout_20> = obj.alloc @layout_20; v53.objref = obj.proj v52 0.i256; v54.i256 = extract_value v51 0.i256; obj.store v53 v54; @@ -1789,19 +1682,8 @@ func private %contract_recv_abi_CoolCoin_1889567281() { v42.objref<@layout_0> = obj.proj v37 0.i256; v43.@layout_0 = obj.load v42; v44.i256 = call %__CoolCoin_recv_0_3 v43 0.i256; - v45.@layout_21 = call %encode_single_root_alloc__gac80 v44; - v46.objref<@layout_21> = obj.alloc @layout_21; - v47.objref = obj.proj v46 0.i256; - v48.i256 = extract_value v45 0.i256; - obj.store v47 v48; - v49.objref = obj.proj v46 1.i256; - v50.i256 = extract_value v45 1.i256; - obj.store v49 v50; - v51.objref = obj.proj v46 0.i256; - v52.i256 = obj.load v51; - v53.objref = obj.proj v46 1.i256; - v54.i256 = obj.load v53; - evm_return v52 v54; + mstore 0.i256 v44 i256; + evm_return 0.i256 32.i256; } func private %contract_recv_abi_CoolCoin_2043438992() { @@ -1820,9 +1702,10 @@ func private %contract_recv_abi_CoolCoin_2043438992() { evm_revert 0.i256 0.i256; block3: - v8.i256 = evm_calldata_size; - (v10.i256, v11.i1) = usubo v8 4.i256; - br v11 block4 block5; + v9.i256 = evm_calldata_load 36.i256; + v10.i256 = evm_calldata_size; + (v12.i256, v13.i1) = usubo v10 4.i256; + br v13 block4 block5; block4: mstore 0.i256 35408467139433450592217433187231851964531694900788300625387963629091585785856.i256 i256; @@ -1830,50 +1713,48 @@ func private %contract_recv_abi_CoolCoin_2043438992() { evm_revert 0.i256 36.i256; block5: - v15.*i8 = evm_malloc v10; - v16.i256 = ptr_to_int v15 i256; - evm_calldata_copy v16 4.i256 v10; - v19.objref = obj.proj v0 0.i256; - obj.store v19 v16; - v21.objref = obj.proj v0 1.i256; - obj.store v21 v10; - v22.@layout_5 = obj.load v0; - v23.@layout_7 = call %decoder_new v22; - v24.objref<@layout_6> = obj.proj v1 0.i256; - v25.@layout_6 = extract_value v23 0.i256; - v26.objref<@layout_5> = obj.proj v24 0.i256; - v27.@layout_5 = extract_value v25 0.i256; - v28.objref = obj.proj v26 0.i256; - v29.i256 = extract_value v27 0.i256; - obj.store v28 v29; - v30.objref = obj.proj v26 1.i256; - v31.i256 = extract_value v27 1.i256; - obj.store v30 v31; - v32.objref = obj.proj v24 1.i256; - v33.i256 = extract_value v25 1.i256; - obj.store v32 v33; - v34.objref = obj.proj v1 1.i256; - v35.i256 = extract_value v23 1.i256; - obj.store v34 v35; - v36.@layout_11 = call %impl_trait_BurnFrom__decode_payload__gf196 v1; - v37.objref<@layout_11> = obj.alloc @layout_11; - v38.objref<@layout_0> = obj.proj v37 0.i256; - v39.@layout_0 = extract_value v36 0.i256; - v40.objref = obj.proj v38 0.i256; - v41.i256 = extract_value v39 0.i256; - obj.store v40 v41; - v42.objref = obj.proj v37 1.i256; - v43.i256 = extract_value v36 1.i256; - obj.store v42 v43; - v44.objref<@layout_0> = obj.proj v37 0.i256; - v45.@layout_0 = obj.load v44; - v46.objref = obj.proj v37 1.i256; - v47.i256 = obj.load v46; + v16.*i8 = evm_malloc v12; + v17.i256 = ptr_to_int v16 i256; + evm_calldata_copy v17 4.i256 v12; + v20.objref = obj.proj v0 0.i256; + obj.store v20 v17; + v22.objref = obj.proj v0 1.i256; + obj.store v22 v12; + v23.@layout_5 = obj.load v0; + v24.@layout_7 = call %decoder_new v23; + v25.objref<@layout_6> = obj.proj v1 0.i256; + v26.@layout_6 = extract_value v24 0.i256; + v27.objref<@layout_5> = obj.proj v25 0.i256; + v28.@layout_5 = extract_value v26 0.i256; + v29.objref = obj.proj v27 0.i256; + v30.i256 = extract_value v28 0.i256; + obj.store v29 v30; + v31.objref = obj.proj v27 1.i256; + v32.i256 = extract_value v28 1.i256; + obj.store v31 v32; + v33.objref = obj.proj v25 1.i256; + v34.i256 = extract_value v26 1.i256; + obj.store v33 v34; + v35.objref = obj.proj v1 1.i256; + v36.i256 = extract_value v24 1.i256; + obj.store v35 v36; + v37.@layout_11 = call %impl_trait_BurnFrom__decode_payload__gf196 v1; + v38.objref<@layout_11> = obj.alloc @layout_11; + v39.objref<@layout_0> = obj.proj v38 0.i256; + v40.@layout_0 = extract_value v37 0.i256; + v41.objref = obj.proj v39 0.i256; + v42.i256 = extract_value v40 0.i256; + obj.store v41 v42; + v43.objref = obj.proj v38 1.i256; + v44.i256 = extract_value v37 1.i256; + obj.store v43 v44; + v45.objref<@layout_0> = obj.proj v38 0.i256; + v46.@layout_0 = obj.load v45; + v47.objref<@layout_2> = obj.alloc @layout_2; v48.objref<@layout_2> = obj.alloc @layout_2; - v49.objref<@layout_2> = obj.alloc @layout_2; - v50.i1 = call %__CoolCoin_recv_1_2 v45 v47 v48 0.i256 v49; - v51.@layout_21 = call %encode_single_root_alloc__g09ca v50; - v52.objref<@layout_21> = obj.alloc @layout_21; + v50.i1 = call %__CoolCoin_recv_1_2 v46 v9 v47 0.i256 v48; + v51.@layout_20 = call %encode_single_root_alloc__g09ca v50; + v52.objref<@layout_20> = obj.alloc @layout_20; v53.objref = obj.proj v52 0.i256; v54.i256 = extract_value v51 0.i256; obj.store v53 v54; @@ -1940,8 +1821,8 @@ func private %contract_recv_abi_CoolCoin_2514000705() { obj.store v34 v35; call %impl_trait_Symbol__decode_payload__gf196 v1; v37.i256 = call %__CoolCoin_recv_0_7; - v38.@layout_21 = call %encode_single_root_alloc__g0c18 v37; - v39.objref<@layout_21> = obj.alloc @layout_21; + v38.@layout_20 = call %encode_single_root_alloc__g0c18 v37; + v39.objref<@layout_20> = obj.alloc @layout_20; v40.objref = obj.proj v39 0.i256; v41.i256 = extract_value v38 0.i256; obj.store v40 v41; @@ -1971,9 +1852,10 @@ func private %contract_recv_abi_CoolCoin_2757214935() { evm_revert 0.i256 0.i256; block3: - v8.i256 = evm_calldata_size; - (v10.i256, v11.i1) = usubo v8 4.i256; - br v11 block4 block5; + v9.i256 = evm_calldata_load 36.i256; + v10.i256 = evm_calldata_size; + (v12.i256, v13.i1) = usubo v10 4.i256; + br v13 block4 block5; block4: mstore 0.i256 35408467139433450592217433187231851964531694900788300625387963629091585785856.i256 i256; @@ -1981,50 +1863,48 @@ func private %contract_recv_abi_CoolCoin_2757214935() { evm_revert 0.i256 36.i256; block5: - v15.*i8 = evm_malloc v10; - v16.i256 = ptr_to_int v15 i256; - evm_calldata_copy v16 4.i256 v10; - v19.objref = obj.proj v0 0.i256; - obj.store v19 v16; - v21.objref = obj.proj v0 1.i256; - obj.store v21 v10; - v22.@layout_5 = obj.load v0; - v23.@layout_7 = call %decoder_new v22; - v24.objref<@layout_6> = obj.proj v1 0.i256; - v25.@layout_6 = extract_value v23 0.i256; - v26.objref<@layout_5> = obj.proj v24 0.i256; - v27.@layout_5 = extract_value v25 0.i256; - v28.objref = obj.proj v26 0.i256; - v29.i256 = extract_value v27 0.i256; - obj.store v28 v29; - v30.objref = obj.proj v26 1.i256; - v31.i256 = extract_value v27 1.i256; - obj.store v30 v31; - v32.objref = obj.proj v24 1.i256; - v33.i256 = extract_value v25 1.i256; - obj.store v32 v33; - v34.objref = obj.proj v1 1.i256; - v35.i256 = extract_value v23 1.i256; - obj.store v34 v35; - v36.@layout_9 = call %impl_trait_DecreaseAllowance__decode_payload__gf196 v1; - v37.objref<@layout_9> = obj.alloc @layout_9; - v38.objref<@layout_0> = obj.proj v37 0.i256; - v39.@layout_0 = extract_value v36 0.i256; - v40.objref = obj.proj v38 0.i256; - v41.i256 = extract_value v39 0.i256; - obj.store v40 v41; - v42.objref = obj.proj v37 1.i256; - v43.i256 = extract_value v36 1.i256; - obj.store v42 v43; - v44.objref<@layout_0> = obj.proj v37 0.i256; - v45.@layout_0 = obj.load v44; - v46.objref = obj.proj v37 1.i256; - v47.i256 = obj.load v46; + v16.*i8 = evm_malloc v12; + v17.i256 = ptr_to_int v16 i256; + evm_calldata_copy v17 4.i256 v12; + v20.objref = obj.proj v0 0.i256; + obj.store v20 v17; + v22.objref = obj.proj v0 1.i256; + obj.store v22 v12; + v23.@layout_5 = obj.load v0; + v24.@layout_7 = call %decoder_new v23; + v25.objref<@layout_6> = obj.proj v1 0.i256; + v26.@layout_6 = extract_value v24 0.i256; + v27.objref<@layout_5> = obj.proj v25 0.i256; + v28.@layout_5 = extract_value v26 0.i256; + v29.objref = obj.proj v27 0.i256; + v30.i256 = extract_value v28 0.i256; + obj.store v29 v30; + v31.objref = obj.proj v27 1.i256; + v32.i256 = extract_value v28 1.i256; + obj.store v31 v32; + v33.objref = obj.proj v25 1.i256; + v34.i256 = extract_value v26 1.i256; + obj.store v33 v34; + v35.objref = obj.proj v1 1.i256; + v36.i256 = extract_value v24 1.i256; + obj.store v35 v36; + v37.@layout_9 = call %impl_trait_DecreaseAllowance__decode_payload__gf196 v1; + v38.objref<@layout_9> = obj.alloc @layout_9; + v39.objref<@layout_0> = obj.proj v38 0.i256; + v40.@layout_0 = extract_value v37 0.i256; + v41.objref = obj.proj v39 0.i256; + v42.i256 = extract_value v40 0.i256; + obj.store v41 v42; + v43.objref = obj.proj v38 1.i256; + v44.i256 = extract_value v37 1.i256; + obj.store v43 v44; + v45.objref<@layout_0> = obj.proj v38 0.i256; + v46.@layout_0 = obj.load v45; + v47.objref<@layout_2> = obj.alloc @layout_2; v48.objref<@layout_2> = obj.alloc @layout_2; - v49.objref<@layout_2> = obj.alloc @layout_2; - v50.i1 = call %__CoolCoin_recv_1_4 v45 v47 v48 0.i256 v49; - v51.@layout_21 = call %encode_single_root_alloc__g09ca v50; - v52.objref<@layout_21> = obj.alloc @layout_21; + v50.i1 = call %__CoolCoin_recv_1_4 v46 v9 v47 0.i256 v48; + v51.@layout_20 = call %encode_single_root_alloc__g09ca v50; + v52.objref<@layout_20> = obj.alloc @layout_20; v53.objref = obj.proj v52 0.i256; v54.i256 = extract_value v51 0.i256; obj.store v53 v54; @@ -2054,9 +1934,10 @@ func private %contract_recv_abi_CoolCoin_2835717307() { evm_revert 0.i256 0.i256; block3: - v8.i256 = evm_calldata_size; - (v10.i256, v11.i1) = usubo v8 4.i256; - br v11 block4 block5; + v9.i256 = evm_calldata_load 36.i256; + v10.i256 = evm_calldata_size; + (v12.i256, v13.i1) = usubo v10 4.i256; + br v13 block4 block5; block4: mstore 0.i256 35408467139433450592217433187231851964531694900788300625387963629091585785856.i256 i256; @@ -2064,50 +1945,48 @@ func private %contract_recv_abi_CoolCoin_2835717307() { evm_revert 0.i256 36.i256; block5: - v15.*i8 = evm_malloc v10; - v16.i256 = ptr_to_int v15 i256; - evm_calldata_copy v16 4.i256 v10; - v19.objref = obj.proj v0 0.i256; - obj.store v19 v16; - v21.objref = obj.proj v0 1.i256; - obj.store v21 v10; - v22.@layout_5 = obj.load v0; - v23.@layout_7 = call %decoder_new v22; - v24.objref<@layout_6> = obj.proj v1 0.i256; - v25.@layout_6 = extract_value v23 0.i256; - v26.objref<@layout_5> = obj.proj v24 0.i256; - v27.@layout_5 = extract_value v25 0.i256; - v28.objref = obj.proj v26 0.i256; - v29.i256 = extract_value v27 0.i256; - obj.store v28 v29; - v30.objref = obj.proj v26 1.i256; - v31.i256 = extract_value v27 1.i256; - obj.store v30 v31; - v32.objref = obj.proj v24 1.i256; - v33.i256 = extract_value v25 1.i256; - obj.store v32 v33; - v34.objref = obj.proj v1 1.i256; - v35.i256 = extract_value v23 1.i256; - obj.store v34 v35; - v36.@layout_10 = call %impl_trait_Transfer__decode_payload__gf196 v1; - v37.objref<@layout_10> = obj.alloc @layout_10; - v38.objref<@layout_0> = obj.proj v37 0.i256; - v39.@layout_0 = extract_value v36 0.i256; - v40.objref = obj.proj v38 0.i256; - v41.i256 = extract_value v39 0.i256; - obj.store v40 v41; - v42.objref = obj.proj v37 1.i256; - v43.i256 = extract_value v36 1.i256; - obj.store v42 v43; - v44.objref<@layout_0> = obj.proj v37 0.i256; - v45.@layout_0 = obj.load v44; - v46.objref = obj.proj v37 1.i256; - v47.i256 = obj.load v46; + v16.*i8 = evm_malloc v12; + v17.i256 = ptr_to_int v16 i256; + evm_calldata_copy v17 4.i256 v12; + v20.objref = obj.proj v0 0.i256; + obj.store v20 v17; + v22.objref = obj.proj v0 1.i256; + obj.store v22 v12; + v23.@layout_5 = obj.load v0; + v24.@layout_7 = call %decoder_new v23; + v25.objref<@layout_6> = obj.proj v1 0.i256; + v26.@layout_6 = extract_value v24 0.i256; + v27.objref<@layout_5> = obj.proj v25 0.i256; + v28.@layout_5 = extract_value v26 0.i256; + v29.objref = obj.proj v27 0.i256; + v30.i256 = extract_value v28 0.i256; + obj.store v29 v30; + v31.objref = obj.proj v27 1.i256; + v32.i256 = extract_value v28 1.i256; + obj.store v31 v32; + v33.objref = obj.proj v25 1.i256; + v34.i256 = extract_value v26 1.i256; + obj.store v33 v34; + v35.objref = obj.proj v1 1.i256; + v36.i256 = extract_value v24 1.i256; + obj.store v35 v36; + v37.@layout_10 = call %impl_trait_Transfer__decode_payload__gf196 v1; + v38.objref<@layout_10> = obj.alloc @layout_10; + v39.objref<@layout_0> = obj.proj v38 0.i256; + v40.@layout_0 = extract_value v37 0.i256; + v41.objref = obj.proj v39 0.i256; + v42.i256 = extract_value v40 0.i256; + obj.store v41 v42; + v43.objref = obj.proj v38 1.i256; + v44.i256 = extract_value v37 1.i256; + obj.store v43 v44; + v45.objref<@layout_0> = obj.proj v38 0.i256; + v46.@layout_0 = obj.load v45; + v47.objref<@layout_2> = obj.alloc @layout_2; v48.objref<@layout_2> = obj.alloc @layout_2; - v49.objref<@layout_2> = obj.alloc @layout_2; - v50.i1 = call %__CoolCoin_recv_0_0 v45 v47 v48 0.i256 v49; - v51.@layout_21 = call %encode_single_root_alloc__g09ca v50; - v52.objref<@layout_21> = obj.alloc @layout_21; + v50.i1 = call %__CoolCoin_recv_0_0 v46 v9 v47 0.i256 v48; + v51.@layout_20 = call %encode_single_root_alloc__g09ca v50; + v52.objref<@layout_20> = obj.alloc @layout_20; v53.objref = obj.proj v52 0.i256; v54.i256 = extract_value v51 0.i256; obj.store v53 v54; @@ -2189,19 +2068,8 @@ func private %contract_recv_abi_CoolCoin_3714247998() { v48.objref<@layout_0> = obj.proj v37 1.i256; v49.@layout_0 = obj.load v48; v50.i256 = call %__CoolCoin_recv_0_4 v47 v49 0.i256; - v51.@layout_21 = call %encode_single_root_alloc__gac80 v50; - v52.objref<@layout_21> = obj.alloc @layout_21; - v53.objref = obj.proj v52 0.i256; - v54.i256 = extract_value v51 0.i256; - obj.store v53 v54; - v55.objref = obj.proj v52 1.i256; - v56.i256 = extract_value v51 1.i256; - obj.store v55 v56; - v57.objref = obj.proj v52 0.i256; - v58.i256 = obj.load v57; - v59.objref = obj.proj v52 1.i256; - v60.i256 = obj.load v59; - evm_return v58 v60; + mstore 0.i256 v50 i256; + evm_return 0.i256 32.i256; } func private %contract_recv_abi_CoolCoin_404098525() { @@ -2257,19 +2125,8 @@ func private %contract_recv_abi_CoolCoin_404098525() { obj.store v34 v35; call %impl_trait_TotalSupply__decode_payload__gf196 v1; v37.i256 = call %__CoolCoin_recv_0_5 0.i256; - v38.@layout_21 = call %encode_single_root_alloc__gac80 v37; - v39.objref<@layout_21> = obj.alloc @layout_21; - v40.objref = obj.proj v39 0.i256; - v41.i256 = extract_value v38 0.i256; - obj.store v40 v41; - v42.objref = obj.proj v39 1.i256; - v43.i256 = extract_value v38 1.i256; - obj.store v42 v43; - v44.objref = obj.proj v39 0.i256; - v45.i256 = obj.load v44; - v46.objref = obj.proj v39 1.i256; - v47.i256 = obj.load v46; - evm_return v45 v47; + mstore 0.i256 v37 i256; + evm_return 0.i256 32.i256; } func private %contract_recv_abi_CoolCoin_599290589() { @@ -2288,9 +2145,10 @@ func private %contract_recv_abi_CoolCoin_599290589() { evm_revert 0.i256 0.i256; block3: - v8.i256 = evm_calldata_size; - (v10.i256, v11.i1) = usubo v8 4.i256; - br v11 block4 block5; + v9.i256 = evm_calldata_load 68.i256; + v10.i256 = evm_calldata_size; + (v12.i256, v13.i1) = usubo v10 4.i256; + br v13 block4 block5; block4: mstore 0.i256 35408467139433450592217433187231851964531694900788300625387963629091585785856.i256 i256; @@ -2298,68 +2156,66 @@ func private %contract_recv_abi_CoolCoin_599290589() { evm_revert 0.i256 36.i256; block5: - v15.*i8 = evm_malloc v10; - v16.i256 = ptr_to_int v15 i256; - evm_calldata_copy v16 4.i256 v10; - v19.objref = obj.proj v0 0.i256; - obj.store v19 v16; - v21.objref = obj.proj v0 1.i256; - obj.store v21 v10; - v22.@layout_5 = obj.load v0; - v23.@layout_7 = call %decoder_new v22; - v24.objref<@layout_6> = obj.proj v1 0.i256; - v25.@layout_6 = extract_value v23 0.i256; - v26.objref<@layout_5> = obj.proj v24 0.i256; - v27.@layout_5 = extract_value v25 0.i256; - v28.objref = obj.proj v26 0.i256; - v29.i256 = extract_value v27 0.i256; - obj.store v28 v29; - v30.objref = obj.proj v26 1.i256; - v31.i256 = extract_value v27 1.i256; + v17.*i8 = evm_malloc v12; + v18.i256 = ptr_to_int v17 i256; + evm_calldata_copy v18 4.i256 v12; + v21.objref = obj.proj v0 0.i256; + obj.store v21 v18; + v23.objref = obj.proj v0 1.i256; + obj.store v23 v12; + v24.@layout_5 = obj.load v0; + v25.@layout_7 = call %decoder_new v24; + v26.objref<@layout_6> = obj.proj v1 0.i256; + v27.@layout_6 = extract_value v25 0.i256; + v28.objref<@layout_5> = obj.proj v26 0.i256; + v29.@layout_5 = extract_value v27 0.i256; + v30.objref = obj.proj v28 0.i256; + v31.i256 = extract_value v29 0.i256; obj.store v30 v31; - v32.objref = obj.proj v24 1.i256; - v33.i256 = extract_value v25 1.i256; + v32.objref = obj.proj v28 1.i256; + v33.i256 = extract_value v29 1.i256; obj.store v32 v33; - v34.objref = obj.proj v1 1.i256; - v35.i256 = extract_value v23 1.i256; + v34.objref = obj.proj v26 1.i256; + v35.i256 = extract_value v27 1.i256; obj.store v34 v35; - v36.@layout_8 = call %impl_trait_TransferFrom__decode_payload__gf196 v1; - v37.objref<@layout_8> = obj.alloc @layout_8; - v38.objref<@layout_0> = obj.proj v37 0.i256; - v39.@layout_0 = extract_value v36 0.i256; - v40.objref = obj.proj v38 0.i256; - v41.i256 = extract_value v39 0.i256; - obj.store v40 v41; - v42.objref<@layout_0> = obj.proj v37 1.i256; - v43.@layout_0 = extract_value v36 1.i256; - v44.objref = obj.proj v42 0.i256; - v45.i256 = extract_value v43 0.i256; - obj.store v44 v45; - v47.objref = obj.proj v37 2.i256; - v48.i256 = extract_value v36 2.i256; - obj.store v47 v48; - v49.objref<@layout_0> = obj.proj v37 0.i256; - v50.@layout_0 = obj.load v49; - v51.objref<@layout_0> = obj.proj v37 1.i256; + v36.objref = obj.proj v1 1.i256; + v37.i256 = extract_value v25 1.i256; + obj.store v36 v37; + v38.@layout_8 = call %impl_trait_TransferFrom__decode_payload__gf196 v1; + v39.objref<@layout_8> = obj.alloc @layout_8; + v40.objref<@layout_0> = obj.proj v39 0.i256; + v41.@layout_0 = extract_value v38 0.i256; + v42.objref = obj.proj v40 0.i256; + v43.i256 = extract_value v41 0.i256; + obj.store v42 v43; + v44.objref<@layout_0> = obj.proj v39 1.i256; + v45.@layout_0 = extract_value v38 1.i256; + v46.objref = obj.proj v44 0.i256; + v47.i256 = extract_value v45 0.i256; + obj.store v46 v47; + v49.objref = obj.proj v39 2.i256; + v50.i256 = extract_value v38 2.i256; + obj.store v49 v50; + v51.objref<@layout_0> = obj.proj v39 0.i256; v52.@layout_0 = obj.load v51; - v53.objref = obj.proj v37 2.i256; - v54.i256 = obj.load v53; + v53.objref<@layout_0> = obj.proj v39 1.i256; + v54.@layout_0 = obj.load v53; v55.objref<@layout_2> = obj.alloc @layout_2; v56.objref<@layout_2> = obj.alloc @layout_2; - v57.i1 = call %__CoolCoin_recv_0_2 v50 v52 v54 v55 0.i256 v56; - v58.@layout_21 = call %encode_single_root_alloc__g09ca v57; - v59.objref<@layout_21> = obj.alloc @layout_21; - v60.objref = obj.proj v59 0.i256; - v61.i256 = extract_value v58 0.i256; - obj.store v60 v61; - v62.objref = obj.proj v59 1.i256; - v63.i256 = extract_value v58 1.i256; - obj.store v62 v63; - v64.objref = obj.proj v59 0.i256; - v65.i256 = obj.load v64; - v66.objref = obj.proj v59 1.i256; - v67.i256 = obj.load v66; - evm_return v65 v67; + v58.i1 = call %__CoolCoin_recv_0_2 v52 v54 v9 v55 0.i256 v56; + v59.@layout_20 = call %encode_single_root_alloc__g09ca v58; + v60.objref<@layout_20> = obj.alloc @layout_20; + v61.objref = obj.proj v60 0.i256; + v62.i256 = extract_value v59 0.i256; + obj.store v61 v62; + v63.objref = obj.proj v60 1.i256; + v64.i256 = extract_value v59 1.i256; + obj.store v63 v64; + v65.objref = obj.proj v60 0.i256; + v66.i256 = obj.load v65; + v67.objref = obj.proj v60 1.i256; + v68.i256 = obj.load v67; + evm_return v66 v68; } func private %contract_recv_abi_CoolCoin_826074471() { @@ -2415,8 +2271,8 @@ func private %contract_recv_abi_CoolCoin_826074471() { obj.store v34 v35; call %impl_trait_Decimals__decode_payload__gf196 v1; v37.i8 = call %__CoolCoin_recv_0_8; - v38.@layout_21 = call %encode_single_root_alloc__gcb0a v37; - v39.objref<@layout_21> = obj.alloc @layout_21; + v38.@layout_20 = call %encode_single_root_alloc__gcb0a v37; + v39.objref<@layout_20> = obj.alloc @layout_20; v40.objref = obj.proj v39 0.i256; v41.i256 = extract_value v38 0.i256; obj.store v40 v41; @@ -2425,81 +2281,80 @@ func private %contract_recv_abi_CoolCoin_826074471() { obj.store v42 v43; v44.objref = obj.proj v39 0.i256; v45.i256 = obj.load v44; - v46.objref = obj.proj v39 1.i256; - v47.i256 = obj.load v46; - evm_return v45 v47; -} - -func private %contract_recv_abi_CoolCoin_961581905() { - block0: - v0.objref<@layout_5> = obj.alloc @layout_5; - v1.objref<@layout_7> = obj.alloc @layout_7; - jump block1; - - block1: - v4.i256 = evm_call_value; - v5.i1 = eq v4 0.i256; - v6.i1 = is_zero v5; - br v6 block2 block3; - - block2: - evm_revert 0.i256 0.i256; - - block3: - v8.i256 = evm_calldata_size; - (v10.i256, v11.i1) = usubo v8 4.i256; - br v11 block4 block5; - - block4: - mstore 0.i256 35408467139433450592217433187231851964531694900788300625387963629091585785856.i256 i256; - mstore 4.i256 17.i256 i256; - evm_revert 0.i256 36.i256; - - block5: - v15.*i8 = evm_malloc v10; - v16.i256 = ptr_to_int v15 i256; - evm_calldata_copy v16 4.i256 v10; - v19.objref = obj.proj v0 0.i256; - obj.store v19 v16; - v21.objref = obj.proj v0 1.i256; - obj.store v21 v10; - v22.@layout_5 = obj.load v0; - v23.@layout_7 = call %decoder_new v22; - v24.objref<@layout_6> = obj.proj v1 0.i256; - v25.@layout_6 = extract_value v23 0.i256; - v26.objref<@layout_5> = obj.proj v24 0.i256; - v27.@layout_5 = extract_value v25 0.i256; - v28.objref = obj.proj v26 0.i256; - v29.i256 = extract_value v27 0.i256; - obj.store v28 v29; - v30.objref = obj.proj v26 1.i256; - v31.i256 = extract_value v27 1.i256; - obj.store v30 v31; - v32.objref = obj.proj v24 1.i256; - v33.i256 = extract_value v25 1.i256; - obj.store v32 v33; - v34.objref = obj.proj v1 1.i256; - v35.i256 = extract_value v23 1.i256; - obj.store v34 v35; - v36.@layout_16 = call %impl_trait_IncreaseAllowance__decode_payload__gf196 v1; - v37.objref<@layout_16> = obj.alloc @layout_16; - v38.objref<@layout_0> = obj.proj v37 0.i256; - v39.@layout_0 = extract_value v36 0.i256; - v40.objref = obj.proj v38 0.i256; - v41.i256 = extract_value v39 0.i256; - obj.store v40 v41; - v42.objref = obj.proj v37 1.i256; - v43.i256 = extract_value v36 1.i256; - obj.store v42 v43; - v44.objref<@layout_0> = obj.proj v37 0.i256; - v45.@layout_0 = obj.load v44; - v46.objref = obj.proj v37 1.i256; + v46.objref = obj.proj v39 1.i256; v47.i256 = obj.load v46; + evm_return v45 v47; +} + +func private %contract_recv_abi_CoolCoin_961581905() { + block0: + v0.objref<@layout_5> = obj.alloc @layout_5; + v1.objref<@layout_7> = obj.alloc @layout_7; + jump block1; + + block1: + v4.i256 = evm_call_value; + v5.i1 = eq v4 0.i256; + v6.i1 = is_zero v5; + br v6 block2 block3; + + block2: + evm_revert 0.i256 0.i256; + + block3: + v9.i256 = evm_calldata_load 36.i256; + v10.i256 = evm_calldata_size; + (v12.i256, v13.i1) = usubo v10 4.i256; + br v13 block4 block5; + + block4: + mstore 0.i256 35408467139433450592217433187231851964531694900788300625387963629091585785856.i256 i256; + mstore 4.i256 17.i256 i256; + evm_revert 0.i256 36.i256; + + block5: + v16.*i8 = evm_malloc v12; + v17.i256 = ptr_to_int v16 i256; + evm_calldata_copy v17 4.i256 v12; + v20.objref = obj.proj v0 0.i256; + obj.store v20 v17; + v22.objref = obj.proj v0 1.i256; + obj.store v22 v12; + v23.@layout_5 = obj.load v0; + v24.@layout_7 = call %decoder_new v23; + v25.objref<@layout_6> = obj.proj v1 0.i256; + v26.@layout_6 = extract_value v24 0.i256; + v27.objref<@layout_5> = obj.proj v25 0.i256; + v28.@layout_5 = extract_value v26 0.i256; + v29.objref = obj.proj v27 0.i256; + v30.i256 = extract_value v28 0.i256; + obj.store v29 v30; + v31.objref = obj.proj v27 1.i256; + v32.i256 = extract_value v28 1.i256; + obj.store v31 v32; + v33.objref = obj.proj v25 1.i256; + v34.i256 = extract_value v26 1.i256; + obj.store v33 v34; + v35.objref = obj.proj v1 1.i256; + v36.i256 = extract_value v24 1.i256; + obj.store v35 v36; + v37.@layout_16 = call %impl_trait_IncreaseAllowance__decode_payload__gf196 v1; + v38.objref<@layout_16> = obj.alloc @layout_16; + v39.objref<@layout_0> = obj.proj v38 0.i256; + v40.@layout_0 = extract_value v37 0.i256; + v41.objref = obj.proj v39 0.i256; + v42.i256 = extract_value v40 0.i256; + obj.store v41 v42; + v43.objref = obj.proj v38 1.i256; + v44.i256 = extract_value v37 1.i256; + obj.store v43 v44; + v45.objref<@layout_0> = obj.proj v38 0.i256; + v46.@layout_0 = obj.load v45; + v47.objref<@layout_2> = obj.alloc @layout_2; v48.objref<@layout_2> = obj.alloc @layout_2; - v49.objref<@layout_2> = obj.alloc @layout_2; - v50.i1 = call %__CoolCoin_recv_1_3 v45 v47 v48 0.i256 v49; - v51.@layout_21 = call %encode_single_root_alloc__g09ca v50; - v52.objref<@layout_21> = obj.alloc @layout_21; + v50.i1 = call %__CoolCoin_recv_1_3 v46 v9 v47 0.i256 v48; + v51.@layout_20 = call %encode_single_root_alloc__g09ca v50; + v52.objref<@layout_20> = obj.alloc @layout_20; v53.objref = obj.proj v52 0.i256; v54.i256 = extract_value v51 0.i256; obj.store v53 v54; @@ -2521,7 +2376,9 @@ func private %contract_runtime_root_CoolCoin() { v1.i256 = evm_calldata_load 0.i256; v3.i256 = shr 224.i256 v1; v4.i32 = trunc v3 i32; - br_table v4 block2 (117300739.i32 block3) (157198259.i32 block4) (404098525.i32 block5) (599290589.i32 block6) (826074471.i32 block7) (961581905.i32 block8) (1086394137.i32 block9) (1117154408.i32 block10) (1889567281.i32 block11) (2043438992.i32 block12) (-1780966591.i32 block13) (-1537752361.i32 block14) (-1459249989.i32 block15) (-580719298.i32 block16); + v6.i1 = gt v4 1086394137.i32; + v7.i1 = is_zero v6; + br v7 block17 block18; block2: evm_revert 0.i256 0.i256; @@ -2581,6 +2438,122 @@ func private %contract_runtime_root_CoolCoin() { block16: call %contract_recv_abi_CoolCoin_3714247998; unreachable; + + block17: + v11.i1 = gt v4 599290589.i32; + v12.i1 = is_zero v11; + br v12 block19 block20; + + block18: + v15.i1 = gt v4 -1780966591.i32; + v16.i1 = is_zero v15; + br v16 block31 block32; + + block19: + v19.i1 = gt v4 157198259.i32; + v20.i1 = is_zero v19; + br v20 block21 block22; + + block20: + v23.i1 = gt v4 961581905.i32; + v24.i1 = is_zero v23; + br v24 block27 block28; + + block21: + v27.i1 = gt v4 117300739.i32; + v28.i1 = is_zero v27; + br v28 block23 block24; + + block22: + v31.i1 = gt v4 404098525.i32; + v32.i1 = is_zero v31; + br v32 block25 block26; + + block23: + v34.i1 = eq v4 117300739.i32; + br v34 block3 block2; + + block24: + v36.i1 = eq v4 157198259.i32; + br v36 block4 block2; + + block25: + v38.i1 = eq v4 404098525.i32; + br v38 block5 block2; + + block26: + v40.i1 = eq v4 599290589.i32; + br v40 block6 block2; + + block27: + v43.i1 = gt v4 826074471.i32; + v44.i1 = is_zero v43; + br v44 block29 block30; + + block28: + v46.i1 = eq v4 1086394137.i32; + br v46 block9 block2; + + block29: + v48.i1 = eq v4 826074471.i32; + br v48 block7 block2; + + block30: + v50.i1 = eq v4 961581905.i32; + br v50 block8 block2; + + block31: + v53.i1 = gt v4 1889567281.i32; + v54.i1 = is_zero v53; + br v54 block33 block34; + + block32: + v57.i1 = gt v4 -1459249989.i32; + v58.i1 = is_zero v57; + br v58 block39 block40; + + block33: + v61.i1 = gt v4 1117154408.i32; + v62.i1 = is_zero v61; + br v62 block35 block36; + + block34: + v65.i1 = gt v4 2043438992.i32; + v66.i1 = is_zero v65; + br v66 block37 block38; + + block35: + v68.i1 = eq v4 1117154408.i32; + br v68 block10 block2; + + block36: + v70.i1 = eq v4 1889567281.i32; + br v70 block11 block2; + + block37: + v72.i1 = eq v4 2043438992.i32; + br v72 block12 block2; + + block38: + v74.i1 = eq v4 -1780966591.i32; + br v74 block13 block2; + + block39: + v77.i1 = gt v4 -1537752361.i32; + v78.i1 = is_zero v77; + br v78 block41 block42; + + block40: + v81.i1 = eq v4 -580719298.i32; + br v81 block16 block2; + + block41: + v83.i1 = eq v4 -1537752361.i32; + br v83 block14 block2; + + block42: + v85.i1 = eq v4 -1459249989.i32; + br v85 block15 block2; } func private %std__lib__evm__effects__copy_words_c4e2(v0.i256, v1.i256, v2.i256) { @@ -2997,42 +2970,6 @@ func private %core__lib__abi__decode_field__g3854_5787(v0.objref<@layout_7>) -> return v17; } -func private %core__lib__abi__decode_field__g3854_7396(v0.objref<@layout_7>) -> i256 { - block0: - jump block1; - - block1: - br 0.i1 block2 block3; - - block2: - v3.i256 = call %std__lib__abi__sol__impl_trait_SolDecoder_68ab__read_word__g463e_7972 v0; - v4.i256 = call %std__lib__abi__sol__impl_trait_SolDecoder_68ab__base__g463e_b56a v0; - v5.i256 = call %std__lib__abi__sol__impl_trait_SolDecoder_68ab__pos__g463e_9608 v0; - (v6.i256, v7.i1) = uaddo v4 v3; - br v7 block5 block6; - - block3: - jump block4; - - block4: - v23.i256 = call %core__lib__abi__impl_trait_u256_85b6__decode_payload__g407e_1373 v0; - return v23; - - block5: - mstore 0.i256 35408467139433450592217433187231851964531694900788300625387963629091585785856.i256 i256; - mstore 4.i256 17.i256 i256; - evm_revert 0.i256 36.i256; - - block6: - call %std__lib__abi__sol__impl_trait_SolDecoder_68ab__set_base__g463e_70f3 v0 v6; - v15.i256 = call %std__lib__abi__sol__impl_trait_SolDecoder_68ab__base__g463e_b56a v0; - call %std__lib__abi__sol__impl_trait_SolDecoder_68ab__set_pos__g463e_e2de v0 v15; - v17.i256 = call %core__lib__abi__impl_trait_u256_85b6__decode_payload__g407e_1373 v0; - call %std__lib__abi__sol__impl_trait_SolDecoder_68ab__set_base__g463e_70f3 v0 v4; - call %std__lib__abi__sol__impl_trait_SolDecoder_68ab__set_pos__g463e_e2de v0 v5; - return v17; -} - func private %core__lib__abi__decode_field__g8463_77f0(v0.objref<@layout_7>) -> @layout_0 { block0: jump block1; @@ -3471,15 +3408,6 @@ func private %core__lib__abi__impl_trait_u256_85b6__decode_payload__g407e_0fba(v return v2; } -func private %core__lib__abi__impl_trait_u256_85b6__decode_payload__g407e_1373(v0.objref<@layout_7>) -> i256 { - block0: - jump block1; - - block1: - v2.i256 = call %std__lib__abi__sol__impl_trait_SolDecoder_68ab__read_word__g463e_da62 v0; - return v2; -} - func private %std__lib__evm__effects__impl_trait_Address_9c1b__decode_payload__g407e_1e55(v0.objref<@layout_7>) -> @layout_0 { block0: jump block1; @@ -3968,19 +3896,6 @@ func private %std__lib__evm__effects__impl_trait_Address_9c1b__decode_payload__g return v11; } -func private %impl_trait_Burn__decode_payload__gf196(v0.objref<@layout_7>) -> @layout_18 { - block0: - jump block1; - - block1: - v2.i256 = call %core__lib__abi__decode_field__g3854_7396 v0; - v3.objref<@layout_18> = obj.alloc @layout_18; - v5.objref = obj.proj v3 0.i256; - obj.store v5 v2; - v6.@layout_18 = obj.load v3; - return v6; -} - func private %impl_trait_Name__decode_payload__gf196(v0.objref<@layout_7>) { block0: jump block1; @@ -4061,9 +3976,9 @@ func private %core__lib__abi__dynamic_payload_size__ge513_7ef0_1(v0.i256) -> i25 return 0.i256; } -func private %impl_trait_ApprovalEvent__emit__gcd5c(v0.@layout_19, v1.objref<@layout_2>) { +func private %impl_trait_ApprovalEvent__emit__gcd5c(v0.@layout_18, v1.objref<@layout_2>) { block0: - v2.objref<@layout_19> = obj.alloc @layout_19; + v2.objref<@layout_18> = obj.alloc @layout_18; v4.objref<@layout_0> = obj.proj v2 0.i256; v5.@layout_0 = extract_value v0 0.i256; v6.objref = obj.proj v4 0.i256; @@ -4082,8 +3997,8 @@ func private %impl_trait_ApprovalEvent__emit__gcd5c(v0.@layout_19, v1.objref<@la block1: v16.objref = obj.proj v2 2.i256; v17.i256 = obj.load v16; - v18.@layout_21 = call %std__lib__evm__effects__encode_abi_payload__ge513_bb73 v17; - v19.objref<@layout_21> = obj.alloc @layout_21; + v18.@layout_20 = call %std__lib__evm__effects__encode_abi_payload__ge513_bb73 v17; + v19.objref<@layout_20> = obj.alloc @layout_20; v20.objref = obj.proj v19 0.i256; v21.i256 = extract_value v18 0.i256; obj.store v20 v21; @@ -4104,9 +4019,9 @@ func private %impl_trait_ApprovalEvent__emit__gcd5c(v0.@layout_19, v1.objref<@la return; } -func private %impl_trait_TransferEvent__emit__gcd5c(v0.@layout_20, v1.objref<@layout_2>) { +func private %impl_trait_TransferEvent__emit__gcd5c(v0.@layout_19, v1.objref<@layout_2>) { block0: - v2.objref<@layout_20> = obj.alloc @layout_20; + v2.objref<@layout_19> = obj.alloc @layout_19; v4.objref<@layout_0> = obj.proj v2 0.i256; v5.@layout_0 = extract_value v0 0.i256; v6.objref = obj.proj v4 0.i256; @@ -4125,8 +4040,8 @@ func private %impl_trait_TransferEvent__emit__gcd5c(v0.@layout_20, v1.objref<@la block1: v16.objref = obj.proj v2 2.i256; v17.i256 = obj.load v16; - v18.@layout_21 = call %std__lib__evm__effects__encode_abi_payload__ge513_5dc2 v17; - v19.objref<@layout_21> = obj.alloc @layout_21; + v18.@layout_20 = call %std__lib__evm__effects__encode_abi_payload__ge513_5dc2 v17; + v19.objref<@layout_20> = obj.alloc @layout_20; v20.objref = obj.proj v19 0.i256; v21.i256 = extract_value v18 0.i256; obj.store v20 v21; @@ -4147,7 +4062,7 @@ func private %impl_trait_TransferEvent__emit__gcd5c(v0.@layout_20, v1.objref<@la return; } -func private %emit__g9cd0(v0.objref<@layout_2>, v1.@layout_19) { +func private %emit__g9cd0(v0.objref<@layout_2>, v1.@layout_18) { block0: jump block1; @@ -4156,7 +4071,7 @@ func private %emit__g9cd0(v0.objref<@layout_2>, v1.@layout_19) { return; } -func private %emit__g4c3d(v0.objref<@layout_2>, v1.@layout_20) { +func private %emit__g4c3d(v0.objref<@layout_2>, v1.@layout_19) { block0: jump block1; @@ -4258,15 +4173,6 @@ func private %core__lib__abi__impl_trait_u256_d99e__encode__g426c_2015(v0.i256, return; } -func private %core__lib__abi__impl_trait_u256_d99e__encode__g426c_2910(v0.i256, v1.objref<@layout_4>) { - block0: - jump block1; - - block1: - call %std__lib__abi__sol__impl_trait_SolEncoder_19ce__write_word_8eda v1 v0; - return; -} - func private %encode__g3cd9(v0.i256, v1.objref<@layout_4>) { block0: jump block1; @@ -4323,48 +4229,48 @@ func private %encode__gbe21(v0.i256, v1.objref<@layout_4>) { return; } -func private %std__lib__evm__effects__encode_abi_payload__geb2e_59d4(v0.@layout_3) -> @layout_21 { +func private %std__lib__evm__effects__encode_abi_payload__geb2e_59d4(v0.@layout_3) -> @layout_20 { block0: jump block1; block1: - v2.@layout_21 = call %core__lib__abi__encode_alloc__g994a_d25b v0; + v2.@layout_20 = call %core__lib__abi__encode_alloc__g994a_d25b v0; return v2; } -func private %std__lib__evm__effects__encode_abi_payload__geb2e_59d4_0(v0.@layout_3) -> @layout_21 { +func private %std__lib__evm__effects__encode_abi_payload__geb2e_59d4_0(v0.@layout_3) -> @layout_20 { block0: jump block1; block1: - v2.@layout_21 = call %core__lib__abi__encode_alloc__g994a_d25b_0 v0; + v2.@layout_20 = call %core__lib__abi__encode_alloc__g994a_d25b_0 v0; return v2; } -func private %std__lib__evm__effects__encode_abi_payload__geb2e_59d4_1(v0.@layout_3) -> @layout_21 { +func private %std__lib__evm__effects__encode_abi_payload__geb2e_59d4_1(v0.@layout_3) -> @layout_20 { block0: jump block1; block1: - v2.@layout_21 = call %core__lib__abi__encode_alloc__g994a_d25b_1 v0; + v2.@layout_20 = call %core__lib__abi__encode_alloc__g994a_d25b_1 v0; return v2; } -func private %std__lib__evm__effects__encode_abi_payload__ge513_5dc2(v0.i256) -> @layout_21 { +func private %std__lib__evm__effects__encode_abi_payload__ge513_5dc2(v0.i256) -> @layout_20 { block0: jump block1; block1: - v2.@layout_21 = call %core__lib__abi__encode_alloc__gac80_c438 v0; + v2.@layout_20 = call %core__lib__abi__encode_alloc__gac80_c438 v0; return v2; } -func private %std__lib__evm__effects__encode_abi_payload__ge513_bb73(v0.i256) -> @layout_21 { +func private %std__lib__evm__effects__encode_abi_payload__ge513_bb73(v0.i256) -> @layout_20 { block0: jump block1; block1: - v2.@layout_21 = call %core__lib__abi__encode_alloc__gac80_492c v0; + v2.@layout_20 = call %core__lib__abi__encode_alloc__gac80_492c v0; return v2; } @@ -4378,7 +4284,7 @@ func private %impl_trait_u8__encode__g426c(v0.i8, v1.objref<@layout_4>) { return; } -func private %core__lib__abi__encode_alloc__gac80_492c(v0.i256) -> @layout_21 { +func private %core__lib__abi__encode_alloc__gac80_492c(v0.i256) -> @layout_20 { block0: jump block1; @@ -4394,16 +4300,16 @@ func private %core__lib__abi__encode_alloc__gac80_492c(v0.i256) -> @layout_21 { obj.store v9 v10; v11.i256 = call %std__lib__abi__sol__impl_trait_SolEncoder_19ce__base_dd69 v4; call %core__lib__abi__impl_trait_u256_d99e__encode__g426c_2015 v0 v4; - v13.objref<@layout_21> = obj.alloc @layout_21; + v13.objref<@layout_20> = obj.alloc @layout_20; v14.objref = obj.proj v13 0.i256; obj.store v14 v11; v15.objref = obj.proj v13 1.i256; obj.store v15 v2; - v16.@layout_21 = obj.load v13; + v16.@layout_20 = obj.load v13; return v16; } -func private %core__lib__abi__encode_alloc__gac80_c438(v0.i256) -> @layout_21 { +func private %core__lib__abi__encode_alloc__gac80_c438(v0.i256) -> @layout_20 { block0: jump block1; @@ -4419,16 +4325,16 @@ func private %core__lib__abi__encode_alloc__gac80_c438(v0.i256) -> @layout_21 { obj.store v9 v10; v11.i256 = call %std__lib__abi__sol__impl_trait_SolEncoder_19ce__base_009f v4; call %core__lib__abi__impl_trait_u256_d99e__encode__g426c_c169 v0 v4; - v13.objref<@layout_21> = obj.alloc @layout_21; + v13.objref<@layout_20> = obj.alloc @layout_20; v14.objref = obj.proj v13 0.i256; obj.store v14 v11; v15.objref = obj.proj v13 1.i256; obj.store v15 v2; - v16.@layout_21 = obj.load v13; + v16.@layout_20 = obj.load v13; return v16; } -func private %core__lib__abi__encode_alloc__g994a_d25b(v0.@layout_3) -> @layout_21 { +func private %core__lib__abi__encode_alloc__g994a_d25b(v0.@layout_3) -> @layout_20 { block0: jump block1; @@ -4448,16 +4354,16 @@ func private %core__lib__abi__encode_alloc__g994a_d25b(v0.@layout_3) -> @layout_ obj.store v12 v13; v14.i256 = call %std__lib__abi__sol__impl_trait_SolEncoder_19ce__base_deb4 v8; call %std__lib__evm__panic__impl_trait_Panic_2bdd__encode__g9c6f_02eb v0 v8; - v16.objref<@layout_21> = obj.alloc @layout_21; + v16.objref<@layout_20> = obj.alloc @layout_20; v17.objref = obj.proj v16 0.i256; obj.store v17 v14; v18.objref = obj.proj v16 1.i256; obj.store v18 v6; - v19.@layout_21 = obj.load v16; + v19.@layout_20 = obj.load v16; return v19; } -func private %core__lib__abi__encode_alloc__g994a_d25b_0(v0.@layout_3) -> @layout_21 { +func private %core__lib__abi__encode_alloc__g994a_d25b_0(v0.@layout_3) -> @layout_20 { block0: jump block1; @@ -4477,16 +4383,16 @@ func private %core__lib__abi__encode_alloc__g994a_d25b_0(v0.@layout_3) -> @layou obj.store v12 v13; v14.i256 = call %std__lib__abi__sol__impl_trait_SolEncoder_19ce__base_deb4_0 v8; call %std__lib__evm__panic__impl_trait_Panic_2bdd__encode__g9c6f_02eb_0 v0 v8; - v16.objref<@layout_21> = obj.alloc @layout_21; + v16.objref<@layout_20> = obj.alloc @layout_20; v17.objref = obj.proj v16 0.i256; obj.store v17 v14; v18.objref = obj.proj v16 1.i256; obj.store v18 v6; - v19.@layout_21 = obj.load v16; + v19.@layout_20 = obj.load v16; return v19; } -func private %core__lib__abi__encode_alloc__g994a_d25b_1(v0.@layout_3) -> @layout_21 { +func private %core__lib__abi__encode_alloc__g994a_d25b_1(v0.@layout_3) -> @layout_20 { block0: jump block1; @@ -4506,12 +4412,12 @@ func private %core__lib__abi__encode_alloc__g994a_d25b_1(v0.@layout_3) -> @layou obj.store v12 v13; v14.i256 = call %std__lib__abi__sol__impl_trait_SolEncoder_19ce__base_deb4_1 v8; call %std__lib__evm__panic__impl_trait_Panic_2bdd__encode__g9c6f_02eb_1 v0 v8; - v16.objref<@layout_21> = obj.alloc @layout_21; + v16.objref<@layout_20> = obj.alloc @layout_20; v17.objref = obj.proj v16 0.i256; obj.store v17 v14; v18.objref = obj.proj v16 1.i256; obj.store v18 v6; - v19.@layout_21 = obj.load v16; + v19.@layout_20 = obj.load v16; return v19; } @@ -4543,7 +4449,7 @@ func private %core__lib__abi__impl_trait_u256_d99e__encode__g426c_c169(v0.i256, return; } -func private %std__lib__evm__effects__encode_calldata__geb2e_13c2(v0.i32, v1.@layout_3) -> @layout_21 { +func private %std__lib__evm__effects__encode_calldata__geb2e_13c2(v0.i32, v1.@layout_3) -> @layout_20 { block0: v2.*i32 = alloca i32; mstore v2 v0 i32; @@ -4553,8 +4459,8 @@ func private %std__lib__evm__effects__encode_calldata__geb2e_13c2(v0.i32, v1.@la v4.i32 = mload v2 i32; v5.i256 = zext v4 i256; v7.i256 = shl 224.i256 v5; - v9.@layout_21 = call %std__lib__evm__effects__encode_abi_payload__geb2e_59d4 v1; - v10.objref<@layout_21> = obj.alloc @layout_21; + v9.@layout_20 = call %std__lib__evm__effects__encode_abi_payload__geb2e_59d4 v1; + v10.objref<@layout_20> = obj.alloc @layout_20; v12.objref = obj.proj v10 0.i256; v13.i256 = extract_value v9 0.i256; obj.store v12 v13; @@ -4590,16 +4496,16 @@ func private %std__lib__evm__effects__encode_calldata__geb2e_13c2(v0.i32, v1.@la br v41 block2 block5; block5: - v42.objref<@layout_21> = obj.alloc @layout_21; + v42.objref<@layout_20> = obj.alloc @layout_20; v44.objref = obj.proj v42 0.i256; obj.store v44 v25; v45.objref = obj.proj v42 1.i256; obj.store v45 v40; - v46.@layout_21 = obj.load v42; + v46.@layout_20 = obj.load v42; return v46; } -func private %std__lib__evm__effects__encode_calldata__geb2e_13c2_0(v0.i32, v1.@layout_3) -> @layout_21 { +func private %std__lib__evm__effects__encode_calldata__geb2e_13c2_0(v0.i32, v1.@layout_3) -> @layout_20 { block0: v2.*i32 = alloca i32; mstore v2 v0 i32; @@ -4609,8 +4515,8 @@ func private %std__lib__evm__effects__encode_calldata__geb2e_13c2_0(v0.i32, v1.@ v4.i32 = mload v2 i32; v5.i256 = zext v4 i256; v7.i256 = shl 224.i256 v5; - v9.@layout_21 = call %std__lib__evm__effects__encode_abi_payload__geb2e_59d4_0 v1; - v10.objref<@layout_21> = obj.alloc @layout_21; + v9.@layout_20 = call %std__lib__evm__effects__encode_abi_payload__geb2e_59d4_0 v1; + v10.objref<@layout_20> = obj.alloc @layout_20; v12.objref = obj.proj v10 0.i256; v13.i256 = extract_value v9 0.i256; obj.store v12 v13; @@ -4646,16 +4552,16 @@ func private %std__lib__evm__effects__encode_calldata__geb2e_13c2_0(v0.i32, v1.@ br v41 block2 block5; block5: - v42.objref<@layout_21> = obj.alloc @layout_21; + v42.objref<@layout_20> = obj.alloc @layout_20; v44.objref = obj.proj v42 0.i256; obj.store v44 v25; v45.objref = obj.proj v42 1.i256; obj.store v45 v40; - v46.@layout_21 = obj.load v42; + v46.@layout_20 = obj.load v42; return v46; } -func private %std__lib__evm__effects__encode_calldata__geb2e_13c2_1(v0.i32, v1.@layout_3) -> @layout_21 { +func private %std__lib__evm__effects__encode_calldata__geb2e_13c2_1(v0.i32, v1.@layout_3) -> @layout_20 { block0: v2.*i32 = alloca i32; mstore v2 v0 i32; @@ -4665,8 +4571,8 @@ func private %std__lib__evm__effects__encode_calldata__geb2e_13c2_1(v0.i32, v1.@ v4.i32 = mload v2 i32; v5.i256 = zext v4 i256; v7.i256 = shl 224.i256 v5; - v9.@layout_21 = call %std__lib__evm__effects__encode_abi_payload__geb2e_59d4_1 v1; - v10.objref<@layout_21> = obj.alloc @layout_21; + v9.@layout_20 = call %std__lib__evm__effects__encode_abi_payload__geb2e_59d4_1 v1; + v10.objref<@layout_20> = obj.alloc @layout_20; v12.objref = obj.proj v10 0.i256; v13.i256 = extract_value v9 0.i256; obj.store v12 v13; @@ -4702,12 +4608,12 @@ func private %std__lib__evm__effects__encode_calldata__geb2e_13c2_1(v0.i32, v1.@ br v41 block2 block5; block5: - v42.objref<@layout_21> = obj.alloc @layout_21; + v42.objref<@layout_20> = obj.alloc @layout_20; v44.objref = obj.proj v42 0.i256; obj.store v44 v25; v45.objref = obj.proj v42 1.i256; obj.store v45 v40; - v46.@layout_21 = obj.load v42; + v46.@layout_20 = obj.load v42; return v46; } @@ -5018,53 +4924,6 @@ func private %encode_field__g859f(v0.i256, v1.objref<@layout_4>, v2.i256) { return; } -func private %core__lib__abi__encode_field__g2e64_555f(v0.i256, v1.objref<@layout_4>, v2.i256) { - block0: - jump block1; - - block1: - br 0.i1 block2 block3; - - block2: - v5.i256 = call %std__lib__abi__sol__impl_trait_SolEncoder_19ce__base_fd6f v1; - v8.i256 = call %core__lib__abi__trait_AbiSize__payload_size__ge513_77e5 v0; - v9.i256 = mload v2 i256; - v10.i256 = sub v9 v5; - call %std__lib__abi__sol__impl_trait_SolEncoder_19ce__write_word_8f67 v1 v10; - v12.i256 = call %std__lib__abi__sol__impl_trait_SolEncoder_19ce__pos_0de4 v1; - v13.i256 = mload v2 i256; - call %std__lib__abi__sol__impl_trait_SolEncoder_19ce__set_base_fa20 v1 v13; - v15.i256 = mload v2 i256; - call %std__lib__abi__sol__impl_trait_SolEncoder_19ce__set_pos_3857 v1 v15; - call %core__lib__abi__impl_trait_u256_d99e__encode__g426c_2910 v0 v1; - call %std__lib__abi__sol__impl_trait_SolEncoder_19ce__set_base_fa20 v1 v5; - call %std__lib__abi__sol__impl_trait_SolEncoder_19ce__set_pos_3857 v1 v12; - v20.i256 = mload v2 i256; - v21.i256 = add v20 v8; - mstore v2 v21 i256; - return; - - block3: - jump block4; - - block4: - br 1.i1 block5 block6; - - block5: - v24.i256 = call %std__lib__abi__sol__impl_trait_SolEncoder_19ce__pos_0de4 v1; - call %core__lib__abi__impl_trait_u256_d99e__encode_to_ptr__gf13e_1b98 v0 v24; - v28.i256 = add v24 32.i256; - call %std__lib__abi__sol__impl_trait_SolEncoder_19ce__set_pos_3857 v1 v28; - return; - - block6: - jump block7; - - block7: - call %core__lib__abi__impl_trait_u256_d99e__encode__g426c_2910 v0 v1; - return; -} - func private %encode_field__g6d7e(v0.i256, v1.objref<@layout_4>, v2.i256) { block0: jump block1; @@ -5152,20 +5011,6 @@ func private %encode_single_root__g859f(v0.i256, v1.objref<@layout_4>) { return; } -func private %encode_single_root__g2e64(v0.i256, v1.objref<@layout_4>) { - block0: - v2.*i256 = alloca i256; - jump block1; - - block1: - v4.i256 = call %std__lib__abi__sol__impl_trait_SolEncoder_19ce__base_fd6f v1; - v6.i256 = add v4 32.i256; - mstore v2 v6 i256; - v7.i256 = ptr_to_int v2 i256; - call %core__lib__abi__encode_field__g2e64_555f v0 v1 v7; - return; -} - func private %encode_single_root__g6d7e(v0.i256, v1.objref<@layout_4>) { block0: v2.*i256 = alloca i256; @@ -5180,7 +5025,7 @@ func private %encode_single_root__g6d7e(v0.i256, v1.objref<@layout_4>) { return; } -func private %encode_single_root_alloc__g472d(v0.i256) -> @layout_21 { +func private %encode_single_root_alloc__g472d(v0.i256) -> @layout_20 { block0: jump block1; @@ -5196,16 +5041,16 @@ func private %encode_single_root_alloc__g472d(v0.i256) -> @layout_21 { obj.store v9 v10; v11.i256 = call %std__lib__abi__sol__impl_trait_SolEncoder_19ce__base_25d4 v4; call %encode_single_root__g859f v0 v4; - v13.objref<@layout_21> = obj.alloc @layout_21; + v13.objref<@layout_20> = obj.alloc @layout_20; v14.objref = obj.proj v13 0.i256; obj.store v14 v11; v15.objref = obj.proj v13 1.i256; obj.store v15 v2; - v16.@layout_21 = obj.load v13; + v16.@layout_20 = obj.load v13; return v16; } -func private %encode_single_root_alloc__g0c18(v0.i256) -> @layout_21 { +func private %encode_single_root_alloc__g0c18(v0.i256) -> @layout_20 { block0: jump block1; @@ -5221,16 +5066,16 @@ func private %encode_single_root_alloc__g0c18(v0.i256) -> @layout_21 { obj.store v9 v10; v11.i256 = call %std__lib__abi__sol__impl_trait_SolEncoder_19ce__base_6030 v4; call %encode_single_root__g6d7e v0 v4; - v13.objref<@layout_21> = obj.alloc @layout_21; + v13.objref<@layout_20> = obj.alloc @layout_20; v14.objref = obj.proj v13 0.i256; obj.store v14 v11; v15.objref = obj.proj v13 1.i256; obj.store v15 v2; - v16.@layout_21 = obj.load v13; + v16.@layout_20 = obj.load v13; return v16; } -func private %encode_single_root_alloc__gcb0a(v0.i8) -> @layout_21 { +func private %encode_single_root_alloc__gcb0a(v0.i8) -> @layout_20 { block0: jump block1; @@ -5246,41 +5091,16 @@ func private %encode_single_root_alloc__gcb0a(v0.i8) -> @layout_21 { obj.store v9 v10; v11.i256 = call %std__lib__abi__sol__impl_trait_SolEncoder_19ce__base_a9a0 v4; call %encode_single_root__g0a88 v0 v4; - v13.objref<@layout_21> = obj.alloc @layout_21; - v14.objref = obj.proj v13 0.i256; - obj.store v14 v11; - v15.objref = obj.proj v13 1.i256; - obj.store v15 v2; - v16.@layout_21 = obj.load v13; - return v16; -} - -func private %encode_single_root_alloc__gac80(v0.i256) -> @layout_21 { - block0: - jump block1; - - block1: - v2.i256 = call %abi_single_root_size__ge513 v0; - v3.@layout_4 = call %std__lib__abi__sol__impl_trait_Sol_1f5f__encoder_new_94e9 v2; - v4.objref<@layout_4> = obj.alloc @layout_4; - v6.objref = obj.proj v4 0.i256; - v7.i256 = extract_value v3 0.i256; - obj.store v6 v7; - v9.objref = obj.proj v4 1.i256; - v10.i256 = extract_value v3 1.i256; - obj.store v9 v10; - v11.i256 = call %std__lib__abi__sol__impl_trait_SolEncoder_19ce__base_fd6f v4; - call %encode_single_root__g2e64 v0 v4; - v13.objref<@layout_21> = obj.alloc @layout_21; + v13.objref<@layout_20> = obj.alloc @layout_20; v14.objref = obj.proj v13 0.i256; obj.store v14 v11; v15.objref = obj.proj v13 1.i256; obj.store v15 v2; - v16.@layout_21 = obj.load v13; + v16.@layout_20 = obj.load v13; return v16; } -func private %encode_single_root_alloc__g09ca(v0.i1) -> @layout_21 { +func private %encode_single_root_alloc__g09ca(v0.i1) -> @layout_20 { block0: jump block1; @@ -5296,27 +5116,15 @@ func private %encode_single_root_alloc__g09ca(v0.i1) -> @layout_21 { obj.store v9 v10; v11.i256 = call %std__lib__abi__sol__impl_trait_SolEncoder_19ce__base_c13e v4; call %encode_single_root__ge927 v0 v4; - v13.objref<@layout_21> = obj.alloc @layout_21; + v13.objref<@layout_20> = obj.alloc @layout_20; v14.objref = obj.proj v13 0.i256; obj.store v14 v11; v15.objref = obj.proj v13 1.i256; obj.store v15 v2; - v16.@layout_21 = obj.load v13; + v16.@layout_20 = obj.load v13; return v16; } -func private %core__lib__abi__impl_trait_u256_d99e__encode_to_ptr__gf13e_1b98(v0.i256, v1.i256) { - block0: - v2.*i256 = alloca i256; - mstore v2 v1 i256; - jump block1; - - block1: - v3.i256 = mload v2 i256; - call %std__lib__abi__sol__impl_trait_Sol_1f5f__store_word_2361 v3 v0; - return; -} - func private %impl_trait_bool__encode_to_ptr__gf13e(v0.i1, v1.i256) { block0: v2.*i256 = alloca i256; @@ -5481,18 +5289,6 @@ func private %std__lib__abi__sol__impl_trait_Sol_1f5f__encoder_new_8043_1(v0.i25 return v3; } -func private %std__lib__abi__sol__impl_trait_Sol_1f5f__encoder_new_94e9(v0.i256) -> @layout_4 { - block0: - v1.*i256 = alloca i256; - mstore v1 v0 i256; - jump block1; - - block1: - v2.i256 = mload v1 i256; - v3.@layout_4 = call %std__lib__abi__sol__impl_SolEncoder_ce34__new_c2ff v2; - return v3; -} - func private %std__lib__abi__sol__impl_trait_Sol_1f5f__encoder_new_9a7a(v0.i256) -> @layout_4 { block0: v1.*i256 = alloca i256; @@ -5648,9 +5444,9 @@ func private %std__lib__evm__storage_map__impl_StorageMap_9f54__get__g2163_9a1d( return v7; } -func private %std__lib__evm__storage_map__impl_StorageMap_9f54__get__ga15b_b5d5(v0.@layout_22) -> i256 { +func private %std__lib__evm__storage_map__impl_StorageMap_9f54__get__ga15b_b5d5(v0.@layout_21) -> i256 { block0: - v1.objref<@layout_22> = obj.alloc @layout_22; + v1.objref<@layout_21> = obj.alloc @layout_21; v3.objref<@layout_0> = obj.proj v1 0.i256; v4.@layout_0 = extract_value v0 0.i256; v5.objref = obj.proj v3 0.i256; @@ -5664,15 +5460,15 @@ func private %std__lib__evm__storage_map__impl_StorageMap_9f54__get__ga15b_b5d5( jump block1; block1: - v12.@layout_22 = obj.load v1; + v12.@layout_21 = obj.load v1; v13.i256 = call %std__lib__evm__storage_map__storagemap_get_word_with_salt__g7bf4_09af v12 1.i256; v14.i256 = call %std__lib__evm__word__impl_trait_u256_1f9e__from_word_4030 v13; return v14; } -func private %std__lib__evm__storage_map__impl_StorageMap_9f54__get__ga15b_b5d5_0(v0.@layout_22) -> i256 { +func private %std__lib__evm__storage_map__impl_StorageMap_9f54__get__ga15b_b5d5_0(v0.@layout_21) -> i256 { block0: - v1.objref<@layout_22> = obj.alloc @layout_22; + v1.objref<@layout_21> = obj.alloc @layout_21; v3.objref<@layout_0> = obj.proj v1 0.i256; v4.@layout_0 = extract_value v0 0.i256; v5.objref = obj.proj v3 0.i256; @@ -5686,15 +5482,15 @@ func private %std__lib__evm__storage_map__impl_StorageMap_9f54__get__ga15b_b5d5_ jump block1; block1: - v12.@layout_22 = obj.load v1; + v12.@layout_21 = obj.load v1; v13.i256 = call %std__lib__evm__storage_map__storagemap_get_word_with_salt__g7bf4_09af_0 v12 1.i256; v14.i256 = call %std__lib__evm__word__impl_trait_u256_1f9e__from_word_4030_0 v13; return v14; } -func private %std__lib__evm__storage_map__impl_StorageMap_9f54__get__ga15b_cf04(v0.@layout_22) -> i256 { +func private %std__lib__evm__storage_map__impl_StorageMap_9f54__get__ga15b_cf04(v0.@layout_21) -> i256 { block0: - v1.objref<@layout_22> = obj.alloc @layout_22; + v1.objref<@layout_21> = obj.alloc @layout_21; v3.objref<@layout_0> = obj.proj v1 0.i256; v4.@layout_0 = extract_value v0 0.i256; v5.objref = obj.proj v3 0.i256; @@ -5708,7 +5504,7 @@ func private %std__lib__evm__storage_map__impl_StorageMap_9f54__get__ga15b_cf04( jump block1; block1: - v12.@layout_22 = obj.load v1; + v12.@layout_21 = obj.load v1; v13.i256 = call %std__lib__evm__storage_map__storagemap_get_word_with_salt__g7bf4_af75 v12 1.i256; v14.i256 = call %std__lib__evm__word__impl_trait_u256_1f9e__from_word_83e7 v13; return v14; @@ -5759,23 +5555,6 @@ func private %grant(v0.i256, v1.i256, v2.@layout_0) { return; } -func private %std__lib__evm__memory_input__impl_trait_MemoryBytes_c1cd__len_07fa(v0.@layout_5) -> i256 { - block0: - v1.objref<@layout_5> = obj.alloc @layout_5; - v3.objref = obj.proj v1 0.i256; - v4.i256 = extract_value v0 0.i256; - obj.store v3 v4; - v6.objref = obj.proj v1 1.i256; - v7.i256 = extract_value v0 1.i256; - obj.store v6 v7; - jump block1; - - block1: - v8.objref = obj.proj v1 1.i256; - v9.i256 = obj.load v8; - return v9; -} - func private %std__lib__evm__memory_input__impl_trait_MemoryBytes_c1cd__len_10c2(v0.@layout_5) -> i256 { block0: v1.objref<@layout_5> = obj.alloc @layout_5; @@ -6269,23 +6048,6 @@ func private %std__lib__evm__memory_input__impl_trait_MemoryBytes_c1cd__len_af05 return v9; } -func private %std__lib__evm__memory_input__impl_trait_MemoryBytes_c1cd__len_c5ca(v0.@layout_5) -> i256 { - block0: - v1.objref<@layout_5> = obj.alloc @layout_5; - v3.objref = obj.proj v1 0.i256; - v4.i256 = extract_value v0 0.i256; - obj.store v3 v4; - v6.objref = obj.proj v1 1.i256; - v7.i256 = extract_value v0 1.i256; - obj.store v6 v7; - jump block1; - - block1: - v8.objref = obj.proj v1 1.i256; - v9.i256 = obj.load v8; - return v9; -} - func private %std__lib__evm__memory_input__impl_trait_MemoryBytes_c1cd__len_c5d0(v0.@layout_5) -> i256 { block0: v1.objref<@layout_5> = obj.alloc @layout_5; @@ -6497,7 +6259,7 @@ func private %standalone_erc20__erc20__mint__g5c3f_3fb6(v0.@layout_0, v1.i256, v v36.@layout_0 = call %zero; v37.@layout_0 = obj.load v4; v38.i256 = mload v5 i256; - v39.objref<@layout_20> = obj.alloc @layout_20; + v39.objref<@layout_19> = obj.alloc @layout_19; v40.objref<@layout_0> = obj.proj v39 0.i256; v41.objref = obj.proj v40 0.i256; v42.i256 = extract_value v36 0.i256; @@ -6508,7 +6270,7 @@ func private %standalone_erc20__erc20__mint__g5c3f_3fb6(v0.@layout_0, v1.i256, v obj.store v45 v46; v48.objref = obj.proj v39 2.i256; obj.store v48 v38; - v49.@layout_20 = obj.load v39; + v49.@layout_19 = obj.load v39; call %emit__g4c3d v3 v49; return; } @@ -6557,7 +6319,7 @@ func private %standalone_erc20__erc20__mint__g5c3f_7deb(v0.@layout_0, v1.i256, v v36.@layout_0 = call %zero; v37.@layout_0 = obj.load v4; v38.i256 = mload v5 i256; - v39.objref<@layout_20> = obj.alloc @layout_20; + v39.objref<@layout_19> = obj.alloc @layout_19; v40.objref<@layout_0> = obj.proj v39 0.i256; v41.objref = obj.proj v40 0.i256; v42.i256 = extract_value v36 0.i256; @@ -6568,7 +6330,7 @@ func private %standalone_erc20__erc20__mint__g5c3f_7deb(v0.@layout_0, v1.i256, v obj.store v45 v46; v48.objref = obj.proj v39 2.i256; obj.store v48 v38; - v49.@layout_20 = obj.load v39; + v49.@layout_19 = obj.load v39; call %emit__g4c3d v3 v49; return; } @@ -6854,37 +6616,6 @@ func private %impl_Cursor__new__g463e(v0.@layout_5) -> @layout_6 { return v11; } -func private %std__lib__abi__sol__impl_SolEncoder_ce34__new_c2ff(v0.i256) -> @layout_4 { - block0: - v1.*i256 = alloca i256; - mstore v1 v0 i256; - jump block1; - - block1: - v2.i256 = mload v1 i256; - v4.i1 = eq v2 0.i256; - br v4 block2 block3; - - block2: - jump block4; - - block3: - v5.i256 = mload v1 i256; - v6.*i8 = evm_malloc v5; - v7.i256 = ptr_to_int v6 i256; - jump block4; - - block4: - v8.i256 = phi (0.i256 block2) (v7 block3); - v9.objref<@layout_4> = obj.alloc @layout_4; - v10.objref = obj.proj v9 0.i256; - obj.store v10 v8; - v12.objref = obj.proj v9 1.i256; - obj.store v12 v8; - v13.@layout_4 = obj.load v9; - return v13; -} - func private %std__lib__abi__sol__impl_SolEncoder_ce34__new_c575(v0.i256) -> @layout_4 { block0: v1.*i256 = alloca i256; @@ -7299,26 +7030,6 @@ func private %core__lib__abi__trait_AbiSize__payload_size__ge513_3812_1(v0.i256) return 32.i256; } -func private %core__lib__abi__trait_AbiSize__payload_size__ge513_77e5(v0.i256) -> i256 { - block0: - v1.*i256 = alloca i256; - mstore v1 v0 i256; - jump block1; - - block1: - return 32.i256; -} - -func private %core__lib__abi__trait_AbiSize__payload_size__ge513_77e5_0(v0.i256) -> i256 { - block0: - v1.*i256 = alloca i256; - mstore v1 v0 i256; - jump block1; - - block1: - return 32.i256; -} - func private %core__lib__abi__impl_trait_String_c06e__payload_size__gc7cf_9b7d(v0.i256) -> i256 { block0: v1.*i256 = alloca i256; @@ -7488,17 +7199,7 @@ func private %core__lib__abi__trait_AbiSize__payload_size__g79ff_f3e8_0(v0.i8) - jump block1; block1: - return 32.i256; -} - -func private %std__lib__abi__sol__impl_trait_SolEncoder_19ce__pos_0de4(v0.objref<@layout_4>) -> i256 { - block0: - jump block1; - - block1: - v3.objref = obj.proj v0 1.i256; - v4.i256 = obj.load v3; - return v4; + return 32.i256; } func private %std__lib__abi__sol__impl_trait_SolDecoder_68ab__pos__g463e_1f4c(v0.objref<@layout_7>) -> i256 { @@ -7649,17 +7350,6 @@ func private %std__lib__abi__sol__impl_trait_SolDecoder_68ab__pos__g463e_8aa3(v0 return v6; } -func private %std__lib__abi__sol__impl_trait_SolDecoder_68ab__pos__g463e_9608(v0.objref<@layout_7>) -> i256 { - block0: - jump block1; - - block1: - v3.objref<@layout_6> = obj.proj v0 0.i256; - v5.objref = obj.proj v3 1.i256; - v6.i256 = obj.load v5; - return v6; -} - func private %std__lib__abi__sol__impl_trait_SolDecoder_68ab__pos__g463e_99ae(v0.objref<@layout_7>) -> i256 { block0: jump block1; @@ -8635,63 +8325,6 @@ func private %std__lib__abi__sol__impl_trait_SolDecoder_68ab__read_word__g463e_7 br v24 block2 block5; } -func private %std__lib__abi__sol__impl_trait_SolDecoder_68ab__read_word__g463e_7972(v0.objref<@layout_7>) -> i256 { - block0: - v1.*i256 = alloca i256; - v2.*i256 = alloca i256; - jump block1; - - block1: - v5.objref<@layout_6> = obj.proj v0 0.i256; - v6.objref<@layout_5> = obj.proj v5 0.i256; - v7.@layout_5 = obj.load v6; - v8.i256 = call %std__lib__evm__memory_input__impl_trait_MemoryBytes_c1cd__len_07fa v7; - mstore v1 v8 i256; - v9.objref<@layout_6> = obj.proj v0 0.i256; - v11.objref = obj.proj v9 1.i256; - v12.i256 = obj.load v11; - (v14.i256, v15.i1) = uaddo v12 32.i256; - br v15 block6 block7; - - block2: - evm_revert 0.i256 0.i256; - - block3: - jump block4; - - block4: - v26.objref<@layout_6> = obj.proj v0 0.i256; - v27.objref<@layout_5> = obj.proj v26 0.i256; - v28.@layout_5 = obj.load v27; - v29.objref<@layout_6> = obj.proj v0 0.i256; - v30.objref = obj.proj v29 1.i256; - v31.i256 = obj.load v30; - v32.i256 = call %std__lib__evm__memory_input__impl_trait_MemoryBytes_c1cd__word_at_4b4e v28 v31; - v34.objref<@layout_6> = obj.proj v0 0.i256; - v35.objref = obj.proj v34 1.i256; - obj.store v35 v14; - return v32; - - block5: - v36.i256 = mload v1 i256; - mstore v2 v36 i256; - v38.i256 = mload v2 i256; - v39.i1 = gt v14 v38; - br v39 block2 block3; - - block6: - mstore 0.i256 35408467139433450592217433187231851964531694900788300625387963629091585785856.i256 i256; - mstore 4.i256 17.i256 i256; - evm_revert 0.i256 36.i256; - - block7: - v21.objref<@layout_6> = obj.proj v0 0.i256; - v22.objref = obj.proj v21 1.i256; - v23.i256 = obj.load v22; - v24.i1 = lt v14 v23; - br v24 block2 block5; -} - func private %std__lib__abi__sol__impl_trait_SolDecoder_68ab__read_word__g463e_7ba8(v0.objref<@layout_7>) -> i256 { block0: v1.*i256 = alloca i256; @@ -9661,63 +9294,6 @@ func private %std__lib__abi__sol__impl_trait_SolDecoder_68ab__read_word__g463e_d br v24 block2 block5; } -func private %std__lib__abi__sol__impl_trait_SolDecoder_68ab__read_word__g463e_da62(v0.objref<@layout_7>) -> i256 { - block0: - v1.*i256 = alloca i256; - v2.*i256 = alloca i256; - jump block1; - - block1: - v5.objref<@layout_6> = obj.proj v0 0.i256; - v6.objref<@layout_5> = obj.proj v5 0.i256; - v7.@layout_5 = obj.load v6; - v8.i256 = call %std__lib__evm__memory_input__impl_trait_MemoryBytes_c1cd__len_c5ca v7; - mstore v1 v8 i256; - v9.objref<@layout_6> = obj.proj v0 0.i256; - v11.objref = obj.proj v9 1.i256; - v12.i256 = obj.load v11; - (v14.i256, v15.i1) = uaddo v12 32.i256; - br v15 block6 block7; - - block2: - evm_revert 0.i256 0.i256; - - block3: - jump block4; - - block4: - v26.objref<@layout_6> = obj.proj v0 0.i256; - v27.objref<@layout_5> = obj.proj v26 0.i256; - v28.@layout_5 = obj.load v27; - v29.objref<@layout_6> = obj.proj v0 0.i256; - v30.objref = obj.proj v29 1.i256; - v31.i256 = obj.load v30; - v32.i256 = call %std__lib__evm__memory_input__impl_trait_MemoryBytes_c1cd__word_at_3283 v28 v31; - v34.objref<@layout_6> = obj.proj v0 0.i256; - v35.objref = obj.proj v34 1.i256; - obj.store v35 v14; - return v32; - - block5: - v36.i256 = mload v1 i256; - mstore v2 v36 i256; - v38.i256 = mload v2 i256; - v39.i1 = gt v14 v38; - br v39 block2 block3; - - block6: - mstore 0.i256 35408467139433450592217433187231851964531694900788300625387963629091585785856.i256 i256; - mstore 4.i256 17.i256 i256; - evm_revert 0.i256 36.i256; - - block7: - v21.objref<@layout_6> = obj.proj v0 0.i256; - v22.objref = obj.proj v21 1.i256; - v23.i256 = obj.load v22; - v24.i1 = lt v14 v23; - br v24 block2 block5; -} - func private %std__lib__abi__sol__impl_trait_SolDecoder_68ab__read_word__g463e_e05e(v0.objref<@layout_7>) -> i256 { block0: v1.*i256 = alloca i256; @@ -9974,8 +9550,8 @@ func private %std__lib__evm__effects__revert_error__geb2e_c430(v0.@layout_3) { jump block1; block1: - v3.@layout_21 = call %std__lib__evm__effects__encode_calldata__geb2e_13c2 1313373041.i32 v0; - v4.objref<@layout_21> = obj.alloc @layout_21; + v3.@layout_20 = call %std__lib__evm__effects__encode_calldata__geb2e_13c2 1313373041.i32 v0; + v4.objref<@layout_20> = obj.alloc @layout_20; v6.objref = obj.proj v4 0.i256; v7.i256 = extract_value v3 0.i256; obj.store v6 v7; @@ -9994,8 +9570,8 @@ func private %std__lib__evm__effects__revert_error__geb2e_c430_0(v0.@layout_3) { jump block1; block1: - v3.@layout_21 = call %std__lib__evm__effects__encode_calldata__geb2e_13c2_0 1313373041.i32 v0; - v4.objref<@layout_21> = obj.alloc @layout_21; + v3.@layout_20 = call %std__lib__evm__effects__encode_calldata__geb2e_13c2_0 1313373041.i32 v0; + v4.objref<@layout_20> = obj.alloc @layout_20; v6.objref = obj.proj v4 0.i256; v7.i256 = extract_value v3 0.i256; obj.store v6 v7; @@ -10014,8 +9590,8 @@ func private %std__lib__evm__effects__revert_error__geb2e_c430_1(v0.@layout_3) { jump block1; block1: - v3.@layout_21 = call %std__lib__evm__effects__encode_calldata__geb2e_13c2_1 1313373041.i32 v0; - v4.objref<@layout_21> = obj.alloc @layout_21; + v3.@layout_20 = call %std__lib__evm__effects__encode_calldata__geb2e_13c2_1 1313373041.i32 v0; + v4.objref<@layout_20> = obj.alloc @layout_20; v6.objref = obj.proj v4 0.i256; v7.i256 = extract_value v3 0.i256; obj.store v6 v7; @@ -10343,19 +9919,6 @@ func private %std__lib__abi__sol__impl_trait_SolDecoder_68ab__set_base__g463e_6e return; } -func private %std__lib__abi__sol__impl_trait_SolDecoder_68ab__set_base__g463e_70f3(v0.objref<@layout_7>, v1.i256) { - block0: - v2.*i256 = alloca i256; - mstore v2 v1 i256; - jump block1; - - block1: - v3.i256 = mload v2 i256; - v6.objref = obj.proj v0 1.i256; - obj.store v6 v3; - return; -} - func private %std__lib__abi__sol__impl_trait_SolEncoder_19ce__set_base_750c(v0.objref<@layout_4>, v1.i256) { block0: v2.*i256 = alloca i256; @@ -10590,19 +10153,6 @@ func private %std__lib__abi__sol__impl_trait_SolDecoder_68ab__set_base__g463e_f8 return; } -func private %std__lib__abi__sol__impl_trait_SolEncoder_19ce__set_base_fa20(v0.objref<@layout_4>, v1.i256) { - block0: - v2.*i256 = alloca i256; - mstore v2 v1 i256; - jump block1; - - block1: - v3.i256 = mload v2 i256; - v6.objref = obj.proj v0 0.i256; - obj.store v6 v3; - return; -} - func private %set__gc9ba(v0.@layout_15, v1.i1) { block0: v2.objref<@layout_15> = obj.alloc @layout_15; @@ -10623,9 +10173,9 @@ func private %set__gc9ba(v0.@layout_15, v1.i1) { return; } -func private %std__lib__evm__storage_map__impl_StorageMap_9f54__set__ga15b_f7f7(v0.@layout_22, v1.i256) { +func private %std__lib__evm__storage_map__impl_StorageMap_9f54__set__ga15b_f7f7(v0.@layout_21, v1.i256) { block0: - v2.objref<@layout_22> = obj.alloc @layout_22; + v2.objref<@layout_21> = obj.alloc @layout_21; v4.objref<@layout_0> = obj.proj v2 0.i256; v5.@layout_0 = extract_value v0 0.i256; v6.objref = obj.proj v4 0.i256; @@ -10640,14 +10190,14 @@ func private %std__lib__evm__storage_map__impl_StorageMap_9f54__set__ga15b_f7f7( block1: v14.i256 = call %std__lib__evm__word__impl_trait_u256_1f9e__to_word_05d2 v1; - v15.@layout_22 = obj.load v2; + v15.@layout_21 = obj.load v2; call %std__lib__evm__storage_map__storagemap_set_word_with_salt__g7bf4_7aa4 v15 1.i256 v14; return; } -func private %std__lib__evm__storage_map__impl_StorageMap_9f54__set__ga15b_f7f7_0(v0.@layout_22, v1.i256) { +func private %std__lib__evm__storage_map__impl_StorageMap_9f54__set__ga15b_f7f7_0(v0.@layout_21, v1.i256) { block0: - v2.objref<@layout_22> = obj.alloc @layout_22; + v2.objref<@layout_21> = obj.alloc @layout_21; v4.objref<@layout_0> = obj.proj v2 0.i256; v5.@layout_0 = extract_value v0 0.i256; v6.objref = obj.proj v4 0.i256; @@ -10662,7 +10212,7 @@ func private %std__lib__evm__storage_map__impl_StorageMap_9f54__set__ga15b_f7f7_ block1: v14.i256 = call %std__lib__evm__word__impl_trait_u256_1f9e__to_word_05d2_0 v1; - v15.@layout_22 = obj.load v2; + v15.@layout_21 = obj.load v2; call %std__lib__evm__storage_map__storagemap_set_word_with_salt__g7bf4_7aa4_0 v15 1.i256 v14; return; } @@ -10736,19 +10286,6 @@ func private %std__lib__abi__sol__impl_trait_SolDecoder_68ab__set_pos__g463e_355 return; } -func private %std__lib__abi__sol__impl_trait_SolEncoder_19ce__set_pos_3857(v0.objref<@layout_4>, v1.i256) { - block0: - v2.*i256 = alloca i256; - mstore v2 v1 i256; - jump block1; - - block1: - v3.i256 = mload v2 i256; - v6.objref = obj.proj v0 1.i256; - obj.store v6 v3; - return; -} - func private %std__lib__abi__sol__impl_trait_SolEncoder_19ce__set_pos_4e67(v0.objref<@layout_4>, v1.i256) { block0: v2.*i256 = alloca i256; @@ -11009,20 +10546,6 @@ func private %std__lib__abi__sol__impl_trait_SolDecoder_68ab__set_pos__g463e_d79 return; } -func private %std__lib__abi__sol__impl_trait_SolDecoder_68ab__set_pos__g463e_e2de(v0.objref<@layout_7>, v1.i256) { - block0: - v2.*i256 = alloca i256; - mstore v2 v1 i256; - jump block1; - - block1: - v3.i256 = mload v2 i256; - v6.objref<@layout_6> = obj.proj v0 0.i256; - v8.objref = obj.proj v6 1.i256; - obj.store v8 v3; - return; -} - func private %std__lib__abi__sol__impl_trait_SolDecoder_68ab__set_pos__g463e_ea2a(v0.objref<@layout_7>, v1.i256) { block0: v2.*i256 = alloca i256; @@ -11054,7 +10577,7 @@ func private %standalone_erc20__erc20__spend_allowance__ga033_1943(v0.@layout_0, block1: v12.@layout_0 = obj.load v4; v13.@layout_0 = obj.load v5; - v14.objref<@layout_22> = obj.alloc @layout_22; + v14.objref<@layout_21> = obj.alloc @layout_21; v15.objref<@layout_0> = obj.proj v14 0.i256; v16.objref = obj.proj v15 0.i256; v17.i256 = extract_value v12 0.i256; @@ -11063,7 +10586,7 @@ func private %standalone_erc20__erc20__spend_allowance__ga033_1943(v0.@layout_0, v20.objref = obj.proj v19 0.i256; v21.i256 = extract_value v13 0.i256; obj.store v20 v21; - v22.@layout_22 = obj.load v14; + v22.@layout_21 = obj.load v14; v23.i256 = call %std__lib__evm__storage_map__impl_StorageMap_9f54__get__ga15b_b5d5 v22; v24.i256 = mload v6 i256; v25.i1 = lt v23 v24; @@ -11071,7 +10594,7 @@ func private %standalone_erc20__erc20__spend_allowance__ga033_1943(v0.@layout_0, call %std__lib__evm__effects__assert_d98e v26; v28.@layout_0 = obj.load v4; v29.@layout_0 = obj.load v5; - v30.objref<@layout_22> = obj.alloc @layout_22; + v30.objref<@layout_21> = obj.alloc @layout_21; v31.objref<@layout_0> = obj.proj v30 0.i256; v32.objref = obj.proj v31 0.i256; v33.i256 = extract_value v28 0.i256; @@ -11080,7 +10603,7 @@ func private %standalone_erc20__erc20__spend_allowance__ga033_1943(v0.@layout_0, v35.objref = obj.proj v34 0.i256; v36.i256 = extract_value v29 0.i256; obj.store v35 v36; - v37.@layout_22 = obj.load v30; + v37.@layout_21 = obj.load v30; v38.i256 = mload v6 i256; (v39.i256, v40.i1) = usubo v23 v38; br v40 block2 block3; @@ -11112,7 +10635,7 @@ func private %standalone_erc20__erc20__spend_allowance__ga033_1943_0(v0.@layout_ block1: v12.@layout_0 = obj.load v4; v13.@layout_0 = obj.load v5; - v14.objref<@layout_22> = obj.alloc @layout_22; + v14.objref<@layout_21> = obj.alloc @layout_21; v15.objref<@layout_0> = obj.proj v14 0.i256; v16.objref = obj.proj v15 0.i256; v17.i256 = extract_value v12 0.i256; @@ -11121,7 +10644,7 @@ func private %standalone_erc20__erc20__spend_allowance__ga033_1943_0(v0.@layout_ v20.objref = obj.proj v19 0.i256; v21.i256 = extract_value v13 0.i256; obj.store v20 v21; - v22.@layout_22 = obj.load v14; + v22.@layout_21 = obj.load v14; v23.i256 = call %std__lib__evm__storage_map__impl_StorageMap_9f54__get__ga15b_b5d5 v22; v24.i256 = mload v6 i256; v25.i1 = lt v23 v24; @@ -11129,7 +10652,7 @@ func private %standalone_erc20__erc20__spend_allowance__ga033_1943_0(v0.@layout_ call %std__lib__evm__effects__assert_d98e v26; v28.@layout_0 = obj.load v4; v29.@layout_0 = obj.load v5; - v30.objref<@layout_22> = obj.alloc @layout_22; + v30.objref<@layout_21> = obj.alloc @layout_21; v31.objref<@layout_0> = obj.proj v30 0.i256; v32.objref = obj.proj v31 0.i256; v33.i256 = extract_value v28 0.i256; @@ -11138,7 +10661,7 @@ func private %standalone_erc20__erc20__spend_allowance__ga033_1943_0(v0.@layout_ v35.objref = obj.proj v34 0.i256; v36.i256 = extract_value v29 0.i256; obj.store v35 v36; - v37.@layout_22 = obj.load v30; + v37.@layout_21 = obj.load v30; v38.i256 = mload v6 i256; (v39.i256, v40.i1) = usubo v23 v38; br v40 block2 block3; @@ -11153,9 +10676,9 @@ func private %standalone_erc20__erc20__spend_allowance__ga033_1943_0(v0.@layout_ return; } -func private %std__lib__evm__storage_map__storagemap_get_word_with_salt__g7bf4_09af(v0.@layout_22, v1.i256) -> i256 { +func private %std__lib__evm__storage_map__storagemap_get_word_with_salt__g7bf4_09af(v0.@layout_21, v1.i256) -> i256 { block0: - v2.objref<@layout_22> = obj.alloc @layout_22; + v2.objref<@layout_21> = obj.alloc @layout_21; v3.*i256 = alloca i256; v5.objref<@layout_0> = obj.proj v2 0.i256; v6.@layout_0 = extract_value v0 0.i256; @@ -11172,15 +10695,15 @@ func private %std__lib__evm__storage_map__storagemap_get_word_with_salt__g7bf4_0 block1: v14.i256 = mload v3 i256; - v15.@layout_22 = obj.load v2; + v15.@layout_21 = obj.load v2; v16.i256 = call %std__lib__evm__storage_map__storagemap_storage_slot_with_salt__g7bf4_e3d6 v15 v14; v17.i256 = evm_sload v16; return v17; } -func private %std__lib__evm__storage_map__storagemap_get_word_with_salt__g7bf4_09af_0(v0.@layout_22, v1.i256) -> i256 { +func private %std__lib__evm__storage_map__storagemap_get_word_with_salt__g7bf4_09af_0(v0.@layout_21, v1.i256) -> i256 { block0: - v2.objref<@layout_22> = obj.alloc @layout_22; + v2.objref<@layout_21> = obj.alloc @layout_21; v3.*i256 = alloca i256; v5.objref<@layout_0> = obj.proj v2 0.i256; v6.@layout_0 = extract_value v0 0.i256; @@ -11197,7 +10720,7 @@ func private %std__lib__evm__storage_map__storagemap_get_word_with_salt__g7bf4_0 block1: v14.i256 = mload v3 i256; - v15.@layout_22 = obj.load v2; + v15.@layout_21 = obj.load v2; v16.i256 = call %std__lib__evm__storage_map__storagemap_storage_slot_with_salt__g7bf4_e3d6_1 v15 v14; v17.i256 = evm_sload v16; return v17; @@ -11262,9 +10785,9 @@ func private %std__lib__evm__storage_map__storagemap_get_word_with_salt__g67a8_7 return v10; } -func private %std__lib__evm__storage_map__storagemap_get_word_with_salt__g7bf4_af75(v0.@layout_22, v1.i256) -> i256 { +func private %std__lib__evm__storage_map__storagemap_get_word_with_salt__g7bf4_af75(v0.@layout_21, v1.i256) -> i256 { block0: - v2.objref<@layout_22> = obj.alloc @layout_22; + v2.objref<@layout_21> = obj.alloc @layout_21; v3.*i256 = alloca i256; v5.objref<@layout_0> = obj.proj v2 0.i256; v6.@layout_0 = extract_value v0 0.i256; @@ -11281,7 +10804,7 @@ func private %std__lib__evm__storage_map__storagemap_get_word_with_salt__g7bf4_a block1: v14.i256 = mload v3 i256; - v15.@layout_22 = obj.load v2; + v15.@layout_21 = obj.load v2; v16.i256 = call %std__lib__evm__storage_map__storagemap_storage_slot_with_salt__g7bf4_2a19 v15 v14; v17.i256 = evm_sload v16; return v17; @@ -11308,9 +10831,9 @@ func private %storagemap_set_word_with_salt__g67a8(v0.@layout_0, v1.i256, v2.i25 return; } -func private %std__lib__evm__storage_map__storagemap_set_word_with_salt__g7bf4_7aa4(v0.@layout_22, v1.i256, v2.i256) { +func private %std__lib__evm__storage_map__storagemap_set_word_with_salt__g7bf4_7aa4(v0.@layout_21, v1.i256, v2.i256) { block0: - v3.objref<@layout_22> = obj.alloc @layout_22; + v3.objref<@layout_21> = obj.alloc @layout_21; v4.*i256 = alloca i256; v5.*i256 = alloca i256; v7.objref<@layout_0> = obj.proj v3 0.i256; @@ -11329,16 +10852,16 @@ func private %std__lib__evm__storage_map__storagemap_set_word_with_salt__g7bf4_7 block1: v16.i256 = mload v4 i256; - v17.@layout_22 = obj.load v3; + v17.@layout_21 = obj.load v3; v18.i256 = call %std__lib__evm__storage_map__storagemap_storage_slot_with_salt__g7bf4_e3d6 v17 v16; v19.i256 = mload v5 i256; evm_sstore v18 v19; return; } -func private %std__lib__evm__storage_map__storagemap_set_word_with_salt__g7bf4_7aa4_0(v0.@layout_22, v1.i256, v2.i256) { +func private %std__lib__evm__storage_map__storagemap_set_word_with_salt__g7bf4_7aa4_0(v0.@layout_21, v1.i256, v2.i256) { block0: - v3.objref<@layout_22> = obj.alloc @layout_22; + v3.objref<@layout_21> = obj.alloc @layout_21; v4.*i256 = alloca i256; v5.*i256 = alloca i256; v7.objref<@layout_0> = obj.proj v3 0.i256; @@ -11357,7 +10880,7 @@ func private %std__lib__evm__storage_map__storagemap_set_word_with_salt__g7bf4_7 block1: v16.i256 = mload v4 i256; - v17.@layout_22 = obj.load v3; + v17.@layout_21 = obj.load v3; v18.i256 = call %std__lib__evm__storage_map__storagemap_storage_slot_with_salt__g7bf4_e3d6_0 v17 v16; v19.i256 = mload v5 i256; evm_sstore v18 v19; @@ -11390,9 +10913,9 @@ func private %storagemap_set_word_with_salt__g9379(v0.@layout_15, v1.i256, v2.i2 return; } -func private %std__lib__evm__storage_map__storagemap_storage_slot_with_salt__g7bf4_2a19(v0.@layout_22, v1.i256) -> i256 { +func private %std__lib__evm__storage_map__storagemap_storage_slot_with_salt__g7bf4_2a19(v0.@layout_21, v1.i256) -> i256 { block0: - v2.objref<@layout_22> = obj.alloc @layout_22; + v2.objref<@layout_21> = obj.alloc @layout_21; v3.*i256 = alloca i256; v5.objref<@layout_0> = obj.proj v2 0.i256; v6.@layout_0 = extract_value v0 0.i256; @@ -11410,7 +10933,7 @@ func private %std__lib__evm__storage_map__storagemap_storage_slot_with_salt__g7b block1: v14.*i8 = evm_malloc 0.i256; v15.i256 = ptr_to_int v14 i256; - v16.@layout_22 = obj.load v2; + v16.@layout_21 = obj.load v2; v17.i256 = call %std__lib__evm__storage_map__impl_trait____9761__write_key__g7528_2c8a v15 v16; (v18.i256, v19.i1) = uaddo v15 v17; br v19 block2 block3; @@ -11538,9 +11061,9 @@ func private %storagemap_storage_slot_with_salt__g9379(v0.@layout_15, v1.i256) - return v29; } -func private %std__lib__evm__storage_map__storagemap_storage_slot_with_salt__g7bf4_e3d6(v0.@layout_22, v1.i256) -> i256 { +func private %std__lib__evm__storage_map__storagemap_storage_slot_with_salt__g7bf4_e3d6(v0.@layout_21, v1.i256) -> i256 { block0: - v2.objref<@layout_22> = obj.alloc @layout_22; + v2.objref<@layout_21> = obj.alloc @layout_21; v3.*i256 = alloca i256; v5.objref<@layout_0> = obj.proj v2 0.i256; v6.@layout_0 = extract_value v0 0.i256; @@ -11558,7 +11081,7 @@ func private %std__lib__evm__storage_map__storagemap_storage_slot_with_salt__g7b block1: v14.*i8 = evm_malloc 0.i256; v15.i256 = ptr_to_int v14 i256; - v16.@layout_22 = obj.load v2; + v16.@layout_21 = obj.load v2; v17.i256 = call %std__lib__evm__storage_map__impl_trait____9761__write_key__g7528_ba59 v15 v16; (v18.i256, v19.i1) = uaddo v15 v17; br v19 block2 block3; @@ -11579,9 +11102,9 @@ func private %std__lib__evm__storage_map__storagemap_storage_slot_with_salt__g7b return v31; } -func private %std__lib__evm__storage_map__storagemap_storage_slot_with_salt__g7bf4_e3d6_0(v0.@layout_22, v1.i256) -> i256 { +func private %std__lib__evm__storage_map__storagemap_storage_slot_with_salt__g7bf4_e3d6_0(v0.@layout_21, v1.i256) -> i256 { block0: - v2.objref<@layout_22> = obj.alloc @layout_22; + v2.objref<@layout_21> = obj.alloc @layout_21; v3.*i256 = alloca i256; v5.objref<@layout_0> = obj.proj v2 0.i256; v6.@layout_0 = extract_value v0 0.i256; @@ -11599,7 +11122,7 @@ func private %std__lib__evm__storage_map__storagemap_storage_slot_with_salt__g7b block1: v14.*i8 = evm_malloc 0.i256; v15.i256 = ptr_to_int v14 i256; - v16.@layout_22 = obj.load v2; + v16.@layout_21 = obj.load v2; v17.i256 = call %std__lib__evm__storage_map__impl_trait____9761__write_key__g7528_ba59_0 v15 v16; (v18.i256, v19.i1) = uaddo v15 v17; br v19 block2 block3; @@ -11620,9 +11143,9 @@ func private %std__lib__evm__storage_map__storagemap_storage_slot_with_salt__g7b return v31; } -func private %std__lib__evm__storage_map__storagemap_storage_slot_with_salt__g7bf4_e3d6_1(v0.@layout_22, v1.i256) -> i256 { +func private %std__lib__evm__storage_map__storagemap_storage_slot_with_salt__g7bf4_e3d6_1(v0.@layout_21, v1.i256) -> i256 { block0: - v2.objref<@layout_22> = obj.alloc @layout_22; + v2.objref<@layout_21> = obj.alloc @layout_21; v3.*i256 = alloca i256; v5.objref<@layout_0> = obj.proj v2 0.i256; v6.@layout_0 = extract_value v0 0.i256; @@ -11640,7 +11163,7 @@ func private %std__lib__evm__storage_map__storagemap_storage_slot_with_salt__g7b block1: v14.*i8 = evm_malloc 0.i256; v15.i256 = ptr_to_int v14 i256; - v16.@layout_22 = obj.load v2; + v16.@layout_21 = obj.load v2; v17.i256 = call %std__lib__evm__storage_map__impl_trait____9761__write_key__g7528_ba59_1 v15 v16; (v18.i256, v19.i1) = uaddo v15 v17; br v19 block2 block3; @@ -11661,21 +11184,6 @@ func private %std__lib__evm__storage_map__storagemap_storage_slot_with_salt__g7b return v31; } -func private %std__lib__abi__sol__impl_trait_Sol_1f5f__store_word_2361(v0.i256, v1.i256) { - block0: - v2.*i256 = alloca i256; - v3.*i256 = alloca i256; - mstore v2 v0 i256; - mstore v3 v1 i256; - jump block1; - - block1: - v4.i256 = mload v2 i256; - v5.i256 = mload v3 i256; - mstore v4 v5 i256; - return; -} - func private %std__lib__abi__sol__impl_trait_Sol_1f5f__store_word_2c7e(v0.i256, v1.i256) { block0: v2.*i256 = alloca i256; @@ -11922,7 +11430,7 @@ func private %standalone_erc20__erc20__transfer__g5c3f_6cc9(v0.@layout_0, v1.@la v54.@layout_0 = obj.load v5; v55.@layout_0 = obj.load v6; v56.i256 = mload v7 i256; - v57.objref<@layout_20> = obj.alloc @layout_20; + v57.objref<@layout_19> = obj.alloc @layout_19; v58.objref<@layout_0> = obj.proj v57 0.i256; v59.objref = obj.proj v58 0.i256; v60.i256 = extract_value v54 0.i256; @@ -11933,7 +11441,7 @@ func private %standalone_erc20__erc20__transfer__g5c3f_6cc9(v0.@layout_0, v1.@la obj.store v63 v64; v66.objref = obj.proj v57 2.i256; obj.store v66 v56; - v67.@layout_20 = obj.load v57; + v67.@layout_19 = obj.load v57; call %emit__g4c3d v4 v67; return; } @@ -12001,7 +11509,7 @@ func private %standalone_erc20__erc20__transfer__g5c3f_c11b(v0.@layout_0, v1.@la v54.@layout_0 = obj.load v5; v55.@layout_0 = obj.load v6; v56.i256 = mload v7 i256; - v57.objref<@layout_20> = obj.alloc @layout_20; + v57.objref<@layout_19> = obj.alloc @layout_19; v58.objref<@layout_0> = obj.proj v57 0.i256; v59.objref = obj.proj v58 0.i256; v60.i256 = extract_value v54 0.i256; @@ -12012,7 +11520,7 @@ func private %standalone_erc20__erc20__transfer__g5c3f_c11b(v0.@layout_0, v1.@la obj.store v63 v64; v66.objref = obj.proj v57 2.i256; obj.store v66 v56; - v67.@layout_20 = obj.load v57; + v67.@layout_19 = obj.load v57; call %emit__g4c3d v4 v67; return; } @@ -12171,28 +11679,6 @@ func private %std__lib__evm__memory_input__impl_trait_MemoryBytes_c1cd__word_at_ return v14; } -func private %std__lib__evm__memory_input__impl_trait_MemoryBytes_c1cd__word_at_3283(v0.@layout_5, v1.i256) -> i256 { - block0: - v2.objref<@layout_5> = obj.alloc @layout_5; - v3.*i256 = alloca i256; - v5.objref = obj.proj v2 0.i256; - v6.i256 = extract_value v0 0.i256; - obj.store v5 v6; - v8.objref = obj.proj v2 1.i256; - v9.i256 = extract_value v0 1.i256; - obj.store v8 v9; - mstore v3 v1 i256; - jump block1; - - block1: - v10.objref = obj.proj v2 0.i256; - v11.i256 = obj.load v10; - v12.i256 = mload v3 i256; - v13.i256 = add v11 v12; - v14.i256 = mload v13 i256; - return v14; -} - func private %std__lib__evm__memory_input__impl_trait_MemoryBytes_c1cd__word_at_348a(v0.@layout_5, v1.i256) -> i256 { block0: v2.objref<@layout_5> = obj.alloc @layout_5; @@ -12281,28 +11767,6 @@ func private %std__lib__evm__memory_input__impl_trait_MemoryBytes_c1cd__word_at_ return v14; } -func private %std__lib__evm__memory_input__impl_trait_MemoryBytes_c1cd__word_at_4b4e(v0.@layout_5, v1.i256) -> i256 { - block0: - v2.objref<@layout_5> = obj.alloc @layout_5; - v3.*i256 = alloca i256; - v5.objref = obj.proj v2 0.i256; - v6.i256 = extract_value v0 0.i256; - obj.store v5 v6; - v8.objref = obj.proj v2 1.i256; - v9.i256 = extract_value v0 1.i256; - obj.store v8 v9; - mstore v3 v1 i256; - jump block1; - - block1: - v10.objref = obj.proj v2 0.i256; - v11.i256 = obj.load v10; - v12.i256 = mload v3 i256; - v13.i256 = add v11 v12; - v14.i256 = mload v13 i256; - return v14; -} - func private %std__lib__evm__memory_input__impl_trait_MemoryBytes_c1cd__word_at_5d2f(v0.@layout_5, v1.i256) -> i256 { block0: v2.objref<@layout_5> = obj.alloc @layout_5; @@ -12871,10 +12335,10 @@ func private %std__lib__evm__storage_map__impl_trait_Address_4d4e__write_key_1cf return v10; } -func private %std__lib__evm__storage_map__impl_trait____9761__write_key__g7528_2c8a(v0.i256, v1.@layout_22) -> i256 { +func private %std__lib__evm__storage_map__impl_trait____9761__write_key__g7528_2c8a(v0.i256, v1.@layout_21) -> i256 { block0: v2.*i256 = alloca i256; - v3.objref<@layout_22> = obj.alloc @layout_22; + v3.objref<@layout_21> = obj.alloc @layout_21; mstore v2 v0 i256; v5.objref<@layout_0> = obj.proj v3 0.i256; v6.@layout_0 = extract_value v1 0.i256; @@ -13042,10 +12506,10 @@ func private %std__lib__evm__storage_map__impl_trait_u256_0dfe__write_key_b1ec(v return 32.i256; } -func private %std__lib__evm__storage_map__impl_trait____9761__write_key__g7528_ba59(v0.i256, v1.@layout_22) -> i256 { +func private %std__lib__evm__storage_map__impl_trait____9761__write_key__g7528_ba59(v0.i256, v1.@layout_21) -> i256 { block0: v2.*i256 = alloca i256; - v3.objref<@layout_22> = obj.alloc @layout_22; + v3.objref<@layout_21> = obj.alloc @layout_21; mstore v2 v0 i256; v5.objref<@layout_0> = obj.proj v3 0.i256; v6.@layout_0 = extract_value v1 0.i256; @@ -13084,10 +12548,10 @@ func private %std__lib__evm__storage_map__impl_trait____9761__write_key__g7528_b return v29; } -func private %std__lib__evm__storage_map__impl_trait____9761__write_key__g7528_ba59_0(v0.i256, v1.@layout_22) -> i256 { +func private %std__lib__evm__storage_map__impl_trait____9761__write_key__g7528_ba59_0(v0.i256, v1.@layout_21) -> i256 { block0: v2.*i256 = alloca i256; - v3.objref<@layout_22> = obj.alloc @layout_22; + v3.objref<@layout_21> = obj.alloc @layout_21; mstore v2 v0 i256; v5.objref<@layout_0> = obj.proj v3 0.i256; v6.@layout_0 = extract_value v1 0.i256; @@ -13126,10 +12590,10 @@ func private %std__lib__evm__storage_map__impl_trait____9761__write_key__g7528_b return v29; } -func private %std__lib__evm__storage_map__impl_trait____9761__write_key__g7528_ba59_1(v0.i256, v1.@layout_22) -> i256 { +func private %std__lib__evm__storage_map__impl_trait____9761__write_key__g7528_ba59_1(v0.i256, v1.@layout_21) -> i256 { block0: v2.*i256 = alloca i256; - v3.objref<@layout_22> = obj.alloc @layout_22; + v3.objref<@layout_21> = obj.alloc @layout_21; mstore v2 v0 i256; v5.objref<@layout_0> = obj.proj v3 0.i256; v6.@layout_0 = extract_value v1 0.i256; @@ -13528,40 +12992,6 @@ func private %std__lib__abi__sol__impl_trait_SolEncoder_19ce__write_word_8727(v0 return; } -func private %std__lib__abi__sol__impl_trait_SolEncoder_19ce__write_word_8eda(v0.objref<@layout_4>, v1.i256) { - block0: - v2.*i256 = alloca i256; - mstore v2 v1 i256; - jump block1; - - block1: - v5.objref = obj.proj v0 1.i256; - v6.i256 = obj.load v5; - v7.i256 = mload v2 i256; - mstore v6 v7 i256; - v10.i256 = add v6 32.i256; - v11.objref = obj.proj v0 1.i256; - obj.store v11 v10; - return; -} - -func private %std__lib__abi__sol__impl_trait_SolEncoder_19ce__write_word_8f67(v0.objref<@layout_4>, v1.i256) { - block0: - v2.*i256 = alloca i256; - mstore v2 v1 i256; - jump block1; - - block1: - v5.objref = obj.proj v0 1.i256; - v6.i256 = obj.load v5; - v7.i256 = mload v2 i256; - mstore v6 v7 i256; - v10.i256 = add v6 32.i256; - v11.objref = obj.proj v0 1.i256; - obj.store v11 v10; - return; -} - func private %std__lib__abi__sol__impl_trait_SolEncoder_19ce__write_word_aa60(v0.objref<@layout_4>, v1.i256) { block0: v2.*i256 = alloca i256; diff --git a/crates/codegen/tests/fixtures/sonatina_ir/high_level_contract.snap b/crates/codegen/tests/fixtures/sonatina_ir/high_level_contract.snap index 6fded11f71..c058a1fd09 100644 --- a/crates/codegen/tests/fixtures/sonatina_ir/high_level_contract.snap +++ b/crates/codegen/tests/fixtures/sonatina_ir/high_level_contract.snap @@ -1,5 +1,6 @@ --- source: crates/codegen/tests/sonatina_ir.rs +assertion_line: 402 expression: output input_file: crates/codegen/tests/fixtures/high_level_contract.fe --- @@ -9,8 +10,6 @@ type @layout_0 = {i256, i256}; type @layout_1 = {@layout_0, i256}; type @layout_2 = {@layout_1, i256}; type @layout_3 = {i256, i256}; -type @layout_4 = {i256, i256}; -type @layout_5 = {i256}; func private %__EchoContract_init(v0.i256, v1.i256, v2.i256) { block0: @@ -54,59 +53,7 @@ func private %__EchoContract_recv_0_2(v0.i256) -> i256 { return v2; } -func private %abi_field_size(v0.i256) -> i256 { - block0: - v1.*i256 = alloca i256; - mstore v1 v0 i256; - jump block1; - - block1: - v2.i256 = mload v1 i256; - v3.i256 = call %core__lib__abi__trait_AbiSize__payload_size__ge513_9950_0 v2; - br 0.i1 block2 block3; - - block2: - (v7.i256, v8.i1) = uaddo 32.i256 v3; - br v8 block5 block6; - - block3: - jump block4; - - block4: - return v3; - - block5: - mstore 0.i256 35408467139433450592217433187231851964531694900788300625387963629091585785856.i256 i256; - mstore 4.i256 17.i256 i256; - evm_revert 0.i256 36.i256; - - block6: - return v7; -} - -func private %abi_single_root_size(v0.i256) -> i256 { - block0: - v1.*i256 = alloca i256; - mstore v1 v0 i256; - jump block1; - - block1: - v2.i256 = mload v1 i256; - v3.i256 = call %abi_field_size v2; - return v3; -} - -func private %std__lib__abi__sol__impl_trait_SolDecoder_68ab__base__g463e_2196(v0.objref<@layout_2>) -> i256 { - block0: - jump block1; - - block1: - v3.objref = obj.proj v0 1.i256; - v4.i256 = obj.load v3; - return v4; -} - -func private %std__lib__abi__sol__impl_trait_SolDecoder_68ab__base__g463e_90a5(v0.objref<@layout_2>) -> i256 { +func private %base(v0.objref<@layout_2>) -> i256 { block0: jump block1; @@ -116,16 +63,6 @@ func private %std__lib__abi__sol__impl_trait_SolDecoder_68ab__base__g463e_90a5(v return v4; } -func private %impl_trait_SolEncoder__base(v0.objref<@layout_3>) -> i256 { - block0: - jump block1; - - block1: - v3.objref = obj.proj v0 0.i256; - v4.i256 = obj.load v3; - return v4; -} - func private %contract_init_abi_EchoContract() { block0: v0.objref<@layout_0> = obj.alloc @layout_0; @@ -185,8 +122,8 @@ func private %contract_init_abi_EchoContract() { v38.objref = obj.proj v1 1.i256; v39.i256 = extract_value v27 1.i256; obj.store v38 v39; - v40.@layout_4 = call %decode_payload__g4770 v1; - v41.objref<@layout_4> = obj.alloc @layout_4; + v40.@layout_3 = call %decode_payload__g4770 v1; + v41.objref<@layout_3> = obj.alloc @layout_3; v42.objref = obj.proj v41 0.i256; v43.i256 = extract_value v40 0.i256; obj.store v42 v43; @@ -266,93 +203,28 @@ func private %contract_recv_abi_EchoContract_1() { obj.store v34 v35; call %impl_trait_Answer__decode_payload__gf196 v1; v37.i256 = call %__EchoContract_recv_0_0; - v38.@layout_4 = call %encode_single_root_alloc v37; - v39.objref<@layout_4> = obj.alloc @layout_4; - v40.objref = obj.proj v39 0.i256; - v41.i256 = extract_value v38 0.i256; - obj.store v40 v41; - v42.objref = obj.proj v39 1.i256; - v43.i256 = extract_value v38 1.i256; - obj.store v42 v43; - v44.objref = obj.proj v39 0.i256; - v45.i256 = obj.load v44; - v46.objref = obj.proj v39 1.i256; - v47.i256 = obj.load v46; - evm_return v45 v47; + mstore 0.i256 v37 i256; + evm_return 0.i256 32.i256; } func private %contract_recv_abi_EchoContract_2() { block0: - v0.objref<@layout_0> = obj.alloc @layout_0; - v1.objref<@layout_2> = obj.alloc @layout_2; jump block1; block1: - v4.i256 = evm_call_value; - v5.i1 = eq v4 0.i256; - v6.i1 = is_zero v5; - br v6 block2 block3; + v2.i256 = evm_call_value; + v3.i1 = eq v2 0.i256; + v4.i1 = is_zero v3; + br v4 block2 block3; block2: evm_revert 0.i256 0.i256; block3: - v8.i256 = evm_calldata_size; - (v10.i256, v11.i1) = usubo v8 4.i256; - br v11 block4 block5; - - block4: - mstore 0.i256 35408467139433450592217433187231851964531694900788300625387963629091585785856.i256 i256; - mstore 4.i256 17.i256 i256; - evm_revert 0.i256 36.i256; - - block5: - v15.*i8 = evm_malloc v10; - v16.i256 = ptr_to_int v15 i256; - evm_calldata_copy v16 4.i256 v10; - v19.objref = obj.proj v0 0.i256; - obj.store v19 v16; - v21.objref = obj.proj v0 1.i256; - obj.store v21 v10; - v22.@layout_0 = obj.load v0; - v23.@layout_2 = call %decoder_new v22; - v24.objref<@layout_1> = obj.proj v1 0.i256; - v25.@layout_1 = extract_value v23 0.i256; - v26.objref<@layout_0> = obj.proj v24 0.i256; - v27.@layout_0 = extract_value v25 0.i256; - v28.objref = obj.proj v26 0.i256; - v29.i256 = extract_value v27 0.i256; - obj.store v28 v29; - v30.objref = obj.proj v26 1.i256; - v31.i256 = extract_value v27 1.i256; - obj.store v30 v31; - v32.objref = obj.proj v24 1.i256; - v33.i256 = extract_value v25 1.i256; - obj.store v32 v33; - v34.objref = obj.proj v1 1.i256; - v35.i256 = extract_value v23 1.i256; - obj.store v34 v35; - v36.@layout_5 = call %impl_trait_Echo__decode_payload__gf196 v1; - v37.objref<@layout_5> = obj.alloc @layout_5; - v38.objref = obj.proj v37 0.i256; - v39.i256 = extract_value v36 0.i256; - obj.store v38 v39; - v40.objref = obj.proj v37 0.i256; - v41.i256 = obj.load v40; - v42.i256 = call %__EchoContract_recv_0_1 v41; - v43.@layout_4 = call %encode_single_root_alloc v42; - v44.objref<@layout_4> = obj.alloc @layout_4; - v45.objref = obj.proj v44 0.i256; - v46.i256 = extract_value v43 0.i256; - obj.store v45 v46; - v47.objref = obj.proj v44 1.i256; - v48.i256 = extract_value v43 1.i256; - obj.store v47 v48; - v49.objref = obj.proj v44 0.i256; - v50.i256 = obj.load v49; - v51.objref = obj.proj v44 1.i256; - v52.i256 = obj.load v51; - evm_return v50 v52; + v6.i256 = evm_calldata_load 4.i256; + v7.i256 = call %__EchoContract_recv_0_1 v6; + mstore 0.i256 v7 i256; + evm_return 0.i256 32.i256; } func private %contract_recv_abi_EchoContract_3() { @@ -408,19 +280,8 @@ func private %contract_recv_abi_EchoContract_3() { obj.store v34 v35; call %impl_trait_GetX__decode_payload__gf196 v1; v37.i256 = call %__EchoContract_recv_0_2 0.i256; - v38.@layout_4 = call %encode_single_root_alloc v37; - v39.objref<@layout_4> = obj.alloc @layout_4; - v40.objref = obj.proj v39 0.i256; - v41.i256 = extract_value v38 0.i256; - obj.store v40 v41; - v42.objref = obj.proj v39 1.i256; - v43.i256 = extract_value v38 1.i256; - obj.store v42 v43; - v44.objref = obj.proj v39 0.i256; - v45.i256 = obj.load v44; - v46.objref = obj.proj v39 1.i256; - v47.i256 = obj.load v46; - evm_return v45 v47; + mstore 0.i256 v37 i256; + evm_return 0.i256 32.i256; } func private %contract_runtime_root_EchoContract() { @@ -449,7 +310,7 @@ func private %contract_runtime_root_EchoContract() { unreachable; } -func private %core__lib__abi__decode_field__g3854_6f45(v0.objref<@layout_2>) -> i256 { +func private %decode_field(v0.objref<@layout_2>) -> i256 { block0: jump block1; @@ -458,8 +319,8 @@ func private %core__lib__abi__decode_field__g3854_6f45(v0.objref<@layout_2>) -> block2: v3.i256 = call %std__lib__abi__sol__impl_trait_SolDecoder_68ab__read_word__g463e_1759 v0; - v4.i256 = call %std__lib__abi__sol__impl_trait_SolDecoder_68ab__base__g463e_2196 v0; - v5.i256 = call %std__lib__abi__sol__impl_trait_SolDecoder_68ab__pos__g463e_f11f v0; + v4.i256 = call %base v0; + v5.i256 = call %pos v0; (v6.i256, v7.i1) = uaddo v4 v3; br v7 block5 block6; @@ -467,7 +328,7 @@ func private %core__lib__abi__decode_field__g3854_6f45(v0.objref<@layout_2>) -> jump block4; block4: - v23.i256 = call %core__lib__abi__impl_trait_u256_85b6__decode_payload__g407e_9510 v0; + v23.i256 = call %decode_payload__g407e v0; return v23; block5: @@ -476,60 +337,15 @@ func private %core__lib__abi__decode_field__g3854_6f45(v0.objref<@layout_2>) -> evm_revert 0.i256 36.i256; block6: - call %std__lib__abi__sol__impl_trait_SolDecoder_68ab__set_base__g463e_3ff5 v0 v6; - v15.i256 = call %std__lib__abi__sol__impl_trait_SolDecoder_68ab__base__g463e_2196 v0; - call %std__lib__abi__sol__impl_trait_SolDecoder_68ab__set_pos__g463e_6dc7 v0 v15; - v17.i256 = call %core__lib__abi__impl_trait_u256_85b6__decode_payload__g407e_9510 v0; - call %std__lib__abi__sol__impl_trait_SolDecoder_68ab__set_base__g463e_3ff5 v0 v4; - call %std__lib__abi__sol__impl_trait_SolDecoder_68ab__set_pos__g463e_6dc7 v0 v5; + call %set_base v0 v6; + v15.i256 = call %base v0; + call %set_pos v0 v15; + v17.i256 = call %decode_payload__g407e v0; + call %set_base v0 v4; + call %set_pos v0 v5; return v17; } -func private %core__lib__abi__decode_field__g3854_ad5b(v0.objref<@layout_2>) -> i256 { - block0: - jump block1; - - block1: - br 0.i1 block2 block3; - - block2: - v3.i256 = call %std__lib__abi__sol__impl_trait_SolDecoder_68ab__read_word__g463e_5e30 v0; - v4.i256 = call %std__lib__abi__sol__impl_trait_SolDecoder_68ab__base__g463e_90a5 v0; - v5.i256 = call %std__lib__abi__sol__impl_trait_SolDecoder_68ab__pos__g463e_21c1 v0; - (v6.i256, v7.i1) = uaddo v4 v3; - br v7 block5 block6; - - block3: - jump block4; - - block4: - v23.i256 = call %core__lib__abi__impl_trait_u256_85b6__decode_payload__g407e_1f61 v0; - return v23; - - block5: - mstore 0.i256 35408467139433450592217433187231851964531694900788300625387963629091585785856.i256 i256; - mstore 4.i256 17.i256 i256; - evm_revert 0.i256 36.i256; - - block6: - call %std__lib__abi__sol__impl_trait_SolDecoder_68ab__set_base__g463e_0c04 v0 v6; - v15.i256 = call %std__lib__abi__sol__impl_trait_SolDecoder_68ab__base__g463e_90a5 v0; - call %std__lib__abi__sol__impl_trait_SolDecoder_68ab__set_pos__g463e_e59d v0 v15; - v17.i256 = call %core__lib__abi__impl_trait_u256_85b6__decode_payload__g407e_1f61 v0; - call %std__lib__abi__sol__impl_trait_SolDecoder_68ab__set_base__g463e_0c04 v0 v4; - call %std__lib__abi__sol__impl_trait_SolDecoder_68ab__set_pos__g463e_e59d v0 v5; - return v17; -} - -func private %core__lib__abi__impl_trait_u256_85b6__decode_payload__g407e_1f61(v0.objref<@layout_2>) -> i256 { - block0: - jump block1; - - block1: - v2.i256 = call %std__lib__abi__sol__impl_trait_SolDecoder_68ab__read_word__g463e_bf2c v0; - return v2; -} - func private %impl_trait_GetX__decode_payload__gf196(v0.objref<@layout_2>) { block0: jump block1; @@ -546,23 +362,23 @@ func private %impl_trait_Answer__decode_payload__gf196(v0.objref<@layout_2>) { return; } -func private %decode_payload__g4770(v0.objref<@layout_2>) -> @layout_4 { +func private %decode_payload__g4770(v0.objref<@layout_2>) -> @layout_3 { block0: jump block1; block1: - v2.i256 = call %core__lib__abi__decode_field__g3854_6f45 v0; - v3.i256 = call %core__lib__abi__decode_field__g3854_6f45 v0; - v4.objref<@layout_4> = obj.alloc @layout_4; + v2.i256 = call %decode_field v0; + v3.i256 = call %decode_field v0; + v4.objref<@layout_3> = obj.alloc @layout_3; v6.objref = obj.proj v4 0.i256; obj.store v6 v2; v8.objref = obj.proj v4 1.i256; obj.store v8 v3; - v9.@layout_4 = obj.load v4; + v9.@layout_3 = obj.load v4; return v9; } -func private %core__lib__abi__impl_trait_u256_85b6__decode_payload__g407e_9510(v0.objref<@layout_2>) -> i256 { +func private %decode_payload__g407e(v0.objref<@layout_2>) -> i256 { block0: jump block1; @@ -571,19 +387,6 @@ func private %core__lib__abi__impl_trait_u256_85b6__decode_payload__g407e_9510(v return v2; } -func private %impl_trait_Echo__decode_payload__gf196(v0.objref<@layout_2>) -> @layout_5 { - block0: - jump block1; - - block1: - v2.i256 = call %core__lib__abi__decode_field__g3854_ad5b v0; - v3.objref<@layout_5> = obj.alloc @layout_5; - v5.objref = obj.proj v3 0.i256; - obj.store v5 v2; - v6.@layout_5 = obj.load v3; - return v6; -} - func private %decoder_new(v0.@layout_0) -> @layout_2 { block0: jump block1; @@ -593,125 +396,6 @@ func private %decoder_new(v0.@layout_0) -> @layout_2 { return v2; } -func private %encode(v0.i256, v1.objref<@layout_3>) { - block0: - jump block1; - - block1: - call %std__lib__abi__sol__impl_trait_SolEncoder_19ce__write_word_d116 v1 v0; - return; -} - -func private %encode_field(v0.i256, v1.objref<@layout_3>, v2.i256) { - block0: - jump block1; - - block1: - br 0.i1 block2 block3; - - block2: - v5.i256 = call %impl_trait_SolEncoder__base v1; - v8.i256 = call %core__lib__abi__trait_AbiSize__payload_size__ge513_9950 v0; - v9.i256 = mload v2 i256; - v10.i256 = sub v9 v5; - call %std__lib__abi__sol__impl_trait_SolEncoder_19ce__write_word_6213 v1 v10; - v12.i256 = call %impl_trait_SolEncoder__pos v1; - v13.i256 = mload v2 i256; - call %impl_trait_SolEncoder__set_base v1 v13; - v15.i256 = mload v2 i256; - call %impl_trait_SolEncoder__set_pos v1 v15; - call %encode v0 v1; - call %impl_trait_SolEncoder__set_base v1 v5; - call %impl_trait_SolEncoder__set_pos v1 v12; - v20.i256 = mload v2 i256; - v21.i256 = add v20 v8; - mstore v2 v21 i256; - return; - - block3: - jump block4; - - block4: - br 1.i1 block5 block6; - - block5: - v24.i256 = call %impl_trait_SolEncoder__pos v1; - call %encode_to_ptr v0 v24; - v28.i256 = add v24 32.i256; - call %impl_trait_SolEncoder__set_pos v1 v28; - return; - - block6: - jump block7; - - block7: - call %encode v0 v1; - return; -} - -func private %encode_single_root(v0.i256, v1.objref<@layout_3>) { - block0: - v2.*i256 = alloca i256; - jump block1; - - block1: - v4.i256 = call %impl_trait_SolEncoder__base v1; - v6.i256 = add v4 32.i256; - mstore v2 v6 i256; - v7.i256 = ptr_to_int v2 i256; - call %encode_field v0 v1 v7; - return; -} - -func private %encode_single_root_alloc(v0.i256) -> @layout_4 { - block0: - jump block1; - - block1: - v2.i256 = call %abi_single_root_size v0; - v3.@layout_3 = call %encoder_new v2; - v4.objref<@layout_3> = obj.alloc @layout_3; - v6.objref = obj.proj v4 0.i256; - v7.i256 = extract_value v3 0.i256; - obj.store v6 v7; - v9.objref = obj.proj v4 1.i256; - v10.i256 = extract_value v3 1.i256; - obj.store v9 v10; - v11.i256 = call %impl_trait_SolEncoder__base v4; - call %encode_single_root v0 v4; - v13.objref<@layout_4> = obj.alloc @layout_4; - v14.objref = obj.proj v13 0.i256; - obj.store v14 v11; - v15.objref = obj.proj v13 1.i256; - obj.store v15 v2; - v16.@layout_4 = obj.load v13; - return v16; -} - -func private %encode_to_ptr(v0.i256, v1.i256) { - block0: - v2.*i256 = alloca i256; - mstore v2 v1 i256; - jump block1; - - block1: - v3.i256 = mload v2 i256; - call %store_word v3 v0; - return; -} - -func private %encoder_new(v0.i256) -> @layout_3 { - block0: - v1.*i256 = alloca i256; - mstore v1 v0 i256; - jump block1; - - block1: - v2.i256 = mload v1 i256; - v3.@layout_3 = call %impl_SolEncoder__new v2; - return v3; -} - func private %std__lib__evm__memory_input__impl_trait_MemoryBytes_c1cd__len_639c(v0.@layout_0) -> i256 { block0: v1.objref<@layout_0> = obj.alloc @layout_0; @@ -729,23 +413,6 @@ func private %std__lib__evm__memory_input__impl_trait_MemoryBytes_c1cd__len_639c return v9; } -func private %std__lib__evm__memory_input__impl_trait_MemoryBytes_c1cd__len_6ee3(v0.@layout_0) -> i256 { - block0: - v1.objref<@layout_0> = obj.alloc @layout_0; - v3.objref = obj.proj v1 0.i256; - v4.i256 = extract_value v0 0.i256; - obj.store v3 v4; - v6.objref = obj.proj v1 1.i256; - v7.i256 = extract_value v0 1.i256; - obj.store v6 v7; - jump block1; - - block1: - v8.objref = obj.proj v1 1.i256; - v9.i256 = obj.load v8; - return v9; -} - func private %std__lib__evm__memory_input__impl_trait_MemoryBytes_c1cd__len_f8c0(v0.@layout_0) -> i256 { block0: v1.objref<@layout_0> = obj.alloc @layout_0; @@ -763,54 +430,6 @@ func private %std__lib__evm__memory_input__impl_trait_MemoryBytes_c1cd__len_f8c0 return v9; } -func private %std__lib__evm__memory_input__impl_trait_MemoryBytes_c1cd__len_fbd3(v0.@layout_0) -> i256 { - block0: - v1.objref<@layout_0> = obj.alloc @layout_0; - v3.objref = obj.proj v1 0.i256; - v4.i256 = extract_value v0 0.i256; - obj.store v3 v4; - v6.objref = obj.proj v1 1.i256; - v7.i256 = extract_value v0 1.i256; - obj.store v6 v7; - jump block1; - - block1: - v8.objref = obj.proj v1 1.i256; - v9.i256 = obj.load v8; - return v9; -} - -func private %impl_SolEncoder__new(v0.i256) -> @layout_3 { - block0: - v1.*i256 = alloca i256; - mstore v1 v0 i256; - jump block1; - - block1: - v2.i256 = mload v1 i256; - v4.i1 = eq v2 0.i256; - br v4 block2 block3; - - block2: - jump block4; - - block3: - v5.i256 = mload v1 i256; - v6.*i8 = evm_malloc v5; - v7.i256 = ptr_to_int v6 i256; - jump block4; - - block4: - v8.i256 = phi (0.i256 block2) (v7 block3); - v9.objref<@layout_3> = obj.alloc @layout_3; - v10.objref = obj.proj v9 0.i256; - obj.store v10 v8; - v12.objref = obj.proj v9 1.i256; - obj.store v12 v8; - v13.@layout_3 = obj.load v9; - return v13; -} - func private %impl_Cursor__new__g463e(v0.@layout_0) -> @layout_1 { block0: jump block1; @@ -855,48 +474,7 @@ func private %impl_SolDecoder__new__g463e(v0.@layout_0) -> @layout_2 { return v16; } -func private %core__lib__abi__trait_AbiSize__payload_size__ge513_9950(v0.i256) -> i256 { - block0: - v1.*i256 = alloca i256; - mstore v1 v0 i256; - jump block1; - - block1: - return 32.i256; -} - -func private %core__lib__abi__trait_AbiSize__payload_size__ge513_9950_0(v0.i256) -> i256 { - block0: - v1.*i256 = alloca i256; - mstore v1 v0 i256; - jump block1; - - block1: - return 32.i256; -} - -func private %std__lib__abi__sol__impl_trait_SolDecoder_68ab__pos__g463e_21c1(v0.objref<@layout_2>) -> i256 { - block0: - jump block1; - - block1: - v3.objref<@layout_1> = obj.proj v0 0.i256; - v5.objref = obj.proj v3 1.i256; - v6.i256 = obj.load v5; - return v6; -} - -func private %impl_trait_SolEncoder__pos(v0.objref<@layout_3>) -> i256 { - block0: - jump block1; - - block1: - v3.objref = obj.proj v0 1.i256; - v4.i256 = obj.load v3; - return v4; -} - -func private %std__lib__abi__sol__impl_trait_SolDecoder_68ab__pos__g463e_f11f(v0.objref<@layout_2>) -> i256 { +func private %pos(v0.objref<@layout_2>) -> i256 { block0: jump block1; @@ -1021,134 +599,7 @@ func private %std__lib__abi__sol__impl_trait_SolDecoder_68ab__read_word__g463e_1 br v24 block2 block5; } -func private %std__lib__abi__sol__impl_trait_SolDecoder_68ab__read_word__g463e_5e30(v0.objref<@layout_2>) -> i256 { - block0: - v1.*i256 = alloca i256; - v2.*i256 = alloca i256; - jump block1; - - block1: - v5.objref<@layout_1> = obj.proj v0 0.i256; - v6.objref<@layout_0> = obj.proj v5 0.i256; - v7.@layout_0 = obj.load v6; - v8.i256 = call %std__lib__evm__memory_input__impl_trait_MemoryBytes_c1cd__len_6ee3 v7; - mstore v1 v8 i256; - v9.objref<@layout_1> = obj.proj v0 0.i256; - v11.objref = obj.proj v9 1.i256; - v12.i256 = obj.load v11; - (v14.i256, v15.i1) = uaddo v12 32.i256; - br v15 block6 block7; - - block2: - evm_revert 0.i256 0.i256; - - block3: - jump block4; - - block4: - v26.objref<@layout_1> = obj.proj v0 0.i256; - v27.objref<@layout_0> = obj.proj v26 0.i256; - v28.@layout_0 = obj.load v27; - v29.objref<@layout_1> = obj.proj v0 0.i256; - v30.objref = obj.proj v29 1.i256; - v31.i256 = obj.load v30; - v32.i256 = call %std__lib__evm__memory_input__impl_trait_MemoryBytes_c1cd__word_at_caf9 v28 v31; - v34.objref<@layout_1> = obj.proj v0 0.i256; - v35.objref = obj.proj v34 1.i256; - obj.store v35 v14; - return v32; - - block5: - v36.i256 = mload v1 i256; - mstore v2 v36 i256; - v38.i256 = mload v2 i256; - v39.i1 = gt v14 v38; - br v39 block2 block3; - - block6: - mstore 0.i256 35408467139433450592217433187231851964531694900788300625387963629091585785856.i256 i256; - mstore 4.i256 17.i256 i256; - evm_revert 0.i256 36.i256; - - block7: - v21.objref<@layout_1> = obj.proj v0 0.i256; - v22.objref = obj.proj v21 1.i256; - v23.i256 = obj.load v22; - v24.i1 = lt v14 v23; - br v24 block2 block5; -} - -func private %std__lib__abi__sol__impl_trait_SolDecoder_68ab__read_word__g463e_bf2c(v0.objref<@layout_2>) -> i256 { - block0: - v1.*i256 = alloca i256; - v2.*i256 = alloca i256; - jump block1; - - block1: - v5.objref<@layout_1> = obj.proj v0 0.i256; - v6.objref<@layout_0> = obj.proj v5 0.i256; - v7.@layout_0 = obj.load v6; - v8.i256 = call %std__lib__evm__memory_input__impl_trait_MemoryBytes_c1cd__len_fbd3 v7; - mstore v1 v8 i256; - v9.objref<@layout_1> = obj.proj v0 0.i256; - v11.objref = obj.proj v9 1.i256; - v12.i256 = obj.load v11; - (v14.i256, v15.i1) = uaddo v12 32.i256; - br v15 block6 block7; - - block2: - evm_revert 0.i256 0.i256; - - block3: - jump block4; - - block4: - v26.objref<@layout_1> = obj.proj v0 0.i256; - v27.objref<@layout_0> = obj.proj v26 0.i256; - v28.@layout_0 = obj.load v27; - v29.objref<@layout_1> = obj.proj v0 0.i256; - v30.objref = obj.proj v29 1.i256; - v31.i256 = obj.load v30; - v32.i256 = call %std__lib__evm__memory_input__impl_trait_MemoryBytes_c1cd__word_at_9b33 v28 v31; - v34.objref<@layout_1> = obj.proj v0 0.i256; - v35.objref = obj.proj v34 1.i256; - obj.store v35 v14; - return v32; - - block5: - v36.i256 = mload v1 i256; - mstore v2 v36 i256; - v38.i256 = mload v2 i256; - v39.i1 = gt v14 v38; - br v39 block2 block3; - - block6: - mstore 0.i256 35408467139433450592217433187231851964531694900788300625387963629091585785856.i256 i256; - mstore 4.i256 17.i256 i256; - evm_revert 0.i256 36.i256; - - block7: - v21.objref<@layout_1> = obj.proj v0 0.i256; - v22.objref = obj.proj v21 1.i256; - v23.i256 = obj.load v22; - v24.i1 = lt v14 v23; - br v24 block2 block5; -} - -func private %std__lib__abi__sol__impl_trait_SolDecoder_68ab__set_base__g463e_0c04(v0.objref<@layout_2>, v1.i256) { - block0: - v2.*i256 = alloca i256; - mstore v2 v1 i256; - jump block1; - - block1: - v3.i256 = mload v2 i256; - v6.objref = obj.proj v0 1.i256; - obj.store v6 v3; - return; -} - -func private %std__lib__abi__sol__impl_trait_SolDecoder_68ab__set_base__g463e_3ff5(v0.objref<@layout_2>, v1.i256) { +func private %set_base(v0.objref<@layout_2>, v1.i256) { block0: v2.*i256 = alloca i256; mstore v2 v1 i256; @@ -1161,34 +612,7 @@ func private %std__lib__abi__sol__impl_trait_SolDecoder_68ab__set_base__g463e_3f return; } -func private %impl_trait_SolEncoder__set_base(v0.objref<@layout_3>, v1.i256) { - block0: - v2.*i256 = alloca i256; - mstore v2 v1 i256; - jump block1; - - block1: - v3.i256 = mload v2 i256; - v6.objref = obj.proj v0 0.i256; - obj.store v6 v3; - return; -} - -func private %std__lib__abi__sol__impl_trait_SolDecoder_68ab__set_pos__g463e_6dc7(v0.objref<@layout_2>, v1.i256) { - block0: - v2.*i256 = alloca i256; - mstore v2 v1 i256; - jump block1; - - block1: - v3.i256 = mload v2 i256; - v6.objref<@layout_1> = obj.proj v0 0.i256; - v8.objref = obj.proj v6 1.i256; - obj.store v8 v3; - return; -} - -func private %std__lib__abi__sol__impl_trait_SolDecoder_68ab__set_pos__g463e_e59d(v0.objref<@layout_2>, v1.i256) { +func private %set_pos(v0.objref<@layout_2>, v1.i256) { block0: v2.*i256 = alloca i256; mstore v2 v1 i256; @@ -1202,34 +626,6 @@ func private %std__lib__abi__sol__impl_trait_SolDecoder_68ab__set_pos__g463e_e59 return; } -func private %impl_trait_SolEncoder__set_pos(v0.objref<@layout_3>, v1.i256) { - block0: - v2.*i256 = alloca i256; - mstore v2 v1 i256; - jump block1; - - block1: - v3.i256 = mload v2 i256; - v6.objref = obj.proj v0 1.i256; - obj.store v6 v3; - return; -} - -func private %store_word(v0.i256, v1.i256) { - block0: - v2.*i256 = alloca i256; - v3.*i256 = alloca i256; - mstore v2 v0 i256; - mstore v3 v1 i256; - jump block1; - - block1: - v4.i256 = mload v2 i256; - v5.i256 = mload v3 i256; - mstore v4 v5 i256; - return; -} - func private %std__lib__evm__memory_input__impl_trait_MemoryBytes_c1cd__word_at_43ea(v0.@layout_0, v1.i256) -> i256 { block0: v2.objref<@layout_0> = obj.alloc @layout_0; @@ -1252,50 +648,6 @@ func private %std__lib__evm__memory_input__impl_trait_MemoryBytes_c1cd__word_at_ return v14; } -func private %std__lib__evm__memory_input__impl_trait_MemoryBytes_c1cd__word_at_9b33(v0.@layout_0, v1.i256) -> i256 { - block0: - v2.objref<@layout_0> = obj.alloc @layout_0; - v3.*i256 = alloca i256; - v5.objref = obj.proj v2 0.i256; - v6.i256 = extract_value v0 0.i256; - obj.store v5 v6; - v8.objref = obj.proj v2 1.i256; - v9.i256 = extract_value v0 1.i256; - obj.store v8 v9; - mstore v3 v1 i256; - jump block1; - - block1: - v10.objref = obj.proj v2 0.i256; - v11.i256 = obj.load v10; - v12.i256 = mload v3 i256; - v13.i256 = add v11 v12; - v14.i256 = mload v13 i256; - return v14; -} - -func private %std__lib__evm__memory_input__impl_trait_MemoryBytes_c1cd__word_at_caf9(v0.@layout_0, v1.i256) -> i256 { - block0: - v2.objref<@layout_0> = obj.alloc @layout_0; - v3.*i256 = alloca i256; - v5.objref = obj.proj v2 0.i256; - v6.i256 = extract_value v0 0.i256; - obj.store v5 v6; - v8.objref = obj.proj v2 1.i256; - v9.i256 = extract_value v0 1.i256; - obj.store v8 v9; - mstore v3 v1 i256; - jump block1; - - block1: - v10.objref = obj.proj v2 0.i256; - v11.i256 = obj.load v10; - v12.i256 = mload v3 i256; - v13.i256 = add v11 v12; - v14.i256 = mload v13 i256; - return v14; -} - func private %std__lib__evm__memory_input__impl_trait_MemoryBytes_c1cd__word_at_d43a(v0.@layout_0, v1.i256) -> i256 { block0: v2.objref<@layout_0> = obj.alloc @layout_0; @@ -1318,40 +670,6 @@ func private %std__lib__evm__memory_input__impl_trait_MemoryBytes_c1cd__word_at_ return v14; } -func private %std__lib__abi__sol__impl_trait_SolEncoder_19ce__write_word_6213(v0.objref<@layout_3>, v1.i256) { - block0: - v2.*i256 = alloca i256; - mstore v2 v1 i256; - jump block1; - - block1: - v5.objref = obj.proj v0 1.i256; - v6.i256 = obj.load v5; - v7.i256 = mload v2 i256; - mstore v6 v7 i256; - v10.i256 = add v6 32.i256; - v11.objref = obj.proj v0 1.i256; - obj.store v11 v10; - return; -} - -func private %std__lib__abi__sol__impl_trait_SolEncoder_19ce__write_word_d116(v0.objref<@layout_3>, v1.i256) { - block0: - v2.*i256 = alloca i256; - mstore v2 v1 i256; - jump block1; - - block1: - v5.objref = obj.proj v0 1.i256; - v6.i256 = obj.load v5; - v7.i256 = mload v2 i256; - mstore v6 v7 i256; - v10.i256 = add v6 32.i256; - v11.objref = obj.proj v0 1.i256; - obj.store v11 v10; - return; -} - object @EchoContract { section init { diff --git a/crates/codegen/tests/fixtures/sonatina_ir/newtype_storage_byplace_effect_arg.snap b/crates/codegen/tests/fixtures/sonatina_ir/newtype_storage_byplace_effect_arg.snap index c44e6355db..9a12982db2 100644 --- a/crates/codegen/tests/fixtures/sonatina_ir/newtype_storage_byplace_effect_arg.snap +++ b/crates/codegen/tests/fixtures/sonatina_ir/newtype_storage_byplace_effect_arg.snap @@ -1,15 +1,14 @@ --- source: crates/codegen/tests/sonatina_ir.rs +assertion_line: 402 expression: output input_file: crates/codegen/tests/fixtures/newtype_storage_byplace_effect_arg.fe --- target = "evm-ethereum-osaka" type @layout_0 = {i256, i256}; -type @layout_1 = {i256, i256}; +type @layout_1 = {@layout_0, i256}; type @layout_2 = {@layout_1, i256}; -type @layout_3 = {@layout_2, i256}; -type @layout_4 = {i256, i256}; func private %__NewtypeByPlaceEffectArg_init() { block0: @@ -40,58 +39,6 @@ func private %__NewtypeByPlaceEffectArg_recv_0_0(v0.i256, v1.i256) -> i256 { return v16; } -func private %abi_field_size(v0.i256) -> i256 { - block0: - v1.*i256 = alloca i256; - mstore v1 v0 i256; - jump block1; - - block1: - v2.i256 = mload v1 i256; - v3.i256 = call %core__lib__abi__trait_AbiSize__payload_size__ge513_a5ce_0 v2; - br 0.i1 block2 block3; - - block2: - (v7.i256, v8.i1) = uaddo 32.i256 v3; - br v8 block5 block6; - - block3: - jump block4; - - block4: - return v3; - - block5: - mstore 0.i256 35408467139433450592217433187231851964531694900788300625387963629091585785856.i256 i256; - mstore 4.i256 17.i256 i256; - evm_revert 0.i256 36.i256; - - block6: - return v7; -} - -func private %abi_single_root_size(v0.i256) -> i256 { - block0: - v1.*i256 = alloca i256; - mstore v1 v0 i256; - jump block1; - - block1: - v2.i256 = mload v1 i256; - v3.i256 = call %abi_field_size v2; - return v3; -} - -func private %base(v0.objref<@layout_0>) -> i256 { - block0: - jump block1; - - block1: - v3.objref = obj.proj v0 0.i256; - v4.i256 = obj.load v3; - return v4; -} - func private %bump(v0.i256) { block0: jump block1; @@ -143,8 +90,8 @@ func private %contract_init_root_NewtypeByPlaceEffectArg() { func private %contract_recv_abi_NewtypeByPlaceEffectArg_1() { block0: - v0.objref<@layout_1> = obj.alloc @layout_1; - v1.objref<@layout_3> = obj.alloc @layout_3; + v0.objref<@layout_0> = obj.alloc @layout_0; + v1.objref<@layout_2> = obj.alloc @layout_2; jump block1; block1: @@ -174,12 +121,12 @@ func private %contract_recv_abi_NewtypeByPlaceEffectArg_1() { obj.store v19 v16; v21.objref = obj.proj v0 1.i256; obj.store v21 v10; - v22.@layout_1 = obj.load v0; - v23.@layout_3 = call %decoder_new v22; - v24.objref<@layout_2> = obj.proj v1 0.i256; - v25.@layout_2 = extract_value v23 0.i256; - v26.objref<@layout_1> = obj.proj v24 0.i256; - v27.@layout_1 = extract_value v25 0.i256; + v22.@layout_0 = obj.load v0; + v23.@layout_2 = call %decoder_new v22; + v24.objref<@layout_1> = obj.proj v1 0.i256; + v25.@layout_1 = extract_value v23 0.i256; + v26.objref<@layout_0> = obj.proj v24 0.i256; + v27.@layout_0 = extract_value v25 0.i256; v28.objref = obj.proj v26 0.i256; v29.i256 = extract_value v27 0.i256; obj.store v28 v29; @@ -194,19 +141,8 @@ func private %contract_recv_abi_NewtypeByPlaceEffectArg_1() { obj.store v34 v35; call %decode_payload v1; v37.i256 = call %__NewtypeByPlaceEffectArg_recv_0_0 1.i256 0.i256; - v38.@layout_4 = call %encode_single_root_alloc v37; - v39.objref<@layout_4> = obj.alloc @layout_4; - v40.objref = obj.proj v39 0.i256; - v41.i256 = extract_value v38 0.i256; - obj.store v40 v41; - v42.objref = obj.proj v39 1.i256; - v43.i256 = extract_value v38 1.i256; - obj.store v42 v43; - v44.objref = obj.proj v39 0.i256; - v45.i256 = obj.load v44; - v46.objref = obj.proj v39 1.i256; - v47.i256 = obj.load v46; - evm_return v45 v47; + mstore 0.i256 v37 i256; + evm_return 0.i256 32.i256; } func private %contract_runtime_root_NewtypeByPlaceEffectArg() { @@ -227,7 +163,7 @@ func private %contract_runtime_root_NewtypeByPlaceEffectArg() { unreachable; } -func private %decode_payload(v0.objref<@layout_3>) { +func private %decode_payload(v0.objref<@layout_2>) { block0: jump block1; @@ -235,144 +171,25 @@ func private %decode_payload(v0.objref<@layout_3>) { return; } -func private %decoder_new(v0.@layout_1) -> @layout_3 { +func private %decoder_new(v0.@layout_0) -> @layout_2 { block0: jump block1; block1: - v2.@layout_3 = call %impl_SolDecoder__new__g463e v0; + v2.@layout_2 = call %impl_SolDecoder__new__g463e v0; return v2; } -func private %encode(v0.i256, v1.objref<@layout_0>) { - block0: - jump block1; - - block1: - call %std__lib__abi__sol__impl_trait_SolEncoder_19ce__write_word_8b2d v1 v0; - return; -} - -func private %encode_field(v0.i256, v1.objref<@layout_0>, v2.i256) { - block0: - jump block1; - - block1: - br 0.i1 block2 block3; - - block2: - v5.i256 = call %base v1; - v8.i256 = call %core__lib__abi__trait_AbiSize__payload_size__ge513_a5ce v0; - v9.i256 = mload v2 i256; - v10.i256 = sub v9 v5; - call %std__lib__abi__sol__impl_trait_SolEncoder_19ce__write_word_a98a v1 v10; - v12.i256 = call %pos v1; - v13.i256 = mload v2 i256; - call %set_base v1 v13; - v15.i256 = mload v2 i256; - call %set_pos v1 v15; - call %encode v0 v1; - call %set_base v1 v5; - call %set_pos v1 v12; - v20.i256 = mload v2 i256; - v21.i256 = add v20 v8; - mstore v2 v21 i256; - return; - - block3: - jump block4; - - block4: - br 1.i1 block5 block6; - - block5: - v24.i256 = call %pos v1; - call %encode_to_ptr v0 v24; - v28.i256 = add v24 32.i256; - call %set_pos v1 v28; - return; - - block6: - jump block7; - - block7: - call %encode v0 v1; - return; -} - -func private %encode_single_root(v0.i256, v1.objref<@layout_0>) { - block0: - v2.*i256 = alloca i256; - jump block1; - - block1: - v4.i256 = call %base v1; - v6.i256 = add v4 32.i256; - mstore v2 v6 i256; - v7.i256 = ptr_to_int v2 i256; - call %encode_field v0 v1 v7; - return; -} - -func private %encode_single_root_alloc(v0.i256) -> @layout_4 { - block0: - jump block1; - - block1: - v2.i256 = call %abi_single_root_size v0; - v3.@layout_0 = call %encoder_new v2; - v4.objref<@layout_0> = obj.alloc @layout_0; - v6.objref = obj.proj v4 0.i256; - v7.i256 = extract_value v3 0.i256; - obj.store v6 v7; - v9.objref = obj.proj v4 1.i256; - v10.i256 = extract_value v3 1.i256; - obj.store v9 v10; - v11.i256 = call %base v4; - call %encode_single_root v0 v4; - v13.objref<@layout_4> = obj.alloc @layout_4; - v14.objref = obj.proj v13 0.i256; - obj.store v14 v11; - v15.objref = obj.proj v13 1.i256; - obj.store v15 v2; - v16.@layout_4 = obj.load v13; - return v16; -} - -func private %encode_to_ptr(v0.i256, v1.i256) { - block0: - v2.*i256 = alloca i256; - mstore v2 v1 i256; - jump block1; - - block1: - v3.i256 = mload v2 i256; - call %store_word v3 v0; - return; -} - -func private %encoder_new(v0.i256) -> @layout_0 { - block0: - v1.*i256 = alloca i256; - mstore v1 v0 i256; - jump block1; - - block1: - v2.i256 = mload v1 i256; - v3.@layout_0 = call %impl_SolEncoder__new v2; - return v3; -} - -func private %impl_SolDecoder__new__g463e(v0.@layout_1) -> @layout_3 { +func private %impl_SolDecoder__new__g463e(v0.@layout_0) -> @layout_2 { block0: jump block1; block1: - v2.@layout_2 = call %impl_Cursor__new__g463e v0; - v4.objref<@layout_3> = obj.alloc @layout_3; - v5.objref<@layout_2> = obj.proj v4 0.i256; - v6.objref<@layout_1> = obj.proj v5 0.i256; - v7.@layout_1 = extract_value v2 0.i256; + v2.@layout_1 = call %impl_Cursor__new__g463e v0; + v4.objref<@layout_2> = obj.alloc @layout_2; + v5.objref<@layout_1> = obj.proj v4 0.i256; + v6.objref<@layout_0> = obj.proj v5 0.i256; + v7.@layout_0 = extract_value v2 0.i256; v8.objref = obj.proj v6 0.i256; v9.i256 = extract_value v7 0.i256; obj.store v8 v9; @@ -384,48 +201,17 @@ func private %impl_SolDecoder__new__g463e(v0.@layout_1) -> @layout_3 { obj.store v13 v14; v15.objref = obj.proj v4 1.i256; obj.store v15 0.i256; - v16.@layout_3 = obj.load v4; + v16.@layout_2 = obj.load v4; return v16; } -func private %impl_SolEncoder__new(v0.i256) -> @layout_0 { +func private %impl_Cursor__new__g463e(v0.@layout_0) -> @layout_1 { block0: - v1.*i256 = alloca i256; - mstore v1 v0 i256; jump block1; block1: - v2.i256 = mload v1 i256; - v4.i1 = eq v2 0.i256; - br v4 block2 block3; - - block2: - jump block4; - - block3: - v5.i256 = mload v1 i256; - v6.*i8 = evm_malloc v5; - v7.i256 = ptr_to_int v6 i256; - jump block4; - - block4: - v8.i256 = phi (0.i256 block2) (v7 block3); - v9.objref<@layout_0> = obj.alloc @layout_0; - v10.objref = obj.proj v9 0.i256; - obj.store v10 v8; - v12.objref = obj.proj v9 1.i256; - obj.store v12 v8; - v13.@layout_0 = obj.load v9; - return v13; -} - -func private %impl_Cursor__new__g463e(v0.@layout_1) -> @layout_2 { - block0: - jump block1; - - block1: - v2.objref<@layout_2> = obj.alloc @layout_2; - v4.objref<@layout_1> = obj.proj v2 0.i256; + v2.objref<@layout_1> = obj.alloc @layout_1; + v4.objref<@layout_0> = obj.proj v2 0.i256; v5.objref = obj.proj v4 0.i256; v6.i256 = extract_value v0 0.i256; obj.store v5 v6; @@ -434,115 +220,10 @@ func private %impl_Cursor__new__g463e(v0.@layout_1) -> @layout_2 { obj.store v8 v9; v10.objref = obj.proj v2 1.i256; obj.store v10 0.i256; - v11.@layout_2 = obj.load v2; + v11.@layout_1 = obj.load v2; return v11; } -func private %core__lib__abi__trait_AbiSize__payload_size__ge513_a5ce(v0.i256) -> i256 { - block0: - v1.*i256 = alloca i256; - mstore v1 v0 i256; - jump block1; - - block1: - return 32.i256; -} - -func private %core__lib__abi__trait_AbiSize__payload_size__ge513_a5ce_0(v0.i256) -> i256 { - block0: - v1.*i256 = alloca i256; - mstore v1 v0 i256; - jump block1; - - block1: - return 32.i256; -} - -func private %pos(v0.objref<@layout_0>) -> i256 { - block0: - jump block1; - - block1: - v3.objref = obj.proj v0 1.i256; - v4.i256 = obj.load v3; - return v4; -} - -func private %set_base(v0.objref<@layout_0>, v1.i256) { - block0: - v2.*i256 = alloca i256; - mstore v2 v1 i256; - jump block1; - - block1: - v3.i256 = mload v2 i256; - v6.objref = obj.proj v0 0.i256; - obj.store v6 v3; - return; -} - -func private %set_pos(v0.objref<@layout_0>, v1.i256) { - block0: - v2.*i256 = alloca i256; - mstore v2 v1 i256; - jump block1; - - block1: - v3.i256 = mload v2 i256; - v6.objref = obj.proj v0 1.i256; - obj.store v6 v3; - return; -} - -func private %store_word(v0.i256, v1.i256) { - block0: - v2.*i256 = alloca i256; - v3.*i256 = alloca i256; - mstore v2 v0 i256; - mstore v3 v1 i256; - jump block1; - - block1: - v4.i256 = mload v2 i256; - v5.i256 = mload v3 i256; - mstore v4 v5 i256; - return; -} - -func private %std__lib__abi__sol__impl_trait_SolEncoder_19ce__write_word_8b2d(v0.objref<@layout_0>, v1.i256) { - block0: - v2.*i256 = alloca i256; - mstore v2 v1 i256; - jump block1; - - block1: - v5.objref = obj.proj v0 1.i256; - v6.i256 = obj.load v5; - v7.i256 = mload v2 i256; - mstore v6 v7 i256; - v10.i256 = add v6 32.i256; - v11.objref = obj.proj v0 1.i256; - obj.store v11 v10; - return; -} - -func private %std__lib__abi__sol__impl_trait_SolEncoder_19ce__write_word_a98a(v0.objref<@layout_0>, v1.i256) { - block0: - v2.*i256 = alloca i256; - mstore v2 v1 i256; - jump block1; - - block1: - v5.objref = obj.proj v0 1.i256; - v6.i256 = obj.load v5; - v7.i256 = mload v2 i256; - mstore v6 v7 i256; - v10.i256 = add v6 32.i256; - v11.objref = obj.proj v0 1.i256; - obj.store v11 v10; - return; -} - object @NewtypeByPlaceEffectArg { section init { diff --git a/crates/codegen/tests/fixtures/sonatina_ir/newtype_storage_field_mut_method_call.snap b/crates/codegen/tests/fixtures/sonatina_ir/newtype_storage_field_mut_method_call.snap index 90c9ea6505..c861cba31e 100644 --- a/crates/codegen/tests/fixtures/sonatina_ir/newtype_storage_field_mut_method_call.snap +++ b/crates/codegen/tests/fixtures/sonatina_ir/newtype_storage_field_mut_method_call.snap @@ -1,15 +1,14 @@ --- source: crates/codegen/tests/sonatina_ir.rs +assertion_line: 402 expression: output input_file: crates/codegen/tests/fixtures/newtype_storage_field_mut_method_call.fe --- target = "evm-ethereum-osaka" type @layout_0 = {i256, i256}; -type @layout_1 = {i256, i256}; +type @layout_1 = {@layout_0, i256}; type @layout_2 = {@layout_1, i256}; -type @layout_3 = {@layout_2, i256}; -type @layout_4 = {i256, i256}; func private %__NewtypeStorageFieldMutMethodCall_init() { block0: @@ -29,58 +28,6 @@ func private %__NewtypeStorageFieldMutMethodCall_recv_0_0(v0.i256) -> i256 { return v3; } -func private %abi_field_size(v0.i256) -> i256 { - block0: - v1.*i256 = alloca i256; - mstore v1 v0 i256; - jump block1; - - block1: - v2.i256 = mload v1 i256; - v3.i256 = call %core__lib__abi__trait_AbiSize__payload_size__ge513_4e75_0 v2; - br 0.i1 block2 block3; - - block2: - (v7.i256, v8.i1) = uaddo 32.i256 v3; - br v8 block5 block6; - - block3: - jump block4; - - block4: - return v3; - - block5: - mstore 0.i256 35408467139433450592217433187231851964531694900788300625387963629091585785856.i256 i256; - mstore 4.i256 17.i256 i256; - evm_revert 0.i256 36.i256; - - block6: - return v7; -} - -func private %abi_single_root_size(v0.i256) -> i256 { - block0: - v1.*i256 = alloca i256; - mstore v1 v0 i256; - jump block1; - - block1: - v2.i256 = mload v1 i256; - v3.i256 = call %abi_field_size v2; - return v3; -} - -func private %base(v0.objref<@layout_0>) -> i256 { - block0: - jump block1; - - block1: - v3.objref = obj.proj v0 0.i256; - v4.i256 = obj.load v3; - return v4; -} - func private %bump(v0.i256) { block0: jump block1; @@ -132,8 +79,8 @@ func private %contract_init_root_NewtypeStorageFieldMutMethodCall() { func private %contract_recv_abi_NewtypeStorageFieldMutMethodCall_1() { block0: - v0.objref<@layout_1> = obj.alloc @layout_1; - v1.objref<@layout_3> = obj.alloc @layout_3; + v0.objref<@layout_0> = obj.alloc @layout_0; + v1.objref<@layout_2> = obj.alloc @layout_2; jump block1; block1: @@ -163,12 +110,12 @@ func private %contract_recv_abi_NewtypeStorageFieldMutMethodCall_1() { obj.store v19 v16; v21.objref = obj.proj v0 1.i256; obj.store v21 v10; - v22.@layout_1 = obj.load v0; - v23.@layout_3 = call %decoder_new v22; - v24.objref<@layout_2> = obj.proj v1 0.i256; - v25.@layout_2 = extract_value v23 0.i256; - v26.objref<@layout_1> = obj.proj v24 0.i256; - v27.@layout_1 = extract_value v25 0.i256; + v22.@layout_0 = obj.load v0; + v23.@layout_2 = call %decoder_new v22; + v24.objref<@layout_1> = obj.proj v1 0.i256; + v25.@layout_1 = extract_value v23 0.i256; + v26.objref<@layout_0> = obj.proj v24 0.i256; + v27.@layout_0 = extract_value v25 0.i256; v28.objref = obj.proj v26 0.i256; v29.i256 = extract_value v27 0.i256; obj.store v28 v29; @@ -183,19 +130,8 @@ func private %contract_recv_abi_NewtypeStorageFieldMutMethodCall_1() { obj.store v34 v35; call %decode_payload v1; v37.i256 = call %__NewtypeStorageFieldMutMethodCall_recv_0_0 1.i256; - v38.@layout_4 = call %encode_single_root_alloc v37; - v39.objref<@layout_4> = obj.alloc @layout_4; - v40.objref = obj.proj v39 0.i256; - v41.i256 = extract_value v38 0.i256; - obj.store v40 v41; - v42.objref = obj.proj v39 1.i256; - v43.i256 = extract_value v38 1.i256; - obj.store v42 v43; - v44.objref = obj.proj v39 0.i256; - v45.i256 = obj.load v44; - v46.objref = obj.proj v39 1.i256; - v47.i256 = obj.load v46; - evm_return v45 v47; + mstore 0.i256 v37 i256; + evm_return 0.i256 32.i256; } func private %contract_runtime_root_NewtypeStorageFieldMutMethodCall() { @@ -216,7 +152,7 @@ func private %contract_runtime_root_NewtypeStorageFieldMutMethodCall() { unreachable; } -func private %decode_payload(v0.objref<@layout_3>) { +func private %decode_payload(v0.objref<@layout_2>) { block0: jump block1; @@ -224,175 +160,25 @@ func private %decode_payload(v0.objref<@layout_3>) { return; } -func private %decoder_new(v0.@layout_1) -> @layout_3 { +func private %decoder_new(v0.@layout_0) -> @layout_2 { block0: jump block1; block1: - v2.@layout_3 = call %impl_SolDecoder__new__g463e v0; + v2.@layout_2 = call %impl_SolDecoder__new__g463e v0; return v2; } -func private %encode(v0.i256, v1.objref<@layout_0>) { - block0: - jump block1; - - block1: - call %std__lib__abi__sol__impl_trait_SolEncoder_19ce__write_word_90ae v1 v0; - return; -} - -func private %encode_field(v0.i256, v1.objref<@layout_0>, v2.i256) { - block0: - jump block1; - - block1: - br 0.i1 block2 block3; - - block2: - v5.i256 = call %base v1; - v8.i256 = call %core__lib__abi__trait_AbiSize__payload_size__ge513_4e75 v0; - v9.i256 = mload v2 i256; - v10.i256 = sub v9 v5; - call %std__lib__abi__sol__impl_trait_SolEncoder_19ce__write_word_9251 v1 v10; - v12.i256 = call %pos v1; - v13.i256 = mload v2 i256; - call %set_base v1 v13; - v15.i256 = mload v2 i256; - call %set_pos v1 v15; - call %encode v0 v1; - call %set_base v1 v5; - call %set_pos v1 v12; - v20.i256 = mload v2 i256; - v21.i256 = add v20 v8; - mstore v2 v21 i256; - return; - - block3: - jump block4; - - block4: - br 1.i1 block5 block6; - - block5: - v24.i256 = call %pos v1; - call %encode_to_ptr v0 v24; - v28.i256 = add v24 32.i256; - call %set_pos v1 v28; - return; - - block6: - jump block7; - - block7: - call %encode v0 v1; - return; -} - -func private %encode_single_root(v0.i256, v1.objref<@layout_0>) { - block0: - v2.*i256 = alloca i256; - jump block1; - - block1: - v4.i256 = call %base v1; - v6.i256 = add v4 32.i256; - mstore v2 v6 i256; - v7.i256 = ptr_to_int v2 i256; - call %encode_field v0 v1 v7; - return; -} - -func private %encode_single_root_alloc(v0.i256) -> @layout_4 { +func private %impl_SolDecoder__new__g463e(v0.@layout_0) -> @layout_2 { block0: jump block1; block1: - v2.i256 = call %abi_single_root_size v0; - v3.@layout_0 = call %encoder_new v2; - v4.objref<@layout_0> = obj.alloc @layout_0; - v6.objref = obj.proj v4 0.i256; - v7.i256 = extract_value v3 0.i256; - obj.store v6 v7; - v9.objref = obj.proj v4 1.i256; - v10.i256 = extract_value v3 1.i256; - obj.store v9 v10; - v11.i256 = call %base v4; - call %encode_single_root v0 v4; - v13.objref<@layout_4> = obj.alloc @layout_4; - v14.objref = obj.proj v13 0.i256; - obj.store v14 v11; - v15.objref = obj.proj v13 1.i256; - obj.store v15 v2; - v16.@layout_4 = obj.load v13; - return v16; -} - -func private %encode_to_ptr(v0.i256, v1.i256) { - block0: - v2.*i256 = alloca i256; - mstore v2 v1 i256; - jump block1; - - block1: - v3.i256 = mload v2 i256; - call %store_word v3 v0; - return; -} - -func private %encoder_new(v0.i256) -> @layout_0 { - block0: - v1.*i256 = alloca i256; - mstore v1 v0 i256; - jump block1; - - block1: - v2.i256 = mload v1 i256; - v3.@layout_0 = call %impl_SolEncoder__new v2; - return v3; -} - -func private %impl_SolEncoder__new(v0.i256) -> @layout_0 { - block0: - v1.*i256 = alloca i256; - mstore v1 v0 i256; - jump block1; - - block1: - v2.i256 = mload v1 i256; - v4.i1 = eq v2 0.i256; - br v4 block2 block3; - - block2: - jump block4; - - block3: - v5.i256 = mload v1 i256; - v6.*i8 = evm_malloc v5; - v7.i256 = ptr_to_int v6 i256; - jump block4; - - block4: - v8.i256 = phi (0.i256 block2) (v7 block3); - v9.objref<@layout_0> = obj.alloc @layout_0; - v10.objref = obj.proj v9 0.i256; - obj.store v10 v8; - v12.objref = obj.proj v9 1.i256; - obj.store v12 v8; - v13.@layout_0 = obj.load v9; - return v13; -} - -func private %impl_SolDecoder__new__g463e(v0.@layout_1) -> @layout_3 { - block0: - jump block1; - - block1: - v2.@layout_2 = call %impl_Cursor__new__g463e v0; - v4.objref<@layout_3> = obj.alloc @layout_3; - v5.objref<@layout_2> = obj.proj v4 0.i256; - v6.objref<@layout_1> = obj.proj v5 0.i256; - v7.@layout_1 = extract_value v2 0.i256; + v2.@layout_1 = call %impl_Cursor__new__g463e v0; + v4.objref<@layout_2> = obj.alloc @layout_2; + v5.objref<@layout_1> = obj.proj v4 0.i256; + v6.objref<@layout_0> = obj.proj v5 0.i256; + v7.@layout_0 = extract_value v2 0.i256; v8.objref = obj.proj v6 0.i256; v9.i256 = extract_value v7 0.i256; obj.store v8 v9; @@ -404,17 +190,17 @@ func private %impl_SolDecoder__new__g463e(v0.@layout_1) -> @layout_3 { obj.store v13 v14; v15.objref = obj.proj v4 1.i256; obj.store v15 0.i256; - v16.@layout_3 = obj.load v4; + v16.@layout_2 = obj.load v4; return v16; } -func private %impl_Cursor__new__g463e(v0.@layout_1) -> @layout_2 { +func private %impl_Cursor__new__g463e(v0.@layout_0) -> @layout_1 { block0: jump block1; block1: - v2.objref<@layout_2> = obj.alloc @layout_2; - v4.objref<@layout_1> = obj.proj v2 0.i256; + v2.objref<@layout_1> = obj.alloc @layout_1; + v4.objref<@layout_0> = obj.proj v2 0.i256; v5.objref = obj.proj v4 0.i256; v6.i256 = extract_value v0 0.i256; obj.store v5 v6; @@ -423,115 +209,10 @@ func private %impl_Cursor__new__g463e(v0.@layout_1) -> @layout_2 { obj.store v8 v9; v10.objref = obj.proj v2 1.i256; obj.store v10 0.i256; - v11.@layout_2 = obj.load v2; + v11.@layout_1 = obj.load v2; return v11; } -func private %core__lib__abi__trait_AbiSize__payload_size__ge513_4e75(v0.i256) -> i256 { - block0: - v1.*i256 = alloca i256; - mstore v1 v0 i256; - jump block1; - - block1: - return 32.i256; -} - -func private %core__lib__abi__trait_AbiSize__payload_size__ge513_4e75_0(v0.i256) -> i256 { - block0: - v1.*i256 = alloca i256; - mstore v1 v0 i256; - jump block1; - - block1: - return 32.i256; -} - -func private %pos(v0.objref<@layout_0>) -> i256 { - block0: - jump block1; - - block1: - v3.objref = obj.proj v0 1.i256; - v4.i256 = obj.load v3; - return v4; -} - -func private %set_base(v0.objref<@layout_0>, v1.i256) { - block0: - v2.*i256 = alloca i256; - mstore v2 v1 i256; - jump block1; - - block1: - v3.i256 = mload v2 i256; - v6.objref = obj.proj v0 0.i256; - obj.store v6 v3; - return; -} - -func private %set_pos(v0.objref<@layout_0>, v1.i256) { - block0: - v2.*i256 = alloca i256; - mstore v2 v1 i256; - jump block1; - - block1: - v3.i256 = mload v2 i256; - v6.objref = obj.proj v0 1.i256; - obj.store v6 v3; - return; -} - -func private %store_word(v0.i256, v1.i256) { - block0: - v2.*i256 = alloca i256; - v3.*i256 = alloca i256; - mstore v2 v0 i256; - mstore v3 v1 i256; - jump block1; - - block1: - v4.i256 = mload v2 i256; - v5.i256 = mload v3 i256; - mstore v4 v5 i256; - return; -} - -func private %std__lib__abi__sol__impl_trait_SolEncoder_19ce__write_word_90ae(v0.objref<@layout_0>, v1.i256) { - block0: - v2.*i256 = alloca i256; - mstore v2 v1 i256; - jump block1; - - block1: - v5.objref = obj.proj v0 1.i256; - v6.i256 = obj.load v5; - v7.i256 = mload v2 i256; - mstore v6 v7 i256; - v10.i256 = add v6 32.i256; - v11.objref = obj.proj v0 1.i256; - obj.store v11 v10; - return; -} - -func private %std__lib__abi__sol__impl_trait_SolEncoder_19ce__write_word_9251(v0.objref<@layout_0>, v1.i256) { - block0: - v2.*i256 = alloca i256; - mstore v2 v1 i256; - jump block1; - - block1: - v5.objref = obj.proj v0 1.i256; - v6.i256 = obj.load v5; - v7.i256 = mload v2 i256; - mstore v6 v7 i256; - v10.i256 = add v6 32.i256; - v11.objref = obj.proj v0 1.i256; - obj.store v11 v10; - return; -} - object @NewtypeStorageFieldMutMethodCall { section init { diff --git a/crates/common/src/diagnostics.rs b/crates/common/src/diagnostics.rs index ea24a851d5..1125c88741 100644 --- a/crates/common/src/diagnostics.rs +++ b/crates/common/src/diagnostics.rs @@ -187,6 +187,7 @@ pub enum DiagnosticPass { MsgLower, EventLower, ErrorLower, + AbiStructLower, ArithmeticAttr, PayableAttr, @@ -215,6 +216,7 @@ impl DiagnosticPass { Self::MsgLower => 9, Self::EventLower => 10, Self::ErrorLower => 16, + Self::AbiStructLower => 17, Self::ArithmeticAttr => 12, Self::PayableAttr => 13, Self::InlineAttr => 14, diff --git a/crates/fe/src/abi.rs b/crates/fe/src/abi.rs index 787eb198ca..17cd2cb3e1 100644 --- a/crates/fe/src/abi.rs +++ b/crates/fe/src/abi.rs @@ -680,6 +680,20 @@ fn semantic_ty_to_abi_desc(db: &DriverDataBase, ty: TyId<'_>) -> Result(db: &'db DriverDataBase, ty: TyId<'db>) -> Option args.first().copied() } +/// Recognise an unbound `core::abi::ArrayView` (I defaulted to `()`) +/// and return `(elem_ty, len_ty)`. +fn core_unbound_array_view_parts<'db>( + db: &'db DriverDataBase, + ty: TyId<'db>, +) -> Option<(TyId<'db>, TyId<'db>)> { + if let Some((_, inner)) = ty.as_capability(db) { + return core_unbound_array_view_parts(db, inner); + } + + let (base, args) = ty.decompose_ty_app(db); + let TyData::TyBase(TyBase::Adt(adt)) = base.data(db) else { + return None; + }; + let adt_ref = adt.adt_ref(db); + let name = adt_ref.name(db)?; + if name.data(db) != "ArrayView" { + return None; + } + if !base + .ingot(db) + .is_some_and(|ingot| ingot.kind(db) == IngotKind::Core) + { + return None; + } + + let elem_ty = args.first().copied()?; + let len_ty = args.get(1).copied()?; + Some((elem_ty, len_ty)) +} + fn is_core_bytes_ty(db: &DriverDataBase, ty: TyId<'_>) -> bool { if let Some((_, inner)) = ty.as_capability(db) { return is_core_bytes_ty(db, inner); @@ -848,6 +893,50 @@ fn is_core_dyn_string_ty(db: &DriverDataBase, ty: TyId<'_>) -> bool { .is_some_and(|ingot| ingot.kind(db) == IngotKind::Core) } +/// Recognise an unbound `core::abi::BytesView` (I defaulted to `()`). +fn is_core_unbound_bytes_view_ty(db: &DriverDataBase, ty: TyId<'_>) -> bool { + if let Some((_, inner)) = ty.as_capability(db) { + return is_core_unbound_bytes_view_ty(db, inner); + } + + let base = ty.base_ty(db); + let TyData::TyBase(TyBase::Adt(adt)) = base.data(db) else { + return false; + }; + let adt_ref = adt.adt_ref(db); + let Some(name) = adt_ref.name(db) else { + return false; + }; + if name.data(db) != "BytesView" { + return false; + } + + base.ingot(db) + .is_some_and(|ingot| ingot.kind(db) == IngotKind::Core) +} + +/// Recognise an unbound `core::abi::StringView` (I defaulted to `()`). +fn is_core_unbound_string_view_ty(db: &DriverDataBase, ty: TyId<'_>) -> bool { + if let Some((_, inner)) = ty.as_capability(db) { + return is_core_unbound_string_view_ty(db, inner); + } + + let base = ty.base_ty(db); + let TyData::TyBase(TyBase::Adt(adt)) = base.data(db) else { + return false; + }; + let adt_ref = adt.adt_ref(db); + let Some(name) = adt_ref.name(db) else { + return false; + }; + if name.data(db) != "StringView" { + return false; + } + + base.ingot(db) + .is_some_and(|ingot| ingot.kind(db) == IngotKind::Core) +} + /// Recognise `std::abi::sol` SolCompat wrapper types like `Uint160` / `Int24` /// and return their Solidity ABI type string (e.g. `"uint160"`, `"int24"`). fn std_sol_compat_abi_type( diff --git a/crates/fe/tests/fixtures/fe_test/abi_dynamic_payload_view.fe b/crates/fe/tests/fixtures/fe_test/abi_dynamic_payload_view.fe new file mode 100644 index 0000000000..ce9f6d1fd4 --- /dev/null +++ b/crates/fe/tests/fixtures/fe_test/abi_dynamic_payload_view.fe @@ -0,0 +1,94 @@ +use std::abi::DynString +use std::evm::{Evm, encode_abi_payload, mem} +use core::abi::BytesView +use std::evm::CallData + +/// Test that BytesView (unbound) works as a msg field type for zero-copy +/// bytes decoding. The handler receives BytesView<()> and binds it to +/// CallData for zero-copy access. +/// +/// Uses the same ABI encoding as Bytes, but the receiver decodes without +/// copying the bytes payload to memory. + +msg DynamicPayloadViewMsg { + #[selector = 0x02] + Check { first: BytesView, marker: u256, second: BytesView } -> u256, +} + +pub contract DynamicPayloadViewReceiver { + recv DynamicPayloadViewMsg { + Check { first, marker, second } -> u256 { + assert(marker == 0xabcdef) + assert(first.len == 33) + assert(second.len == 1) + first.len + second.len + } + } +} + +/// Test the contract by sending raw ABI-encoded calldata that matches +/// the Bytes encoding (since BytesView uses the same wire format). +/// We reuse the DynamicPayloadReceiver from the existing test to +/// produce the calldata, then call our contract with it. + +msg OriginalMsg { + #[selector = 0x02] + Check { first: Bytes, marker: u256, second: Bytes } -> u256, +} + +fn two_word_bytes() -> Bytes +uses (evm: mut Evm) +{ + let payload_len: u256 = 33 + let payload_size: u256 = 96 + let data_ptr = mem::alloc(payload_size) + + evm.mstore(addr: data_ptr, value: payload_len) + evm.mstore( + addr: data_ptr + 32, + value: 0x1111111111111111111111111111111111111111111111111111111111111111, + ) + evm.mstore( + addr: data_ptr + 64, + value: 0x2200000000000000000000000000000000000000000000000000000000000000, + ) + + Bytes { data: data_ptr, len: payload_len, size: payload_size } +} + +fn one_byte_bytes() -> Bytes +uses (evm: mut Evm) +{ + let payload_len: u256 = 1 + let payload_size: u256 = 64 + let data_ptr = mem::alloc(payload_size) + + evm.mstore(addr: data_ptr, value: payload_len) + evm.mstore( + addr: data_ptr + 32, + value: 0x3300000000000000000000000000000000000000000000000000000000000000, + ) + + Bytes { data: data_ptr, len: payload_len, size: payload_size } +} + +#[test] +fn test_msg_dynamic_payload_view_decoding() uses (evm: mut Evm) { + let receiver = evm.create2(value: 0, args: (), salt: 0) + assert(receiver.inner != 0) + + // Send using OriginalMsg (which uses Bytes, encodable) to the receiver + // that decodes as BytesView. Same ABI wire format. + let result: u256 = evm.call( + addr: receiver, + gas: 1000000, + value: 0, + message: OriginalMsg::Check { + first: two_word_bytes(), + marker: 0xabcdef, + second: one_byte_bytes(), + }, + ) + + assert(result == 34) +} diff --git a/crates/fe/tests/fixtures/fe_test/abi_struct_g1point.fe b/crates/fe/tests/fixtures/fe_test/abi_struct_g1point.fe new file mode 100644 index 0000000000..71d032bf30 --- /dev/null +++ b/crates/fe/tests/fixtures/fe_test/abi_struct_g1point.fe @@ -0,0 +1,41 @@ +use std::abi::sol +use std::evm::Evm + +#[abi] +pub struct G1Point { + pub x: u256, + pub y: u256, +} + +msg PointMsg { + #[selector = sol("add((uint256,uint256),(uint256,uint256))")] + Add { a: G1Point, b: G1Point } -> (u256, u256), +} + +pub contract PointAdder { + init() {} + recv PointMsg { + Add { a, b } -> (u256, u256) { + (a.x + b.x, a.y + b.y) + } + } +} + +#[test] +fn test_abi_struct_roundtrip() uses (evm: mut Evm) { + let c = evm.create2(value: 0, args: (), salt: 0) + assert(c.inner != 0) + + let (rx, ry): (u256, u256) = evm.call( + addr: c, + gas: 1000000, + value: 0, + message: PointMsg::Add { + a: G1Point { x: 10, y: 20 }, + b: G1Point { x: 30, y: 40 }, + }, + ) + + assert(rx == 40) + assert(ry == 60) +} diff --git a/crates/hir/src/analysis/analysis_pass.rs b/crates/hir/src/analysis/analysis_pass.rs index 5ebc7e3b92..6c5ed3658b 100644 --- a/crates/hir/src/analysis/analysis_pass.rs +++ b/crates/hir/src/analysis/analysis_pass.rs @@ -1,7 +1,7 @@ use crate::analysis::{HirAnalysisDb, diagnostics::DiagnosticVoucher}; use crate::{ - ArithmeticAttrError, ErrorDiagnostic, EventError, InlineAttrError, LoopUnrollAttrError, - ParserError, PayableError, SelectorError, + AbiStructError, ArithmeticAttrError, ErrorDiagnostic, EventError, InlineAttrError, + LoopUnrollAttrError, ParserError, PayableError, SelectorError, hir_def::{ModuleTree, TopLevelMod}, lower::{parse_file_impl, scope_graph_impl}, }; @@ -131,6 +131,22 @@ impl ModuleAnalysisPass for ErrorLowerPass { } } +/// Analysis pass that collects abi struct lowering diagnostics from `#[abi]` struct desugaring. +pub struct AbiStructLowerPass {} + +impl ModuleAnalysisPass for AbiStructLowerPass { + fn run_on_module<'db>( + &mut self, + db: &'db dyn HirAnalysisDb, + top_mod: TopLevelMod<'db>, + ) -> Vec> { + scope_graph_impl::accumulated::(db, top_mod) + .into_iter() + .map(|d| Box::new(d.clone()) as _) + .collect::>() + } +} + /// Analysis pass that collects arithmetic attribute validation errors. pub struct ArithmeticAttrPass {} diff --git a/crates/hir/src/analysis/diagnostics.rs b/crates/hir/src/analysis/diagnostics.rs index 6aceaa7b77..56f984a0a2 100644 --- a/crates/hir/src/analysis/diagnostics.rs +++ b/crates/hir/src/analysis/diagnostics.rs @@ -712,6 +712,49 @@ impl DiagnosticVoucher for crate::ErrorDiagnostic { } } +impl DiagnosticVoucher for crate::AbiStructError { + fn to_complete(&self, _db: &dyn SpannedHirAnalysisDb) -> CompleteDiagnostic { + use crate::AbiStructErrorKind; + + let primary_span = Span::new(self.file, self.primary_range, SpanKind::Original); + + let (code, message, label, notes) = match &self.kind { + AbiStructErrorKind::AbiAttrOnNonStruct { item_kind } => ( + 1, + format!("`#[abi]` is only valid on structs (found on {item_kind})"), + "`#[abi]` must be placed on a `struct` item".to_string(), + vec!["move `#[abi]` to a struct declaration".to_string()], + ), + AbiStructErrorKind::InvalidAbiAttrForm => ( + 2, + "invalid `#[abi]` attribute form".to_string(), + "expected `#[abi]` without arguments".to_string(), + vec!["remove arguments and use `#[abi]`".to_string()], + ), + AbiStructErrorKind::GenericAbiStruct => ( + 3, + "`#[abi]` structs must be non-generic".to_string(), + "generics are not supported on `#[abi]` structs".to_string(), + vec!["remove generic parameters from the abi struct".to_string()], + ), + }; + + let error_code = GlobalErrorCode::new(DiagnosticPass::AbiStructLower, code); + + CompleteDiagnostic::new( + Severity::Error, + message, + vec![SubDiagnostic::new( + LabelStyle::Primary, + label, + Some(primary_span), + )], + notes, + error_code, + ) + } +} + impl DiagnosticVoucher for crate::InlineAttrError { fn to_complete(&self, _db: &dyn SpannedHirAnalysisDb) -> CompleteDiagnostic { use crate::hir_def::InlineAttrErrorKind; @@ -3045,6 +3088,18 @@ impl DiagnosticVoucher for BodyDiag<'_> { } } + Self::WhereConstPredicateFailed { primary } => CompleteDiagnostic { + severity, + message: "where clause const predicate failed".to_string(), + sub_diagnostics: vec![SubDiagnostic { + style: LabelStyle::Primary, + message: "const predicate evaluated to `false`".to_string(), + span: primary.resolve(db), + }], + notes: Vec::new(), + error_code, + }, + Self::InvalidCast { primary, from, diff --git a/crates/hir/src/analysis/mod.rs b/crates/hir/src/analysis/mod.rs index 9b32b894e9..65d3683292 100644 --- a/crates/hir/src/analysis/mod.rs +++ b/crates/hir/src/analysis/mod.rs @@ -6,8 +6,8 @@ pub mod place; pub mod semantic; use self::analysis_pass::{ - AnalysisPassManager, ArithmeticAttrPass, ErrorLowerPass, EventLowerPass, InlineAttrPass, - LoopUnrollAttrPass, MsgLowerPass, ParsingPass, PayableAttrPass, + AbiStructLowerPass, AnalysisPassManager, ArithmeticAttrPass, ErrorLowerPass, EventLowerPass, + InlineAttrPass, LoopUnrollAttrPass, MsgLowerPass, ParsingPass, PayableAttrPass, }; use self::name_resolution::ImportAnalysisPass; use self::ty::{ @@ -33,6 +33,7 @@ pub fn initialize_analysis_pass() -> AnalysisPassManager { pass_manager.add_module_pass("MsgLower", Box::new(MsgLowerPass {})); pass_manager.add_module_pass("EventLower", Box::new(EventLowerPass {})); pass_manager.add_module_pass("ErrorLower", Box::new(ErrorLowerPass {})); + pass_manager.add_module_pass("AbiStructLower", Box::new(AbiStructLowerPass {})); pass_manager.add_module_pass("InlineAttr", Box::new(InlineAttrPass {})); pass_manager.add_module_pass("LoopUnrollAttr", Box::new(LoopUnrollAttrPass {})); pass_manager.add_module_pass("MsgSelector", Box::new(MsgSelectorAnalysisPass {})); diff --git a/crates/hir/src/analysis/name_resolution/method_selection.rs b/crates/hir/src/analysis/name_resolution/method_selection.rs index fe0c012fb5..ca1924307e 100644 --- a/crates/hir/src/analysis/name_resolution/method_selection.rs +++ b/crates/hir/src/analysis/name_resolution/method_selection.rs @@ -1,4 +1,4 @@ -use crate::core::hir_def::{IdentId, Trait, scope_graph::ScopeId}; +use crate::core::hir_def::{HirIngot, IdentId, Trait, scope_graph::ScopeId}; use common::indexmap::{IndexMap, IndexSet}; use rustc_hash::FxHashSet; use thin_vec::ThinVec; @@ -168,12 +168,24 @@ impl<'db, 'a> CandidateAssembler<'db, 'a> { let receiver_is_ty_param = receiver_is_ty_param_like(self.db, self.receiver.original()); if !receiver_is_ty_param { + // The scope ingot's trait env already includes impls from all its + // transitive dependencies (resolved_external_ingots). Only search + // the receiver type's ingot separately if it is NOT already covered + // by the scope ingot's dependency tree. Otherwise the same impl + // can appear twice (once from each ingot's trait env), causing + // spurious "multiple trait candidates" errors. + let receiver_ingot = self.receiver.original().ingot(self.db); + let receiver_ingot_is_scope_dep = receiver_ingot.is_some_and(|recv_ingot| { + recv_ingot == scope_ingot + || scope_ingot + .resolved_external_ingots(self.db) + .iter() + .any(|(_, dep)| *dep == recv_ingot) + }); + let search_ingots = [ Some(scope_ingot), - self.receiver - .original() - .ingot(self.db) - .filter(|&ingot| ingot != scope_ingot), + receiver_ingot.filter(|_| !receiver_ingot_is_scope_dep), ]; for ingot in search_ingots.into_iter().flatten() { for &imp in impls_for_ty(self.db, ingot, self.receiver.canonical()) { diff --git a/crates/hir/src/analysis/ty/diagnostics.rs b/crates/hir/src/analysis/ty/diagnostics.rs index d19fc43086..17808b1ba3 100644 --- a/crates/hir/src/analysis/ty/diagnostics.rs +++ b/crates/hir/src/analysis/ty/diagnostics.rs @@ -403,6 +403,9 @@ pub enum BodyDiag<'db> { primary: DynLazySpan<'db>, comparison: Option, }, + WhereConstPredicateFailed { + primary: DynLazySpan<'db>, + }, InvalidCast { primary: DynLazySpan<'db>, @@ -778,6 +781,7 @@ impl<'db> BodyDiag<'db> { Self::InvalidCast { .. } => 55, Self::ConstValueMustBeKnown(..) => 64, Self::StaticAssertFailed { .. } => 81, + Self::WhereConstPredicateFailed { .. } => 82, Self::AccessedFieldNotFound { .. } => 15, Self::OpsTraitNotImplemented { .. } => 16, Self::UnsupportedUnaryPlus(..) => 52, diff --git a/crates/hir/src/analysis/ty/ty_check/callable.rs b/crates/hir/src/analysis/ty/ty_check/callable.rs index d56b7ea037..bf5926d208 100644 --- a/crates/hir/src/analysis/ty/ty_check/callable.rs +++ b/crates/hir/src/analysis/ty/ty_check/callable.rs @@ -788,5 +788,65 @@ impl<'db> Callable<'db> { span: span.clone(), }); } + + // Check where-clause const predicates. + self.check_const_predicates(tc, span); + } + + /// Evaluate where-clause const predicates with the call's concrete generic + /// args. If any predicate evaluates to `false`, push a diagnostic. + fn check_const_predicates(&self, tc: &mut TyChecker<'db>, span: DynLazySpan<'db>) { + use crate::analysis::semantic::{SemConstScalar, SemConstValue, eval_body_owner_const}; + use crate::hir_def::{CallableDef, WhereClauseOwner}; + + let db = tc.db; + let func = match self.callable_def { + CallableDef::Func(f) => f, + CallableDef::VariantCtor(_) => return, + }; + + let where_clause = WhereClauseOwner::Func(func).where_clause(db); + let const_preds = where_clause.const_predicates(db); + if const_preds.is_empty() { + return; + } + + // Skip evaluation if any generic arg still contains inference variables. + if self + .generic_args + .iter() + .any(|ty| collect_flags(db, *ty).contains(TyFlags::HAS_VAR)) + { + return; + } + + let bool_ty = TyId::bool(db); + for body in const_preds { + let owner = BodyOwner::AnonConstBody { + body: *body, + expected: bool_ty, + }; + match eval_body_owner_const(db, owner, self.generic_args.clone()) { + Ok(value) => { + let is_false = matches!( + value.value(db), + SemConstValue::Scalar { + value: SemConstScalar::Bool(false), + .. + } + ); + if is_false { + tc.push_diag(BodyDiag::WhereConstPredicateFailed { + primary: span.clone(), + }); + } + } + Err(_) => { + // CTFE evaluation failed -- silently skip for the prototype. + // In a production implementation, we'd emit a more specific + // diagnostic here. + } + } + } } } diff --git a/crates/hir/src/analysis/ty/ty_check/mod.rs b/crates/hir/src/analysis/ty/ty_check/mod.rs index 7c17944585..1a51eaf4e5 100644 --- a/crates/hir/src/analysis/ty/ty_check/mod.rs +++ b/crates/hir/src/analysis/ty/ty_check/mod.rs @@ -71,7 +71,7 @@ use super::{ BorrowKind, CapabilityKind, InvalidCause, Kind, MAX_INLINE_STRING_BYTES, StringFallback, TyId, TyVarSort, }, - ty_lower::{lower_hir_ty, resolve_callable_input_effect_key}, + ty_lower::{collect_generic_params, lower_hir_ty, resolve_callable_input_effect_key}, unify::{InferenceKey, Snapshot, UnificationError, UnificationTable}, }; use crate::analysis::semantic::SemanticCodeRegionRef; @@ -2347,7 +2347,27 @@ impl<'db> TyChecker<'db> { receiver_ty: TyId<'db>, ) -> TyId<'db> { let mut ty = TyId::func(self.db, method); - for &arg in receiver_ty.generic_args(self.db) { + + // Only apply generic args from the receiver that correspond to the + // parent impl's params. The receiver type may carry additional args + // (e.g. defaulted struct params) that must NOT be applied to the + // method's own generics -- those get fresh type variables via + // instantiate_callable_to_term below. + let inherited_count = match method { + CallableDef::Func(func) if func.is_associated_func(self.db) => { + let parent = GenericParamOwner::Func(func).parent(self.db).unwrap(); + collect_generic_params(self.db, parent) + .params(self.db) + .len() + } + _ => receiver_ty.generic_args(self.db).len(), + }; + + for &arg in receiver_ty + .generic_args(self.db) + .iter() + .take(inherited_count) + { if ty.applicable_ty(self.db).is_none() { break; } diff --git a/crates/hir/src/core/hir_def/attr.rs b/crates/hir/src/core/hir_def/attr.rs index 2d7a13f881..e5595abc66 100644 --- a/crates/hir/src/core/hir_def/attr.rs +++ b/crates/hir/src/core/hir_def/attr.rs @@ -18,6 +18,23 @@ impl ArithmeticMode { } } +/// Dispatch strategy requested via `#[dispatch(linear)]` or `#[dispatch(binary_search)]`. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub enum DispatchAttr { + Linear, + BinarySearch, +} + +impl DispatchAttr { + pub fn parse(name: &str) -> Option { + match name { + "linear" => Some(Self::Linear), + "binary_search" => Some(Self::BinarySearch), + _ => None, + } + } +} + #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, salsa::Update)] pub enum InlineHint { Hint, @@ -311,6 +328,24 @@ impl<'db> AttrListId<'db> { }) .last() } + + pub fn dispatch_attr(self, db: &'db dyn HirDb) -> Option { + self.data(db) + .iter() + .filter_map(|attr| { + let Attr::Normal(normal_attr) = attr else { + return None; + }; + let path = normal_attr.path.to_opt()?; + let ident = path.as_ident(db)?; + if ident.data(db) != "dispatch" { + return None; + } + normal_attr.dispatch_attr_arg(db) + }) + .last() + } + pub fn inline_attr(self, db: &'db dyn HirDb) -> Option { match parse_inline_attr_specs(self.data(db).iter().filter_map(|attr| { let Attr::Normal(normal_attr) = attr else { @@ -427,6 +462,21 @@ impl<'db> NormalAttr<'db> { ArithmeticMode::parse(mode) } + pub fn dispatch_attr_arg(&self, db: &'db dyn HirDb) -> Option { + let [arg] = self.args.as_slice() else { + return None; + }; + if arg.has_value { + return None; + } + let name = arg + .key + .to_opt() + .and_then(|path| path.as_ident(db)) + .map(|ident| ident.data(db).as_str())?; + DispatchAttr::parse(name) + } + pub(crate) fn keyword_attr_spec(&self, db: &'db dyn HirDb) -> KeywordAttrSpec { KeywordAttrSpec { has_value: self.has_value, diff --git a/crates/hir/src/core/hir_def/item.rs b/crates/hir/src/core/hir_def/item.rs index ace967a509..8afdeb8a2c 100644 --- a/crates/hir/src/core/hir_def/item.rs +++ b/crates/hir/src/core/hir_def/item.rs @@ -1670,6 +1670,7 @@ pub enum TrackedItemVariant<'db> { StaticAssertCondition, StaticAssertComparisonLhs, StaticAssertComparisonRhs, + WhereConstPredicate, Joined(Box, Box), } impl TrackedItemVariant<'_> { diff --git a/crates/hir/src/core/hir_def/params.rs b/crates/hir/src/core/hir_def/params.rs index 41b1bac296..8dc76e6235 100644 --- a/crates/hir/src/core/hir_def/params.rs +++ b/crates/hir/src/core/hir_def/params.rs @@ -108,6 +108,8 @@ pub struct FuncParamListId<'db> { pub struct WhereClauseId<'db> { #[return_ref] pub data: Vec>, + #[return_ref] + pub const_predicates: Vec>, } #[derive(Debug, Clone, PartialEq, Eq, Hash, derive_more::From)] diff --git a/crates/hir/src/core/lower/abi_struct.rs b/crates/hir/src/core/lower/abi_struct.rs new file mode 100644 index 0000000000..bc0c0551f7 --- /dev/null +++ b/crates/hir/src/core/lower/abi_struct.rs @@ -0,0 +1,363 @@ +use parser::ast::{self, prelude::*}; +use salsa::Accumulator as _; + +use super::{ + FileLowerCtxt, + attr::{has_named_attr, lower_attrs_without_named, named_attr_specs}, + hir_builder::HirBuilder, + msg::{ + build_head_size_body_expr, create_direct_encode_assoc_const, create_head_size_assoc_const, + create_is_dynamic_assoc_const, create_payload_size_func, + }, +}; +use crate::{ + hir_def::{ + ArithBinOp, AttrListId, BinOp, Expr, FieldDef, FieldDefListId, FieldIndex, FuncModifiers, + GenericParamListId, IdentId, Partial, Pat, PathId, Stmt, Struct, TrackedItemVariant, + TypeId, TypeKind, Visibility, + }, + span::AbiStructDesugared, +}; + +/// Diagnostics accumulated during `#[abi]` struct lowering / validation. +#[salsa::accumulator] +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct AbiStructError { + pub kind: AbiStructErrorKind, + pub file: common::file::File, + pub primary_range: parser::TextRange, + pub struct_name: Option, +} + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub enum AbiStructErrorKind { + AbiAttrOnNonStruct { item_kind: &'static str }, + InvalidAbiAttrForm, + GenericAbiStruct, +} + +pub(super) fn is_abi_struct(ast: &ast::Struct) -> bool { + has_named_attr(ast.attr_list(), "abi") +} + +pub(super) fn report_abi_attr_on_non_struct_item<'db>( + ctxt: &mut FileLowerCtxt<'db>, + attrs: Option, + item_kind: &'static str, +) { + let db = ctxt.db(); + let file = ctxt.top_mod().file(db); + + for attr in named_attr_specs(attrs, "abi") { + AbiStructError { + kind: AbiStructErrorKind::AbiAttrOnNonStruct { item_kind }, + file, + primary_range: attr.range, + struct_name: None, + } + .accumulate(db); + } +} + +pub(super) fn lower_abi_struct<'db>( + ctxt: &mut FileLowerCtxt<'db>, + ast: ast::Struct, +) -> Struct<'db> { + let db = ctxt.db(); + let file = ctxt.top_mod().file(db); + + let abi_desugared = AbiStructDesugared { + abi_struct: parser::ast::AstPtr::new(&ast), + }; + let mut builder = HirBuilder::new(ctxt, abi_desugared); + + let struct_name_token = ast.name(); + let struct_name = struct_name_token.as_ref().map(|n| n.text().to_string()); + + // Strip #[abi] attribute, validate it is bare + let stripped_abi_attr = lower_attrs_without_named(builder.ctxt(), ast.attr_list(), "abi"); + let attributes = stripped_abi_attr.retained; + if let Some(attr) = stripped_abi_attr + .removed + .iter() + .find(|attr| !attr.is_bare()) + { + AbiStructError { + kind: AbiStructErrorKind::InvalidAbiAttrForm, + file, + primary_range: attr.range, + struct_name: struct_name.clone(), + } + .accumulate(db); + } + + let vis = super::lower_visibility(&ast); + let generic_params = GenericParamListId::lower_ast_opt(builder.ctxt(), ast.generic_params()); + if !generic_params.data(db).is_empty() { + let range = ast + .generic_params() + .map(|g| g.syntax().text_range()) + .unwrap_or_else(|| ast.syntax().text_range()); + AbiStructError { + kind: AbiStructErrorKind::GenericAbiStruct, + file, + primary_range: range, + struct_name: struct_name.clone(), + } + .accumulate(db); + } + + let where_clause = + crate::hir_def::WhereClauseId::lower_ast_opt(builder.ctxt(), ast.where_clause()); + + let parsed_fields = parse_abi_struct_fields(builder.ctxt(), &ast); + + let fields_hir = FieldDefListId::new(db, parsed_fields.hir_fields); + + let name_ident = IdentId::lower_token_partial(builder.ctxt(), struct_name_token); + + let struct_ = builder.struct_item( + name_ident, + attributes, + vis, + generic_params, + where_clause, + fields_hir, + ); + + // Only generate trait impls when the struct is well-formed + if !parsed_fields.is_valid { + return struct_; + } + if !generic_params.data(db).is_empty() { + return struct_; + } + + let Some(struct_name_ident) = name_ident.to_opt() else { + return struct_; + }; + let self_ty = TypeId::new( + db, + TypeKind::Path(Partial::Present(PathId::from_ident(db, struct_name_ident))), + ); + + let field_specs = parsed_fields.field_specs.clone(); + + // Generate impl AbiSize + lower_abi_struct_abi_size_impl(&mut builder, self_ty, &field_specs); + + // Generate impl Encode + lower_abi_struct_encode_impl(&mut builder, self_ty, &field_specs); + + // Generate impl Decode + lower_abi_struct_decode_impl(&mut builder, self_ty, &field_specs); + + struct_ +} + +struct ParsedAbiStructFields<'db> { + hir_fields: Vec>, + field_specs: Vec<(IdentId<'db>, TypeId<'db>)>, + is_valid: bool, +} + +fn parse_abi_struct_fields<'db>( + ctxt: &mut FileLowerCtxt<'db>, + ast: &ast::Struct, +) -> ParsedAbiStructFields<'db> { + let mut hir_fields = Vec::new(); + let mut field_specs = Vec::new(); + let mut is_valid = true; + + let Some(fields) = ast.fields() else { + return ParsedAbiStructFields { + hir_fields, + field_specs, + is_valid, + }; + }; + + for field in fields { + let attrs = AttrListId::lower_ast_opt(ctxt, field.attr_list()); + let name_ident = IdentId::lower_token_partial(ctxt, field.name()); + let ty_ref = TypeId::lower_ast_partial(ctxt, field.ty()); + let vis = super::lower_field_visibility(&field); + + hir_fields.push(FieldDef::new(attrs, name_ident, ty_ref, vis)); + + let (Some(name_ident), Some(ty)) = (name_ident.to_opt(), ty_ref.to_opt()) else { + is_valid = false; + continue; + }; + + field_specs.push((name_ident, ty)); + } + + ParsedAbiStructFields { + hir_fields, + field_specs, + is_valid, + } +} + +fn lower_abi_struct_abi_size_impl<'db>( + builder: &mut HirBuilder<'_, 'db, AbiStructDesugared>, + self_ty: TypeId<'db>, + field_specs: &[(IdentId<'db>, TypeId<'db>)], +) { + let db = builder.db(); + let roots = builder.roots(); + let trait_path = PathId::from_ident(db, roots.core) + .push_str(db, "abi") + .push_str(db, "AbiSize"); + let trait_ref = Partial::Present(crate::hir_def::TraitRefId::new( + db, + Partial::Present(trait_path), + )); + let ty = Partial::Present(self_ty); + let impl_trait_idx = builder.ctxt().next_impl_trait_idx(); + builder.with_item_scope( + TrackedItemVariant::ImplTrait(impl_trait_idx), + |builder, id| { + let consts = vec![ + create_head_size_assoc_const(builder, field_specs), + create_is_dynamic_assoc_const(builder, field_specs), + ]; + let impl_trait = + builder.new_impl_trait(id, trait_ref, ty, vec![], consts, builder.origin()); + create_payload_size_func(builder, field_specs); + impl_trait + }, + ); +} + +fn lower_abi_struct_encode_impl<'db>( + builder: &mut HirBuilder<'_, 'db, AbiStructDesugared>, + self_ty: TypeId<'db>, + field_specs: &[(IdentId<'db>, TypeId<'db>)], +) { + let field_specs = field_specs.to_vec(); + + let impl_trait_idx = builder.ctxt().next_impl_trait_idx(); + let trait_ref = Partial::Present(builder.core_abi_trait_ref_sol("Encode")); + let ty = Partial::Present(self_ty); + builder.with_item_scope( + TrackedItemVariant::ImplTrait(impl_trait_idx), + |builder, id| { + let direct_encode_const = create_direct_encode_assoc_const(builder, &field_specs); + let impl_trait = builder.new_impl_trait( + id, + trait_ref, + ty, + vec![], + vec![direct_encode_const], + builder.origin(), + ); + + // encode() method + let abi_encoder_trait_ref = builder.core_abi_trait_ref_sol("AbiEncoder"); + let (e_generic_params, e_ty) = + builder.type_param_with_trait_bound("E", abi_encoder_trait_ref); + + let encoder_ident = builder.ident("e"); + let params = builder.params([ + builder.param_own_self(), + builder.param_mut_underscore_named(encoder_ident, e_ty), + ]); + + builder.func_generic( + "encode", + e_generic_params, + params, + None, + FuncModifiers::new(Visibility::Private, false, false, false), + |body| { + body.encode_fields(&field_specs, encoder_ident, e_ty); + }, + ); + + // encode_to_ptr() method + let ptr_ident = builder.ident("ptr"); + let ptr_ty = builder.ty_ident(builder.ident("u256")); + let ptr_param = builder.param_underscore_named(ptr_ident, ptr_ty); + let params = builder.params([builder.param_own_self(), ptr_param]); + let encode_to_ptr_ident = builder.ident("encode_to_ptr"); + + builder.func_with_body( + encode_to_ptr_ident, + builder.empty_generic_params(), + params, + None, + FuncModifiers::new(Visibility::Private, false, false, false), + |body| { + let db = body.db(); + let self_expr = body.path_expr(PathId::from_ident(db, IdentId::make_self(db))); + let mut field_ptr_ident = ptr_ident; + + for (index, (field_name, field_ty)) in field_specs.iter().copied().enumerate() { + let receiver = body.push_expr(Expr::Field( + self_expr, + Partial::Present(FieldIndex::Ident(field_name)), + )); + let field_ptr = body.ident_expr(field_ptr_ident); + let call = + body.method_call_expr(receiver, encode_to_ptr_ident, vec![field_ptr]); + body.emit_expr_stmt(call); + + if index + 1 != field_specs.len() { + let next_ptr_ident = IdentId::new(db, format!("__field_ptr{index}")); + let current_ptr = body.ident_expr(field_ptr_ident); + let field_size = build_head_size_body_expr(body, field_ty); + let next_ptr = body.push_expr(Expr::Bin( + current_ptr, + field_size, + BinOp::Arith(ArithBinOp::Add), + )); + let next_ptr_pat = body.push_pat(Pat::Path( + Partial::Present(PathId::from_ident(db, next_ptr_ident)), + false, + )); + body.emit_stmt(Stmt::Let(next_ptr_pat, None, Some(next_ptr))); + field_ptr_ident = next_ptr_ident; + } + } + }, + ); + impl_trait + }, + ); +} + +fn lower_abi_struct_decode_impl<'db>( + builder: &mut HirBuilder<'_, 'db, AbiStructDesugared>, + self_ty: TypeId<'db>, + field_specs: &[(IdentId<'db>, TypeId<'db>)], +) { + let fields = field_specs.to_vec(); + let field_names: Vec<_> = fields.iter().map(|(name, _)| *name).collect(); + + let trait_ref = builder.core_abi_trait_ref_sol("Decode"); + + builder.impl_trait(trait_ref, self_ty, |builder| { + let abi_decoder_trait_ref = builder.core_abi_trait_ref_sol("AbiDecoder"); + let (d_generic_params, d_ty) = + builder.type_param_with_trait_bound("D", abi_decoder_trait_ref); + + let decoder_ident = builder.ident("d"); + let params = builder.params([builder.param_mut_underscore_named(decoder_ident, d_ty)]); + + builder.func_generic( + "decode_payload", + d_generic_params, + params, + Some(builder.self_ty()), + FuncModifiers::new(Visibility::Private, false, false, false), + |body| { + for (name, ty) in fields.iter().copied() { + body.decode_into(name, ty, d_ty); + } + body.return_record_self(&field_names); + }, + ); + }); +} diff --git a/crates/hir/src/core/lower/hir_builder.rs b/crates/hir/src/core/lower/hir_builder.rs index 1c3be3a505..88fac24a9e 100644 --- a/crates/hir/src/core/lower/hir_builder.rs +++ b/crates/hir/src/core/lower/hir_builder.rs @@ -113,7 +113,7 @@ where } pub(super) fn empty_where_clause(&self) -> WhereClauseId<'db> { - WhereClauseId::new(self.db(), vec![]) + WhereClauseId::new(self.db(), vec![], vec![]) } pub(super) fn empty_effect_params(&self) -> EffectParamListId<'db> { diff --git a/crates/hir/src/core/lower/item.rs b/crates/hir/src/core/lower/item.rs index a42132a4b0..fe9a47fcc8 100644 --- a/crates/hir/src/core/lower/item.rs +++ b/crates/hir/src/core/lower/item.rs @@ -1,7 +1,7 @@ use parser::ast::{self, WhereClauseOwner as _, prelude::*}; use salsa::Accumulator as _; -use super::{FileLowerCtxt, attr::named_attr_specs}; +use super::{FileLowerCtxt, abi_struct, attr::named_attr_specs}; use crate::{ hir_def::{ AttrListId, Body, BodyKind, CompBinOp, EffectParamListId, FuncParamListId, @@ -69,6 +69,7 @@ impl<'db> ItemKind<'db> { super::arithmetic::report_invalid_mod_arithmetic_attrs(ctxt, mod_.attr_list()); super::event::report_event_attr_on_non_struct_item(ctxt, mod_.attr_list(), "mod"); super::error::report_error_attr_on_non_struct_item(ctxt, mod_.attr_list(), "mod"); + abi_struct::report_abi_attr_on_non_struct_item(ctxt, mod_.attr_list(), "mod"); super::payable::report_payable_attr_on_unsupported_item( ctxt, mod_.attr_list(), @@ -80,6 +81,7 @@ impl<'db> ItemKind<'db> { super::arithmetic::report_invalid_function_arithmetic_attrs(ctxt, &fn_); super::event::report_event_attr_on_non_struct_item(ctxt, fn_.attr_list(), "fn"); super::error::report_error_attr_on_non_struct_item(ctxt, fn_.attr_list(), "fn"); + abi_struct::report_abi_attr_on_non_struct_item(ctxt, fn_.attr_list(), "fn"); super::payable::report_payable_attr_on_unsupported_item( ctxt, fn_.attr_list(), @@ -116,6 +118,11 @@ impl<'db> ItemKind<'db> { contract.attr_list(), "contract", ); + abi_struct::report_abi_attr_on_non_struct_item( + ctxt, + contract.attr_list(), + "contract", + ); super::payable::report_payable_attr_on_unsupported_item( ctxt, contract.attr_list(), @@ -131,6 +138,7 @@ impl<'db> ItemKind<'db> { ); super::event::report_event_attr_on_non_struct_item(ctxt, enum_.attr_list(), "enum"); super::error::report_error_attr_on_non_struct_item(ctxt, enum_.attr_list(), "enum"); + abi_struct::report_abi_attr_on_non_struct_item(ctxt, enum_.attr_list(), "enum"); super::payable::report_payable_attr_on_unsupported_item( ctxt, enum_.attr_list(), @@ -146,6 +154,7 @@ impl<'db> ItemKind<'db> { ); super::event::report_event_attr_on_non_struct_item(ctxt, msg.attr_list(), "msg"); super::error::report_error_attr_on_non_struct_item(ctxt, msg.attr_list(), "msg"); + abi_struct::report_abi_attr_on_non_struct_item(ctxt, msg.attr_list(), "msg"); super::payable::report_payable_attr_on_unsupported_item( ctxt, msg.attr_list(), @@ -169,6 +178,11 @@ impl<'db> ItemKind<'db> { alias.attr_list(), "type alias", ); + abi_struct::report_abi_attr_on_non_struct_item( + ctxt, + alias.attr_list(), + "type alias", + ); super::payable::report_payable_attr_on_unsupported_item( ctxt, alias.attr_list(), @@ -184,6 +198,7 @@ impl<'db> ItemKind<'db> { ); super::event::report_event_attr_on_non_struct_item(ctxt, impl_.attr_list(), "impl"); super::error::report_error_attr_on_non_struct_item(ctxt, impl_.attr_list(), "impl"); + abi_struct::report_abi_attr_on_non_struct_item(ctxt, impl_.attr_list(), "impl"); super::payable::report_payable_attr_on_unsupported_item( ctxt, impl_.attr_list(), @@ -207,6 +222,7 @@ impl<'db> ItemKind<'db> { trait_.attr_list(), "trait", ); + abi_struct::report_abi_attr_on_non_struct_item(ctxt, trait_.attr_list(), "trait"); super::payable::report_payable_attr_on_unsupported_item( ctxt, trait_.attr_list(), @@ -230,6 +246,11 @@ impl<'db> ItemKind<'db> { impl_trait.attr_list(), "impl trait", ); + abi_struct::report_abi_attr_on_non_struct_item( + ctxt, + impl_trait.attr_list(), + "impl trait", + ); super::payable::report_payable_attr_on_unsupported_item( ctxt, impl_trait.attr_list(), @@ -253,6 +274,7 @@ impl<'db> ItemKind<'db> { const_.attr_list(), "const", ); + abi_struct::report_abi_attr_on_non_struct_item(ctxt, const_.attr_list(), "const"); super::payable::report_payable_attr_on_unsupported_item( ctxt, const_.attr_list(), @@ -276,6 +298,11 @@ impl<'db> ItemKind<'db> { assert_.attr_list(), "static assertion", ); + abi_struct::report_abi_attr_on_non_struct_item( + ctxt, + assert_.attr_list(), + "static assertion", + ); super::payable::report_payable_attr_on_unsupported_item( ctxt, assert_.attr_list(), @@ -291,6 +318,7 @@ impl<'db> ItemKind<'db> { ); super::event::report_event_attr_on_non_struct_item(ctxt, use_.attr_list(), "use"); super::error::report_error_attr_on_non_struct_item(ctxt, use_.attr_list(), "use"); + abi_struct::report_abi_attr_on_non_struct_item(ctxt, use_.attr_list(), "use"); super::payable::report_payable_attr_on_unsupported_item( ctxt, use_.attr_list(), @@ -314,6 +342,7 @@ impl<'db> ItemKind<'db> { extern_.attr_list(), "extern", ); + abi_struct::report_abi_attr_on_non_struct_item(ctxt, extern_.attr_list(), "extern"); super::payable::report_payable_attr_on_unsupported_item( ctxt, extern_.attr_list(), @@ -336,6 +365,11 @@ impl<'db> ItemKind<'db> { fn_.attr_list(), "extern fn", ); + abi_struct::report_abi_attr_on_non_struct_item( + ctxt, + fn_.attr_list(), + "extern fn", + ); super::payable::report_payable_attr_on_unsupported_item( ctxt, fn_.attr_list(), @@ -489,6 +523,7 @@ impl<'db> Struct<'db> { pub(super) fn lower_ast(ctxt: &mut FileLowerCtxt<'db>, ast: ast::Struct) -> Self { let is_event_struct = super::event::is_event_struct(&ast); let is_error_struct = super::error::is_error_struct(&ast); + let is_abi_struct = abi_struct::is_abi_struct(&ast); if is_event_struct && is_error_struct { super::error::report_event_error_attr_conflict(ctxt, &ast); @@ -500,6 +535,10 @@ impl<'db> Struct<'db> { super::event::report_indexed_attrs_outside_event_struct(ctxt, &ast); return super::error::lower_error_struct(ctxt, ast); } + if is_abi_struct { + super::event::report_indexed_attrs_outside_event_struct(ctxt, &ast); + return super::abi_struct::lower_abi_struct(ctxt, ast); + } super::event::report_indexed_attrs_outside_event_struct(ctxt, &ast); diff --git a/crates/hir/src/core/lower/mod.rs b/crates/hir/src/core/lower/mod.rs index bfe7905a63..fba3634026 100644 --- a/crates/hir/src/core/lower/mod.rs +++ b/crates/hir/src/core/lower/mod.rs @@ -20,6 +20,7 @@ use crate::{ }, span::HirOrigin, }; +pub use abi_struct::{AbiStructError, AbiStructErrorKind}; pub use arithmetic::{ArithmeticAttrError, ArithmeticAttrErrorKind}; pub use error::{ErrorDiagnostic, ErrorDiagnosticKind}; pub use event::{EventError, EventErrorKind}; @@ -30,6 +31,7 @@ pub use stmt::LoopUnrollAttrError; pub(crate) mod parse; +mod abi_struct; mod arithmetic; mod attr; mod body; diff --git a/crates/hir/src/core/lower/params.rs b/crates/hir/src/core/lower/params.rs index 24625899c2..3b28d39023 100644 --- a/crates/hir/src/core/lower/params.rs +++ b/crates/hir/src/core/lower/params.rs @@ -1,7 +1,9 @@ use parser::ast::{self}; use super::FileLowerCtxt; -use crate::core::hir_def::{Body, IdentId, Partial, TypeId, TypeKind, TypeMode, params::*}; +use crate::core::hir_def::{ + Body, BodyKind, IdentId, Partial, TrackedItemVariant, TypeId, TypeKind, TypeMode, params::*, +}; impl<'db> GenericArgListId<'db> { pub(super) fn lower_ast(ctxt: &mut FileLowerCtxt<'db>, ast: ast::GenericArgList) -> Self { @@ -52,10 +54,21 @@ impl<'db> FuncParamListId<'db> { impl<'db> WhereClauseId<'db> { pub(super) fn lower_ast(ctxt: &mut FileLowerCtxt<'db>, ast: ast::WhereClause) -> Self { let predicates = ast - .into_iter() + .iter() .map(|pred| WherePredicate::lower_ast(ctxt, pred)) .collect::>(); - Self::new(ctxt.db(), predicates) + let const_predicates = ast + .const_predicates() + .map(|cp| { + Body::lower_ast_with_variant( + ctxt, + cp.expr(), + TrackedItemVariant::WhereConstPredicate, + BodyKind::Anonymous, + ) + }) + .collect::>(); + Self::new(ctxt.db(), predicates, const_predicates) } pub(super) fn lower_ast_opt( @@ -63,7 +76,7 @@ impl<'db> WhereClauseId<'db> { ast: Option, ) -> Self { ast.map(|ast| Self::lower_ast(ctxt, ast)) - .unwrap_or_else(|| Self::new(ctxt.db(), Vec::new())) + .unwrap_or_else(|| Self::new(ctxt.db(), Vec::new(), Vec::new())) } } diff --git a/crates/hir/src/core/span/mod.rs b/crates/hir/src/core/span/mod.rs index a06aadf772..667de9666b 100644 --- a/crates/hir/src/core/span/mod.rs +++ b/crates/hir/src/core/span/mod.rs @@ -241,6 +241,8 @@ pub enum DesugaredOrigin { Event(EventDesugared), /// The HIR node is the result of desugaring a `#[error]` struct. Error(ErrorDesugared), + /// The HIR node is the result of desugaring a `#[abi]` struct. + AbiStruct(AbiStructDesugared), } /// Tracks the origin of HIR nodes desugared from a `msg` block. @@ -280,6 +282,13 @@ pub struct ErrorDesugared { pub error_struct: AstPtr, } +/// Tracks the origin of HIR nodes desugared from an `#[abi]` struct. +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct AbiStructDesugared { + /// The original `struct` AST node annotated with `#[abi]`. + pub abi_struct: AstPtr, +} + #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct UseDesugared { pub root: AstPtr, diff --git a/crates/hir/src/core/span/transition.rs b/crates/hir/src/core/span/transition.rs index 0f62710ad3..a3ac63e436 100644 --- a/crates/hir/src/core/span/transition.rs +++ b/crates/hir/src/core/span/transition.rs @@ -532,6 +532,9 @@ impl DesugaredOrigin { Self::Error(super::ErrorDesugared { error_struct }) => { error_struct.to_node(&root).syntax().text_range() } + Self::AbiStruct(super::AbiStructDesugared { abi_struct }) => { + abi_struct.to_node(&root).syntax().text_range() + } }; Span::new(file, range, SpanKind::Original) diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index d6942a78aa..1421f12236 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -1,8 +1,9 @@ use common::InputDb; pub use core::lower::{ - ArithmeticAttrError, ArithmeticAttrErrorKind, ErrorDiagnostic, ErrorDiagnosticKind, EventError, - EventErrorKind, InlineAttrError, LoopUnrollAttrError, PayableError, PayableErrorKind, - SelectorError, SelectorErrorKind, parse::ParserError, + AbiStructError, AbiStructErrorKind, ArithmeticAttrError, ArithmeticAttrErrorKind, + ErrorDiagnostic, ErrorDiagnosticKind, EventError, EventErrorKind, InlineAttrError, + LoopUnrollAttrError, PayableError, PayableErrorKind, SelectorError, SelectorErrorKind, + parse::ParserError, }; pub mod analysis; diff --git a/crates/hir/src/test_db.rs b/crates/hir/src/test_db.rs index ef60ccf120..c58deacd4b 100644 --- a/crates/hir/src/test_db.rs +++ b/crates/hir/src/test_db.rs @@ -10,8 +10,9 @@ use std::ops::Range; use crate::analysis::{ analysis_pass::{ - AnalysisPassManager, ArithmeticAttrPass, ErrorLowerPass, EventLowerPass, InlineAttrPass, - LoopUnrollAttrPass, MsgLowerPass, ParsingPass, PayableAttrPass, + AbiStructLowerPass, AnalysisPassManager, ArithmeticAttrPass, ErrorLowerPass, + EventLowerPass, InlineAttrPass, LoopUnrollAttrPass, MsgLowerPass, ParsingPass, + PayableAttrPass, }, diagnostics::{DiagnosticVoucher, SpannedHirAnalysisDb}, name_resolution::ImportAnalysisPass, @@ -370,6 +371,7 @@ pub fn initialize_analysis_pass() -> AnalysisPassManager { pass_manager.add_module_pass("MsgLower", Box::new(MsgLowerPass {})); pass_manager.add_module_pass("EventLower", Box::new(EventLowerPass {})); pass_manager.add_module_pass("ErrorLower", Box::new(ErrorLowerPass {})); + pass_manager.add_module_pass("AbiStructLower", Box::new(AbiStructLowerPass {})); pass_manager.add_module_pass("InlineAttr", Box::new(InlineAttrPass {})); pass_manager.add_module_pass("LoopUnrollAttr", Box::new(LoopUnrollAttrPass {})); pass_manager.add_module_pass("MsgSelector", Box::new(MsgSelectorAnalysisPass {})); diff --git a/crates/mir/src/runtime/ir.rs b/crates/mir/src/runtime/ir.rs index db4f0d6e12..5d8c7a8e13 100644 --- a/crates/mir/src/runtime/ir.rs +++ b/crates/mir/src/runtime/ir.rs @@ -811,6 +811,7 @@ pub enum RuntimeSyntheticSpec<'db> { contract: Contract<'db>, dispatch: Box<[DispatchArm<'db>]>, default: DispatchDefault<'db>, + dispatch_strategy: DispatchStrategy, }, CodeRegionRoot { symbol: String, @@ -925,12 +926,106 @@ pub enum RuntimeInputPlan<'db> { decode_fn: RuntimeInstance<'db>, projected_fields: Box<[u32]>, }, + /// Optimized path for non-dynamic types whose fields each fit in a single + /// ABI head slot. Each field is loaded directly via `calldataload` at a + /// known offset, skipping malloc / calldatacopy / MemoryBytes / SolDecoder + /// entirely. + /// + /// Eligibility is determined by querying `AbiSize::IS_DYNAMIC` (must be + /// false) and `AbiSize::HEAD_SIZE` on each field (must be exactly 32). + DirectCalldataLoad { + msg_ty: TyId<'db>, + /// Per-field ABI head sizes (in bytes), as queried from + /// `AbiSize::HEAD_SIZE` on each field type. The calldata offset of + /// field `i` is `4 + sum(field_head_sizes[..i])`. + field_head_sizes: Box<[u32]>, + /// Which of those fields the handler actually uses (same semantics + /// as `projected_fields` in `DecodeCalldataPayload`). + projected_fields: Box<[u32]>, + }, + /// Hybrid path for message types where some fields are non-mut scalars at + /// known ABI offsets and others require the full decode pipeline. + /// + /// Non-mut scalar fields are loaded directly via `calldataload` at their + /// ABI offset (`4 + field_index * 32`), skipping malloc / calldatacopy / + /// SolDecoder entirely. The remaining fields go through the standard + /// `DecodeCalldataPayload` decode path and are extracted from the decoded + /// tuple. + /// + /// This is the core of the "lazy access" optimization: data stays in + /// calldata until mutation forces materialization. Fe's `mut` vs non-`mut` + /// gives escape analysis for free -- a non-mut parameter is read-only by + /// construction and can safely be kept calldata-backed. + LazyCalldataLoad { + msg_ty: TyId<'db>, + /// The decode function for the full message type, used for fields that + /// cannot be lazy-loaded. `None` when every field uses a non-Decode + /// strategy (Direct, SkipWithOffset, or LazyDynamicView). + decode_fn: Option>, + /// Per-field load strategy, indexed by the message struct's field order. + field_strategies: Box<[FieldLoadStrategy]>, + /// Which fields the handler actually uses (same as `projected_fields` + /// in `DecodeCalldataPayload`), mapping handler param position to + /// struct field index. + projected_fields: Box<[u32]>, + }, +} + +/// Describes how a single field of a message struct should be loaded from +/// calldata in a `LazyCalldataLoad` plan. +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Update)] +pub enum FieldLoadStrategy { + /// Load directly via `calldataload` at offset `4 + field_index * 32`. + /// Only valid for non-mut primitive scalar fields at known word-aligned + /// ABI offsets. + Direct, + /// Load through the standard SolDecoder pipeline. Used for mut fields, + /// dynamic types, or fields whose ABI encoding is not a simple word. + Decode, + /// Skip this field in the decoder and pass the absolute calldata byte + /// offset to the handler. The handler receives an `ArrayView` whose + /// `start` is the calldata offset, ready for zero-copy element access + /// via `CallData`. + /// + /// `head_size` is the total ABI head size (in bytes) of this field so + /// the builder can compute offsets for subsequent fields. + SkipWithOffset { + /// The ABI head-size of this ArrayView field in bytes + /// (N * element_head_size). + head_size: u32, + }, + /// Decode a dynamic-typed view (BytesView or StringView) directly from + /// calldata without copying the payload into memory. + /// + /// The ABI head slot at the field's offset contains a byte-offset + /// pointer into the tail region. The codegen reads that pointer, + /// follows it to the tail, reads the length word, and constructs an + /// unbound BytesView/StringView with `start` and `len` set. + /// + /// `is_string_view` distinguishes StringView (which wraps BytesView in + /// an outer struct) from BytesView. + LazyDynamicView { + /// `true` for StringView fields, `false` for BytesView fields. + is_string_view: bool, + }, } #[derive(Clone, Debug, PartialEq, Eq, Hash, Update)] pub enum RuntimeReturnPlan<'db> { Unit, - Value { ty: TyId<'db> }, + Value { + ty: TyId<'db>, + }, + /// Optimized path for a single word-scalar return value: emit a direct + /// `mstore` at offset 0 and `return(0, 32)` instead of calling + /// `encode_single_root_alloc`. + /// + /// Eligibility is determined by querying `Encode::DIRECT_ENCODE` (must + /// be true) and verifying the runtime representation is a u256 word + /// scalar (so the value can be passed directly to `mstore`). + DirectScalarReturn { + ty: TyId<'db>, + }, } #[derive(Clone, Debug, PartialEq, Eq, Hash, Update)] @@ -945,6 +1040,15 @@ pub enum DispatchDefault<'db> { Call { wrapper: RuntimeInstance<'db> }, } +/// Strategy used for runtime selector dispatch in a contract. +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Update)] +pub enum DispatchStrategy { + /// Linear if-else chain (O(n)). Cheap for small selector counts. + Linear, + /// Binary-search tree (O(log n)). Cheaper for large selector counts. + BinarySearch, +} + #[salsa::interned] #[derive(Debug)] pub struct RuntimeObject<'db> { diff --git a/crates/mir/src/runtime/package.rs b/crates/mir/src/runtime/package.rs index b693a7f6b5..d949e1af48 100644 --- a/crates/mir/src/runtime/package.rs +++ b/crates/mir/src/runtime/package.rs @@ -2,20 +2,25 @@ use hir::semantic::{RecvArmAbiInfo, RecvArmView}; use hir::{ analysis::{ semantic::{ - GenericSubst, ImplEnv, ManualContractSection, RootSemanticInstanceError, - SemanticInstance, SemanticInstanceKey, get_or_build_semantic_instance, + EffectProviderSubst, GenericSubst, ImplEnv, ManualContractSection, + RootSemanticInstanceError, SemConstScalar, SemConstValue, SemanticInstance, + SemanticInstanceKey, eval_const_instance, get_or_build_semantic_instance, owner_effect_bindings, root_semantic_instance_key, }, ty::{ const_ty::ConstTyData, corelib::{resolve_core_trait, resolve_lib_type_path}, - trait_def::{TraitInstId, resolve_trait_method_instance}, - trait_resolution::TraitSolveCx, + trait_def::{ + TraitInstId, assoc_const_body_and_impl_args_for_trait_inst, + resolve_trait_method_instance, + }, + trait_resolution::{PredicateListId, TraitSolveCx}, ty_check::{BodyOwner, LocalBinding}, - ty_def::{TyData, TyId}, + ty_def::{PrimTy, TyBase, TyData, TyId}, }, }, hir_def::{Contract, Func, IdentId, InlineHint, ItemKind, ManualContractRootAttr, TopLevelMod}, + span::{DesugaredOrigin, HirOrigin}, }; use rustc_hash::{FxHashMap, FxHashSet}; @@ -39,11 +44,12 @@ use crate::{ }, runtime::{ AddressSpaceKind, ConstRegionId, ContractInitAbiPlan, ContractRecvAbiPlan, DispatchArm, - DispatchDefault, EntryEffectArgPlan, InitArgsPlan, LayoutId, LayoutKey, RefKind, RefView, - ResolvedCodeRegion, RuntimeClass, RuntimeCodeRegion, RuntimeCodeRegionKey, RuntimeFunction, - RuntimeFunctionOwner, RuntimeInlineHint, RuntimeInputPlan, RuntimeLinkage, RuntimeObject, - RuntimePackage, RuntimePackagePlan, RuntimeReturnPlan, RuntimeSection, RuntimeSectionName, - RuntimeSectionRef, RuntimeSyntheticSpec, ScalarClass, ScalarRepr, ScalarRole, + DispatchDefault, DispatchStrategy, EntryEffectArgPlan, FieldLoadStrategy, InitArgsPlan, + LayoutId, LayoutKey, RefKind, RefView, ResolvedCodeRegion, RuntimeClass, RuntimeCodeRegion, + RuntimeCodeRegionKey, RuntimeFunction, RuntimeFunctionOwner, RuntimeInlineHint, + RuntimeInputPlan, RuntimeLinkage, RuntimeObject, RuntimePackage, RuntimePackagePlan, + RuntimeReturnPlan, RuntimeSection, RuntimeSectionName, RuntimeSectionRef, + RuntimeSyntheticSpec, ScalarClass, ScalarRepr, ScalarRole, TargetRootProviderMaterialization, }, verify::verify_runtime_package, @@ -657,17 +663,51 @@ fn contract_runtime_root<'db>( dispatch.push(DispatchArm { selector, wrapper }); } dispatch.sort_by_key(|arm| arm.selector); + + let dispatch_strategy = resolve_dispatch_strategy(db, contract, dispatch.len()); + Ok(synthetic_instance( db, RuntimeSyntheticSpec::ContractRuntimeRoot { contract, dispatch: dispatch.into_boxed_slice(), default, + dispatch_strategy, }, Vec::new(), )) } +/// Determine which dispatch strategy to use for a contract. +/// +/// If the contract has a `#[dispatch(linear)]` or `#[dispatch(binary_search)]` attribute, +/// that takes precedence. Otherwise, auto-select based on the number of selectors: +/// linear for 3 or fewer, binary search for 4 or more. +fn resolve_dispatch_strategy<'db>( + db: &'db dyn MirDb, + contract: Contract<'db>, + selector_count: usize, +) -> DispatchStrategy { + use hir::hir_def::{DispatchAttr, ItemKind}; + + if let Some(dispatch_attr) = ItemKind::from(contract) + .attrs(db) + .and_then(|attrs| attrs.dispatch_attr(db)) + { + return match dispatch_attr { + DispatchAttr::Linear => DispatchStrategy::Linear, + DispatchAttr::BinarySearch => DispatchStrategy::BinarySearch, + }; + } + + // Auto threshold: binary search is worthwhile at 4+ selectors. + if selector_count > 3 { + DispatchStrategy::BinarySearch + } else { + DispatchStrategy::Linear + } +} + fn contract_init_root<'db>( db: &'db dyn MirDb, contract: Contract<'db>, @@ -770,20 +810,42 @@ fn contract_recv_wrapper<'db>( }, )?, )?; - let projected_fields = visible_recv_arg_fields( + let semantic = semantic_instance_for_root_owner( db, - semantic_instance_for_root_owner( - db, - BodyOwner::ContractRecvArm { - contract, - recv_idx: recv.recv_idx(db), - arm_idx: arm.arm_idx(db), - }, - )?, - arm, - ); + BodyOwner::ContractRecvArm { + contract, + recv_idx: recv.recv_idx(db), + arm_idx: arm.arm_idx(db), + }, + )?; + let projected_fields = visible_recv_arg_fields(db, semantic, arm); let input = if abi_info.args_ty == TyId::unit(db) { RuntimeInputPlan::None + } else if let Some(field_head_sizes) = + direct_calldata_load_info(db, contract.scope(), abi_info.args_ty) + { + RuntimeInputPlan::DirectCalldataLoad { + msg_ty: abi_info.args_ty, + field_head_sizes, + projected_fields, + } + } else if let Some(strategies) = lazy_field_strategies(db, abi_info.args_ty, semantic, arm) { + let needs_decode = strategies.contains(&FieldLoadStrategy::Decode); + let decode_fn = if needs_decode { + Some(resolve_decode_instance( + db, + contract.scope(), + abi_info.args_ty, + )?) + } else { + None + }; + RuntimeInputPlan::LazyCalldataLoad { + msg_ty: abi_info.args_ty, + decode_fn, + field_strategies: strategies, + projected_fields, + } } else { RuntimeInputPlan::DecodeCalldataPayload { msg_ty: abi_info.args_ty, @@ -792,7 +854,11 @@ fn contract_recv_wrapper<'db>( } }; let ret = if let Some(ret_ty) = abi_info.ret_ty { - RuntimeReturnPlan::Value { ty: ret_ty } + if is_direct_return_eligible(db, contract.scope(), ret_ty) { + RuntimeReturnPlan::DirectScalarReturn { ty: ret_ty } + } else { + RuntimeReturnPlan::Value { ty: ret_ty } + } } else { RuntimeReturnPlan::Unit }; @@ -1908,8 +1974,9 @@ fn runtime_synthetic_spec_symbol_key<'db>( contract, dispatch, default, + dispatch_strategy, } => format!( - "__synthetic:contract_runtime_root:{}:{}:{}", + "__synthetic:contract_runtime_root:{}:{}:{}:{:?}", item_identity(db, contract.into()), dispatch .iter() @@ -1920,7 +1987,8 @@ fn runtime_synthetic_spec_symbol_key<'db>( )) .collect::>() .join(","), - dispatch_default_symbol_key(db, &default) + dispatch_default_symbol_key(db, &default), + dispatch_strategy ), RuntimeSyntheticSpec::CodeRegionRoot { symbol, callee } => { format!( @@ -1995,8 +2063,9 @@ fn runtime_synthetic_spec_sort_key<'db>( contract, dispatch, default, + dispatch_strategy, } => format!( - "__synthetic:contract_runtime_root:{}:{}:{}", + "__synthetic:contract_runtime_root:{}:{}:{}:{:?}", item_identity(db, contract.into()), dispatch .iter() @@ -2007,7 +2076,8 @@ fn runtime_synthetic_spec_sort_key<'db>( )) .collect::>() .join(","), - dispatch_default_sort_key(db, &default) + dispatch_default_sort_key(db, &default), + dispatch_strategy ), RuntimeSyntheticSpec::CodeRegionRoot { symbol, callee } => { format!( @@ -2069,6 +2139,463 @@ fn init_args_plan_sort_key<'db>(db: &'db dyn MirDb, plan: &InitArgsPlan<'db>) -> } } +// --------------------------------------------------------------------------- +// Const trait value queries +// +// These functions evaluate ABI trait associated constants (HEAD_SIZE, +// IS_DYNAMIC, DIRECT_ENCODE) for a concrete type via CTFE, replacing the +// old type-structure heuristics. +// --------------------------------------------------------------------------- + +/// Evaluate an associated const from a trait impl for a concrete type. +/// +/// Resolves the impl body for `const_name` on the trait instantiated with the +/// given args, then runs CTFE to produce a `SemConstId`. +fn eval_trait_assoc_const<'db>( + db: &'db dyn MirDb, + scope: hir::hir_def::scope_graph::ScopeId<'db>, + trait_path: &[&str], + trait_args: Vec>, + const_name: &str, +) -> Option> { + let trait_def = resolve_core_trait(db, scope, trait_path)?; + let inst = TraitInstId::new_simple(db, trait_def, trait_args); + let assumptions = PredicateListId::empty_list(db); + let solve_cx = TraitSolveCx::new(db, scope).with_assumptions(assumptions); + let name = IdentId::new(db, const_name.to_string()); + let (body, impl_args) = + assoc_const_body_and_impl_args_for_trait_inst(db, solve_cx, inst, name)?; + let key = SemanticInstanceKey::new( + db, + BodyOwner::AnonConstBody { + body, + expected: TyId::invalid(db, hir::analysis::ty::ty_def::InvalidCause::Other), + }, + GenericSubst::new(db, impl_args), + EffectProviderSubst::empty(db), + ImplEnv::new(db, scope, assumptions, vec![inst]), + ); + let instance = get_or_build_semantic_instance(db, key); + eval_const_instance(db, instance).ok() +} + +/// Query `AbiSize::HEAD_SIZE` for `ty`, returning the value as a `u32`. +fn query_head_size<'db>( + db: &'db dyn MirDb, + scope: hir::hir_def::scope_graph::ScopeId<'db>, + ty: TyId<'db>, +) -> Option { + let const_id = eval_trait_assoc_const(db, scope, &["abi", "AbiSize"], vec![ty], "HEAD_SIZE")?; + match const_id.value(db) { + SemConstValue::Scalar { + value: SemConstScalar::Int { value }, + .. + } => { + let v: u64 = value.try_into().ok()?; + u32::try_from(v).ok() + } + _ => None, + } +} + +/// Query `AbiSize::IS_DYNAMIC` for `ty`, returning `true` if the type is +/// dynamically-sized in ABI encoding. +fn query_is_dynamic<'db>( + db: &'db dyn MirDb, + scope: hir::hir_def::scope_graph::ScopeId<'db>, + ty: TyId<'db>, +) -> Option { + let const_id = eval_trait_assoc_const(db, scope, &["abi", "AbiSize"], vec![ty], "IS_DYNAMIC")?; + match const_id.value(db) { + SemConstValue::Scalar { + value: SemConstScalar::Bool(v), + .. + } => Some(v), + _ => None, + } +} + +/// Query `Encode::DIRECT_ENCODE` for `ty`, returning `true` if the type +/// supports direct ABI encoding (single-word store). +fn query_direct_encode<'db>( + db: &'db dyn MirDb, + scope: hir::hir_def::scope_graph::ScopeId<'db>, + ty: TyId<'db>, +) -> Option { + let abi_ty = resolve_lib_type_path(db, scope, "std::abi::Sol")?; + let const_id = eval_trait_assoc_const( + db, + scope, + &["abi", "Encode"], + vec![ty, abi_ty], + "DIRECT_ENCODE", + )?; + match const_id.value(db) { + SemConstValue::Scalar { + value: SemConstScalar::Bool(v), + .. + } => Some(v), + _ => None, + } +} + +/// Returns `true` if `ty` supports `DirectScalarReturn`: the type has +/// `Encode::DIRECT_ENCODE == true` AND its runtime representation is a full +/// u256 word scalar (so the value can be passed directly to `mstore` without +/// widening). +fn is_direct_return_eligible<'db>( + db: &'db dyn MirDb, + scope: hir::hir_def::scope_graph::ScopeId<'db>, + ty: TyId<'db>, +) -> bool { + // Runtime check: only u256-width unsigned scalars can be mstore'd directly. + let base = ty.base_ty(db); + let is_word_scalar = matches!( + base.data(db), + TyData::TyBase(TyBase::Prim(PrimTy::U256 | PrimTy::Usize)) + ); + if !is_word_scalar { + return false; + } + // Trait query: verify DIRECT_ENCODE is true. + query_direct_encode(db, scope, ty).unwrap_or(false) +} + +/// Returns `true` if `msg_ty` is a compiler-generated message struct (from a +/// `msg` declaration). Manual `MsgVariant` impls may reorder fields in their +/// encode/decode, making direct calldataload unsafe. +fn is_compiler_generated_msg<'db>(db: &'db dyn MirDb, msg_ty: TyId<'db>) -> bool { + let Some(adt_ref) = msg_ty.adt_ref(db) else { + return false; + }; + match adt_ref { + hir::analysis::ty::adt_def::AdtRef::Struct(struct_) => { + matches!( + hir::span::struct_ast(db, struct_), + HirOrigin::Desugared(DesugaredOrigin::Msg(_)) + ) + } + _ => false, + } +} + +/// Check if `msg_ty` is eligible for the `DirectCalldataLoad` optimization by +/// querying actual const trait values instead of matching on type structure. +/// +/// Returns `Some(field_head_sizes)` if eligible, `None` otherwise. +/// +/// Eligibility requires: +/// - The type is a compiler-generated message struct (canonical field order). +/// - `AbiSize::IS_DYNAMIC` is false on the msg type. +/// - Each field has `AbiSize::HEAD_SIZE == 32` (one ABI word) and has a scalar +/// runtime representation that allows direct calldataload. +fn direct_calldata_load_info<'db>( + db: &'db dyn MirDb, + scope: hir::hir_def::scope_graph::ScopeId<'db>, + msg_ty: TyId<'db>, +) -> Option> { + // Only compiler-generated msg structs have canonical ABI field layout. + if !is_compiler_generated_msg(db, msg_ty) { + return None; + } + let fields = msg_ty.field_types(db); + if fields.is_empty() { + return None; + } + // The msg type must not be dynamically-sized. + if query_is_dynamic(db, scope, msg_ty).unwrap_or(true) { + return None; + } + // Each field must have HEAD_SIZE == 32 (one ABI word) and must be a + // primitive scalar type so calldataload produces a usable value. + let mut head_sizes = Vec::with_capacity(fields.len()); + for &field_ty in fields.iter() { + let head_size = query_head_size(db, scope, field_ty)?; + if head_size != 32 { + return None; + } + // Also verify the field has a scalar runtime representation. ADT + // wrappers (e.g. Address { inner: u256 }) would have HEAD_SIZE == 32 + // but use aggregate runtime representation. + let base = field_ty.base_ty(db); + let is_scalar_prim = matches!( + base.data(db), + TyData::TyBase(TyBase::Prim( + PrimTy::Bool + | PrimTy::U8 + | PrimTy::U16 + | PrimTy::U32 + | PrimTy::U64 + | PrimTy::U128 + | PrimTy::U256 + | PrimTy::Usize + | PrimTy::I8 + | PrimTy::I16 + | PrimTy::I32 + | PrimTy::I64 + | PrimTy::I128 + | PrimTy::I256 + | PrimTy::Isize + )) + ); + if !is_scalar_prim { + return None; + } + head_sizes.push(head_size); + } + Some(head_sizes.into_boxed_slice()) +} + +/// Returns `true` if `ty` is a primitive scalar type that occupies exactly one +/// 32-byte ABI word AND has a scalar runtime representation (i.e. the runtime +/// carries it as a plain word, not an aggregate). +/// +/// Only primitive bool and integer types qualify. ADT wrappers like +/// `Address { inner: u256 }` are ABI-word-sized but have aggregate runtime +/// representations, so they are excluded. +fn is_primitive_word_scalar(db: &dyn MirDb, ty: TyId<'_>) -> bool { + let base = ty.base_ty(db); + match base.data(db) { + TyData::TyBase(TyBase::Prim(prim)) => matches!( + prim, + PrimTy::Bool + | PrimTy::U8 + | PrimTy::U16 + | PrimTy::U32 + | PrimTy::U64 + | PrimTy::U128 + | PrimTy::U256 + | PrimTy::Usize + | PrimTy::I8 + | PrimTy::I16 + | PrimTy::I32 + | PrimTy::I64 + | PrimTy::I128 + | PrimTy::I256 + | PrimTy::Isize + ), + _ => false, + } +} + +/// If `ty` is an unbound `ArrayView` (I defaulted to `()`) from the core +/// ingot, returns the total ABI head size in bytes (`N * element_head_size`). +/// Returns `None` for any other type. +fn array_view_head_size(db: &dyn MirDb, ty: TyId<'_>) -> Option { + use common::ingot::IngotKind; + use hir::analysis::ty::const_ty::EvaluatedConstTy; + + let base = ty.base_ty(db); + let TyData::TyBase(TyBase::Adt(adt)) = base.data(db) else { + return None; + }; + let adt_ref = adt.adt_ref(db); + let name = adt_ref.name(db)?; + if name.data(db) != "ArrayView" { + return None; + } + if !base + .ingot(db) + .is_some_and(|ingot| ingot.kind(db) == IngotKind::Core) + { + return None; + } + + let (_, args) = ty.decompose_ty_app(db); + if args.len() < 2 { + return None; + } + let elem_ty = args[0]; + let len_ty = args[1]; + + let TyData::ConstTy(const_ty) = len_ty.data(db) else { + return None; + }; + let n: u32 = match const_ty.data(db) { + ConstTyData::Evaluated(EvaluatedConstTy::LitInt(int_id), _) => int_id + .data(db) + .to_u32_digits() + .first() + .copied() + .unwrap_or(0), + _ => return None, + }; + + let elem_head_size = static_abi_head_size(db, elem_ty)?; + Some(n * elem_head_size) +} + +/// Returns `true` if `ty` is an unbound `BytesView` (= `BytesView<()>`) from +/// the core ingot. These are dynamic ABI types whose head slot is a 32-byte +/// offset pointer into the tail region. +fn is_bytes_view_ty(db: &dyn MirDb, ty: TyId<'_>) -> bool { + use common::ingot::IngotKind; + + let base = ty.base_ty(db); + let TyData::TyBase(TyBase::Adt(adt)) = base.data(db) else { + return false; + }; + let adt_ref = adt.adt_ref(db); + let Some(name) = adt_ref.name(db) else { + return false; + }; + if name.data(db) != "BytesView" { + return false; + } + base.ingot(db) + .is_some_and(|ingot| ingot.kind(db) == IngotKind::Core) +} + +/// Returns `true` if `ty` is an unbound `StringView` (= `StringView<()>`) from +/// the core ingot. StringView wraps BytesView and shares the same dynamic ABI +/// wire format. +fn is_string_view_ty(db: &dyn MirDb, ty: TyId<'_>) -> bool { + use common::ingot::IngotKind; + + let base = ty.base_ty(db); + let TyData::TyBase(TyBase::Adt(adt)) = base.data(db) else { + return false; + }; + let adt_ref = adt.adt_ref(db); + let Some(name) = adt_ref.name(db) else { + return false; + }; + if name.data(db) != "StringView" { + return false; + } + base.ingot(db) + .is_some_and(|ingot| ingot.kind(db) == IngotKind::Core) +} + +/// Returns the statically-known ABI head size (in bytes) for `ty`, or `None` +/// if the size is dynamic or cannot be determined at compile time. +pub(crate) fn static_abi_head_size(db: &dyn MirDb, ty: TyId<'_>) -> Option { + if is_primitive_word_scalar(db, ty) { + return Some(32); + } + let fields = ty.field_types(db); + if fields.len() == 1 { + return static_abi_head_size(db, fields[0]); + } + if ty.is_array(db) { + let n = ty.array_len(db)? as u32; + let (_, args) = ty.decompose_ty_app(db); + let elem_ty = *args.first()?; + let elem_size = static_abi_head_size(db, elem_ty)?; + return Some(n * elem_size); + } + if let Some(size) = array_view_head_size(db, ty) { + return Some(size); + } + // BytesView and StringView are dynamic types whose head slot is a + // 32-byte offset pointer into the tail region. + if is_bytes_view_ty(db, ty) || is_string_view_ty(db, ty) { + return Some(32); + } + None +} + +/// Determine the per-field load strategies for a lazy calldata load plan. +/// +/// Returns `Some(strategies)` if at least one field can use direct load AND +/// at least one field needs the decode path (genuinely mixed case). +/// Returns `None` if all fields use the same strategy. +fn lazy_field_strategies<'db>( + db: &'db dyn MirDb, + msg_ty: TyId<'db>, + semantic: SemanticInstance<'db>, + arm: RecvArmView<'db>, +) -> Option> { + if !is_compiler_generated_msg(db, msg_ty) { + return None; + } + let field_types = msg_ty.field_types(db); + if field_types.is_empty() { + return None; + } + + let binding_plans = runtime_visible_binding_plans(db, semantic); + let arg_bindings = arm.arg_bindings(db); + let tuple_index_by_pat: FxHashMap<_, _> = arg_bindings + .iter() + .map(|b| (b.pat, b.tuple_index)) + .collect(); + + let mut field_is_mut = vec![false; field_types.len()]; + for entry in binding_plans.iter() { + if let LocalBinding::Local { pat, is_mut: true } = entry.binding + && let Some(&tuple_idx) = tuple_index_by_pat.get(&pat) + { + field_is_mut[tuple_idx as usize] = true; + } + } + + let mut strategies: Vec = field_types + .iter() + .enumerate() + .map(|(i, &field_ty)| { + if !field_is_mut[i] && is_primitive_word_scalar(db, field_ty) { + FieldLoadStrategy::Direct + } else if !field_is_mut[i] { + if let Some(head_size) = array_view_head_size(db, field_ty) { + FieldLoadStrategy::SkipWithOffset { head_size } + } else if is_bytes_view_ty(db, field_ty) { + FieldLoadStrategy::LazyDynamicView { + is_string_view: false, + } + } else if is_string_view_ty(db, field_ty) { + FieldLoadStrategy::LazyDynamicView { + is_string_view: true, + } + } else { + FieldLoadStrategy::Decode + } + } else { + FieldLoadStrategy::Decode + } + }) + .collect(); + + let mut all_preceding_static = true; + for (i, &field_ty) in field_types.iter().enumerate() { + if static_abi_head_size(db, field_ty).is_none() { + all_preceding_static = false; + } + match strategies[i] { + FieldLoadStrategy::Direct + | FieldLoadStrategy::SkipWithOffset { .. } + | FieldLoadStrategy::LazyDynamicView { .. } => { + if !all_preceding_static { + strategies[i] = FieldLoadStrategy::Decode; + } + } + FieldLoadStrategy::Decode => {} + } + } + + let has_direct = strategies.contains(&FieldLoadStrategy::Direct); + let has_skip = strategies + .iter() + .any(|s| matches!(s, FieldLoadStrategy::SkipWithOffset { .. })); + let has_lazy_view = strategies + .iter() + .any(|s| matches!(s, FieldLoadStrategy::LazyDynamicView { .. })); + let has_decode = strategies.contains(&FieldLoadStrategy::Decode); + + // Return the strategies if the LazyCalldataLoad plan is beneficial: + // - SkipWithOffset or LazyDynamicView fields always need the hybrid + // codegen path (no standalone fast-path exists for them). + // - A mix of Direct + Decode benefits from lazy access. + // - All-Direct is handled by DirectCalldataLoad (return None). + // - All-Decode is handled by DecodeCalldataPayload (return None). + let distinct_count = has_direct as u8 + has_skip as u8 + has_lazy_view as u8 + has_decode as u8; + if has_skip || has_lazy_view || distinct_count >= 2 { + Some(strategies.into_boxed_slice()) + } else { + None + } +} + fn runtime_input_plan_symbol_key<'db>(db: &'db dyn MirDb, plan: &RuntimeInputPlan<'db>) -> String { match plan { RuntimeInputPlan::None => "none".to_string(), @@ -2081,6 +2608,29 @@ fn runtime_input_plan_symbol_key<'db>(db: &'db dyn MirDb, plan: &RuntimeInputPla type_identity(db, *msg_ty), runtime_instance_symbol_key(db, *decode_fn) ), + RuntimeInputPlan::DirectCalldataLoad { + msg_ty, + field_head_sizes, + projected_fields, + } => format!( + "direct_load:{}:{field_head_sizes:?}:{projected_fields:?}", + type_identity(db, *msg_ty), + ), + RuntimeInputPlan::LazyCalldataLoad { + msg_ty, + decode_fn, + field_strategies, + projected_fields, + } => { + let decode_key = decode_fn + .map(|f| runtime_instance_symbol_key(db, f)) + .unwrap_or_else(|| "none".to_string()); + format!( + "lazy:{}:{}:{field_strategies:?}:{projected_fields:?}", + type_identity(db, *msg_ty), + decode_key + ) + } } } @@ -2096,6 +2646,29 @@ fn runtime_input_plan_sort_key<'db>(db: &'db dyn MirDb, plan: &RuntimeInputPlan< type_identity(db, *msg_ty), runtime_instance_sort_key(db, *decode_fn) ), + RuntimeInputPlan::DirectCalldataLoad { + msg_ty, + field_head_sizes, + projected_fields, + } => format!( + "direct_load:{}:{field_head_sizes:?}:{projected_fields:?}", + type_identity(db, *msg_ty), + ), + RuntimeInputPlan::LazyCalldataLoad { + msg_ty, + decode_fn, + field_strategies, + projected_fields, + } => { + let decode_key = decode_fn + .map(|f| runtime_instance_sort_key(db, f)) + .unwrap_or_else(|| "none".to_string()); + format!( + "lazy:{}:{}:{field_strategies:?}:{projected_fields:?}", + type_identity(db, *msg_ty), + decode_key + ) + } } } @@ -2684,11 +3257,17 @@ pub contract DecodeHarness { let top_mod = db.top_mod(file); let raw_plan = recv_wrapper_plan(&db, top_mod, "raw(uint256)"); - let RuntimeInputPlan::DecodeCalldataPayload { - projected_fields, .. - } = raw_plan.input - else { - panic!("raw(uint256) should decode calldata payload"); + let projected_fields = match raw_plan.input { + RuntimeInputPlan::DirectCalldataLoad { + projected_fields, .. + } + | RuntimeInputPlan::LazyCalldataLoad { + projected_fields, .. + } + | RuntimeInputPlan::DecodeCalldataPayload { + projected_fields, .. + } => projected_fields, + RuntimeInputPlan::None => panic!("raw(uint256) should have input plan"), }; assert!( projected_fields.is_empty(), @@ -2696,11 +3275,17 @@ pub contract DecodeHarness { ); let swap_plan = recv_wrapper_plan(&db, top_mod, "swap(uint64,uint64)"); - let RuntimeInputPlan::DecodeCalldataPayload { - projected_fields, .. - } = swap_plan.input - else { - panic!("swap(uint64,uint64) should decode calldata payload"); + let projected_fields = match swap_plan.input { + RuntimeInputPlan::DirectCalldataLoad { + projected_fields, .. + } + | RuntimeInputPlan::LazyCalldataLoad { + projected_fields, .. + } + | RuntimeInputPlan::DecodeCalldataPayload { + projected_fields, .. + } => projected_fields, + RuntimeInputPlan::None => panic!("swap(uint64,uint64) should have input plan"), }; assert_eq!( projected_fields.as_ref(), @@ -2774,4 +3359,913 @@ pub contract NoInitBox {} "contract init root should always call the synthesized init abi wrapper" ); } + + #[test] + fn direct_calldataload_uses_trait_queried_head_sizes() { + let mut db = DriverDataBase::default(); + let file_url = + Url::parse("file:///direct_calldataload_uses_trait_queried_head_sizes.fe").unwrap(); + db.workspace().touch( + &mut db, + file_url.clone(), + Some( + r#" +use std::abi::sol + +msg QueryMsg { + #[selector = sol("lookup(uint256,uint64)")] + Lookup { key: u256, flags: u64 } -> u256, +} + +pub contract Store { + recv QueryMsg { + Lookup { key, flags } -> u256 { key } + } +} +"# + .to_string(), + ), + ); + let file = db + .workspace() + .get(&db, &file_url) + .expect("file should be loaded"); + let top_mod = db.top_mod(file); + + let plan = recv_wrapper_plan(&db, top_mod, "lookup(uint256,uint64)"); + match plan.input { + RuntimeInputPlan::DirectCalldataLoad { + field_head_sizes, + projected_fields, + .. + } => { + // Both u256 and u64 have HEAD_SIZE == 32 in ABI encoding. + assert_eq!( + field_head_sizes.as_ref(), + &[32, 32], + "trait-queried field_head_sizes should be [32, 32] for (u256, u64)" + ); + assert_eq!( + projected_fields.as_ref(), + &[0, 1], + "projected fields should be [0, 1] for Lookup {{ key, flags }}" + ); + } + other => panic!("expected DirectCalldataLoad for primitive-field msg, got {other:?}"), + } + // Return plan should be DirectScalarReturn since return type is u256. + assert!( + matches!(plan.ret, RuntimeReturnPlan::DirectScalarReturn { .. }), + "u256 return should use DirectScalarReturn (DIRECT_ENCODE + word scalar): {:?}", + plan.ret + ); + } + + #[test] + fn direct_calldataload_excluded_for_dynamic_fields() { + let mut db = DriverDataBase::default(); + let file_url = + Url::parse("file:///direct_calldataload_excluded_for_dynamic_fields.fe").unwrap(); + db.workspace().touch( + &mut db, + file_url.clone(), + Some( + r#" +use std::abi::sol + +msg StringMsg { + #[selector = sol("greet(string)")] + Greet { name: String<32> }, +} + +pub contract Greeter { + recv StringMsg { + Greet { name: _ } {} + } +} +"# + .to_string(), + ), + ); + let file = db + .workspace() + .get(&db, &file_url) + .expect("file should be loaded"); + let top_mod = db.top_mod(file); + + let plan = recv_wrapper_plan(&db, top_mod, "greet(string)"); + assert!( + matches!(plan.input, RuntimeInputPlan::DecodeCalldataPayload { .. }), + "msg with dynamic String field should fall back to decode path: {:?}", + plan.input + ); + } + + #[test] + fn direct_scalar_return_excluded_for_non_word_types() { + let mut db = DriverDataBase::default(); + let file_url = + Url::parse("file:///direct_scalar_return_excluded_for_non_word_types.fe").unwrap(); + db.workspace().touch( + &mut db, + file_url.clone(), + Some( + r#" +use std::abi::sol + +msg NarrowMsg { + #[selector = sol("narrow()")] + Narrow -> u64, +} + +pub contract NarrowReturn { + recv NarrowMsg { + Narrow -> u64 { 42 } + } +} +"# + .to_string(), + ), + ); + let file = db + .workspace() + .get(&db, &file_url) + .expect("file should be loaded"); + let top_mod = db.top_mod(file); + + let plan = recv_wrapper_plan(&db, top_mod, "narrow()"); + assert!( + matches!(plan.ret, RuntimeReturnPlan::Value { .. }), + "u64 return should use Value path (not DirectScalarReturn): {:?}", + plan.ret + ); + } + + #[test] + fn lazy_calldataload_for_mixed_scalar_and_aggregate_params() { + let mut db = DriverDataBase::default(); + let file_url = Url::parse("file:///lazy_calldataload_mixed.fe").unwrap(); + db.workspace().touch( + &mut db, + file_url.clone(), + Some( + r#" +use std::abi::sol +use std::evm::Address + +msg MixedMsg { + #[selector = sol("mixed(uint256,address)")] + Mixed { id: u256, addr: Address }, +} + +pub contract MixedBox { + recv MixedMsg { + Mixed { id, addr } { + // id is non-mut primitive scalar -> eligible for direct calldataload + // addr is Address (struct with aggregate repr) -> needs decode + } + } +} +"# + .to_string(), + ), + ); + let file = db + .workspace() + .get(&db, &file_url) + .expect("file should be loaded"); + let top_mod = db.top_mod(file); + + let plan = recv_wrapper_plan(&db, top_mod, "mixed(uint256,address)"); + match plan.input { + RuntimeInputPlan::LazyCalldataLoad { + field_strategies, + projected_fields, + .. + } => { + assert_eq!( + field_strategies.len(), + 2, + "mixed msg should have 2 field strategies" + ); + assert_eq!( + field_strategies[0], + FieldLoadStrategy::Direct, + "non-mut u256 `id` should use Direct load" + ); + assert_eq!( + field_strategies[1], + FieldLoadStrategy::Decode, + "Address `addr` (aggregate type) should use Decode" + ); + assert_eq!( + projected_fields.as_ref(), + &[0, 1], + "both fields should be projected in order" + ); + } + other => panic!( + "mixed(uint256,address) should use LazyCalldataLoad, got {:?}", + std::mem::discriminant(&other) + ), + } + } + + #[test] + fn lazy_calldataload_not_used_for_all_scalar_params() { + let mut db = DriverDataBase::default(); + let file_url = Url::parse("file:///lazy_calldataload_all_scalar.fe").unwrap(); + db.workspace().touch( + &mut db, + file_url.clone(), + Some( + r#" +use std::abi::sol + +msg AllScalarMsg { + #[selector = sol("allscalar(uint256,uint64)")] + AllScalar { a: u256, b: u64 } -> u256, +} + +pub contract AllScalarBox { + recv AllScalarMsg { + AllScalar { a, b } -> u256 { a } + } +} +"# + .to_string(), + ), + ); + let file = db + .workspace() + .get(&db, &file_url) + .expect("file should be loaded"); + let top_mod = db.top_mod(file); + + let plan = recv_wrapper_plan(&db, top_mod, "allscalar(uint256,uint64)"); + // All fields are non-mut scalars, so lazy_field_strategies returns + // None (all Direct). The plan should be DirectCalldataLoad. + assert!( + !matches!(plan.input, RuntimeInputPlan::LazyCalldataLoad { .. }), + "all-scalar non-mut msg should not use LazyCalldataLoad, got {:?}", + std::mem::discriminant(&plan.input) + ); + } + + #[test] + fn lazy_calldataload_mut_scalar_forces_decode() { + let mut db = DriverDataBase::default(); + let file_url = Url::parse("file:///lazy_calldataload_mut_scalar.fe").unwrap(); + db.workspace().touch( + &mut db, + file_url.clone(), + Some( + r#" +use std::abi::sol +use std::evm::Address + +msg MutMixedMsg { + #[selector = sol("mutmixed(uint256,uint256,address)")] + MutMixed { id: u256, tag: u256, addr: Address }, +} + +pub contract MutMixedBox { + recv MutMixedMsg { + MutMixed { mut id, tag, addr } { + // id is bound with `mut` -> must go through decoder + // tag is non-mut scalar -> eligible for direct calldataload + // addr is Address (aggregate) -> must go through decoder + } + } +} +"# + .to_string(), + ), + ); + let file = db + .workspace() + .get(&db, &file_url) + .expect("file should be loaded"); + let top_mod = db.top_mod(file); + + let plan = recv_wrapper_plan(&db, top_mod, "mutmixed(uint256,uint256,address)"); + match plan.input { + RuntimeInputPlan::LazyCalldataLoad { + field_strategies, .. + } => { + assert_eq!(field_strategies.len(), 3); + assert_eq!( + field_strategies[0], + FieldLoadStrategy::Decode, + "mut u256 `id` should use Decode" + ); + assert_eq!( + field_strategies[1], + FieldLoadStrategy::Direct, + "non-mut u256 `tag` should use Direct" + ); + assert_eq!( + field_strategies[2], + FieldLoadStrategy::Decode, + "Address `addr` should use Decode" + ); + } + other => panic!( + "mutmixed should use LazyCalldataLoad, got {:?}", + std::mem::discriminant(&other) + ), + } + } + + #[test] + fn lazy_calldataload_array_field_uses_decode() { + let mut db = DriverDataBase::default(); + let file_url = Url::parse("file:///lazy_calldataload_array.fe").unwrap(); + db.workspace().touch( + &mut db, + file_url.clone(), + Some( + r#" +use std::abi::sol + +msg ArrayMsg { + #[selector = sol("withArray(uint256,uint256[32])")] + WithArray { id: u256, data: [u256; 32] }, +} + +pub contract ArrayBox { + recv ArrayMsg { + WithArray { id, data } { + // id is non-mut primitive scalar -> Direct + // data is [u256; 32] (fixed-size array) -> must use Decode + } + } +} +"# + .to_string(), + ), + ); + let file = db + .workspace() + .get(&db, &file_url) + .expect("file should be loaded"); + let top_mod = db.top_mod(file); + + let plan = recv_wrapper_plan(&db, top_mod, "withArray(uint256,uint256[32])"); + match plan.input { + RuntimeInputPlan::LazyCalldataLoad { + field_strategies, .. + } => { + assert_eq!( + field_strategies.len(), + 2, + "array msg should have 2 field strategies" + ); + assert_eq!( + field_strategies[0], + FieldLoadStrategy::Direct, + "non-mut u256 `id` should use Direct load" + ); + assert_eq!( + field_strategies[1], + FieldLoadStrategy::Decode, + "fixed-size array `data: [u256; 32]` must use Decode, not Direct" + ); + } + RuntimeInputPlan::DecodeCalldataPayload { .. } => { + panic!( + "withArray(uint256,uint256[32]) should use LazyCalldataLoad (mixed Direct/Decode), \ + got DecodeCalldataPayload" + ); + } + other => panic!( + "withArray should use LazyCalldataLoad, got {:?}", + std::mem::discriminant(&other) + ), + } + } + + #[test] + fn lazy_calldataload_all_arrays_uses_full_decode() { + let mut db = DriverDataBase::default(); + let file_url = Url::parse("file:///lazy_calldataload_all_arrays.fe").unwrap(); + db.workspace().touch( + &mut db, + file_url.clone(), + Some( + r#" +use std::abi::sol + +msg AllArraysMsg { + #[selector = sol("allArrays(uint256[2],uint256[3])")] + AllArrays { a: [u256; 2], b: [u256; 3] }, +} + +pub contract AllArraysBox { + recv AllArraysMsg { + AllArrays { a, b } {} + } +} +"# + .to_string(), + ), + ); + let file = db + .workspace() + .get(&db, &file_url) + .expect("file should be loaded"); + let top_mod = db.top_mod(file); + + let plan = recv_wrapper_plan(&db, top_mod, "allArrays(uint256[2],uint256[3])"); + // All fields are arrays (not scalars), so lazy_field_strategies should + // return None (all Decode). The plan should remain DecodeCalldataPayload. + assert!( + matches!(plan.input, RuntimeInputPlan::DecodeCalldataPayload { .. }), + "all-array msg should use DecodeCalldataPayload (not LazyCalldataLoad), got {:?}", + std::mem::discriminant(&plan.input) + ); + } + + #[test] + fn lazy_calldataload_array_before_scalar_uses_accumulated_offsets() { + // When a multi-word field (array) with a statically known size + // precedes scalar fields, the accumulated offset formula still works. + // The array field uses Decode, the trailing scalars use Direct at + // their correct accumulated offsets. + let mut db = DriverDataBase::default(); + let file_url = Url::parse("file:///lazy_calldataload_array_before_scalar.fe").unwrap(); + db.workspace().touch( + &mut db, + file_url.clone(), + Some( + r#" +use std::abi::sol + +msg ArrayBeforeScalarMsg { + #[selector = sol("arrayFirst(uint256[32],uint256,uint256)")] + ArrayFirst { data: [u256; 32], x: u256, y: u256 }, +} + +pub contract ArrayBeforeScalarBox { + recv ArrayBeforeScalarMsg { + ArrayFirst { data, x, y } {} + } +} +"# + .to_string(), + ), + ); + let file = db + .workspace() + .get(&db, &file_url) + .expect("file should be loaded"); + let top_mod = db.top_mod(file); + + let plan = recv_wrapper_plan(&db, top_mod, "arrayFirst(uint256[32],uint256,uint256)"); + // The array [u256; 32] has a known static ABI size (32 * 32 = 1024 bytes), + // so accumulated offsets are valid for the trailing scalars. + match plan.input { + RuntimeInputPlan::LazyCalldataLoad { + field_strategies, .. + } => { + assert_eq!(field_strategies.len(), 3); + assert_eq!( + field_strategies[0], + FieldLoadStrategy::Decode, + "[u256; 32] should use Decode" + ); + assert_eq!( + field_strategies[1], + FieldLoadStrategy::Direct, + "x (u256 after array) should use Direct at accumulated offset" + ); + assert_eq!( + field_strategies[2], + FieldLoadStrategy::Direct, + "y (u256 after array) should use Direct at accumulated offset" + ); + } + other => panic!( + "arrayFirst should use LazyCalldataLoad, got {:?}", + std::mem::discriminant(&other) + ), + } + } + + #[test] + fn lazy_calldataload_merkle_pattern_scalars_before_array() { + let mut db = DriverDataBase::default(); + let file_url = Url::parse("file:///lazy_calldataload_merkle.fe").unwrap(); + db.workspace().touch( + &mut db, + file_url.clone(), + Some( + r#" +use std::abi::sol + +msg MerkleMsg { + #[selector = sol("computeRoot(uint256,uint256,uint256,uint256[32])")] + ComputeRoot { leaf: u256, index: u256, siblings_len: u256, siblings: [u256; 32] }, +} + +pub contract MerkleBox { + recv MerkleMsg { + ComputeRoot { leaf, index, siblings_len, siblings } {} + } +} +"# + .to_string(), + ), + ); + let file = db + .workspace() + .get(&db, &file_url) + .expect("file should be loaded"); + let top_mod = db.top_mod(file); + + let plan = recv_wrapper_plan( + &db, + top_mod, + "computeRoot(uint256,uint256,uint256,uint256[32])", + ); + match plan.input { + RuntimeInputPlan::LazyCalldataLoad { + field_strategies, .. + } => { + assert_eq!(field_strategies.len(), 4); + assert_eq!( + field_strategies[0], + FieldLoadStrategy::Direct, + "leaf (u256, position 0) should be Direct" + ); + assert_eq!( + field_strategies[1], + FieldLoadStrategy::Direct, + "index (u256, position 1) should be Direct" + ); + assert_eq!( + field_strategies[2], + FieldLoadStrategy::Direct, + "siblings_len (u256, position 2) should be Direct" + ); + assert_eq!( + field_strategies[3], + FieldLoadStrategy::Decode, + "siblings ([u256; 32]) must use Decode" + ); + } + other => panic!( + "merkle-pattern msg should use LazyCalldataLoad, got {:?}", + std::mem::discriminant(&other) + ), + } + } + + #[test] + fn lazy_calldataload_array_view_uses_skip_with_offset() { + let mut db = DriverDataBase::default(); + let file_url = Url::parse("file:///lazy_calldataload_array_view.fe").unwrap(); + db.workspace().touch( + &mut db, + file_url.clone(), + Some( + r#" +use std::abi::sol +use std::abi::ArrayView + +msg SkipMsg { + #[selector = sol("withSkip(uint256,uint256[32],uint256)")] + WithSkip { id: u256, data: ArrayView, tail: u256 }, +} + +pub contract SkipBox { + recv SkipMsg { + WithSkip { id, data, tail } {} + } +} +"# + .to_string(), + ), + ); + let file = db + .workspace() + .get(&db, &file_url) + .expect("file should be loaded"); + let top_mod = db.top_mod(file); + + let plan = recv_wrapper_plan(&db, top_mod, "withSkip(uint256,uint256[32],uint256)"); + match plan.input { + RuntimeInputPlan::LazyCalldataLoad { + field_strategies, + projected_fields, + .. + } => { + assert_eq!( + field_strategies.len(), + 3, + "array-view msg should have 3 field strategies" + ); + assert_eq!( + field_strategies[0], + FieldLoadStrategy::Direct, + "id (u256, position 0) should be Direct" + ); + assert_eq!( + field_strategies[1], + FieldLoadStrategy::SkipWithOffset { head_size: 1024 }, + "data (ArrayView) should be SkipWithOffset with head_size 1024" + ); + assert_eq!( + field_strategies[2], + FieldLoadStrategy::Direct, + "tail (u256, position 2) should be Direct" + ); + assert_eq!( + projected_fields.as_ref(), + &[0, 1, 2], + "all three fields should be projected" + ); + } + other => panic!( + "withSkip should use LazyCalldataLoad, got {:?}", + std::mem::discriminant(&other) + ), + } + } + + #[test] + fn lazy_calldataload_bytes_view_uses_lazy_dynamic_view() { + let mut db = DriverDataBase::default(); + let file_url = Url::parse("file:///lazy_calldataload_bytes_view.fe").unwrap(); + db.workspace().touch( + &mut db, + file_url.clone(), + Some( + r#" +use std::abi::sol +use std::abi::BytesView + +msg BytesViewMsg { + #[selector = sol("withBytes(uint256,bytes)")] + WithBytes { id: u256, data: BytesView<()> }, +} + +pub contract BytesViewBox { + recv BytesViewMsg { + WithBytes { id, data } { + // id is non-mut scalar -> Direct + // data is BytesView (non-mut, dynamic) -> LazyDynamicView + } + } +} +"# + .to_string(), + ), + ); + let file = db + .workspace() + .get(&db, &file_url) + .expect("file should be loaded"); + let top_mod = db.top_mod(file); + + let plan = recv_wrapper_plan(&db, top_mod, "withBytes(uint256,bytes)"); + match plan.input { + RuntimeInputPlan::LazyCalldataLoad { + field_strategies, + projected_fields, + .. + } => { + assert_eq!( + field_strategies.len(), + 2, + "bytes view msg should have 2 field strategies" + ); + assert_eq!( + field_strategies[0], + FieldLoadStrategy::Direct, + "non-mut u256 `id` should use Direct load" + ); + assert_eq!( + field_strategies[1], + FieldLoadStrategy::LazyDynamicView { + is_string_view: false + }, + "non-mut BytesView `data` should use LazyDynamicView" + ); + assert_eq!( + projected_fields.as_ref(), + &[0, 1], + "both fields should be projected" + ); + } + other => panic!( + "withBytes should use LazyCalldataLoad, got {:?}", + std::mem::discriminant(&other) + ), + } + } + + #[test] + fn lazy_calldataload_string_view_uses_lazy_dynamic_view() { + let mut db = DriverDataBase::default(); + let file_url = Url::parse("file:///lazy_calldataload_string_view.fe").unwrap(); + db.workspace().touch( + &mut db, + file_url.clone(), + Some( + r#" +use std::abi::sol +use std::abi::StringView + +msg StringViewMsg { + #[selector = sol("withString(uint256,string)")] + WithString { id: u256, name: StringView<()> }, +} + +pub contract StringViewBox { + recv StringViewMsg { + WithString { id, name } { + // id is non-mut scalar -> Direct + // name is StringView (non-mut, dynamic) -> LazyDynamicView + } + } +} +"# + .to_string(), + ), + ); + let file = db + .workspace() + .get(&db, &file_url) + .expect("file should be loaded"); + let top_mod = db.top_mod(file); + + let plan = recv_wrapper_plan(&db, top_mod, "withString(uint256,string)"); + match plan.input { + RuntimeInputPlan::LazyCalldataLoad { + field_strategies, + projected_fields, + .. + } => { + assert_eq!( + field_strategies.len(), + 2, + "string view msg should have 2 field strategies" + ); + assert_eq!( + field_strategies[0], + FieldLoadStrategy::Direct, + "non-mut u256 `id` should use Direct load" + ); + assert_eq!( + field_strategies[1], + FieldLoadStrategy::LazyDynamicView { + is_string_view: true + }, + "non-mut StringView `name` should use LazyDynamicView(is_string_view=true)" + ); + assert_eq!( + projected_fields.as_ref(), + &[0, 1], + "both fields should be projected" + ); + } + other => panic!( + "withString should use LazyCalldataLoad, got {:?}", + std::mem::discriminant(&other) + ), + } + } + + #[test] + fn lazy_calldataload_mut_bytes_view_forces_decode() { + let mut db = DriverDataBase::default(); + let file_url = Url::parse("file:///lazy_calldataload_mut_bytes_view.fe").unwrap(); + db.workspace().touch( + &mut db, + file_url.clone(), + Some( + r#" +use std::abi::sol +use std::abi::BytesView + +msg MutBytesViewMsg { + #[selector = sol("mutBytes(uint256,bytes)")] + MutBytes { id: u256, data: BytesView<()> }, +} + +pub contract MutBytesViewBox { + recv MutBytesViewMsg { + MutBytes { id, mut data } { + // id is non-mut scalar -> Direct + // data is mut BytesView -> must Decode (not LazyDynamicView) + } + } +} +"# + .to_string(), + ), + ); + let file = db + .workspace() + .get(&db, &file_url) + .expect("file should be loaded"); + let top_mod = db.top_mod(file); + + let plan = recv_wrapper_plan(&db, top_mod, "mutBytes(uint256,bytes)"); + match plan.input { + RuntimeInputPlan::LazyCalldataLoad { + field_strategies, .. + } => { + assert_eq!(field_strategies.len(), 2); + assert_eq!( + field_strategies[0], + FieldLoadStrategy::Direct, + "non-mut u256 `id` should use Direct" + ); + assert_eq!( + field_strategies[1], + FieldLoadStrategy::Decode, + "mut BytesView `data` must use Decode, not LazyDynamicView" + ); + } + other => panic!( + "mutBytes should use LazyCalldataLoad, got {:?}", + std::mem::discriminant(&other) + ), + } + } + + #[test] + fn lazy_calldataload_bytes_view_after_dynamic_field_falls_back_to_decode() { + // When a dynamic field precedes a BytesView field, the BytesView's + // head offset is not statically known, so it must fall back to Decode. + let mut db = DriverDataBase::default(); + let file_url = Url::parse("file:///lazy_calldataload_bytes_view_after_dynamic.fe").unwrap(); + db.workspace().touch( + &mut db, + file_url.clone(), + Some( + r#" +use std::abi::sol +use std::abi::{BytesView, StringView} + +msg DynamicFirstMsg { + #[selector = sol("dynFirst(bytes,bytes)")] + DynFirst { a: BytesView<()>, b: BytesView<()> }, +} + +pub contract DynamicFirstBox { + recv DynamicFirstMsg { + DynFirst { a, b } {} + } +} +"# + .to_string(), + ), + ); + let file = db + .workspace() + .get(&db, &file_url) + .expect("file should be loaded"); + let top_mod = db.top_mod(file); + + let plan = recv_wrapper_plan(&db, top_mod, "dynFirst(bytes,bytes)"); + // Both fields are BytesView. The first one gets LazyDynamicView + // (head offset statically known at byte 4), the second one also + // gets LazyDynamicView because the first has a static head size of 32. + match plan.input { + RuntimeInputPlan::LazyCalldataLoad { + field_strategies, .. + } => { + assert_eq!(field_strategies.len(), 2); + // Both BytesView fields have HEAD_SIZE=32, so both have + // statically known head offsets. + assert_eq!( + field_strategies[0], + FieldLoadStrategy::LazyDynamicView { + is_string_view: false + }, + "first BytesView should use LazyDynamicView" + ); + assert_eq!( + field_strategies[1], + FieldLoadStrategy::LazyDynamicView { + is_string_view: false + }, + "second BytesView should also use LazyDynamicView (head offset is static)" + ); + } + RuntimeInputPlan::DecodeCalldataPayload { .. } => { + panic!( + "dynFirst(bytes,bytes) should use LazyCalldataLoad \ + (both LazyDynamicView), got DecodeCalldataPayload" + ); + } + other => panic!( + "dynFirst should use LazyCalldataLoad, got {:?}", + std::mem::discriminant(&other) + ), + } + } } diff --git a/crates/mir/src/runtime/synthetic.rs b/crates/mir/src/runtime/synthetic.rs index 4840175474..39d3c44682 100644 --- a/crates/mir/src/runtime/synthetic.rs +++ b/crates/mir/src/runtime/synthetic.rs @@ -25,12 +25,13 @@ use crate::{ layout_size_bytes, runtime::{ AddressSpaceKind, BorrowAccess, ConstScalar, ContractInitAbiPlan, ContractRecvAbiPlan, - DispatchDefault, EntryEffectArgPlan, InitArgsPlan, PlaceElem, PlaceRoot, RBlock, RBlockId, - RExpr, RLocal, RLocalId, RStmt, RTerminator, RefKind, RefView, RuntimeBody, - RuntimeBoundarySpec, RuntimeBuiltin, RuntimeCarrier, RuntimeClass, RuntimeExitBehavior, - RuntimeInputPlan, RuntimeInterfaceSignature, RuntimeLocalRoot, RuntimeParamPlan, - RuntimePlace, RuntimeReturnPlan, RuntimeSyntheticSpec, ScalarClass, ScalarRepr, ScalarRole, - TargetRootProviderBinding, TargetRootProviderMaterialization, + DispatchDefault, DispatchStrategy, EntryEffectArgPlan, FieldLoadStrategy, InitArgsPlan, + PlaceElem, PlaceRoot, RBlock, RBlockId, RExpr, RLocal, RLocalId, RStmt, RTerminator, + RefKind, RefView, RuntimeBody, RuntimeBoundarySpec, RuntimeBuiltin, RuntimeCarrier, + RuntimeClass, RuntimeExitBehavior, RuntimeInputPlan, RuntimeInterfaceSignature, + RuntimeLocalRoot, RuntimeParamPlan, RuntimePlace, RuntimeReturnPlan, RuntimeSyntheticSpec, + ScalarClass, ScalarRepr, ScalarRole, TargetRootProviderBinding, + TargetRootProviderMaterialization, lower::{ boundary::{RuntimeValueAddress, RuntimeValueSource}, classify::{ref_class_for_place_result, semantic_return_ty}, @@ -105,8 +106,11 @@ pub(crate) fn lower_synthetic_runtime_body<'db>( .. } => builder.build_contract_init_root(init_abi, runtime_region), RuntimeSyntheticSpec::ContractRuntimeRoot { - dispatch, default, .. - } => builder.build_contract_runtime_root(&dispatch, default), + dispatch, + default, + dispatch_strategy, + .. + } => builder.build_contract_runtime_root(&dispatch, default, dispatch_strategy), } builder.finish() } @@ -477,52 +481,317 @@ impl<'db> SyntheticBodyBuilder<'db> { }; let mut call_args = Vec::new(); - if let RuntimeInputPlan::DecodeCalldataPayload { - msg_ty, - decode_fn, - projected_fields, - } = plan.input - { - let size = self.push_builtin_value( - cont_bb, - TyId::u256(self.db), - RuntimeClass::Scalar(word_scalar_class()), - RuntimeBuiltin::CallDataSize, - ); - let payload_len = self.push_binary_word(cont_bb, ArithBinOp::Sub, size, four); - let payload_ptr = self.push_builtin_value( - cont_bb, - TyId::u256(self.db), - RuntimeClass::Scalar(word_scalar_class()), - RuntimeBuiltin::Malloc { size: payload_len }, - ); - self.push_side_effect_builtin( - cont_bb, - RuntimeBuiltin::CallDataCopy { - dst: payload_ptr, - offset: four, - len: payload_len, - }, - ); - let input = self.push_memory_bytes_value( - cont_bb, - plan.contract.scope(), - payload_ptr, - payload_len, - ); - let decoder_new = - resolve_sol_decoder_new(self.db, plan.contract.scope()).expect("decoder_new"); - let decoder = self.push_call_result(cont_bb, decoder_new, vec![input]); - if let Some(decoded) = self.push_call(cont_bb, decode_fn, vec![decoder]) { - call_args.extend(self.extract_selected_tuple_fields( + match plan.input { + RuntimeInputPlan::None => {} + + RuntimeInputPlan::DirectCalldataLoad { + msg_ty, + field_head_sizes, + projected_fields, + } => { + // Optimized path: load each field directly from calldata at + // known offsets. Offsets are computed from per-field HEAD_SIZE + // values queried from the AbiSize trait. + // + // calldataload always returns a raw u256 word. If the target + // field has a narrower scalar class (u64, bool, etc.) we emit + // a Cast to match the handler's expected representation. + let field_types = msg_ty.field_types(self.db); + let env = self.runtime_type_env(plan.contract.scope()); + let mut loaded_fields = Vec::with_capacity(field_head_sizes.len()); + let mut calldata_offset: u32 = 4; // skip 4-byte selector + for (i, &head_size) in field_head_sizes.iter().enumerate() { + let offset = self.push_const_word(cont_bb, calldata_offset); + // Load as raw u256 (matches calldataload's output class) + let raw = self.push_builtin_value( + cont_bb, + TyId::u256(self.db), + RuntimeClass::Scalar(word_scalar_class()), + RuntimeBuiltin::CallDataLoad { offset }, + ); + let field_ty = field_types[i]; + let field_scalar = match top_level_class_for_ty_in_env( + self.db, + env, + field_ty, + AddressSpaceKind::Memory, + ) { + Some(RuntimeClass::Scalar(sc)) => sc, + _ => word_scalar_class(), + }; + // Cast to the field's actual scalar class if needed + let value = if field_scalar == word_scalar_class() { + raw + } else { + let casted = self.push_local( + field_ty, + RuntimeCarrier::Value(RuntimeClass::Scalar(field_scalar.clone())), + RuntimeLocalRoot::None, + ); + self.push_stmt( + cont_bb, + RStmt::Assign { + dst: casted, + expr: RExpr::Cast { + value: raw, + to: field_scalar, + }, + }, + ); + casted + }; + loaded_fields.push(value); + calldata_offset += head_size; + } + // Select the fields the handler expects, in the order it + // expects them (projected_fields maps handler param position + // to struct field index). + for &field_idx in projected_fields.iter() { + call_args.push(loaded_fields[field_idx as usize]); + } + } + + RuntimeInputPlan::DecodeCalldataPayload { + msg_ty, + decode_fn, + projected_fields, + } => { + // Generic path: malloc + calldatacopy + SolDecoder + let size = self.push_builtin_value( + cont_bb, + TyId::u256(self.db), + RuntimeClass::Scalar(word_scalar_class()), + RuntimeBuiltin::CallDataSize, + ); + let payload_len = self.push_binary_word(cont_bb, ArithBinOp::Sub, size, four); + let payload_ptr = self.push_builtin_value( + cont_bb, + TyId::u256(self.db), + RuntimeClass::Scalar(word_scalar_class()), + RuntimeBuiltin::Malloc { size: payload_len }, + ); + self.push_side_effect_builtin( + cont_bb, + RuntimeBuiltin::CallDataCopy { + dst: payload_ptr, + offset: four, + len: payload_len, + }, + ); + let input = self.push_memory_bytes_value( cont_bb, - decoded, - msg_ty, plan.contract.scope(), - &projected_fields, - )); + payload_ptr, + payload_len, + ); + let decoder_new = + resolve_sol_decoder_new(self.db, plan.contract.scope()).expect("decoder_new"); + let decoder = self.push_call_result(cont_bb, decoder_new, vec![input]); + if let Some(decoded) = self.push_call(cont_bb, decode_fn, vec![decoder]) { + call_args.extend(self.extract_selected_tuple_fields( + cont_bb, + decoded, + msg_ty, + plan.contract.scope(), + &projected_fields, + )); + } + } + + RuntimeInputPlan::LazyCalldataLoad { + msg_ty, + decode_fn, + field_strategies, + projected_fields, + } => { + // Hybrid path: direct-load non-mut scalar fields via + // calldataload, skip ArrayView fields by passing the + // calldata offset, decode the rest through the standard + // pipeline. + let field_types = msg_ty.field_types(self.db); + let env = self.runtime_type_env(plan.contract.scope()); + + // Phase 1: direct-load and skip-with-offset fields at known + // ABI offsets. Accumulated byte offset starts after the + // 4-byte selector. + let mut loaded_fields: Vec> = vec![None; field_strategies.len()]; + let mut accumulated_offset: u32 = 4; + for (i, strategy) in field_strategies.iter().enumerate() { + match *strategy { + FieldLoadStrategy::Direct => { + let offset = self.push_const_word(cont_bb, accumulated_offset); + let raw = self.push_builtin_value( + cont_bb, + TyId::u256(self.db), + RuntimeClass::Scalar(word_scalar_class()), + RuntimeBuiltin::CallDataLoad { offset }, + ); + let field_ty = field_types[i]; + let field_scalar = match top_level_class_for_ty_in_env( + self.db, + env, + field_ty, + AddressSpaceKind::Memory, + ) { + Some(RuntimeClass::Scalar(sc)) => sc, + _ => word_scalar_class(), + }; + let value = if field_scalar == word_scalar_class() { + raw + } else { + let casted = self.push_local( + field_ty, + RuntimeCarrier::Value(RuntimeClass::Scalar( + field_scalar.clone(), + )), + RuntimeLocalRoot::None, + ); + self.push_stmt( + cont_bb, + RStmt::Assign { + dst: casted, + expr: RExpr::Cast { + value: raw, + to: field_scalar, + }, + }, + ); + casted + }; + loaded_fields[i] = Some(value); + accumulated_offset += 32; + } + FieldLoadStrategy::SkipWithOffset { head_size } => { + // Construct an ArrayView value whose `start` + // field holds the absolute calldata byte offset. + let field_ty = field_types[i]; + let field_class = top_level_class_for_ty_in_env( + self.db, + env, + field_ty, + AddressSpaceKind::Memory, + ) + .expect("SkipWithOffset field should have a runtime class"); + + let offset_val = self.push_const_word(cont_bb, accumulated_offset); + let value = self.push_array_view_value( + cont_bb, + field_ty, + &field_class, + offset_val, + ); + loaded_fields[i] = Some(value); + accumulated_offset += head_size; + } + FieldLoadStrategy::LazyDynamicView { is_string_view } => { + // Read the dynamic offset pointer from the head slot, + // follow it to the tail, read the length word, and + // construct an unbound BytesView/StringView. + let field_ty = field_types[i]; + let field_class = top_level_class_for_ty_in_env( + self.db, + env, + field_ty, + AddressSpaceKind::Memory, + ) + .expect("LazyDynamicView field should have a runtime class"); + + let value = self.push_dynamic_view_from_calldata( + cont_bb, + accumulated_offset, + field_ty, + &field_class, + is_string_view, + ); + loaded_fields[i] = Some(value); + // Dynamic types have a 32-byte head slot (offset pointer). + accumulated_offset += 32; + } + FieldLoadStrategy::Decode => { + // Track the offset for Decode fields too, if + // their static size is known (needed to keep + // accumulated_offset correct for subsequent + // fields). + if let Some(size) = crate::runtime::package::static_abi_head_size( + self.db, + field_types[i], + ) { + accumulated_offset += size; + } + // The actual value is filled in Phase 2. + } + } + } + + // Phase 2: decode the remaining fields through the full + // calldatacopy + SolDecoder pipeline. + if let Some(decode_fn) = decode_fn { + let size = self.push_builtin_value( + cont_bb, + TyId::u256(self.db), + RuntimeClass::Scalar(word_scalar_class()), + RuntimeBuiltin::CallDataSize, + ); + let payload_len = self.push_binary_word(cont_bb, ArithBinOp::Sub, size, four); + let payload_ptr = self.push_builtin_value( + cont_bb, + TyId::u256(self.db), + RuntimeClass::Scalar(word_scalar_class()), + RuntimeBuiltin::Malloc { size: payload_len }, + ); + self.push_side_effect_builtin( + cont_bb, + RuntimeBuiltin::CallDataCopy { + dst: payload_ptr, + offset: four, + len: payload_len, + }, + ); + let input = self.push_memory_bytes_value( + cont_bb, + plan.contract.scope(), + payload_ptr, + payload_len, + ); + let decoder_new = resolve_sol_decoder_new(self.db, plan.contract.scope()) + .expect("decoder_new"); + let decoder = self.push_call_result(cont_bb, decoder_new, vec![input]); + if let Some(decoded) = self.push_call(cont_bb, decode_fn, vec![decoder]) { + // Extract only the Decode fields from the decoded + // tuple, filling them into loaded_fields. + let decode_field_indices: Vec = field_strategies + .iter() + .enumerate() + .filter(|(_, s)| **s == FieldLoadStrategy::Decode) + .map(|(i, _)| i as u32) + .collect(); + let decoded_values = self.extract_selected_tuple_fields( + cont_bb, + decoded, + msg_ty, + plan.contract.scope(), + &decode_field_indices, + ); + let mut decode_iter = decoded_values.into_iter(); + for (i, strategy) in field_strategies.iter().enumerate() { + if *strategy == FieldLoadStrategy::Decode { + loaded_fields[i] = decode_iter.next(); + } + } + } + } + + // Phase 3: select the fields the handler expects, in the + // order it expects them (projected_fields maps handler param + // position to struct field index). + for &field_idx in projected_fields.iter() { + if let Some(value) = loaded_fields[field_idx as usize] { + call_args.push(value); + } + } } } + call_args.extend(self.owner_effect_call_args( cont_bb, plan.user_recv, @@ -538,7 +807,27 @@ impl<'db> SyntheticBodyBuilder<'db> { len: zero, }; } + + RuntimeReturnPlan::DirectScalarReturn { .. } => { + // Optimized path: mstore the scalar at offset 0, return 32 + // bytes. Skips the encode_single_root_alloc call entirely. + let ret_value = ret.expect("value-returning recv wrapper should produce a value"); + self.push_side_effect_builtin( + cont_bb, + RuntimeBuiltin::Mstore { + addr: zero, + value: ret_value, + }, + ); + let thirty_two = self.push_const_word(cont_bb, 32); + self.blocks[cont_bb.index()].terminator = RTerminator::ReturnData { + offset: zero, + len: thirty_two, + }; + } + RuntimeReturnPlan::Value { .. } => { + // Generic path: call encode_single_root_alloc let ret_value = ret.expect("value-returning recv wrapper should produce a value"); let scope = plan.contract.scope(); let encode_alloc = resolve_sol_encode_single_root_alloc( @@ -603,6 +892,7 @@ impl<'db> SyntheticBodyBuilder<'db> { &mut self, dispatch: &[crate::runtime::DispatchArm<'db>], default: DispatchDefault<'db>, + strategy: DispatchStrategy, ) { let zero = self.push_const_word(RBlockId::from_u32(0), 0); let selector = self.push_builtin_value( @@ -631,11 +921,62 @@ impl<'db> SyntheticBodyBuilder<'db> { args: Box::default(), }, }; - self.blocks[0].terminator = RTerminator::SwitchScalar { - discr: selector, - cases: cases.into_boxed_slice(), - default: default_bb, + match strategy { + DispatchStrategy::Linear => { + self.blocks[0].terminator = RTerminator::SwitchScalar { + discr: selector, + cases: cases.into_boxed_slice(), + default: default_bb, + }; + } + DispatchStrategy::BinarySearch => { + self.emit_dispatch_tree(selector, RBlockId::from_u32(0), &cases, default_bb); + } + } + } + + fn emit_dispatch_tree( + &mut self, + selector: RLocalId, + into_block: RBlockId, + arms: &[(ConstScalar, RBlockId)], + default_block: RBlockId, + ) { + let terminator = match arms.len() { + 0 => RTerminator::Goto(default_block), + 1 => { + let selector_match = self.push_selector_const(into_block, arms[0].0.clone()); + let cond = + self.push_bool_binary(into_block, CompBinOp::Eq, selector, selector_match); + RTerminator::Branch { + cond, + then_bb: arms[0].1, + else_bb: default_block, + } + } + _ => { + let pivot_idx = (arms.len() - 1) / 2; + let pivot = arms[pivot_idx].0.clone(); + let left_block = self.new_block(); + let right_block = self.new_block(); + let pivot_value = self.push_selector_const(into_block, pivot); + let cond = + self.push_bool_binary(into_block, CompBinOp::LtEq, selector, pivot_value); + self.emit_dispatch_tree(selector, left_block, &arms[..=pivot_idx], default_block); + self.emit_dispatch_tree( + selector, + right_block, + &arms[pivot_idx + 1..], + default_block, + ); + RTerminator::Branch { + cond, + then_bb: left_block, + else_bb: right_block, + } + } }; + self.blocks[into_block.index()].terminator = terminator; } fn emit_nonpayable_guard(&mut self, zero: RLocalId) -> RBlockId { @@ -1149,6 +1490,22 @@ impl<'db> SyntheticBodyBuilder<'db> { ) } + fn push_selector_const(&mut self, bb: RBlockId, value: ConstScalar) -> RLocalId { + let dst = self.push_local( + TyId::u256(self.db), + RuntimeCarrier::Value(RuntimeClass::Scalar(selector_scalar_class())), + RuntimeLocalRoot::None, + ); + self.push_stmt( + bb, + RStmt::Assign { + dst, + expr: RExpr::ConstScalar(value), + }, + ); + dst + } + fn push_const_scalar(&mut self, bb: RBlockId, value: ConstScalar) -> RLocalId { let dst = self.push_local( TyId::u256(self.db), @@ -1239,6 +1596,152 @@ impl<'db> SyntheticBodyBuilder<'db> { local } + /// Construct an unbound `ArrayView` aggregate value with `start` set to + /// `offset_value`. The unbound ArrayView has fields `(input: (), start: u256)`; + /// field 0 (`input`) is zero-sized and needs no store, field 1 (`start`) + /// receives the calldata byte offset. + fn push_array_view_value( + &mut self, + bb: RBlockId, + semantic_ty: TyId<'db>, + class: &RuntimeClass<'db>, + offset_value: RLocalId, + ) -> RLocalId { + let local = self.push_local( + semantic_ty, + RuntimeCarrier::Value(class.clone()), + RuntimeLocalRoot::Slot(class.clone()), + ); + let root = PlaceRoot::Slot(local); + self.push_stmt( + bb, + RStmt::Store { + dst: RuntimePlace { + root, + path: vec![PlaceElem::Field(hir::analysis::semantic::FieldIndex(1))] + .into_boxed_slice(), + }, + src: offset_value, + }, + ); + local + } + + /// Construct an unbound `BytesView` or `StringView` value by reading the + /// dynamic offset pointer and length directly from calldata. + /// + /// ABI encoding of dynamic types: the head slot at `head_offset` (absolute + /// calldata byte position) contains a byte offset relative to the ABI + /// payload start (byte 4). Following that offset leads to the tail, which + /// starts with a 32-byte length word followed by the padded data. + /// + /// For BytesView: fields are `(input: (), start: u256, len: u256)`. + /// For StringView: field is `(bytes: BytesView<()>)`, so we store into + /// nested field paths. + fn push_dynamic_view_from_calldata( + &mut self, + bb: RBlockId, + head_offset: u32, + semantic_ty: TyId<'db>, + class: &RuntimeClass<'db>, + is_string_view: bool, + ) -> RLocalId { + // Step 1: Read the offset pointer from the head slot. + // calldataload(head_offset) gives the byte offset relative to payload start. + let head_pos = self.push_const_word(bb, head_offset); + let rel_offset = self.push_builtin_value( + bb, + TyId::u256(self.db), + RuntimeClass::Scalar(word_scalar_class()), + RuntimeBuiltin::CallDataLoad { offset: head_pos }, + ); + + // Step 2: Compute the absolute calldata position of the tail. + // tail_abs = 4 + rel_offset (payload starts at byte 4 after selector) + let selector_size = self.push_const_word(bb, 4); + let tail_abs = self.push_binary_word(bb, ArithBinOp::Add, rel_offset, selector_size); + + // Step 3: Read the length word from the start of the tail. + let data_len = self.push_builtin_value( + bb, + TyId::u256(self.db), + RuntimeClass::Scalar(word_scalar_class()), + RuntimeBuiltin::CallDataLoad { offset: tail_abs }, + ); + + // Step 4: Compute data_start = tail_abs + 32 (skip the length word). + let thirty_two = self.push_const_word(bb, 32); + let data_start = self.push_binary_word(bb, ArithBinOp::Add, tail_abs, thirty_two); + + // Step 5: Construct the aggregate value. + let local = self.push_local( + semantic_ty, + RuntimeCarrier::Value(class.clone()), + RuntimeLocalRoot::Slot(class.clone()), + ); + let root = PlaceRoot::Slot(local); + + if is_string_view { + // StringView has field 0 = bytes: BytesView<()>. + // BytesView has field 0 = input: () (zero-sized), field 1 = start, field 2 = len. + // Store into nested field paths: [0, 1] for start, [0, 2] for len. + self.push_stmt( + bb, + RStmt::Store { + dst: RuntimePlace { + root: root.clone(), + path: vec![ + PlaceElem::Field(hir::analysis::semantic::FieldIndex(0)), + PlaceElem::Field(hir::analysis::semantic::FieldIndex(1)), + ] + .into_boxed_slice(), + }, + src: data_start, + }, + ); + self.push_stmt( + bb, + RStmt::Store { + dst: RuntimePlace { + root: root.clone(), + path: vec![ + PlaceElem::Field(hir::analysis::semantic::FieldIndex(0)), + PlaceElem::Field(hir::analysis::semantic::FieldIndex(2)), + ] + .into_boxed_slice(), + }, + src: data_len, + }, + ); + } else { + // BytesView has field 0 = input: () (zero-sized), field 1 = start, field 2 = len. + self.push_stmt( + bb, + RStmt::Store { + dst: RuntimePlace { + root: root.clone(), + path: vec![PlaceElem::Field(hir::analysis::semantic::FieldIndex(1))] + .into_boxed_slice(), + }, + src: data_start, + }, + ); + self.push_stmt( + bb, + RStmt::Store { + dst: RuntimePlace { + root: root.clone(), + path: vec![PlaceElem::Field(hir::analysis::semantic::FieldIndex(2))] + .into_boxed_slice(), + }, + src: data_len, + }, + ); + } + + local + } + fn push_synthetic_default_value( &mut self, bb: RBlockId, diff --git a/crates/mir/src/verify/package.rs b/crates/mir/src/verify/package.rs index c7e707ff4a..49244acae2 100644 --- a/crates/mir/src/verify/package.rs +++ b/crates/mir/src/verify/package.rs @@ -3,9 +3,9 @@ use rustc_hash::FxHashSet; use crate::{ db::MirDb, runtime::{ - DispatchDefault, RExpr, RStmt, RTerminator, ResolvedCodeRegion, RuntimeCodeRegion, - RuntimeFunctionOwner, RuntimeObject, RuntimePackage, RuntimeProgramView, - RuntimeSyntheticSpec, + DispatchArm, DispatchDefault, RBlockId, RExpr, RStmt, RTerminator, ResolvedCodeRegion, + RuntimeBody, RuntimeCodeRegion, RuntimeFunctionOwner, RuntimeObject, RuntimePackage, + RuntimeProgramView, RuntimeSyntheticSpec, code_region::{code_region_runtime_entry, code_region_section_name, code_region_symbol}, }, verify::{VerifyError, verify_runtime_body}, @@ -137,46 +137,7 @@ fn verify_synthetic_function<'db>( RuntimeFunctionOwner::Synthetic(spec) => match spec { RuntimeSyntheticSpec::ContractRuntimeRoot { dispatch, default, .. - } => { - let Some(entry) = body.blocks.first() else { - return Err(VerifyError::InvalidReturnClass); - }; - let RTerminator::SwitchScalar { - cases, - default: default_bb, - .. - } = &entry.terminator - else { - return Err(VerifyError::InvalidReturnClass); - }; - if cases.len() != dispatch.len() { - return Err(VerifyError::InvalidReturnClass); - } - for ((_, block), arm) in cases.iter().zip(dispatch.iter()) { - let Some(target) = body.block(*block) else { - return Err(VerifyError::MissingRuntimeBlock(*block)); - }; - let RTerminator::TerminalCall { callee, args } = &target.terminator else { - return Err(VerifyError::InvalidReturnClass); - }; - if *callee != arm.wrapper || !args.is_empty() { - return Err(VerifyError::InvalidReturnClass); - } - } - - let Some(default_target) = body.block(*default_bb) else { - return Err(VerifyError::MissingRuntimeBlock(*default_bb)); - }; - match (default, &default_target.terminator) { - (DispatchDefault::RevertEmpty, RTerminator::Revert { .. }) => {} - ( - DispatchDefault::Call { wrapper }, - RTerminator::TerminalCall { callee, args }, - ) if *callee == wrapper && args.is_empty() => {} - _ => return Err(VerifyError::InvalidReturnClass), - } - Ok(()) - } + } => verify_contract_runtime_dispatch(body, &dispatch, default), RuntimeSyntheticSpec::ContractInitRoot { .. } => { verify_has_terminator(body, |term| matches!(term, RTerminator::ReturnData { .. })) } @@ -195,6 +156,164 @@ fn verify_synthetic_function<'db>( } } +fn verify_contract_runtime_dispatch<'db>( + body: &RuntimeBody<'db>, + dispatch: &[DispatchArm<'db>], + default: DispatchDefault<'db>, +) -> Result<(), VerifyError<'db>> { + let Some(entry) = body.blocks.first() else { + return Err(VerifyError::InvalidReturnClass); + }; + + if let RTerminator::SwitchScalar { + cases, + default: default_bb, + .. + } = &entry.terminator + { + return verify_contract_runtime_switch(body, dispatch, default, cases, *default_bb); + } + + let mut seen_blocks = FxHashSet::default(); + let mut seen_arms = vec![false; dispatch.len()]; + let mut saw_default = false; + verify_contract_runtime_dispatch_block( + body, + RBlockId::from_u32(0), + dispatch, + default, + &mut seen_arms, + &mut saw_default, + &mut seen_blocks, + )?; + + if saw_default && seen_arms.into_iter().all(|seen| seen) { + Ok(()) + } else { + Err(VerifyError::InvalidReturnClass) + } +} + +fn verify_contract_runtime_switch<'db>( + body: &RuntimeBody<'db>, + dispatch: &[DispatchArm<'db>], + default: DispatchDefault<'db>, + cases: &[(crate::runtime::ConstScalar, RBlockId)], + default_bb: RBlockId, +) -> Result<(), VerifyError<'db>> { + if cases.len() != dispatch.len() { + return Err(VerifyError::InvalidReturnClass); + } + for ((_, block), arm) in cases.iter().zip(dispatch.iter()) { + verify_contract_runtime_arm_target(body, *block, arm)?; + } + + verify_contract_runtime_default_target(body, default_bb, default) +} + +fn verify_contract_runtime_dispatch_block<'db>( + body: &RuntimeBody<'db>, + block: RBlockId, + dispatch: &[DispatchArm<'db>], + default: DispatchDefault<'db>, + seen_arms: &mut [bool], + saw_default: &mut bool, + seen_blocks: &mut FxHashSet, +) -> Result<(), VerifyError<'db>> { + if !seen_blocks.insert(block) { + return Ok(()); + } + + let Some(target) = body.block(block) else { + return Err(VerifyError::MissingRuntimeBlock(block)); + }; + match &target.terminator { + RTerminator::Goto(target) => verify_contract_runtime_dispatch_block( + body, + *target, + dispatch, + default, + seen_arms, + saw_default, + seen_blocks, + ), + RTerminator::Branch { + then_bb, else_bb, .. + } => { + verify_contract_runtime_dispatch_block( + body, + *then_bb, + dispatch, + default, + seen_arms, + saw_default, + seen_blocks, + )?; + verify_contract_runtime_dispatch_block( + body, + *else_bb, + dispatch, + default, + seen_arms, + saw_default, + seen_blocks, + ) + } + RTerminator::TerminalCall { callee, args } if args.is_empty() => { + if let Some(idx) = dispatch.iter().position(|arm| arm.wrapper == *callee) { + seen_arms[idx] = true; + Ok(()) + } else if matches!(default, DispatchDefault::Call { wrapper } if wrapper == *callee) { + *saw_default = true; + Ok(()) + } else { + Err(VerifyError::InvalidReturnClass) + } + } + RTerminator::Revert { .. } if matches!(default, DispatchDefault::RevertEmpty) => { + *saw_default = true; + Ok(()) + } + _ => Err(VerifyError::InvalidReturnClass), + } +} + +fn verify_contract_runtime_arm_target<'db>( + body: &RuntimeBody<'db>, + block: RBlockId, + arm: &DispatchArm<'db>, +) -> Result<(), VerifyError<'db>> { + let Some(target) = body.block(block) else { + return Err(VerifyError::MissingRuntimeBlock(block)); + }; + let RTerminator::TerminalCall { callee, args } = &target.terminator else { + return Err(VerifyError::InvalidReturnClass); + }; + if *callee != arm.wrapper || !args.is_empty() { + return Err(VerifyError::InvalidReturnClass); + } + Ok(()) +} + +fn verify_contract_runtime_default_target<'db>( + body: &RuntimeBody<'db>, + block: RBlockId, + default: DispatchDefault<'db>, +) -> Result<(), VerifyError<'db>> { + let Some(target) = body.block(block) else { + return Err(VerifyError::MissingRuntimeBlock(block)); + }; + match (default, &target.terminator) { + (DispatchDefault::RevertEmpty, RTerminator::Revert { .. }) => Ok(()), + (DispatchDefault::Call { wrapper }, RTerminator::TerminalCall { callee, args }) + if *callee == wrapper && args.is_empty() => + { + Ok(()) + } + _ => Err(VerifyError::InvalidReturnClass), + } +} + fn verify_has_terminator<'db>( body: &crate::runtime::RuntimeBody<'db>, pred: impl Fn(&RTerminator<'db>) -> bool, diff --git a/crates/parser/src/ast/param.rs b/crates/parser/src/ast/param.rs index 67195c839e..0fadecc76c 100644 --- a/crates/parser/src/ast/param.rs +++ b/crates/parser/src/ast/param.rs @@ -292,6 +292,11 @@ impl WhereClause { pub fn where_kw(&self) -> Option { support::token(self.syntax(), SK::WhereKw) } + + /// Returns an iterator over const predicates `{ expr }` in this where clause. + pub fn const_predicates(&self) -> impl Iterator { + support::children(self.syntax()) + } } ast_node! { @@ -299,6 +304,18 @@ ast_node! { pub struct WherePredicate, SK::WherePredicate, } + +ast_node! { + /// `{ const_expr }` in a where clause + pub struct WhereConstPredicate, + SK::WhereConstPredicate, +} +impl WhereConstPredicate { + /// Returns the block expression inside the const predicate. + pub fn expr(&self) -> Option { + support::child(self.syntax()) + } +} impl WherePredicate { /// Returns `T` in `T: Trait`. pub fn ty(&self) -> Option { @@ -717,6 +734,45 @@ mod tests { assert!(count == 3); } + #[test] + #[wasm_bindgen_test] + fn where_clause_with_const_predicate() { + // The const predicate `{ true }` must be followed by something that + // shows it is not the item body. Here a trailing comma + another + // type predicate achieves that. + let source = r#"where { true }, T: Trait"#; + let wc = parse_where_clause(source); + + let type_preds: Vec<_> = wc.iter().collect(); + assert_eq!(type_preds.len(), 1); + assert!(matches!( + type_preds[0].ty().unwrap().kind(), + TypeKind::Path(_) + )); + + let const_preds: Vec<_> = wc.const_predicates().collect(); + assert_eq!(const_preds.len(), 1); + assert!(const_preds[0].expr().is_some()); + } + + #[test] + #[wasm_bindgen_test] + fn where_clause_const_predicate_then_body() { + // In real code, `fn foo() where T: Trait, { expr } { body }` -- + // the const predicate is followed by the item body `{`. + // Test via a full function parse. + let f = parse_func("fn foo() where T: Trait, { true } {}"); + let wc = f.sig().where_clause().expect("missing where clause"); + + let type_preds: Vec<_> = wc.iter().collect(); + assert_eq!(type_preds.len(), 1); + + let const_preds: Vec<_> = wc.const_predicates().collect(); + assert_eq!(const_preds.len(), 1); + + assert!(f.body().is_some(), "function body should still be parsed"); + } + #[test] #[wasm_bindgen_test] fn generic_param_with_assoc_type() { diff --git a/crates/parser/src/parser/param.rs b/crates/parser/src/parser/param.rs index b5abcd3de2..4ab28449ca 100644 --- a/crates/parser/src/parser/param.rs +++ b/crates/parser/src/parser/param.rs @@ -476,10 +476,18 @@ impl super::Parse for WhereClauseScope { parser.bump_expected(SyntaxKind::WhereKw); let mut pred_count = 0; + // Track whether a comma was just consumed. A `{` is only parsed as a + // const predicate when preceded by a comma (or as the first predicate + // right after `where`). Without a comma, `{` is the item body. + let mut after_comma = true; loop { parser.set_newline_as_trivia(true); match parser.current_kind() { + Some(SyntaxKind::LBrace) if after_comma && is_where_const_predicate(parser) => { + parser.parse(WhereConstPredicateScope::default())?; + pred_count += 1; + } Some(kind) if is_type_start(kind) => { parser.parse(WherePredicateScope::default())?; pred_count += 1; @@ -487,7 +495,8 @@ impl super::Parse for WhereClauseScope { _ => break, } - if !parser.bump_if(SyntaxKind::Comma) + after_comma = parser.bump_if(SyntaxKind::Comma); + if !after_comma && parser.current_kind().is_some() && is_type_start(parser.current_kind().unwrap()) { @@ -509,6 +518,7 @@ impl super::Parse for WhereClauseScope { }, )? { parser.bump(); + after_comma = true; } else { break; } @@ -542,6 +552,36 @@ impl super::Parse for WherePredicateScope { } } +define_scope! { WhereConstPredicateScope, WhereConstPredicate } +impl super::Parse for WhereConstPredicateScope { + type Error = Recovery; + + fn parse(&mut self, parser: &mut Parser) -> Result<(), Self::Error> { + parser.parse(BlockExprScope::default())?; + Ok(()) + } +} + +/// Disambiguate `{ expr }` (const predicate) from `{ body }` (function/struct +/// body). Uses a dry run: parse the block expression, then check if what +/// follows looks like more where predicates or the item body `{`. +fn is_where_const_predicate(parser: &mut Parser) -> bool { + parser.dry_run(|p| { + if p.parse_ok(BlockExprScope::default()).is_err() { + return false; + } + // After the closing `}`, if another `{` (body), comma, or type start + // follows, this block was a const predicate. At EOF or before a + // non-where token, it was the item body. + match p.current_kind() { + Some(SyntaxKind::Comma) => true, + Some(kind) if is_type_start(kind) => true, + Some(SyntaxKind::LBrace) => true, + _ => false, + } + }) +} + pub(crate) fn parse_where_clause_opt( parser: &mut Parser, ) -> Result<(), Recovery> { diff --git a/crates/parser/src/syntax_kind.rs b/crates/parser/src/syntax_kind.rs index 5a7bff11be..a91be51e9b 100644 --- a/crates/parser/src/syntax_kind.rs +++ b/crates/parser/src/syntax_kind.rs @@ -515,6 +515,8 @@ pub enum SyntaxKind { WhereClause, /// `Option: Trait1 + Trait2` WherePredicate, + /// `{ const_expr }` in a where clause + WhereConstPredicate, /// `Transfer { to: Address, amount: u256 } -> bool` MsgVariant, /// `{ to: Address, amount: u256 }` @@ -794,6 +796,7 @@ impl SyntaxKind { SyntaxKind::KindBoundMono => "kind bound", SyntaxKind::WhereClause => "`where` clause", SyntaxKind::WherePredicate => "`where` predicate", + SyntaxKind::WhereConstPredicate => "`where` const predicate", SyntaxKind::UsesClause => "`uses` clause", SyntaxKind::UsesParamList => "`uses` parameter list", SyntaxKind::UsesParam => "`uses` parameter", diff --git a/crates/uitest/fixtures/ty_check/where_const_predicate.fe b/crates/uitest/fixtures/ty_check/where_const_predicate.fe new file mode 100644 index 0000000000..5450441675 --- /dev/null +++ b/crates/uitest/fixtures/ty_check/where_const_predicate.fe @@ -0,0 +1,20 @@ +fn good() where T: Add, { true } +{ +} + +fn bad() where T: Add, { false } +{ +} + +trait Add {} + +struct Foo {} +impl Add for Foo {} + +fn call_good() { + good() +} + +fn call_bad() { + bad() +} diff --git a/crates/uitest/fixtures/ty_check/where_const_predicate.snap b/crates/uitest/fixtures/ty_check/where_const_predicate.snap new file mode 100644 index 0000000000..102fd2fdcd --- /dev/null +++ b/crates/uitest/fixtures/ty_check/where_const_predicate.snap @@ -0,0 +1,11 @@ +--- +source: crates/uitest/tests/ty_check.rs +assertion_line: 27 +expression: diags +input_file: fixtures/ty_check/where_const_predicate.fe +--- +error[8-0082]: where clause const predicate failed + ┌─ where_const_predicate.fe:19:5 + │ +19 │ bad() + │ ^^^^^^^^ const predicate evaluated to `false` diff --git a/crates/uitest/fixtures/ty_check/where_const_predicate_arithmetic.fe b/crates/uitest/fixtures/ty_check/where_const_predicate_arithmetic.fe new file mode 100644 index 0000000000..6ff243c7a4 --- /dev/null +++ b/crates/uitest/fixtures/ty_check/where_const_predicate_arithmetic.fe @@ -0,0 +1,25 @@ +trait Sized { + const SIZE: u256 +} + +struct Small {} +impl Sized for Small { + const SIZE: u256 = 1 +} + +struct Big {} +impl Sized for Big { + const SIZE: u256 = 100 +} + +fn needs_big() where T: Sized, { T::SIZE >= 50 } +{ +} + +fn ok_call() { + needs_big() +} + +fn bad_call() { + needs_big() +} diff --git a/crates/uitest/fixtures/ty_check/where_const_predicate_arithmetic.snap b/crates/uitest/fixtures/ty_check/where_const_predicate_arithmetic.snap new file mode 100644 index 0000000000..b57cf20f1b --- /dev/null +++ b/crates/uitest/fixtures/ty_check/where_const_predicate_arithmetic.snap @@ -0,0 +1,11 @@ +--- +source: crates/uitest/tests/ty_check.rs +assertion_line: 27 +expression: diags +input_file: fixtures/ty_check/where_const_predicate_arithmetic.fe +--- +error[8-0082]: where clause const predicate failed + ┌─ where_const_predicate_arithmetic.fe:24:5 + │ +24 │ needs_big() + │ ^^^^^^^^^^^^^^^^ const predicate evaluated to `false` diff --git a/ingots/core/src/abi.fe b/ingots/core/src/abi.fe index 5a7ab41fb8..0a9152d247 100644 --- a/ingots/core/src/abi.fe +++ b/ingots/core/src/abi.fe @@ -137,6 +137,13 @@ pub trait AbiDecoder { fn read_word(mut self) -> u256 fn peek_word(self, _ at: u256) -> u256 + /// Advance the cursor by `bytes` without reading or validating. + /// Used to skip over unused fixed-size fields in ABI decoding. + #[arithmetic(unchecked)] + fn skip_bytes(mut self, _ bytes: u256) { + self.set_pos(self.pos() + bytes) + } + fn alloc(mut self, _ size: u256) -> u256 } @@ -177,6 +184,7 @@ pub trait Encode: AbiSize { fn encode_to_ptr(own self, _ ptr: u256) } +#[inline(always)] pub fn decode_or_revert(d: mut D) -> T where T: Decode, D: AbiDecoder { @@ -198,10 +206,12 @@ pub const fn abi_single_root_head_size() -> u256 { abi_field_head_size() } +#[inline(always)] pub fn abi_payload_size(_ value: T) -> u256 { value.payload_size() } +#[inline(always)] pub fn abi_field_size(_ value: T) -> u256 { let payload_size = value.payload_size() if T::IS_DYNAMIC { @@ -210,6 +220,7 @@ pub fn abi_field_size(_ value: T) -> u256 { payload_size } +#[inline(always)] pub fn abi_single_root_size(_ value: T) -> u256 { abi_field_size(value) } @@ -221,6 +232,7 @@ pub fn dynamic_payload_size(_ value: T) -> u256 { 0 } +#[inline(always)] pub fn decode_payload_root(_ d: mut D) -> T where T: Decode, D: AbiDecoder @@ -228,6 +240,7 @@ pub fn decode_payload_root(_ d: mut D) -> T T::decode_payload(d) } +#[inline(always)] pub fn decode_single_root(_ d: mut D) -> T where T: Decode + AbiSize, D: AbiDecoder @@ -235,6 +248,7 @@ pub fn decode_single_root(_ d: mut D) -> T decode_field(mut d) } +#[inline(always)] pub fn decode_field(_ d: mut D) -> T where T: Decode + AbiSize, D: AbiDecoder @@ -254,6 +268,17 @@ pub fn decode_field(_ d: mut D) -> T T::decode_payload(d) } +/// Skip past a fixed-size field without decoding it. +/// Advances the decoder cursor by the field's head size. +/// For fixed-size types this skips the entire encoding. +/// For dynamic types this only skips the offset pointer (32 bytes). +pub fn skip_field(_ d: mut D) + where T: AbiSize, + D: AbiDecoder +{ + d.skip_bytes(abi_field_head_size()) +} + fn decode_field_at(d: mut D, pos: u256) -> T where T: Decode + AbiSize, D: AbiDecoder @@ -262,6 +287,7 @@ fn decode_field_at(d: mut D, pos: u256) -> T decode_field(mut d) } +#[inline(always)] #[arithmetic(unchecked)] pub fn encode_root(_ value: own T, _ e: mut E) where T: Encode, E: AbiEncoder @@ -276,6 +302,7 @@ pub fn encode_root(_ value: own T, _ e: mut E) value.encode(mut e) } +#[inline(always)] #[arithmetic(unchecked)] pub fn encode_single_root(_ value: own T, _ e: mut E) where T: Encode + AbiSize, E: AbiEncoder @@ -284,6 +311,7 @@ pub fn encode_single_root(_ value: own T, _ e: mut E) encode_field(value, mut e, mut tail) } +#[inline(always)] #[arithmetic(unchecked)] pub fn encode_field(_ value: own T, _ e: mut E, _ tail: mut u256) where T: Encode + AbiSize, E: AbiEncoder @@ -375,6 +403,14 @@ fn packed_string_len(_ word: u256) -> u256 { len } +/// A zero-copy view over a `bytes` payload in ABI-encoded data. +/// +/// When `I` defaults to `()`, the view is *unbound* -- it records only the +/// data start offset and length. Call `.over(input)` to bind a byte source +/// and get a `BytesView` with byte/word access. +/// +/// `BytesView` is a bound zero-copy view over calldata. +/// `BytesView` (= `BytesView<()>`) is an unbound position. pub struct BytesView { pub input: I, pub start: u256, @@ -385,9 +421,12 @@ impl Copy for BytesView where I: Copy {} -impl BytesView - where I: ByteInput -{ +impl BytesView { + /// Construct a BytesView with the given input, start offset, and length. + fn from_parts(_ input: I, _ start: u256, _ len: u256) -> Self { + BytesView { input, start, len } + } + pub fn len(self) -> u256 { self.len } @@ -395,7 +434,11 @@ impl BytesView pub fn is_empty(self) -> bool { self.len == 0 } +} +impl BytesView + where I: ByteInput +{ #[arithmetic(unchecked)] pub fn byte_at(self, _ offset: u256) -> u8 { self.input.byte_at(self.start + offset) @@ -407,6 +450,17 @@ impl BytesView } } +impl BytesView<()> { + /// Bind a byte source to produce a bound `BytesView` with byte access. + pub fn over(self, _ input: I) -> BytesView { + BytesView::from_parts(input, self.start, self.len) + } +} + +/// A zero-copy view over a `string` payload in ABI-encoded data. +/// +/// `StringView<()>` is an unbound position -- call `.over(input)` to bind a +/// byte source for character access. pub struct StringView { pub bytes: BytesView, } @@ -415,17 +469,24 @@ impl Copy for StringView where I: Copy {} -impl StringView - where I: ByteInput -{ +impl StringView { + /// Construct a StringView from a BytesView. + fn from_bytes(_ bytes: BytesView) -> Self { + StringView { bytes } + } + pub fn len(self) -> u256 { - self.bytes.len() + self.bytes.len } pub fn is_empty(self) -> bool { - self.bytes.is_empty() + self.bytes.len == 0 } +} +impl StringView + where I: ByteInput +{ pub fn byte_at(self, _ offset: u256) -> u8 { self.bytes.byte_at(offset) } @@ -435,6 +496,92 @@ impl StringView } } +impl StringView<()> { + /// Bind a byte source to produce a bound `StringView` with character access. + pub fn over(self, _ input: J) -> StringView { + let bound_bytes = BytesView::from_parts(input, self.bytes.start, self.bytes.len) + StringView::from_bytes(bound_bytes) + } +} + +/// A zero-copy view over a fixed-size array in ABI-encoded data. +/// +/// Instead of decoding all N elements into memory, `ArrayView` stores +/// the byte input source and the offset where the array starts. Elements +/// are read on demand via `get(index)`, paying only for what you use. +/// +/// When `I` defaults to `()`, the view is *unbound* -- it records only the +/// byte offset where the array lives. Call `.over(input)` to bind a byte +/// source and get an `ArrayView` with element access. +/// +/// `ArrayView` is a bound zero-copy view over calldata. +/// `ArrayView` is an unbound position (I defaults to ()). +pub struct ArrayView { + pub input: I, + pub start: u256, +} + +impl Copy for ArrayView + where I: Copy +{} + +impl ArrayView { + /// Construct an ArrayView with the given input and start offset. + fn from_parts(_ input: I, _ start: u256) -> Self { + ArrayView { input, start } + } +} + +impl ArrayView + where T: AbiSize, I: ByteInput +{ + pub fn len(self) -> usize { + N + } + + /// Read element at `index` from the underlying input source. + /// Reads directly from calldata/memory -- no copy. + #[arithmetic(unchecked)] + pub fn get(self, _ index: usize) -> u256 { + let byte_offset = self.start + (index as u256) * abi_field_head_size() + self.input.word_at(byte_offset) + } +} + +impl ArrayView + where T: AbiSize +{ + /// Bind a byte source to produce a bound `ArrayView` with element access. + pub fn over(self, _ input: I) -> ArrayView { + ArrayView::from_parts(input, self.start) + } +} + +impl AbiSize for ArrayView + where T: AbiSize +{ + const HEAD_SIZE: u256 = (N as u256) * abi_field_head_size() + const IS_DYNAMIC: bool = T::IS_DYNAMIC +} + +impl AbiSize for BytesView<()> { + const HEAD_SIZE: u256 = 32 + const IS_DYNAMIC: bool = true + + fn payload_size(self) -> u256 { + 32 + round_up_words(self.len) + } +} + +impl AbiSize for StringView<()> { + const HEAD_SIZE: u256 = 32 + const IS_DYNAMIC: bool = true + + fn payload_size(self) -> u256 { + self.bytes.payload_size() + } +} + /// Owned handle to a Solidity ABI `string` payload stored in linear memory. /// /// `data` points at the ABI tail payload: the length word followed by packed @@ -471,9 +618,7 @@ impl DynString { } pub fn view(self) -> StringView { - StringView { - bytes: self.as_bytes().view(), - } + StringView::from_bytes(self.as_bytes().view()) } pub fn byte_at(self, _ index: u256) -> u8 { @@ -521,11 +666,7 @@ impl Bytes { base: self.data + 32, len: self.len, } - BytesView { - input, - start: 0, - len: self.len, - } + BytesView::from_parts(input, 0, self.len) } pub fn byte_at(self, _ index: u256) -> u8 { @@ -2482,3 +2623,100 @@ impl Encode for [T; N] } } } + +/// Decode an unbound ArrayView: captures the cursor position and advances +/// past the array without copying any elements. Zero cost at decode time. +/// Use `.over(input)` to bind a byte source for element access. +impl Decode for ArrayView + where T: AbiSize +{ + #[arithmetic(unchecked)] + fn decode_payload>(_ d: mut D) -> Self { + let start = d.pos() + let total_bytes = (N as u256) * abi_field_head_size() + d.set_pos(start + total_bytes) + ArrayView { input: (), start } + } +} + +impl AbiSpan for ArrayView + where T: AbiSize +{ + fn payload_end(_ input: I2, base: u256, pos: u256) -> u256 { + let _ = base + pos + (N as u256) * abi_field_head_size() + } +} + +impl Encode for ArrayView + where T: AbiSize +{ + const DIRECT_ENCODE: bool = false + + fn encode>(own self, _ e: mut E) { + super::panic() + } + + fn encode_to_ptr(own self, _ ptr: u256) { + super::panic() + } +} + +/// Decode an unbound BytesView: reads the length word and records the data +/// position, then advances past the padded payload. Zero memory allocation. +/// Use `.over(input)` to bind a byte source for byte access. +impl Decode for BytesView<()> { + #[arithmetic(unchecked)] + fn decode_payload>(_ d: mut D) -> Self { + let data_len = d.read_word() + let data_start = d.pos() + let padded = round_up_words(data_len) + d.set_pos(data_start + padded) + BytesView<()>::from_parts((), data_start, data_len) + } +} + +impl AbiSpan for BytesView<()> { + fn payload_end(_ input: I, base: u256, pos: u256) -> u256 { + let data_len = input.word_at(pos) + pos + 32 + round_up_words(data_len) + } +} + +impl Encode for BytesView<()> { + const DIRECT_ENCODE: bool = false + + fn encode>(own self, _ e: mut E) { + super::panic() + } + + fn encode_to_ptr(own self, _ ptr: u256) { + super::panic() + } +} + +/// Decode an unbound StringView: same zero-copy strategy as BytesView. +impl Decode for StringView<()> { + fn decode_payload>(_ d: mut D) -> Self { + StringView<()>::from_bytes(BytesView<()>::decode_payload(d)) + } +} + +impl AbiSpan for StringView<()> { + fn payload_end(_ input: I, base: u256, pos: u256) -> u256 { + let data_len = input.word_at(pos) + pos + 32 + round_up_words(data_len) + } +} + +impl Encode for StringView<()> { + const DIRECT_ENCODE: bool = false + + fn encode>(own self, _ e: mut E) { + super::panic() + } + + fn encode_to_ptr(own self, _ ptr: u256) { + super::panic() + } +} diff --git a/ingots/std/src/abi.fe b/ingots/std/src/abi.fe index 40583e6df2..8243f2f59f 100644 --- a/ingots/std/src/abi.fe +++ b/ingots/std/src/abi.fe @@ -1,4 +1,4 @@ -pub use core::abi::{Bytes, DynArray, DynString} +pub use core::abi::{ArrayView, Bytes, BytesView, DynArray, DynString, StringView} pub type Text = DynString pub type Vec = DynArray pub use sol::{self, *} diff --git a/ingots/std/src/abi/sol.fe b/ingots/std/src/abi/sol.fe index 2d18eb56cc..a21c580dc6 100644 --- a/ingots/std/src/abi/sol.fe +++ b/ingots/std/src/abi/sol.fe @@ -310,26 +310,32 @@ impl AbiDecoder for SolDecoder { type Input = I + #[inline(always)] fn input(self) -> Self::Input { self.cur.input } + #[inline(always)] fn base(self) -> u256 { self.base } + #[inline(always)] fn set_base(mut self, _ new_base: u256) { self.base = new_base } + #[inline(always)] fn pos(self) -> u256 { self.cur.pos } + #[inline(always)] fn set_pos(mut self, _ new_pos: u256) { self.cur.pos = new_pos } + #[inline(always)] fn read_u8(mut self) -> u8 { let len = self.cur.input.len() let new_pos = self.cur.pos + 1 @@ -341,6 +347,7 @@ impl AbiDecoder for SolDecoder b } + #[inline(always)] fn read_word(mut self) -> u256 { let len = self.cur.input.len() let new_pos = self.cur.pos + 32 @@ -352,6 +359,7 @@ impl AbiDecoder for SolDecoder w } + #[inline(always)] #[arithmetic(unchecked)] fn peek_word(self, _ at: u256) -> u256 { let len = self.cur.input.len() @@ -362,6 +370,7 @@ impl AbiDecoder for SolDecoder self.cur.input.word_at(at) } + #[inline(always)] fn alloc(mut self, _ size: u256) -> u256 { mem::alloc(size) } @@ -383,28 +392,34 @@ impl SolEncoder { } impl AbiEncoder for SolEncoder { + #[inline(always)] fn base(self) -> u256 { self.base } + #[inline(always)] fn set_base(mut self, _ new_base: u256) { self.base = new_base } + #[inline(always)] fn pos(self) -> u256 { self.pos } + #[inline(always)] fn set_pos(mut self, _ new_pos: u256) { self.pos = new_pos } + #[inline(always)] #[arithmetic(unchecked)] fn write_u8(mut self, _ v: u8) { mstore8(addr: self.pos, value: v) self.pos = self.pos + 1 } + #[inline(always)] #[arithmetic(unchecked)] fn write_word(mut self, _ v: u256) { let p = self.pos @@ -412,6 +427,7 @@ impl AbiEncoder for SolEncoder { self.pos = p + 32 } + #[inline(always)] fn write_word_at(mut self, at: u256, value: u256) { mstore(addr: at, value: value) }