Created
May 17, 2020 22:07
-
-
Save loredanacirstea/a3a92e833e213af81ba12b38b36d7eba 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 "TestWasm11" { | |
code { | |
datacopy(0, dataoffset("Runtime"), datasize("Runtime")) | |
return(0, datasize("Runtime")) | |
} | |
object "Runtime" { | |
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/c11.yul (Ewasm) ======= | |
Pretty printed source: | |
object "TestWasm11" { | |
code { | |
{ | |
let _1 := datasize("Runtime") | |
datacopy(0, dataoffset("Runtime"), _1) | |
return(0, _1) | |
} | |
} | |
object "Runtime" { | |
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 "TestWasm11" { | |
code { | |
function main() | |
{ | |
let _1 := datasize("Runtime") | |
let _2 := 0 | |
let _3:i32 := u256_to_i32(_2, _2, _2, _1) | |
let _4:i32 := u256_to_i32(_2, _2, _2, dataoffset("Runtime")) | |
let p:i32 := u256_to_i32(_2, _2, _2, _2) | |
let r:i32 := i32.add(p, 64:i32) | |
if i32.lt_u(r, p) { unreachable() } | |
eth.codeCopy(r, _4, _3) | |
let _5:i32 := u256_to_i32(_2, _2, _2, _1) | |
let p_1:i32 := u256_to_i32(_2, _2, _2, _2) | |
let r_1:i32 := i32.add(p_1, 64:i32) | |
if i32.lt_u(r_1, p_1) { unreachable() } | |
eth.finish(r_1, _5) | |
} | |
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) | |
} | |
} | |
object "Runtime" { | |
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: | |
0061736d0100000001170460000060047e7e7e7e017e60027f7f0060037f7f7f0002270208657468657265756d08636f6465436f7079000308657468657265756d0666696e697368000203030200010503010001060100071102066d656d6f72790200046d61696e000200cf080752756e74696d650061736d01000000013a0860000060017e017e60027e7e017e60037e7e7e017e60047e7e7e7e017e60087e7e7e7e7e7e7e7e0060087e7e7e7e7e7e7e7e017e60027f7f0002130108657468657265756d0666696e6973680007030d0c00030604020404010101050505030100010610037e0142000b7e0142000b7e0142000b071102066d656d6f72790200046d61696e00010ab2070ca903011e7e420021002000210120002102420521032000210420002105200021064201210720072108200020008420002007848450ada745ada745ad2109024003402009a745ad500d0102404200210a0240200442001005210b200b42005104400240200542001005210c200c42005104400240200642001005210d200d42005104402008420454ad210a05200d42015104404200210a054201210a0b0b0b05200c42015104404200210a054201210a0b0b0b05200b42015104404200210a054201210a0b0b0b0240420042004200200aa7ad1004210e2300210f23012110230221110b200e200f8420102011848450ada745ad42005204400c030b024020002001200220032004200520062008100321122300211323012114230221150b201221002013210120142102201521030b024020082007420010022116230021170b024020064200201710022118230021190b02402005420020191002211a2300211b0b024020044200201b1002211c2300211d0b201c2104201a210520182106201621080b0b42004200420042002000200120022003100b42004200420042004200420042004220100c0b2c01037e200020017c2105200520027c21032005200054ada72003200554ada772ada7ad21042004240020030b6f010b7e200320077c210c200c42007c210b024020022006200c200354ada7200b200c54ada772ada7ad1002210d2300210e0b200d210a024020012005200e1002210f230021100b200f2109024020002004201010022111230021120b2011210820092400200a2401200b240220080b2301047e200020018420022003848450ada7ad210720052400200624012007240220040b2a01027e02402000200154ad21032003420151044042ffffffff0f2102052000200152ad21020b0b20020b2f01017e4200200020018420028452ad4200520440000b4200200342208852ad4200520440000b2003a7ad210420040b2c01027e2000200120022003100621052005a742c000a76aad21042004a72005a749ad4200520440000b20040b1c01017e20004208864280fe0383200042088842ff018384210120010b1b01027e20001008421086210220022000421088100884210120010b1b01027e20001009422086210220022000422088100984210120010b4a01017e2000200120022003100721082008a72004100a3703002008a74208a76aada72005100a3703002008a74210a76aada72006100a3703002008a74218a76aada72007100a3703000b1c01007e20002001200220031007a720042005200620071006a710000b0ac40102910101097e42c70821004200210120012001200120001003210220012001200142f500100321032001200120012001100321042004a742c000a76aad21052005a72004a749ad4200520440000b2005a72003a72002a710002001200120012000100321062001200120012001100321072007a742c000a76aad21082008a72007a749ad4200520440000b2008a72006a710010b2f01017e4200200020018420028452ad4200520440000b4200200342208852ad4200520440000b2003a7ad210420040b | |
Text representation: | |
(module | |
;; sub-module "Runtime" will be encoded as custom section in binary here, but is skipped in text mode. | |
(import "ethereum" "codeCopy" (func $eth.codeCopy (param i32 i32 i32))) | |
(import "ethereum" "finish" (func $eth.finish (param i32 i32))) | |
(memory $memory (export "memory") 1) | |
(export "main" (func $main)) | |
(func $main | |
(local $_1 i64) | |
(local $_2 i64) | |
(local $_3 i64) | |
(local $_4 i64) | |
(local $p i64) | |
(local $r i64) | |
(local $_5 i64) | |
(local $p_1 i64) | |
(local $r_1 i64) | |
(local.set $_1 (datasize "Runtime")) | |
(local.set $_2 (i64.const 0)) | |
(local.set $_3 (call $u256_to_i32 (local.get $_2) (local.get $_2) (local.get $_2) (local.get $_1))) | |
(local.set $_4 (call $u256_to_i32 (local.get $_2) (local.get $_2) (local.get $_2) (dataoffset "Runtime"))) | |
(local.set $p (call $u256_to_i32 (local.get $_2) (local.get $_2) (local.get $_2) (local.get $_2))) | |
(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))) | |
(call $eth.codeCopy (i32.wrap_i64 (local.get $r)) (i32.wrap_i64 (local.get $_4)) (i32.wrap_i64 (local.get $_3))) | |
(local.set $_5 (call $u256_to_i32 (local.get $_2) (local.get $_2) (local.get $_2) (local.get $_1))) | |
(local.set $p_1 (call $u256_to_i32 (local.get $_2) (local.get $_2) (local.get $_2) (local.get $_2))) | |
(local.set $r_1 (i64.extend_i32_u (i32.add (i32.wrap_i64 (local.get $p_1)) (i32.wrap_i64 (i64.const 64))))) | |
(if (i64.ne (i64.extend_i32_u (i32.lt_u (i32.wrap_i64 (local.get $r_1)) (i32.wrap_i64 (local.get $p_1)))) (i64.const 0)) (then | |
(unreachable))) | |
(call $eth.finish (i32.wrap_i64 (local.get $r_1)) (i32.wrap_i64 (local.get $_5))) | |
) | |
(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) | |
) | |
) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment