Created
May 19, 2020 19:13
-
-
Save loredanacirstea/62343e082857cf6e151a2645c0e3d47a to your computer and use it in GitHub Desktop.
yulToEwasm_for loop - bug
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
====== original source ===== | |
object "TestWasm12" { | |
code { | |
let len := 4 | |
let result := 5 | |
for { let i := 1 } lt(i, len) { i := add(i, 1) } { | |
result := add(result, i) | |
} | |
mstore(0, result) | |
return (0, 32) | |
} | |
} | |
======= ./tests/contracts/c12.yul (Ewasm) ======= | |
Pretty printed source: | |
object "TestWasm12" { | |
code { | |
{ | |
let result := 5 | |
let i := 1 | |
let i_1 := i | |
for { } lt(i_1, 4) { i_1 := add(i_1, i) } | |
{ result := add(result, i_1) } | |
mstore(0, result) | |
return(0, 32) | |
} | |
} | |
} | |
========================== | |
Translated source: | |
object "TestWasm12" { | |
code { | |
function main() | |
{ | |
let result := 0 | |
let result_1 := result | |
let result_2 := result | |
let result_3 := 5 | |
let i := result | |
let i_1 := result | |
let i_2 := result | |
let i_3 := 1 | |
let i_4 := i_3 | |
let _1:i32 := i32.eqz(i32.eqz(i64.eqz(i64.or(i64.or(result, result), i64.or(result, i_3))))) | |
for { } | |
i32.eqz(_1) | |
{ | |
let r4, carry := add_carry(i_4, i_3, 0) | |
let r3, carry_1 := add_carry(i_2, 0, carry) | |
let r2, carry_2 := add_carry(i_1, 0, carry_1) | |
let r1, carry_3 := add_carry(i, 0, carry_2) | |
i := r1 | |
i_1 := r2 | |
i_2 := r3 | |
i_4 := r4 | |
} | |
{ | |
let z:i32 := false | |
switch cmp(i, 0) | |
case 0:i32 { | |
switch cmp(i_1, 0) | |
case 0:i32 { | |
switch cmp(i_2, 0) | |
case 0:i32 { z := i64.lt_u(i_4, 4) } | |
case 1:i32 { z := 0:i32 } | |
default { z := 1:i32 } | |
} | |
case 1:i32 { z := 0:i32 } | |
default { z := 1:i32 } | |
} | |
case 1:i32 { z := 0:i32 } | |
default { z := 1:i32 } | |
let _2, _3, _4, _5 := iszero(0, 0, 0, i64.extend_i32_u(z)) | |
if i32.eqz(i64.eqz(i64.or(i64.or(_2, _3), i64.or(_4, _5)))) { break } | |
let result_4, result_5, result_6, result_7 := add(result, result_1, result_2, result_3, i, i_1, i_2, i_4) | |
result := result_4 | |
result_1 := result_5 | |
result_2 := result_6 | |
result_3 := result_7 | |
} | |
mstore(0, 0, 0, 0, result, result_1, result_2, result_3) | |
return(0, 0, 0, 0, 0, 0, 0, 32) | |
} | |
function add_carry(x, y, c) -> r, r_c | |
{ | |
let t := i64.add(x, y) | |
r := i64.add(t, c) | |
r_c := i64.extend_i32_u(i32.or(i64.lt_u(t, x), i64.lt_u(r, t))) | |
} | |
function add(x1, x2, x3, x4, y1, y2, y3, y4) -> r1, r2, r3, r4 | |
{ | |
let t := i64.add(x4, y4) | |
r4 := i64.add(t, 0) | |
let r3_1, carry := add_carry(x3, y3, i64.extend_i32_u(i32.or(i64.lt_u(t, x4), i64.lt_u(r4, t)))) | |
r3 := r3_1 | |
let r2_1, carry_1 := add_carry(x2, y2, carry) | |
r2 := r2_1 | |
let r1_1, carry_2 := add_carry(x1, y1, carry_1) | |
r1 := r1_1 | |
} | |
function iszero(x1, x2, x3, x4) -> r1, r2, r3, r4 | |
{ | |
r4 := i64.extend_i32_u(i64.eqz(i64.or(i64.or(x1, x2), i64.or(x3, x4)))) | |
} | |
function cmp(a, b) -> r:i32 | |
{ | |
switch i64.lt_u(a, b) | |
case 1:i32 { r := 0xffffffff:i32 } | |
default { r := i64.ne(a, b) } | |
} | |
function u256_to_i32(x1, x2, x3, x4) -> v:i32 | |
{ | |
if i64.ne(0, i64.or(i64.or(x1, x2), x3)) { unreachable() } | |
if i64.ne(0, i64.shr_u(x4, 32)) { unreachable() } | |
v := i32.wrap_i64(x4) | |
} | |
function to_internal_i32ptr(x1, x2, x3, x4) -> r:i32 | |
{ | |
let p:i32 := u256_to_i32(x1, x2, x3, x4) | |
r := i32.add(p, 64:i32) | |
if i32.lt_u(r, p) { unreachable() } | |
} | |
function endian_swap_16(x) -> y | |
{ | |
y := i64.or(i64.and(i64.shl(x, 8), 0xff00), i64.and(i64.shr_u(x, 8), 0xff)) | |
} | |
function endian_swap_32(x) -> y | |
{ | |
let hi := i64.shl(endian_swap_16(x), 16) | |
y := i64.or(hi, endian_swap_16(i64.shr_u(x, 16))) | |
} | |
function endian_swap(x) -> y | |
{ | |
let hi := i64.shl(endian_swap_32(x), 32) | |
y := i64.or(hi, endian_swap_32(i64.shr_u(x, 32))) | |
} | |
function mstore(x1, x2, x3, x4, y1, y2, y3, y4) | |
{ | |
let _1:i32 := to_internal_i32ptr(x1, x2, x3, x4) | |
i64.store(_1, endian_swap(y1)) | |
i64.store(i32.add(_1, 8:i32), endian_swap(y2)) | |
i64.store(i32.add(_1, 16:i32), endian_swap(y3)) | |
i64.store(i32.add(_1, 24:i32), endian_swap(y4)) | |
} | |
function return(x1, x2, x3, x4, y1, y2, y3, y4) | |
{ | |
eth.finish(to_internal_i32ptr(x1, x2, x3, x4), u256_to_i32(y1, y2, y3, y4)) | |
} | |
} | |
} | |
Binary representation: | |
0061736d01000000013a0860000060017e017e60027e7e017e60037e7e7e017e60047e7e7e7e017e60087e7e7e7e7e7e7e7e0060087e7e7e7e7e7e7e7e017e60027f7f0002130108657468657265756d0666696e6973680007030d0c00030604020404010101050505030100010610037e0142000b7e0142000b7e0142000b071102066d656d6f72790200046d61696e00010ab2070ca903011e7e420021002000210120002102420521032000210420002105200021064201210720072108200020008420002007848450ada745ada745ad2109024003402009a745ad500d0102404200210a0240200442001005210b200b42005104400240200542001005210c200c42005104400240200642001005210d200d42005104402008420454ad210a05200d42015104404200210a054201210a0b0b0b05200c42015104404200210a054201210a0b0b0b05200b42015104404200210a054201210a0b0b0b0240420042004200200aa7ad1004210e2300210f23012110230221110b200e200f8420102011848450ada745ad42005204400c030b024020002001200220032004200520062008100321122300211323012114230221150b201221002013210120142102201521030b024020082007420010022116230021170b024020064200201710022118230021190b02402005420020191002211a2300211b0b024020044200201b1002211c2300211d0b201c2104201a210520182106201621080b0b42004200420042002000200120022003100b42004200420042004200420042004220100c0b2c01037e200020017c2105200520027c21032005200054ada72003200554ada772ada7ad21042004240020030b6f010b7e200320077c210c200c42007c210b024020022006200c200354ada7200b200c54ada772ada7ad1002210d2300210e0b200d210a024020012005200e1002210f230021100b200f2109024020002004201010022111230021120b2011210820092400200a2401200b240220080b2301047e200020018420022003848450ada7ad210720052400200624012007240220040b2a01027e02402000200154ad21032003420151044042ffffffff0f2102052000200152ad21020b0b20020b2f01017e4200200020018420028452ad4200520440000b4200200342208852ad4200520440000b2003a7ad210420040b2c01027e2000200120022003100621052005a742c000a76aad21042004a72005a749ad4200520440000b20040b1c01017e20004208864280fe0383200042088842ff018384210120010b1b01027e20001008421086210220022000421088100884210120010b1b01027e20001009422086210220022000422088100984210120010b4a01017e2000200120022003100721082008a72004100a3703002008a74208a76aada72005100a3703002008a74210a76aada72006100a3703002008a74218a76aada72007100a3703000b1c01007e20002001200220031007a720042005200620071006a710000b | |
Text representation: | |
(module | |
(import "ethereum" "finish" (func $eth.finish (param i32 i32))) | |
(memory $memory (export "memory") 1) | |
(export "main" (func $main)) | |
(global $global_ (mut i64) (i64.const 0)) | |
(global $global__4 (mut i64) (i64.const 0)) | |
(global $global__5 (mut i64) (i64.const 0)) | |
(func $main | |
(local $result i64) | |
(local $result_1 i64) | |
(local $result_2 i64) | |
(local $result_3 i64) | |
(local $i i64) | |
(local $i_1 i64) | |
(local $i_2 i64) | |
(local $i_3 i64) | |
(local $i_4 i64) | |
(local $_1 i64) | |
(local $z i64) | |
(local $condition i64) | |
(local $condition_2 i64) | |
(local $condition_3 i64) | |
(local $_2 i64) | |
(local $_3 i64) | |
(local $_4 i64) | |
(local $_5 i64) | |
(local $result_4 i64) | |
(local $result_5 i64) | |
(local $result_6 i64) | |
(local $result_7 i64) | |
(local $r4 i64) | |
(local $carry i64) | |
(local $r3 i64) | |
(local $carry_1 i64) | |
(local $r2 i64) | |
(local $carry_2 i64) | |
(local $r1 i64) | |
(local $carry_3 i64) | |
(local.set $result (i64.const 0)) | |
(local.set $result_1 (local.get $result)) | |
(local.set $result_2 (local.get $result)) | |
(local.set $result_3 (i64.const 5)) | |
(local.set $i (local.get $result)) | |
(local.set $i_1 (local.get $result)) | |
(local.set $i_2 (local.get $result)) | |
(local.set $i_3 (i64.const 1)) | |
(local.set $i_4 (local.get $i_3)) | |
(local.set $_1 (i64.extend_i32_u (i32.eqz (i32.wrap_i64 (i64.extend_i32_u (i32.eqz (i32.wrap_i64 (i64.extend_i32_u (i64.eqz (i64.or (i64.or (local.get $result) (local.get $result)) (i64.or (local.get $result) (local.get $i_3)))))))))))) | |
(block $label_ | |
(loop | |
(br_if $label_ (i64.eqz (i64.extend_i32_u (i32.eqz (i32.wrap_i64 (local.get $_1)))))) | |
(block $label__1 | |
(local.set $z (i64.const 0)) | |
(block | |
(local.set $condition (call $cmp (local.get $i) (i64.const 0))) | |
(if (i64.eq (local.get $condition) (i64.const 0)) (then | |
(block | |
(local.set $condition_2 (call $cmp (local.get $i_1) (i64.const 0))) | |
(if (i64.eq (local.get $condition_2) (i64.const 0)) (then | |
(block | |
(local.set $condition_3 (call $cmp (local.get $i_2) (i64.const 0))) | |
(if (i64.eq (local.get $condition_3) (i64.const 0)) (then | |
(local.set $z (i64.extend_i32_u (i64.lt_u (local.get $i_4) (i64.const 4)))) | |
)(else | |
(if (i64.eq (local.get $condition_3) (i64.const 1)) (then | |
(local.set $z (i64.const 0)) | |
)(else | |
(local.set $z (i64.const 1)) | |
)) | |
)) | |
) | |
)(else | |
(if (i64.eq (local.get $condition_2) (i64.const 1)) (then | |
(local.set $z (i64.const 0)) | |
)(else | |
(local.set $z (i64.const 1)) | |
)) | |
)) | |
) | |
)(else | |
(if (i64.eq (local.get $condition) (i64.const 1)) (then | |
(local.set $z (i64.const 0)) | |
)(else | |
(local.set $z (i64.const 1)) | |
)) | |
)) | |
) | |
(block | |
(local.set $_2 (call $iszero (i64.const 0) (i64.const 0) (i64.const 0) (i64.extend_i32_u (i32.wrap_i64 (local.get $z))))) | |
(local.set $_3 (global.get $global_)) | |
(local.set $_4 (global.get $global__4)) | |
(local.set $_5 (global.get $global__5)) | |
) | |
(if (i64.ne (i64.extend_i32_u (i32.eqz (i32.wrap_i64 (i64.extend_i32_u (i64.eqz (i64.or (i64.or (local.get $_2) (local.get $_3)) (i64.or (local.get $_4) (local.get $_5)))))))) (i64.const 0)) (then | |
(br $label_) | |
)) | |
(block | |
(local.set $result_4 (call $add (local.get $result) (local.get $result_1) (local.get $result_2) (local.get $result_3) (local.get $i) (local.get $i_1) (local.get $i_2) (local.get $i_4))) | |
(local.set $result_5 (global.get $global_)) | |
(local.set $result_6 (global.get $global__4)) | |
(local.set $result_7 (global.get $global__5)) | |
) | |
(local.set $result (local.get $result_4)) | |
(local.set $result_1 (local.get $result_5)) | |
(local.set $result_2 (local.get $result_6)) | |
(local.set $result_3 (local.get $result_7)) | |
) | |
(block | |
(local.set $r4 (call $add_carry (local.get $i_4) (local.get $i_3) (i64.const 0))) | |
(local.set $carry (global.get $global_)) | |
) | |
(block | |
(local.set $r3 (call $add_carry (local.get $i_2) (i64.const 0) (local.get $carry))) | |
(local.set $carry_1 (global.get $global_)) | |
) | |
(block | |
(local.set $r2 (call $add_carry (local.get $i_1) (i64.const 0) (local.get $carry_1))) | |
(local.set $carry_2 (global.get $global_)) | |
) | |
(block | |
(local.set $r1 (call $add_carry (local.get $i) (i64.const 0) (local.get $carry_2))) | |
(local.set $carry_3 (global.get $global_)) | |
) | |
(local.set $i (local.get $r1)) | |
(local.set $i_1 (local.get $r2)) | |
(local.set $i_2 (local.get $r3)) | |
(local.set $i_4 (local.get $r4)) | |
) | |
) | |
(call $mstore (i64.const 0) (i64.const 0) (i64.const 0) (i64.const 0) (local.get $result) (local.get $result_1) (local.get $result_2) (local.get $result_3)) | |
(call $return (i64.const 0) (i64.const 0) (i64.const 0) (i64.const 0) (i64.const 0) (i64.const 0) (i64.const 0) (i64.const 32)) | |
) | |
(func $add_carry | |
(param $x i64) | |
(param $y i64) | |
(param $c i64) | |
(result i64) | |
(local $r i64) | |
(local $r_c i64) | |
(local $t i64) | |
(local.set $t (i64.add (local.get $x) (local.get $y))) | |
(local.set $r (i64.add (local.get $t) (local.get $c))) | |
(local.set $r_c (i64.extend_i32_u (i32.wrap_i64 (i64.extend_i32_u (i32.or (i32.wrap_i64 (i64.extend_i32_u (i64.lt_u (local.get $t) (local.get $x)))) (i32.wrap_i64 (i64.extend_i32_u (i64.lt_u (local.get $r) (local.get $t))))))))) | |
(global.set $global_ (local.get $r_c)) | |
(local.get $r) | |
) | |
(func $add | |
(param $x1 i64) | |
(param $x2 i64) | |
(param $x3 i64) | |
(param $x4 i64) | |
(param $y1 i64) | |
(param $y2 i64) | |
(param $y3 i64) | |
(param $y4 i64) | |
(result i64) | |
(local $r1 i64) | |
(local $r2 i64) | |
(local $r3 i64) | |
(local $r4 i64) | |
(local $t i64) | |
(local $r3_1 i64) | |
(local $carry i64) | |
(local $r2_1 i64) | |
(local $carry_1 i64) | |
(local $r1_1 i64) | |
(local $carry_2 i64) | |
(local.set $t (i64.add (local.get $x4) (local.get $y4))) | |
(local.set $r4 (i64.add (local.get $t) (i64.const 0))) | |
(block | |
(local.set $r3_1 (call $add_carry (local.get $x3) (local.get $y3) (i64.extend_i32_u (i32.wrap_i64 (i64.extend_i32_u (i32.or (i32.wrap_i64 (i64.extend_i32_u (i64.lt_u (local.get $t) (local.get $x4)))) (i32.wrap_i64 (i64.extend_i32_u (i64.lt_u (local.get $r4) (local.get $t)))))))))) | |
(local.set $carry (global.get $global_)) | |
) | |
(local.set $r3 (local.get $r3_1)) | |
(block | |
(local.set $r2_1 (call $add_carry (local.get $x2) (local.get $y2) (local.get $carry))) | |
(local.set $carry_1 (global.get $global_)) | |
) | |
(local.set $r2 (local.get $r2_1)) | |
(block | |
(local.set $r1_1 (call $add_carry (local.get $x1) (local.get $y1) (local.get $carry_1))) | |
(local.set $carry_2 (global.get $global_)) | |
) | |
(local.set $r1 (local.get $r1_1)) | |
(global.set $global_ (local.get $r2)) | |
(global.set $global__4 (local.get $r3)) | |
(global.set $global__5 (local.get $r4)) | |
(local.get $r1) | |
) | |
(func $iszero | |
(param $x1 i64) | |
(param $x2 i64) | |
(param $x3 i64) | |
(param $x4 i64) | |
(result i64) | |
(local $r1 i64) | |
(local $r2 i64) | |
(local $r3 i64) | |
(local $r4 i64) | |
(local.set $r4 (i64.extend_i32_u (i32.wrap_i64 (i64.extend_i32_u (i64.eqz (i64.or (i64.or (local.get $x1) (local.get $x2)) (i64.or (local.get $x3) (local.get $x4)))))))) | |
(global.set $global_ (local.get $r2)) | |
(global.set $global__4 (local.get $r3)) | |
(global.set $global__5 (local.get $r4)) | |
(local.get $r1) | |
) | |
(func $cmp | |
(param $a i64) | |
(param $b i64) | |
(result i64) | |
(local $r i64) | |
(local $condition_6 i64) | |
(block | |
(local.set $condition_6 (i64.extend_i32_u (i64.lt_u (local.get $a) (local.get $b)))) | |
(if (i64.eq (local.get $condition_6) (i64.const 1)) (then | |
(local.set $r (i64.const 4294967295)) | |
)(else | |
(local.set $r (i64.extend_i32_u (i64.ne (local.get $a) (local.get $b)))) | |
)) | |
) | |
(local.get $r) | |
) | |
(func $u256_to_i32 | |
(param $x1 i64) | |
(param $x2 i64) | |
(param $x3 i64) | |
(param $x4 i64) | |
(result i64) | |
(local $v i64) | |
(if (i64.ne (i64.extend_i32_u (i64.ne (i64.const 0) (i64.or (i64.or (local.get $x1) (local.get $x2)) (local.get $x3)))) (i64.const 0)) (then | |
(unreachable))) | |
(if (i64.ne (i64.extend_i32_u (i64.ne (i64.const 0) (i64.shr_u (local.get $x4) (i64.const 32)))) (i64.const 0)) (then | |
(unreachable))) | |
(local.set $v (i64.extend_i32_u (i32.wrap_i64 (local.get $x4)))) | |
(local.get $v) | |
) | |
(func $to_internal_i32ptr | |
(param $x1 i64) | |
(param $x2 i64) | |
(param $x3 i64) | |
(param $x4 i64) | |
(result i64) | |
(local $r i64) | |
(local $p i64) | |
(local.set $p (call $u256_to_i32 (local.get $x1) (local.get $x2) (local.get $x3) (local.get $x4))) | |
(local.set $r (i64.extend_i32_u (i32.add (i32.wrap_i64 (local.get $p)) (i32.wrap_i64 (i64.const 64))))) | |
(if (i64.ne (i64.extend_i32_u (i32.lt_u (i32.wrap_i64 (local.get $r)) (i32.wrap_i64 (local.get $p)))) (i64.const 0)) (then | |
(unreachable))) | |
(local.get $r) | |
) | |
(func $endian_swap_16 | |
(param $x i64) | |
(result i64) | |
(local $y i64) | |
(local.set $y (i64.or (i64.and (i64.shl (local.get $x) (i64.const 8)) (i64.const 65280)) (i64.and (i64.shr_u (local.get $x) (i64.const 8)) (i64.const 255)))) | |
(local.get $y) | |
) | |
(func $endian_swap_32 | |
(param $x i64) | |
(result i64) | |
(local $y i64) | |
(local $hi i64) | |
(local.set $hi (i64.shl (call $endian_swap_16 (local.get $x)) (i64.const 16))) | |
(local.set $y (i64.or (local.get $hi) (call $endian_swap_16 (i64.shr_u (local.get $x) (i64.const 16))))) | |
(local.get $y) | |
) | |
(func $endian_swap | |
(param $x i64) | |
(result i64) | |
(local $y i64) | |
(local $hi i64) | |
(local.set $hi (i64.shl (call $endian_swap_32 (local.get $x)) (i64.const 32))) | |
(local.set $y (i64.or (local.get $hi) (call $endian_swap_32 (i64.shr_u (local.get $x) (i64.const 32))))) | |
(local.get $y) | |
) | |
(func $mstore | |
(param $x1 i64) | |
(param $x2 i64) | |
(param $x3 i64) | |
(param $x4 i64) | |
(param $y1 i64) | |
(param $y2 i64) | |
(param $y3 i64) | |
(param $y4 i64) | |
(local $_1 i64) | |
(local.set $_1 (call $to_internal_i32ptr (local.get $x1) (local.get $x2) (local.get $x3) (local.get $x4))) | |
(i64.store (i32.wrap_i64 (local.get $_1)) (call $endian_swap (local.get $y1))) | |
(i64.store (i32.wrap_i64 (i64.extend_i32_u (i32.add (i32.wrap_i64 (local.get $_1)) (i32.wrap_i64 (i64.const 8))))) (call $endian_swap (local.get $y2))) | |
(i64.store (i32.wrap_i64 (i64.extend_i32_u (i32.add (i32.wrap_i64 (local.get $_1)) (i32.wrap_i64 (i64.const 16))))) (call $endian_swap (local.get $y3))) | |
(i64.store (i32.wrap_i64 (i64.extend_i32_u (i32.add (i32.wrap_i64 (local.get $_1)) (i32.wrap_i64 (i64.const 24))))) (call $endian_swap (local.get $y4))) | |
) | |
(func $return | |
(param $x1 i64) | |
(param $x2 i64) | |
(param $x3 i64) | |
(param $x4 i64) | |
(param $y1 i64) | |
(param $y2 i64) | |
(param $y3 i64) | |
(param $y4 i64) | |
(call $eth.finish (i32.wrap_i64 (call $to_internal_i32ptr (local.get $x1) (local.get $x2) (local.get $x3) (local.get $x4))) (i32.wrap_i64 (call $u256_to_i32 (local.get $y1) (local.get $y2) (local.get $y3) (local.get $y4)))) | |
) | |
) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment