From 98224d6afc21d49c98bc18c4d55b1facaa1af666 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Mon, 9 Oct 2017 12:24:13 -0700 Subject: [PATCH 01/33] fuzz atomic loads and stores --- src/tools/translate-to-fuzz.h | 26 +- test/passes/translate-to-fuzz.txt | 1242 +++++++++++++++++++++-------- 2 files changed, 928 insertions(+), 340 deletions(-) diff --git a/src/tools/translate-to-fuzz.h b/src/tools/translate-to-fuzz.h index 821416d87a5..a2b0c93938d 100644 --- a/src/tools/translate-to-fuzz.h +++ b/src/tools/translate-to-fuzz.h @@ -780,7 +780,7 @@ class TranslateToFuzzReader { return ret; } - Expression* makeLoad(WasmType type) { + Load* makeNonAtomicLoad(WasmType type) { auto offset = logify(get()); auto ptr = makePointer(); switch (type) { @@ -813,10 +813,20 @@ class TranslateToFuzzReader { } } - Store* makeStore(WasmType type) { + Expression* makeLoad(WasmType type) { + auto* ret = makeNonAtomicLoad(type); + if (oneIn(2)) return ret; + // make it atomic + wasm.memory.shared = true; + ret->isAtomic = true; + ret->align = ret->bytes; + return ret; + } + + Store* makeNonAtomicStore(WasmType type) { if (type == unreachable) { // make a normal store, then make it unreachable - auto* ret = makeStore(getConcreteType()); + auto* ret = makeNonAtomicStore(getConcreteType()); switch (upTo(3)) { case 0: ret->ptr = make(unreachable); break; case 1: ret->value = make(unreachable); break; @@ -861,6 +871,16 @@ class TranslateToFuzzReader { } } + Store* makeStore(WasmType type) { + auto* ret = makeNonAtomicStore(type); + if (oneIn(2)) return ret; + // make it atomic + wasm.memory.shared = true; + ret->isAtomic = true; + ret->align = ret->bytes; + return ret; + } + Expression* makeConst(WasmType type) { Literal value; switch (upTo(4)) { diff --git a/test/passes/translate-to-fuzz.txt b/test/passes/translate-to-fuzz.txt index 3b49f86c1b4..edd79cd0958 100644 --- a/test/passes/translate-to-fuzz.txt +++ b/test/passes/translate-to-fuzz.txt @@ -1,9 +1,9 @@ (module (type $FUNCSIG$j (func (result i64))) (global $hangLimit (mut i32) (i32.const 100)) - (table 0 0 anyfunc) - - (memory $0 1 1) + (table 2 anyfunc) + (elem (i32.const 0) $func_0 $func_1) + (memory $0 (shared 1 1)) (data (i32.const 0) "\00C\00[\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00") (export "func_0" (func $func_0)) (export "hangLimitInitializer" (func $hangLimitInitializer)) @@ -16,7 +16,7 @@ (get_global $hangLimit) ) (return - (i64.const -68719476736) + (i64.const 65535) ) ) (set_global $hangLimit @@ -29,136 +29,121 @@ (block $label$0 (result i64) (nop) (br_if $label$0 - (i64.const 127) - (i32.eqz - (loop $label$37 (result i32) - (block - (if - (i32.eqz - (get_global $hangLimit) - ) - (return - (i64.const -524288) - ) + (loop $label$64 (result i64) + (block + (if + (i32.eqz + (get_global $hangLimit) ) - (set_global $hangLimit - (i32.sub - (get_global $hangLimit) - (i32.const 1) - ) + (return + (i64.const -9223372036854775808) ) ) - (block $label$38 (result i32) - (if - (i32.eqz - (i32.wrap/i64 - (i64.const -82) - ) - ) - (br_if $label$37 - (i32.eqz - (i64.gt_u - (i64.const 79723535910970419) - (i64.const 255) - ) + (set_global $hangLimit + (i32.sub + (get_global $hangLimit) + (i32.const 1) + ) + ) + ) + (block $label$65 (result i64) + (drop + (select + (i64.atomic.load16_s offset=4 + (i32.and + (i32.const -94) + (i32.const 31) ) ) - (block $label$39 - (loop $label$40 - (block - (if - (i32.eqz - (get_global $hangLimit) + (i64.const -84) + (if (result i32) + (block $label$66 (result i32) + (loop $label$67 + (block + (if + (i32.eqz + (get_global $hangLimit) + ) + (return + (i64.const 134217728) + ) ) - (return - (i64.const 1073741824) + (set_global $hangLimit + (i32.sub + (get_global $hangLimit) + (i32.const 1) + ) ) ) - (set_global $hangLimit - (i32.sub - (get_global $hangLimit) - (i32.const 1) + (block $label$68 + (set_local $0 + (loop $label$69 (result i32) + (block + (if + (i32.eqz + (get_global $hangLimit) + ) + (return + (i64.const 9223372036854775807) + ) + ) + (set_global $hangLimit + (i32.sub + (get_global $hangLimit) + (i32.const 1) + ) + ) + ) + (block $label$70 (result i32) + (nop) + (return + (i64.const 4503599627370496) + ) + ) + ) ) ) ) - (set_local $1 - (call $deNan64 - (select - (call $deNan64 - (f64.convert_s/i64 - (i64.const 286791702) - ) - ) - (call $deNan64 - (select - (tee_local $1 - (block $label$44 (result f64) - (set_local $1 - (get_local $1) - ) - (get_local $1) - ) - ) - (call $deNan64 - (f64.copysign - (call $deNan64 - (select - (f64.const 18445) - (f64.const 251925010) - (i32.const 286004740) - ) + (return + (i64.const -35184372088832) + ) + ) + (block $label$71 (result i32) + (block $label$72 + (if + (i32.eqz + (select + (loop $label$75 (result i32) + (block + (if + (i32.eqz + (get_global $hangLimit) ) - (block $label$45 (result f64) - (nop) - (loop $label$46 (result f64) - (block - (if - (i32.eqz - (get_global $hangLimit) - ) - (return - (i64.const -57) - ) - ) - (set_global $hangLimit - (i32.sub - (get_global $hangLimit) - (i32.const 1) - ) - ) - ) - (get_local $1) - ) + (return + (i64.const -9223372036854775808) ) ) - ) - (br_if $label$38 - (i32.reinterpret/f32 - (f32.const -9223372036854775808) - ) - (i32.eqz - (get_local $0) + (set_global $hangLimit + (i32.sub + (get_global $hangLimit) + (i32.const 1) + ) ) ) + (get_local $0) ) - ) - (tee_local $0 - (if (result i32) - (i32.trunc_u/f64 - (get_local $1) - ) - (block $label$41 (result i32) - (nop) - (br $label$40) - ) - (loop $label$42 (result i32) + (tee_local $0 + (get_local $0) + ) + (block $label$73 (result i32) + (loop $label$74 (block (if (i32.eqz (get_global $hangLimit) ) (return - (i64.const 2241978001322417182) + (i64.const 4294967295) ) ) (set_global $hangLimit @@ -168,15 +153,83 @@ ) ) ) - (block (result i32) - (loop $label$43 + (nop) + ) + (br $label$64) + ) + ) + ) + (block $label$76 + (nop) + (drop + (i32.const 225447522) + ) + ) + (nop) + ) + ) + (return + (i64.const 3333579868552515411) + ) + ) + (block $label$77 (result i32) + (block $label$78 + (i32.store16 offset=2 align=1 + (i32.and + (select + (get_local $0) + (block $label$83 (result i32) + (nop) + (br $label$78) + ) + (loop $label$79 (result i32) + (block + (if + (i32.eqz + (get_global $hangLimit) + ) + (return + (i64.const -1) + ) + ) + (set_global $hangLimit + (i32.sub + (get_global $hangLimit) + (i32.const 1) + ) + ) + ) + (block (result i32) + (loop $label$80 + (block + (if + (i32.eqz + (get_global $hangLimit) + ) + (return + (i64.const 4294967211) + ) + ) + (set_global $hangLimit + (i32.sub + (get_global $hangLimit) + (i32.const 1) + ) + ) + ) + (set_local $1 + (f64.const -2) + ) + ) + (br_if $label$79 + (loop $label$81 (result i32) (block (if (i32.eqz (get_global $hangLimit) ) (return - (i64.const -8796093022208) + (i64.const -2147483647) ) ) (set_global $hangLimit @@ -186,30 +239,64 @@ ) ) ) - (set_local $0 - (select - (i32.const -70) - (get_local $0) - (get_local $0) - ) - ) - ) - (br_if $label$42 - (select - (get_local $0) - (get_local $0) - (get_local $0) - ) + (i32.const 1398478431) ) - (f64.le - (call $deNan64 - (f64.min - (get_local $1) - (get_local $1) + ) + (block $label$82 (result i32) + (set_local $1 + (f64.atomic.load offset=22 + (i32.and + (tee_local $0 + (get_local $0) + ) + (i32.const 31) ) ) - (get_local $1) ) + (br $label$64) + ) + ) + ) + ) + (i32.const 31) + ) + (if (result i32) + (select + (br_if $label$77 + (i32.const 2418) + (get_local $0) + ) + (i32.const 65535) + (i32.const 1532516688) + ) + (block $label$84 (result i32) + (drop + (get_local $0) + ) + (i32.const 50) + ) + (block $label$85 (result i32) + (drop + (get_local $1) + ) + (br_if $label$77 + (get_local $0) + (get_local $0) + ) + ) + ) + ) + (br_if $label$64 + (i32.eqz + (tee_local $0 + (tee_local $0 + (if (result i32) + (i32.eqz + (get_local $0) + ) + (get_local $0) + (i32.wrap/i64 + (i64.const -35) ) ) ) @@ -217,42 +304,83 @@ ) ) ) + (br $label$64) ) - (if - (i32.const 1142375256) - (block $label$47 - (block $label$48 - (nop) - (block $label$49 - (set_local $0 - (i32.const -1) + ) + ) + ) + (br $label$64) + ) + ) + (select + (loop $label$6 (result i32) + (block + (if + (i32.eqz + (get_global $hangLimit) + ) + (return + (i64.const 96) + ) + ) + (set_global $hangLimit + (i32.sub + (get_global $hangLimit) + (i32.const 1) + ) + ) + ) + (block (result i32) + (block $label$7 + (if + (block $label$8 (result i32) + (nop) + (block $label$9 (result i32) + (br $label$7) + ) + ) + (drop + (call $deNan64 + (select + (f64.const 49) + (call $deNan64 + (f64.reinterpret/i64 + (i64.const -1024) ) - (loop $label$50 - (block - (if - (i32.eqz - (get_global $hangLimit) + ) + (i32.popcnt + (select + (loop $label$13 (result i32) + (block + (if + (i32.eqz + (get_global $hangLimit) + ) + (return + (i64.const -128) + ) ) - (return - (i64.const 8589934592) + (set_global $hangLimit + (i32.sub + (get_global $hangLimit) + (i32.const 1) + ) ) ) - (set_global $hangLimit - (i32.sub - (get_global $hangLimit) - (i32.const 1) - ) + (tee_local $0 + (get_local $0) ) ) - (block $label$51 - (loop $label$52 + (get_local $0) + (select + (loop $label$10 (result i32) (block (if (i32.eqz (get_global $hangLimit) ) (return - (i64.const 15442) + (i64.const 2147483646) ) ) (set_global $hangLimit @@ -262,204 +390,589 @@ ) ) ) - (block - (f64.store offset=3 align=4 - (i32.and - (select - (i32.const 255) - (br_if $label$38 - (get_local $0) - (get_local $0) - ) - (i32.const -4194304) - ) - (i32.const 31) - ) - (get_local $1) - ) - (br_if $label$52 - (i32.const 111) - ) - (nop) - ) + (get_local $0) ) - (set_local $0 - (block $label$53 (result i32) - (set_local $0 - (i32.const -512) + (tee_local $0 + (block $label$11 (result i32) + (block $label$12 + (set_local $1 + (get_local $1) + ) + (nop) ) - (br $label$47) + (br $label$7) ) ) + (i32.const -16) ) ) ) ) - (block $label$54 - (set_local $1 - (f64.const 36028797018963968) - ) - ) ) - (if - (i32.eqz - (select - (get_local $0) - (block $label$60 (result i32) - (br_if $label$37 + ) + (block $label$18 + (br_if $label$18 + (if (result i32) + (block $label$19 (result i32) + (nop) + (br_if $label$19 + (if (result i32) (i32.eqz - (i32.const -4194304) - ) - ) - (select - (br_if $label$60 (tee_local $0 - (get_local $0) - ) - (i32.eqz - (block $label$61 (result i32) - (nop) - (get_local $0) - ) + (i32.const -2) ) ) (if (result i32) - (i32.eqz - (if (result i32) + (i32.const 35) + (f64.eq + (get_local $1) + (if (result f64) (i32.eqz - (i64.ne - (i64.const -1024) - (i64.load32_u offset=4 - (i32.and - (get_local $0) - (i32.const 31) - ) + (i32.const 3) + ) + (get_local $1) + (f64.const -nan:0xfffffffffff99) + ) + ) + (block $label$20 (result i32) + (block $label$21 + (set_local $1 + (f64.const 48964419687002166075064320) + ) + (set_local $0 + (i32.atomic.load8_u offset=2 + (i32.and + (get_local $0) + (i32.const 31) ) ) ) - (block $label$62 (result i32) - (set_local $0 - (get_local $0) + ) + (i32.const -19) + ) + ) + (get_local $0) + ) + (get_local $0) + ) + ) + (block $label$22 (result i32) + (if + (select + (i32.const 252465421) + (loop $label$23 (result i32) + (block + (if + (i32.eqz + (get_global $hangLimit) + ) + (return + (i64.const 4294967295) + ) + ) + (set_global $hangLimit + (i32.sub + (get_global $hangLimit) + (i32.const 1) + ) + ) + ) + (block (result i32) + (nop) + (br_if $label$23 + (get_local $0) + ) + (i32.const 1113085277) + ) + ) + (i32.const -2147483648) + ) + (block $label$24 + (loop $label$25 + (block + (if + (i32.eqz + (get_global $hangLimit) + ) + (return + (i64.const 5425231479272327498) + ) + ) + (set_global $hangLimit + (i32.sub + (get_global $hangLimit) + (i32.const 1) + ) + ) + ) + (block + (drop + (block $label$26 (result i32) + (nop) + (br $label$6) + ) + ) + (br_if $label$25 + (i32.eqz + (br_if $label$22 + (i32.const -1) + (i32.eqz + (i32.const -5) + ) ) - (loop $label$63 (result i32) - (block - (if - (i32.eqz - (get_global $hangLimit) - ) - (return - (i64.const -95) - ) + ) + ) + (nop) + ) + ) + (nop) + ) + (block $label$27 + (loop $label$28 + (block + (if + (i32.eqz + (get_global $hangLimit) + ) + (return + (i64.const -1) + ) + ) + (set_global $hangLimit + (i32.sub + (get_global $hangLimit) + (i32.const 1) + ) + ) + ) + (if + (i32.eqz + (i32.const 2147483647) + ) + (set_local $1 + (call $deNan64 + (f64.convert_s/i32 + (i32.const -65536) + ) + ) + ) + (block $label$29 + (loop $label$30 + (block + (if + (i32.eqz + (get_global $hangLimit) ) - (set_global $hangLimit - (i32.sub - (get_global $hangLimit) - (i32.const 1) - ) + (return + (i64.const 8) ) ) - (block (result i32) - (set_local $1 - (get_local $1) - ) - (br_if $label$63 - (get_local $0) + (set_global $hangLimit + (i32.sub + (get_global $hangLimit) + (i32.const 1) ) - (i32.const 48) ) ) - ) - (block $label$64 (result i32) - (if - (i32.eqz - (i32.wrap/i64 - (loop $label$65 (result i64) - (block - (if - (i32.eqz - (get_global $hangLimit) - ) - (return - (i64.const 470816280) - ) - ) - (set_global $hangLimit - (i32.sub - (get_global $hangLimit) - (i32.const 1) - ) - ) + (block + (set_local $1 + (f64.const 7530232817714476184253323e49) + ) + (br_if $label$30 + (i32.eqz + (br_if $label$22 + (get_local $0) + (i32.eqz + (get_local $0) ) - (i64.const 108) ) ) ) - (nop) - (drop - (f64.const 2075497995636940095578691e82) + (block $label$31 + (nop) ) ) - (loop $label$66 (result i32) - (block - (if - (i32.eqz - (get_global $hangLimit) - ) - (return - (i64.const -27) - ) - ) - (set_global $hangLimit - (i32.sub - (get_global $hangLimit) - (i32.const 1) - ) + ) + (if + (i32.eqz + (get_local $0) + ) + (nop) + (set_local $1 + (f64.const -nan:0xfffffffffffc5) + ) + ) + ) + ) + ) + (block $label$32 + (nop) + (br_if $label$6 + (i32.eqz + (get_local $0) + ) + ) + ) + ) + ) + (br $label$18) + ) + (i32.const 1549477211) + ) + ) + (f32.atomic.store offset=2 + (i32.and + (i64.le_s + (i64.const -134217728) + (if (result i64) + (i32.eqz + (if (result i32) + (i32.eqz + (f64.eq + (if (result f64) + (i32.eqz + (i32.add + (tee_local $0 + (get_local $0) ) + (i32.const 925706789) ) - (block (result i32) - (nop) - (br_if $label$66 - (i32.const -36) + ) + (get_local $1) + (f64.const -8796093022208) + ) + (call $deNan64 + (select + (f64.const -nan:0xfffffffffffde) + (if (result f64) + (i32.eqz + (get_local $0) ) - (get_local $0) + (if (result f64) + (get_local $0) + (f64.const 1599288660) + (get_local $1) + ) + (f64.const -1) ) + (get_local $0) ) ) ) ) - (block $label$67 (result i32) - (f64.store offset=1 + (block $label$33 (result i32) + (br $label$6) + ) + (block $label$34 (result i32) + (br_if $label$7 + (i32.const -32768) + ) + (br $label$18) + ) + ) + ) + (block $label$35 (result i64) + (i64.store offset=4 align=2 + (i32.and + (select + (i32.trunc_s/f32 + (f32.const -144115188075855872) + ) + (i32.const 32767) + (get_local $0) + ) + (i32.const 31) + ) + (i64.const -70) + ) + (br $label$7) + ) + (block $label$36 (result i64) + (if + (i32.wrap/i64 + (i64.load32_s offset=4 align=1 (i32.and - (br_if $label$38 - (get_local $0) - (i32.eqz - (i32.reinterpret/f32 - (f32.const 2706.389892578125) + (get_local $0) + (i32.const 31) + ) + ) + ) + (block $label$37 + (set_local $1 + (loop $label$38 (result f64) + (block + (if + (i32.eqz + (get_global $hangLimit) + ) + (return + (i64.const -67) + ) + ) + (set_global $hangLimit + (i32.sub + (get_global $hangLimit) + (i32.const 1) ) ) ) + (get_local $1) + ) + ) + (set_local $1 + (get_local $1) + ) + ) + (nop) + ) + (block $label$39 (result i64) + (drop + (f32.const 2305843009213693952) + ) + (i64.reinterpret/f64 + (f64.const -nan:0xfffffffffffc4) + ) + ) + ) + ) + ) + (i32.const 31) + ) + (if (result f32) + (i32.eqz + (tee_local $0 + (loop $label$40 (result i32) + (block + (if + (i32.eqz + (get_global $hangLimit) + ) + (return + (i64.const 196) + ) + ) + (set_global $hangLimit + (i32.sub + (get_global $hangLimit) + (i32.const 1) + ) + ) + ) + (block (result i32) + (block $label$41 + (set_local $1 + (get_local $1) + ) + (i32.store8 offset=1 + (i32.and + (i32.const 65535) (i32.const 31) ) - (f64.const 68719476736) + (get_local $0) ) - (i32.const 25) ) - (i32.const 1449089114) + (br_if $label$40 + (tee_local $0 + (i32.const 512) + ) + ) + (get_local $0) ) - (get_local $0) ) ) - (select - (i32.const -4) + ) + (f32.const -nan:0x7fffdc) + (block $label$42 (result f32) + (f32.atomic.load offset=4 + (i32.and + (i32.const 15443) + (i32.const 31) + ) + ) + ) + ) + ) + ) + ) + (if + (i32.const 705695255) + (block $label$43 + (block $label$44 + (loop $label$45 + (block + (if (i32.eqz - (loop $label$58 (result i32) + (get_global $hangLimit) + ) + (return + (i64.const -4096) + ) + ) + (set_global $hangLimit + (i32.sub + (get_global $hangLimit) + (i32.const 1) + ) + ) + ) + (block + (drop + (tee_local $0 + (block $label$46 (result i32) + (nop) + (i32.const -2147483648) + ) + ) + ) + (br_if $label$45 + (i32.const 504176137) + ) + (nop) + ) + ) + ) + (nop) + ) + (block $label$48 + (i32.store8 offset=4 + (i32.and + (i32.const 675167853) + (i32.const 31) + ) + (loop $label$49 (result i32) + (block + (if + (i32.eqz + (get_global $hangLimit) + ) + (return + (i64.const 1080949681082599709) + ) + ) + (set_global $hangLimit + (i32.sub + (get_global $hangLimit) + (i32.const 1) + ) + ) + ) + (block $label$50 (result i32) + (drop + (i64.atomic.load offset=3 + (i32.and + (get_local $0) + (i32.const 31) + ) + ) + ) + (br $label$48) + ) + ) + ) + (br_if $label$6 + (i32.eqz + (i32.const 2147483647) + ) + ) + ) + ) + ) + (br_if $label$6 + (get_local $0) + ) + (tee_local $0 + (if (result i32) + (i32.eqz + (block $label$51 (result i32) + (if + (tee_local $0 + (i32.const 65534) + ) + (block $label$52 + (drop + (i64.const 2397) + ) + (br_if $label$52 + (i32.eqz + (select + (get_local $0) + (select + (loop $label$53 (result i32) + (block + (if + (i32.eqz + (get_global $hangLimit) + ) + (return + (i64.const -122) + ) + ) + (set_global $hangLimit + (i32.sub + (get_global $hangLimit) + (i32.const 1) + ) + ) + ) + (block (result i32) + (nop) + (br_if $label$53 + (i32.eqz + (select + (get_local $0) + (get_local $0) + (get_local $0) + ) + ) + ) + (get_local $0) + ) + ) + (i32.const -2048) + (get_local $0) + ) + (i32.const -8192) + ) + ) + ) + ) + (block $label$54 + (drop + (get_local $0) + ) + (drop + (f32.const -nan:0x7fffb3) + ) + ) + ) + (block $label$55 (result i32) + (loop $label$56 + (block + (if + (i32.eqz + (get_global $hangLimit) + ) + (return + (i64.const -32) + ) + ) + (set_global $hangLimit + (i32.sub + (get_global $hangLimit) + (i32.const 1) + ) + ) + ) + (block + (block $label$57 + (loop $label$58 (block (if (i32.eqz (get_global $hangLimit) ) (return - (i64.const 303239698) + (i64.const -4398046511104) ) ) (set_global $hangLimit @@ -469,70 +982,125 @@ ) ) ) - (block $label$59 (result i32) - (br_if $label$38 - (i32.const 268435456) - (i32.eqz - (br_if $label$59 - (get_local $0) - (get_local $0) - ) - ) - ) - ) + (nop) + ) + (drop + (i64.const -274877906944) ) ) - (tee_local $0 - (tee_local $0 - (tee_local $0 - (i32.const 975322409) + (br_if $label$56 + (i32.eqz + (select + (f32.eq + (f32.const 1) + (f32.const 20) + ) + (i32.const 1769303922) + (i32.const -32768) ) ) ) + (nop) ) ) + (return + (i64.const -288230376151711744) + ) ) - (block $label$68 - (block $label$69 - (br_if $label$39 - (block $label$70 (result i32) - (if - (i32.clz - (br_if $label$38 - (get_local $0) - (get_local $0) - ) + ) + ) + (block $label$59 (result i32) + (br_if $label$6 + (i32.eqz + (br_if $label$59 + (if (result i32) + (i32.const 1997631503) + (i32.const -111) + (block $label$62 (result i32) + (f32.atomic.store offset=3 + (i32.and + (i32.const -536870912) + (i32.const 31) ) - (block $label$71 - (set_local $1 - (f64.const 1.1754943508222875e-38) - ) - (set_local $0 - (i32.const 32) + (f32.const 8589934592) + ) + (br $label$6) + ) + ) + (i32.eqz + (select + (block $label$60 (result i32) + (drop + (f32.const 1142358272) + ) + (br $label$6) + ) + (i32.load8_s + (i32.and + (select + (i32.const 973242160) + (select + (select + (i32.const -1) + (i32.const 606678629) + (get_local $0) + ) + (i32.const -268435456) + (block $label$61 (result i32) + (i32.const -32768) + ) + ) + (get_local $0) ) + (i32.const 31) ) - (nop) ) - (get_local $0) + (i32.const 131072) ) ) - (nop) ) - (nop) - ) - (block $label$72 - (nop) ) ) + (br $label$6) + ) + (block $label$63 (result i32) + (nop) + (br $label$6) ) ) ) - (get_local $0) ) ) + (tee_local $0 + (i32.const -1) + ) + (get_local $0) + ) + ) + ) + ) + (func $func_1 (result f32) + (local $0 i64) + (local $1 f32) + (local $2 f64) + (local $3 f32) + (block + (if + (i32.eqz + (get_global $hangLimit) + ) + (return + (f32.const 691027220365312) + ) + ) + (set_global $hangLimit + (i32.sub + (get_global $hangLimit) + (i32.const 1) ) ) ) + (unreachable) ) (func $hangLimitInitializer (set_global $hangLimit From 162b311342fad0c6e22d642755b05496123d603a Mon Sep 17 00:00:00 2001 From: "Alon Zakai (kripken)" Date: Thu, 12 Oct 2017 12:34:59 -0700 Subject: [PATCH 02/33] refactor makeConcrete in -ttf --- src/tools/translate-to-fuzz.h | 93 +++++++---------------------------- 1 file changed, 18 insertions(+), 75 deletions(-) diff --git a/src/tools/translate-to-fuzz.h b/src/tools/translate-to-fuzz.h index a2b0c93938d..53a5c8ebd51 100644 --- a/src/tools/translate-to-fuzz.h +++ b/src/tools/translate-to-fuzz.h @@ -356,10 +356,10 @@ class TranslateToFuzzReader { nesting++; Expression* ret; switch (type) { - case i32: ret = _makei32(); break; - case i64: ret = _makei64(); break; - case f32: ret = _makef32(); break; - case f64: ret = _makef64(); break; + case i32: + case i64: + case f32: + case f64: ret = _makeConcrete(type); break; case none: ret = _makenone(); break; case unreachable: ret = _makeunreachable(); break; default: WASM_UNREACHABLE(); @@ -368,78 +368,21 @@ class TranslateToFuzzReader { return ret; } - Expression* _makei32() { + Expression* _makeConcrete(WasmType type) { switch (upTo(13)) { - case 0: return makeBlock(i32); - case 1: return makeIf(i32); - case 2: return makeLoop(i32); - case 3: return makeBreak(i32); - case 4: return makeCall(i32); - case 5: return makeCallIndirect(i32); - case 6: return makeGetLocal(i32); - case 7: return makeSetLocal(i32); - case 8: return makeLoad(i32); - case 9: return makeConst(i32); - case 10: return makeUnary(i32); - case 11: return makeBinary(i32); - case 12: return makeSelect(i32); - } - WASM_UNREACHABLE(); - } - - Expression* _makei64() { - switch (upTo(13)) { - case 0: return makeBlock(i64); - case 1: return makeIf(i64); - case 2: return makeLoop(i64); - case 3: return makeBreak(i64); - case 4: return makeCall(i64); - case 5: return makeCallIndirect(i64); - case 6: return makeGetLocal(i64); - case 7: return makeSetLocal(i64); - case 8: return makeLoad(i64); - case 9: return makeConst(i64); - case 10: return makeUnary(i64); - case 11: return makeBinary(i64); - case 12: return makeSelect(i64); - } - WASM_UNREACHABLE(); - } - - Expression* _makef32() { - switch (upTo(13)) { - case 0: return makeBlock(f32); - case 1: return makeIf(f32); - case 2: return makeLoop(f32); - case 3: return makeBreak(f32); - case 4: return makeCall(f32); - case 5: return makeCallIndirect(f32); - case 6: return makeGetLocal(f32); - case 7: return makeSetLocal(f32); - case 8: return makeLoad(f32); - case 9: return makeConst(f32); - case 10: return makeUnary(f32); - case 11: return makeBinary(f32); - case 12: return makeSelect(f32); - } - WASM_UNREACHABLE(); - } - - Expression* _makef64() { - switch (upTo(13)) { - case 0: return makeBlock(f64); - case 1: return makeIf(f64); - case 2: return makeLoop(f64); - case 3: return makeBreak(f64); - case 4: return makeCall(f64); - case 5: return makeCallIndirect(f64); - case 6: return makeGetLocal(f64); - case 7: return makeSetLocal(f64); - case 8: return makeLoad(f64); - case 9: return makeConst(f64); - case 10: return makeUnary(f64); - case 11: return makeBinary(f64); - case 12: return makeSelect(f64); + case 0: return makeBlock(type); + case 1: return makeIf(type); + case 2: return makeLoop(type); + case 3: return makeBreak(type); + case 4: return makeCall(type); + case 5: return makeCallIndirect(type); + case 6: return makeGetLocal(type); + case 7: return makeSetLocal(type); + case 8: return makeLoad(type); + case 9: return makeConst(type); + case 10: return makeUnary(type); + case 11: return makeBinary(type); + case 12: return makeSelect(type); } WASM_UNREACHABLE(); } From 923d6fdadd5b1c5e79b84f469146f462e92b8051 Mon Sep 17 00:00:00 2001 From: "Alon Zakai (kripken)" Date: Thu, 12 Oct 2017 13:15:51 -0700 Subject: [PATCH 03/33] refactor wake/wait finalization --- src/wasm-builder.h | 2 -- src/wasm/wasm.cpp | 2 ++ 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/wasm-builder.h b/src/wasm-builder.h index 4591c9c0db0..cb935893380 100644 --- a/src/wasm-builder.h +++ b/src/wasm-builder.h @@ -212,7 +212,6 @@ class Builder { wait->expected = expected; wait->timeout = timeout; wait->expectedType = type; - wait->type = i32; wait->finalize(); return wait; } @@ -220,7 +219,6 @@ class Builder { auto* wake = allocator.alloc(); wake->ptr = ptr; wake->wakeCount = wakeCount; - wake->type = i32; wake->finalize(); return wake; } diff --git a/src/wasm/wasm.cpp b/src/wasm/wasm.cpp index f4562fe640f..6441991c950 100644 --- a/src/wasm/wasm.cpp +++ b/src/wasm/wasm.cpp @@ -390,12 +390,14 @@ void AtomicCmpxchg::finalize() { } void AtomicWait::finalize() { + type = i32; if (ptr->type == unreachable || expected->type == unreachable || timeout->type == unreachable) { type = unreachable; } } void AtomicWake::finalize() { + type = i32; if (ptr->type == unreachable || wakeCount->type == unreachable) { type = unreachable; } From f83c0170fc70204ceac8629fe3073b8da0b7b920 Mon Sep 17 00:00:00 2001 From: "Alon Zakai (kripken)" Date: Thu, 12 Oct 2017 13:16:01 -0700 Subject: [PATCH 04/33] fuzz atomics --- src/tools/translate-to-fuzz.h | 60 ++++++++++++++++++++++++++++++++++- 1 file changed, 59 insertions(+), 1 deletion(-) diff --git a/src/tools/translate-to-fuzz.h b/src/tools/translate-to-fuzz.h index 53a5c8ebd51..950fd58ce9f 100644 --- a/src/tools/translate-to-fuzz.h +++ b/src/tools/translate-to-fuzz.h @@ -369,7 +369,7 @@ class TranslateToFuzzReader { } Expression* _makeConcrete(WasmType type) { - switch (upTo(13)) { + switch (upTo(14)) { case 0: return makeBlock(type); case 1: return makeIf(type); case 2: return makeLoop(type); @@ -383,6 +383,7 @@ class TranslateToFuzzReader { case 10: return makeUnary(type); case 11: return makeBinary(type); case 12: return makeSelect(type); + case 13: return makeAtomic(type); } WASM_UNREACHABLE(); } @@ -1066,6 +1067,63 @@ class TranslateToFuzzReader { return builder.makeUnreachable(); } + Expression* makeAtomic(WasmType type) { + if (type != i32 && type != i64) return makeTrivial(type); + if (type == i32 && oneIn(2)) { + if (oneIn(2)) { + auto* ptr = makePointer(); + auto expectedType = pick(i32, i64); + auto* expected = make(expectedType); + auto* timeout = make(i64); + return builder.makeAtomicWait(ptr, expected, timeout, expectedType); + } else { + auto* ptr = makePointer(); + auto* count = make(i32); + return builder.makeAtomicWake(ptr, count); + } + } + Index bytes; + switch (type) { + case i32: { + switch (upTo(3)) { + case 0: bytes = 1; break; + case 1: bytes = pick(1, 2); break; + case 2: bytes = pick(1, 2, 4); break; + default: WASM_UNREACHABLE(); + } + break; + } + case i64: { + switch (upTo(4)) { + case 0: bytes = 1; break; + case 1: bytes = pick(1, 2); break; + case 2: bytes = pick(1, 2, 4); break; + case 3: bytes = pick(1, 2, 4, 8); break; + default: WASM_UNREACHABLE(); + } + break; + } + case f32: { + bytes = pick(1, 2, 4); break; + } + case f64: { + bytes = pick(1, 2, 4, 8); break; + } + default: WASM_UNREACHABLE(); + } + auto offset = logify(get()); + auto* ptr = makePointer(); + if (oneIn(2)) { + auto* value = make(type); + return builder.makeAtomicRMW(pick(AtomicRMWOp::Add, AtomicRMWOp::Sub, AtomicRMWOp::And, AtomicRMWOp::Or, AtomicRMWOp::Xor, AtomicRMWOp::Xchg), + bytes, offset, ptr, value, type); + } else { + auto* expected = make(type); + auto* replacement = make(type); + return builder.makeAtomicCmpxchg(bytes, offset, ptr, expected, replacement, type); + } + } + // special getters WasmType getType() { From 64ab0d5277eb5a079b03b947e4d2c5a384fa4c6a Mon Sep 17 00:00:00 2001 From: "Alon Zakai (kripken)" Date: Thu, 12 Oct 2017 15:30:04 -0700 Subject: [PATCH 05/33] add some asserts --- src/tools/translate-to-fuzz.h | 1 + src/wasm-interpreter.h | 8 ++++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/tools/translate-to-fuzz.h b/src/tools/translate-to-fuzz.h index 950fd58ce9f..8c83ff53b6e 100644 --- a/src/tools/translate-to-fuzz.h +++ b/src/tools/translate-to-fuzz.h @@ -364,6 +364,7 @@ class TranslateToFuzzReader { case unreachable: ret = _makeunreachable(); break; default: WASM_UNREACHABLE(); } + assert(ret->type == type); // we should create the right type of thing nesting--; return ret; } diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h index 0b01fb1d351..8f958ee42b5 100644 --- a/src/wasm-interpreter.h +++ b/src/wasm-interpreter.h @@ -118,7 +118,11 @@ template class ExpressionRunner : public Visitor { public: Flow visit(Expression *curr) { - return Visitor::visit(curr); + auto ret = Visitor::visit(curr); + if (!ret.breaking()) { + assert(ret.value.type == curr->type); + } + return ret; } Flow visitBlock(Block *curr) { @@ -461,7 +465,7 @@ class ExpressionRunner : public Visitor { Flow visitUnreachable(Unreachable *curr) { NOTE_ENTER("Unreachable"); trap("unreachable"); - return Flow(); + WASM_UNREACHABLE(); } Literal truncSFloat(Unary* curr, Literal value) { From e98a91807a5a29676be5211ca7ef38a24ef0dc49 Mon Sep 17 00:00:00 2001 From: "Alon Zakai (kripken)" Date: Thu, 12 Oct 2017 15:30:09 -0700 Subject: [PATCH 06/33] test update --- test/passes/translate-to-fuzz.txt | 1782 +++++++++++++++-------------- 1 file changed, 936 insertions(+), 846 deletions(-) diff --git a/test/passes/translate-to-fuzz.txt b/test/passes/translate-to-fuzz.txt index edd79cd0958..6f301689536 100644 --- a/test/passes/translate-to-fuzz.txt +++ b/test/passes/translate-to-fuzz.txt @@ -1,11 +1,13 @@ (module (type $FUNCSIG$j (func (result i64))) + (type $FUNCSIG$i (func (result i32))) (global $hangLimit (mut i32) (i32.const 100)) - (table 2 anyfunc) - (elem (i32.const 0) $func_0 $func_1) + (table 4 anyfunc) + (elem (i32.const 0) $func_1 $func_1 $func_1 $func_1) (memory $0 (shared 1 1)) (data (i32.const 0) "\00C\00[\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00") (export "func_0" (func $func_0)) + (export "func_2" (func $func_2)) (export "hangLimitInitializer" (func $hangLimitInitializer)) (func $func_0 (type $FUNCSIG$j) (result i64) (local $0 i32) @@ -16,7 +18,7 @@ (get_global $hangLimit) ) (return - (i64.const 65535) + (i64.const 1024) ) ) (set_global $hangLimit @@ -28,44 +30,96 @@ ) (block $label$0 (result i64) (nop) - (br_if $label$0 - (loop $label$64 (result i64) - (block - (if - (i32.eqz - (get_global $hangLimit) - ) - (return - (i64.const -9223372036854775808) - ) + (return + (i64.const 386994477) + ) + ) + ) + (func $func_1 (type $FUNCSIG$i) (result i32) + (local $0 f64) + (block + (if + (i32.eqz + (get_global $hangLimit) + ) + (return + (i32.const 942701876) + ) + ) + (set_global $hangLimit + (i32.sub + (get_global $hangLimit) + (i32.const 1) + ) + ) + ) + (block $label$0 (result i32) + (set_local $0 + (get_local $0) + ) + (return + (i32.const 9282) + ) + ) + ) + (func $func_2 (type $FUNCSIG$i) (result i32) + (local $0 f32) + (local $1 f64) + (local $2 f64) + (block + (if + (i32.eqz + (get_global $hangLimit) + ) + (return + (i32.const 16) + ) + ) + (set_global $hangLimit + (i32.sub + (get_global $hangLimit) + (i32.const 1) + ) + ) + ) + (block $label$0 (result i32) + (if + (i32.const 274205712) + (block $label$1 + (drop + (f32.atomic.load offset=4 + (i32.const 842759483) ) - (set_global $hangLimit - (i32.sub - (get_global $hangLimit) - (i32.const 1) + ) + (loop $label$2 + (block + (if + (i32.eqz + (get_global $hangLimit) + ) + (return + (i32.const -524288) + ) + ) + (set_global $hangLimit + (i32.sub + (get_global $hangLimit) + (i32.const 1) + ) ) ) - ) - (block $label$65 (result i64) - (drop - (select - (i64.atomic.load16_s offset=4 + (block + (block $label$3 + (i64.atomic.store32 offset=22 (i32.and - (i32.const -94) - (i32.const 31) - ) - ) - (i64.const -84) - (if (result i32) - (block $label$66 (result i32) - (loop $label$67 + (loop $label$4 (result i32) (block (if (i32.eqz (get_global $hangLimit) ) (return - (i64.const 134217728) + (i32.const 65535) ) ) (set_global $hangLimit @@ -75,427 +129,237 @@ ) ) ) - (block $label$68 - (set_local $0 - (loop $label$69 (result i32) - (block - (if - (i32.eqz - (get_global $hangLimit) - ) - (return - (i64.const 9223372036854775807) - ) - ) - (set_global $hangLimit - (i32.sub - (get_global $hangLimit) - (i32.const 1) - ) - ) - ) - (block $label$70 (result i32) - (nop) - (return - (i64.const 4503599627370496) - ) - ) - ) - ) - ) - ) - (return - (i64.const -35184372088832) + (i32.const -128) ) + (i32.const 31) ) - (block $label$71 (result i32) - (block $label$72 - (if - (i32.eqz - (select - (loop $label$75 (result i32) - (block - (if - (i32.eqz - (get_global $hangLimit) - ) - (return - (i64.const -9223372036854775808) - ) - ) - (set_global $hangLimit - (i32.sub - (get_global $hangLimit) - (i32.const 1) - ) - ) - ) - (get_local $0) - ) - (tee_local $0 - (get_local $0) - ) - (block $label$73 (result i32) - (loop $label$74 - (block - (if - (i32.eqz - (get_global $hangLimit) - ) - (return - (i64.const 4294967295) - ) - ) - (set_global $hangLimit - (i32.sub - (get_global $hangLimit) - (i32.const 1) - ) - ) - ) - (nop) - ) - (br $label$64) - ) + (i64.const 127) + ) + (if + (i32.eqz + (loop $label$5 (result i32) + (block + (if + (i32.eqz + (get_global $hangLimit) + ) + (return + (i32.const -86) ) ) - (block $label$76 - (nop) - (drop - (i32.const 225447522) + (set_global $hangLimit + (i32.sub + (get_global $hangLimit) + (i32.const 1) ) ) - (nop) ) - ) - (return - (i64.const 3333579868552515411) - ) - ) - (block $label$77 (result i32) - (block $label$78 - (i32.store16 offset=2 align=1 - (i32.and - (select - (get_local $0) - (block $label$83 (result i32) - (nop) - (br $label$78) - ) - (loop $label$79 (result i32) - (block - (if - (i32.eqz - (get_global $hangLimit) - ) - (return - (i64.const -1) - ) + (block (result i32) + (block $label$6 + (drop + (block $label$7 (result f64) + (if + (br_if $label$0 + (i32.const 1091126348) + (i32.const 33554432) ) - (set_global $hangLimit - (i32.sub - (get_global $hangLimit) - (i32.const 1) - ) + (drop + (call $func_0) ) - ) - (block (result i32) - (loop $label$80 - (block - (if - (i32.eqz - (get_global $hangLimit) - ) - (return - (i64.const 4294967211) - ) - ) - (set_global $hangLimit - (i32.sub - (get_global $hangLimit) - (i32.const 1) + (block $label$8 + (br_if $label$5 + (i32.eqz + (i32.trunc_u/f64 + (f64.const 1652571306646628140174554e16) ) ) ) - (set_local $1 - (f64.const -2) - ) - ) - (br_if $label$79 - (loop $label$81 (result i32) - (block - (if - (i32.eqz - (get_global $hangLimit) - ) - (return - (i64.const -2147483647) + (block $label$9 + (f64.atomic.store offset=4 + (i32.and + (loop $label$10 (result i32) + (block + (if + (i32.eqz + (get_global $hangLimit) + ) + (return + (i32.const 807806537) + ) + ) + (set_global $hangLimit + (i32.sub + (get_global $hangLimit) + (i32.const 1) + ) + ) + ) + (block (result i32) + (f64.store offset=4 + (i32.and + (i64.le_u + (i64.const -1) + (i64.atomic.rmw8_u.cmpxchg offset=3 + (i32.and + (select + (i32.const -128) + (i32.const -2) + (i32.const 33554432) + ) + (i32.const 31) + ) + (block $label$11 (result i64) + (nop) + (i64.const -1) + ) + (i64.const -33554432) + ) + ) + (i32.const 31) + ) + (get_local $1) + ) + (br_if $label$10 + (i32.const -1) + ) + (i32.const -1) + ) ) + (i32.const 31) ) - (set_global $hangLimit - (i32.sub - (get_global $hangLimit) - (i32.const 1) + (get_local $1) + ) + (if + (i32.eqz + (i32.atomic.rmw16_u.cmpxchg offset=1 + (i32.and + (i32.const -16384) + (i32.const 31) + ) + (block $label$12 (result i32) + (nop) + (i32.const -82) + ) + (loop $label$13 (result i32) + (block + (if + (i32.eqz + (get_global $hangLimit) + ) + (return + (i32.const 945497692) + ) + ) + (set_global $hangLimit + (i32.sub + (get_global $hangLimit) + (i32.const 1) + ) + ) + ) + (block (result i32) + (drop + (i64.const 1949008919083353346) + ) + (br_if $label$13 + (i32.const 1091126348) + ) + (i32.atomic.load offset=4 + (i32.const 2) + ) + ) + ) ) ) - ) - (i32.const 1398478431) - ) - ) - (block $label$82 (result i32) - (set_local $1 - (f64.atomic.load offset=22 - (i32.and - (tee_local $0 - (get_local $0) + (loop $label$14 + (block + (if + (i32.eqz + (get_global $hangLimit) + ) + (return + (i32.const 421008146) + ) + ) + (set_global $hangLimit + (i32.sub + (get_global $hangLimit) + (i32.const 1) + ) + ) + ) + (block + (nop) + (br_if $label$14 + (i32.const 2097152) + ) + (set_local $0 + (if (result f32) + (i32.eqz + (if (result i32) + (i32.const 319888671) + (loop $label$15 (result i32) + (block + (if + (i32.eqz + (get_global $hangLimit) + ) + (return + (i32.const 65535) + ) + ) + (set_global $hangLimit + (i32.sub + (get_global $hangLimit) + (i32.const 1) + ) + ) + ) + (i32.const 112) + ) + (i32.const 1043932195) + ) + ) + (f32.const 521149984) + (get_local $0) + ) + ) ) - (i32.const 31) ) + (nop) ) ) - (br $label$64) ) ) + (br $label$6) ) ) - (i32.const 31) - ) - (if (result i32) - (select - (br_if $label$77 - (i32.const 2418) - (get_local $0) - ) - (i32.const 65535) - (i32.const 1532516688) - ) - (block $label$84 (result i32) - (drop - (get_local $0) - ) - (i32.const 50) - ) - (block $label$85 (result i32) - (drop - (get_local $1) - ) - (br_if $label$77 - (get_local $0) - (get_local $0) - ) - ) - ) - ) - (br_if $label$64 - (i32.eqz - (tee_local $0 - (tee_local $0 - (if (result i32) + (loop $label$16 + (block + (if (i32.eqz - (get_local $0) - ) - (get_local $0) - (i32.wrap/i64 - (i64.const -35) - ) - ) - ) - ) - ) - ) - ) - (br $label$64) - ) - ) - ) - ) - (br $label$64) - ) - ) - (select - (loop $label$6 (result i32) - (block - (if - (i32.eqz - (get_global $hangLimit) - ) - (return - (i64.const 96) - ) - ) - (set_global $hangLimit - (i32.sub - (get_global $hangLimit) - (i32.const 1) - ) - ) - ) - (block (result i32) - (block $label$7 - (if - (block $label$8 (result i32) - (nop) - (block $label$9 (result i32) - (br $label$7) - ) - ) - (drop - (call $deNan64 - (select - (f64.const 49) - (call $deNan64 - (f64.reinterpret/i64 - (i64.const -1024) - ) - ) - (i32.popcnt - (select - (loop $label$13 (result i32) - (block - (if - (i32.eqz - (get_global $hangLimit) - ) - (return - (i64.const -128) - ) - ) - (set_global $hangLimit - (i32.sub - (get_global $hangLimit) - (i32.const 1) - ) - ) - ) - (tee_local $0 - (get_local $0) - ) - ) - (get_local $0) - (select - (loop $label$10 (result i32) - (block - (if - (i32.eqz - (get_global $hangLimit) - ) - (return - (i64.const 2147483646) - ) - ) - (set_global $hangLimit - (i32.sub - (get_global $hangLimit) - (i32.const 1) - ) - ) - ) - (get_local $0) - ) - (tee_local $0 - (block $label$11 (result i32) - (block $label$12 - (set_local $1 - (get_local $1) - ) - (nop) - ) - (br $label$7) - ) - ) - (i32.const -16) - ) - ) - ) - ) - ) - ) - (block $label$18 - (br_if $label$18 - (if (result i32) - (block $label$19 (result i32) - (nop) - (br_if $label$19 - (if (result i32) - (i32.eqz - (tee_local $0 - (i32.const -2) - ) - ) - (if (result i32) - (i32.const 35) - (f64.eq - (get_local $1) - (if (result f64) - (i32.eqz - (i32.const 3) - ) - (get_local $1) - (f64.const -nan:0xfffffffffff99) - ) + (get_global $hangLimit) ) - (block $label$20 (result i32) - (block $label$21 - (set_local $1 - (f64.const 48964419687002166075064320) - ) - (set_local $0 - (i32.atomic.load8_u offset=2 - (i32.and - (get_local $0) - (i32.const 31) - ) - ) - ) - ) - (i32.const -19) + (return + (i32.const 255) ) ) - (get_local $0) - ) - (get_local $0) - ) - ) - (block $label$22 (result i32) - (if - (select - (i32.const 252465421) - (loop $label$23 (result i32) - (block - (if - (i32.eqz - (get_global $hangLimit) - ) - (return - (i64.const 4294967295) - ) - ) - (set_global $hangLimit - (i32.sub - (get_global $hangLimit) - (i32.const 1) - ) - ) - ) - (block (result i32) - (nop) - (br_if $label$23 - (get_local $0) - ) - (i32.const 1113085277) + (set_global $hangLimit + (i32.sub + (get_global $hangLimit) + (i32.const 1) ) ) - (i32.const -2147483648) ) - (block $label$24 - (loop $label$25 + (block $label$17 + (loop $label$18 (block (if (i32.eqz (get_global $hangLimit) ) (return - (i64.const 5425231479272327498) + (i32.const -32768) ) ) (set_global $hangLimit @@ -505,250 +369,342 @@ ) ) ) - (block - (drop - (block $label$26 (result i32) - (nop) - (br $label$6) - ) - ) - (br_if $label$25 - (i32.eqz - (br_if $label$22 - (i32.const -1) + (block $label$19 + (loop $label$20 + (block + (if (i32.eqz - (i32.const -5) + (get_global $hangLimit) + ) + (return + (i32.const 1348217658) + ) + ) + (set_global $hangLimit + (i32.sub + (get_global $hangLimit) + (i32.const 1) + ) + ) + ) + (block $label$21 + (block $label$22 + (block $label$23 + (nop) + (nop) + ) + (if + (i32.const 255) + (set_local $1 + (f64.const 208) + ) + (nop) ) ) ) ) - (nop) - ) - ) - (nop) - ) - (block $label$27 - (loop $label$28 - (block (if (i32.eqz - (get_global $hangLimit) - ) - (return - (i64.const -1) - ) - ) - (set_global $hangLimit - (i32.sub - (get_global $hangLimit) - (i32.const 1) - ) - ) - ) - (if - (i32.eqz - (i32.const 2147483647) - ) - (set_local $1 - (call $deNan64 - (f64.convert_s/i32 - (i32.const -65536) + (call_indirect $FUNCSIG$i + (i32.const 2) ) ) - ) - (block $label$29 - (loop $label$30 - (block - (if - (i32.eqz - (get_global $hangLimit) - ) - (return - (i64.const 8) + (block $label$24 + (drop + (f64.const 1797693134862315708145274e284) + ) + (if + (i32.eqz + (if (result i32) + (i32.eqz + (i32.const -32768) + ) + (i32.const 1263160137) + (i32.const -2147483648) ) ) - (set_global $hangLimit - (i32.sub - (get_global $hangLimit) - (i32.const 1) + (nop) + (br_if $label$3 + (i32.eqz + (i32.const -512) ) ) ) - (block - (set_local $1 - (f64.const 7530232817714476184253323e49) - ) - (br_if $label$30 - (i32.eqz - (br_if $label$22 - (get_local $0) - (i32.eqz - (get_local $0) - ) + ) + (block $label$25 + (loop $label$26 + (block + (if + (i32.eqz + (get_global $hangLimit) + ) + (return + (i32.const 1364404325) + ) + ) + (set_global $hangLimit + (i32.sub + (get_global $hangLimit) + (i32.const 1) ) ) ) - (block $label$31 + (block (nop) + (br_if $label$26 + (i32.const -134217728) + ) + (set_local $2 + (get_local $1) + ) ) ) - ) - (if - (i32.eqz - (get_local $0) - ) - (nop) - (set_local $1 - (f64.const -nan:0xfffffffffffc5) + (if + (i32.const 29) + (nop) + (nop) ) ) ) ) ) - (block $label$32 - (nop) - (br_if $label$6 - (i32.eqz - (get_local $0) + (br_if $label$1 + (i32.eqz + (block $label$27 (result i32) + (return + (i32.const 2376257) + ) ) ) ) ) ) - (br $label$18) ) - (i32.const 1549477211) - ) - ) - (f32.atomic.store offset=2 - (i32.and - (i64.le_s - (i64.const -134217728) - (if (result i64) - (i32.eqz - (if (result i32) - (i32.eqz - (f64.eq - (if (result f64) - (i32.eqz - (i32.add - (tee_local $0 - (get_local $0) - ) - (i32.const 925706789) - ) - ) - (get_local $1) - (f64.const -8796093022208) - ) - (call $deNan64 - (select - (f64.const -nan:0xfffffffffffde) - (if (result f64) - (i32.eqz - (get_local $0) - ) - (if (result f64) - (get_local $0) - (f64.const 1599288660) - (get_local $1) - ) - (f64.const -1) - ) - (get_local $0) - ) - ) + (br_if $label$5 + (i32.eqz + (call $func_1) + ) + ) + (br_if $label$0 + (if (result i32) + (select + (i32.trunc_u/f32 + (call $deNan32 + (f32.add + (get_local $0) + (f32.const 3.284356114571644e-24) ) ) - (block $label$33 (result i32) - (br $label$6) - ) - (block $label$34 (result i32) - (br_if $label$7 - (i32.const -32768) + ) + (select + (i32.const -87) + (f32.ne + (tee_local $0 + (f32.const -16) ) - (br $label$18) + (f32.const 3402823466385288598117041e14) ) + (i32.const 268435456) ) + (call $func_1) ) - (block $label$35 (result i64) - (i64.store offset=4 align=2 - (i32.and - (select - (i32.trunc_s/f32 - (f32.const -144115188075855872) - ) - (i32.const 32767) - (get_local $0) - ) - (i32.const 31) + (block $label$33 (result i32) + (drop + (select + (i64.const 128) + (i64.const -72) + (i32.const 251725317) ) - (i64.const -70) ) - (br $label$7) + (i32.const 520554502) ) - (block $label$36 (result i64) - (if - (i32.wrap/i64 - (i64.load32_s offset=4 align=1 - (i32.and - (get_local $0) - (i32.const 31) + (block $label$34 (result i32) + (loop $label$35 (result i32) + (block + (if + (i32.eqz + (get_global $hangLimit) + ) + (return + (i32.const 1) + ) + ) + (set_global $hangLimit + (i32.sub + (get_global $hangLimit) + (i32.const 1) ) ) ) - (block $label$37 - (set_local $1 - (loop $label$38 (result f64) - (block - (if - (i32.eqz - (get_global $hangLimit) + (block (result i32) + (block $label$36 + (block $label$37 + (loop $label$38 + (block + (if + (i32.eqz + (get_global $hangLimit) + ) + (return + (i32.const 255) + ) ) - (return - (i64.const -67) + (set_global $hangLimit + (i32.sub + (get_global $hangLimit) + (i32.const 1) + ) ) ) - (set_global $hangLimit - (i32.sub - (get_global $hangLimit) - (i32.const 1) + (block $label$39 + (nop) + (nop) + ) + ) + (loop $label$40 + (block + (if + (i32.eqz + (get_global $hangLimit) + ) + (return + (i32.const 1700610397) + ) + ) + (set_global $hangLimit + (i32.sub + (get_global $hangLimit) + (i32.const 1) + ) + ) + ) + (block + (br_if $label$36 + (i32.eqz + (i32.const 65535) + ) + ) + (br_if $label$40 + (i32.eqz + (i32.load8_s offset=4 + (i32.and + (call_indirect $FUNCSIG$i + (i32.const 3) + ) + (i32.const 31) + ) + ) + ) + ) + (set_local $0 + (call $deNan32 + (select + (call $deNan32 + (select + (block $label$41 (result f32) + (if + (i32.const 50529027) + (block $label$42 + (set_local $1 + (tee_local $1 + (f64.atomic.load offset=3 + (i32.and + (i32.const 84346374) + (i32.const 31) + ) + ) + ) + ) + (nop) + ) + (nop) + ) + (call $deNan32 + (f32.add + (call $deNan32 + (f32.mul + (br_if $label$41 + (f32.const 94) + (i32.const -2048) + ) + (loop $label$43 (result f32) + (block + (if + (i32.eqz + (get_global $hangLimit) + ) + (return + (i32.const -1) + ) + ) + (set_global $hangLimit + (i32.sub + (get_global $hangLimit) + (i32.const 1) + ) + ) + ) + (loop $label$44 (result f32) + (block + (if + (i32.eqz + (get_global $hangLimit) + ) + (return + (i32.const 17273) + ) + ) + (set_global $hangLimit + (i32.sub + (get_global $hangLimit) + (i32.const 1) + ) + ) + ) + (f32.const 1.1001502146955268e-22) + ) + ) + ) + ) + (get_local $0) + ) + ) + ) + (get_local $0) + (i32.const -32) + ) + ) + (get_local $0) + (i32.const 32766) + ) + ) ) ) ) - (get_local $1) ) ) - (set_local $1 - (get_local $1) + (br_if $label$35 + (i32.load offset=4 align=1 + (i32.and + (i32.const 471341842) + (i32.const 31) + ) + ) ) - ) - (nop) - ) - (block $label$39 (result i64) - (drop - (f32.const 2305843009213693952) - ) - (i64.reinterpret/f64 - (f64.const -nan:0xfffffffffffc4) + (i32.const -2147483648) ) ) ) ) - ) - (i32.const 31) - ) - (if (result f32) - (i32.eqz - (tee_local $0 - (loop $label$40 (result i32) + (i64.ne + (loop $label$28 (result i64) (block (if (i32.eqz (get_global $hangLimit) ) (return - (i64.const 196) + (i32.const 167774215) ) ) (set_global $hangLimit @@ -758,153 +714,257 @@ ) ) ) - (block (result i32) - (block $label$41 - (set_local $1 - (get_local $1) - ) - (i32.store8 offset=1 - (i32.and - (i32.const 65535) - (i32.const 31) + (block $label$29 (result i64) + (drop + (tee_local $2 + (f64.atomic.load offset=3 + (i32.and + (i32.const 1578633994) + (i32.const 31) + ) ) - (get_local $0) - ) - ) - (br_if $label$40 - (tee_local $0 - (i32.const 512) ) ) - (get_local $0) + (i64.const 5203425946582667613) ) ) - ) - ) - (f32.const -nan:0x7fffdc) - (block $label$42 (result f32) - (f32.atomic.load offset=4 - (i32.and - (i32.const 15443) - (i32.const 31) - ) + (i64.const 536870912) ) ) ) ) ) - ) - (if - (i32.const 705695255) - (block $label$43 - (block $label$44 - (loop $label$45 - (block - (if - (i32.eqz - (get_global $hangLimit) + (block $label$45 + (drop + (i64.atomic.rmw8_u.cmpxchg offset=4 + (i32.and + (i32.trunc_s/f64 + (call $deNan64 + (select + (f64.const 4611686018427387904) + (if (result f64) + (i32.eqz + (i32.const -2147483647) + ) + (get_local $1) + (block $label$46 (result f64) + (f64.atomic.store offset=22 + (i32.and + (i32.const 13648) + (i32.const 31) + ) + (f64.const 2.3366969264770927e-173) + ) + (br $label$3) + ) + ) + (call $func_1) + ) ) - (return - (i64.const -4096) + ) + (i32.const 31) + ) + (loop $label$47 (result i64) + (block + (if + (i32.eqz + (get_global $hangLimit) + ) + (return + (i32.const 4194304) + ) + ) + (set_global $hangLimit + (i32.sub + (get_global $hangLimit) + (i32.const 1) + ) ) ) - (set_global $hangLimit - (i32.sub - (get_global $hangLimit) - (i32.const 1) + (block $label$48 (result i64) + (if + (call_indirect $FUNCSIG$i + (i32.const 0) + ) + (block $label$49 + (br_if $label$2 + (i32.eqz + (i32.const 32767) + ) + ) + (nop) + ) + (block $label$50 + (set_local $0 + (f32.const -nan:0x7fffb0) + ) + (drop + (i64.const 288803243302454280) + ) + ) ) + (br $label$45) ) ) - (block - (drop - (tee_local $0 - (block $label$46 (result i32) - (nop) - (i32.const -2147483648) + (i64.const 144115188075855872) + ) + ) + (block $label$51 + (br_if $label$3 + (i32.eqz + (i32.trunc_u/f64 + (f64.atomic.load offset=3 + (i32.and + (if (result i32) + (i32.eqz + (call_indirect $FUNCSIG$i + (i32.const 2) + ) + ) + (block $label$52 (result i32) + (if + (i32.eqz + (i64.lt_s + (i64.const -23) + (i64.const 2147483647) + ) + ) + (drop + (f64.const -1) + ) + (nop) + ) + (br $label$1) + ) + (block $label$53 (result i32) + (set_local $1 + (f64.const 9223372036854775808) + ) + (if (result i32) + (i32.eqz + (if (result i32) + (i32.const 20530187) + (block $label$54 (result i32) + (nop) + (i32.const 0) + ) + (i32.const 533) + ) + ) + (i32.const -43) + (br_if $label$53 + (if (result i32) + (block $label$55 (result i32) + (set_local $0 + (f32.const -1048576) + ) + (br $label$51) + ) + (i32.const 163) + (i32.const 4096) + ) + (i32.eqz + (i32.const -536870912) + ) + ) + ) + ) + ) + (i32.const 31) ) ) ) - (br_if $label$45 - (i32.const 504176137) - ) - (nop) ) ) ) - (nop) ) - (block $label$48 - (i32.store8 offset=4 + (block $label$56 + (f64.atomic.store offset=4 (i32.and - (i32.const 675167853) + (i32.const 1566528337) (i32.const 31) ) - (loop $label$49 (result i32) - (block - (if - (i32.eqz - (get_global $hangLimit) - ) - (return - (i64.const 1080949681082599709) - ) - ) - (set_global $hangLimit - (i32.sub - (get_global $hangLimit) - (i32.const 1) - ) - ) - ) - (block $label$50 (result i32) - (drop - (i64.atomic.load offset=3 - (i32.and - (get_local $0) - (i32.const 31) - ) - ) + (f64.atomic.load offset=4 + (i32.and + (i64.ge_u + (i64.const 134616423) + (i64.const 274877906944) ) - (br $label$48) + (i32.const 31) ) ) ) - (br_if $label$6 - (i32.eqz - (i32.const 2147483647) + (f32.store offset=22 + (i32.and + (i32.const 2048) + (i32.const 31) ) + (f32.const 1.6651135147759403e-30) ) + (nop) ) ) - ) - (br_if $label$6 - (get_local $0) - ) - (tee_local $0 - (if (result i32) + (br_if $label$3 (i32.eqz - (block $label$51 (result i32) - (if - (tee_local $0 - (i32.const 65534) - ) - (block $label$52 - (drop - (i64.const 2397) - ) - (br_if $label$52 - (i32.eqz + (block $label$57 (result i32) + (drop + (f64.atomic.load offset=3 + (i32.and + (i32.atomic.rmw16_u.cmpxchg offset=4 + (i32.and + (loop $label$58 (result i32) + (block + (if + (i32.eqz + (get_global $hangLimit) + ) + (return + (i32.const 208) + ) + ) + (set_global $hangLimit + (i32.sub + (get_global $hangLimit) + (i32.const 1) + ) + ) + ) + (i32.gt_u + (i32.const 67108864) + (i32.atomic.rmw8_u.cmpxchg offset=3 + (i32.and + (i32.const 4) + (i32.const 31) + ) + (i32.const 2071396369) + (i32.const -47) + ) + ) + ) + (i32.const 31) + ) + (i32.trunc_u/f32 + (call $deNan32 + (f32.neg + (f32.load offset=4 align=2 + (i32.and + (i32.const 343242608) + (i32.const 31) + ) + ) + ) + ) + ) (select - (get_local $0) - (select - (loop $label$53 (result i32) + (i32.trunc_s/f32 + (loop $label$59 (result f32) (block (if (i32.eqz (get_global $hangLimit) ) (return - (i64.const -122) + (i32.const 131072) ) ) (set_global $hangLimit @@ -914,193 +974,223 @@ ) ) ) - (block (result i32) - (nop) - (br_if $label$53 - (i32.eqz - (select - (get_local $0) - (get_local $0) - (get_local $0) - ) + (block $label$60 (result f32) + (call $deNan32 + (select + (get_local $0) + (get_local $0) + (i32.const -1) ) ) - (get_local $0) ) ) - (i32.const -2048) - (get_local $0) ) - (i32.const -8192) + (call_indirect $FUNCSIG$i + (i32.const 1) + ) + (i32.const 0) ) ) + (i32.const 31) ) ) - (block $label$54 - (drop - (get_local $0) - ) - (drop - (f32.const -nan:0x7fffb3) + ) + (br $label$2) + ) + ) + ) + ) + (br_if $label$2 + (i32.const -1048576) + ) + (if + (block $label$61 (result i32) + (set_local $0 + (f32.const 1.1754943508222875e-38) + ) + (br $label$1) + ) + (block $label$62 + (br_if $label$2 + (br_if $label$0 + (i32.load offset=4 + (i32.and + (select + (call_indirect $FUNCSIG$i + (i32.const 0) + ) + (i32.const -32769) + (call $func_1) ) + (i32.const 31) ) ) - (block $label$55 (result i32) - (loop $label$56 - (block - (if - (i32.eqz - (get_global $hangLimit) - ) - (return - (i64.const -32) - ) + (i32.eqz + (i32.const 127) + ) + ) + ) + (drop + (call $deNan64 + (f64.convert_s/i64 + (call $func_0) + ) + ) + ) + ) + (block $label$63 + (nop) + (i64.atomic.store32 offset=3 + (i32.and + (loop $label$64 (result i32) + (block + (if + (i32.eqz + (get_global $hangLimit) ) - (set_global $hangLimit - (i32.sub - (get_global $hangLimit) - (i32.const 1) - ) + (return + (i32.const 127) ) ) - (block - (block $label$57 - (loop $label$58 - (block - (if - (i32.eqz - (get_global $hangLimit) - ) - (return - (i64.const -4398046511104) - ) + (set_global $hangLimit + (i32.sub + (get_global $hangLimit) + (i32.const 1) + ) + ) + ) + (block $label$65 (result i32) + (drop + (loop $label$66 (result i32) + (block + (if + (i32.eqz + (get_global $hangLimit) ) - (set_global $hangLimit - (i32.sub - (get_global $hangLimit) - (i32.const 1) - ) + (return + (i32.const -27) ) ) - (nop) - ) - (drop - (i64.const -274877906944) - ) - ) - (br_if $label$56 - (i32.eqz - (select - (f32.eq - (f32.const 1) - (f32.const 20) + (set_global $hangLimit + (i32.sub + (get_global $hangLimit) + (i32.const 1) ) - (i32.const 1769303922) - (i32.const -32768) - ) - ) - ) - (nop) - ) - ) - (return - (i64.const -288230376151711744) - ) - ) - ) - ) - (block $label$59 (result i32) - (br_if $label$6 - (i32.eqz - (br_if $label$59 - (if (result i32) - (i32.const 1997631503) - (i32.const -111) - (block $label$62 (result i32) - (f32.atomic.store offset=3 - (i32.and - (i32.const -536870912) - (i32.const 31) ) - (f32.const 8589934592) ) - (br $label$6) - ) - ) - (i32.eqz - (select - (block $label$60 (result i32) + (block $label$67 (result i32) (drop - (f32.const 1142358272) - ) - (br $label$6) - ) - (i32.load8_s - (i32.and - (select - (i32.const 973242160) - (select - (select - (i32.const -1) - (i32.const 606678629) - (get_local $0) + (i64.div_u + (i64.const 8073603073429087267) + (loop $label$68 (result i64) + (block + (if + (i32.eqz + (get_global $hangLimit) + ) + (return + (i32.const -262144) + ) + ) + (set_global $hangLimit + (i32.sub + (get_global $hangLimit) + (i32.const 1) + ) + ) ) - (i32.const -268435456) - (block $label$61 (result i32) - (i32.const -32768) + (i64.atomic.rmw8_u.cmpxchg offset=3 + (i32.and + (i32.const 49) + (i32.const 31) + ) + (i64.const -34359738368) + (i64.const 4409085041636091956) ) ) - (get_local $0) ) - (i32.const 31) ) + (br $label$1) + ) + ) + ) + (call_indirect $FUNCSIG$i + (i32.const 3) + ) + ) + ) + (i32.const 31) + ) + (i64.load16_s offset=4 + (i32.and + (i32.clz + (i32.atomic.load8_s offset=4 + (br_if $label$0 + (i32.const 1073741824) + (i32.eqz + (i32.const 1879902727) ) - (i32.const 131072) ) ) ) + (i32.const 31) ) ) - (br $label$6) ) - (block $label$63 (result i32) - (nop) - (br $label$6) + ) + ) + ) + ) + ) + (if + (i32.eqz + (if (result i32) + (i64.ge_s + (i64.atomic.load offset=22 + (i32.and + (i32.const -16777216) + (i32.const 31) + ) + ) + (if (result i64) + (if (result i32) + (i32.eqz + (call $func_1) + ) + (block $label$69 (result i32) + (drop + (get_local $0) + ) + (i32.const 29) + ) + (block $label$70 (result i32) + (i32.const 1073741824) + ) + ) + (block $label$71 (result i64) + (i64.const 6669) + ) + (block $label$72 (result i64) + (i64.const -36028797018963968) ) ) ) + (i32.const -1) + (i32.const 2097152) ) ) - (tee_local $0 - (i32.const -1) + (block $label$73 + (set_local $2 + (get_local $1) + ) + ) + (block $label$74 + (nop) ) - (get_local $0) - ) - ) - ) - ) - (func $func_1 (result f32) - (local $0 i64) - (local $1 f32) - (local $2 f64) - (local $3 f32) - (block - (if - (i32.eqz - (get_global $hangLimit) - ) - (return - (f32.const 691027220365312) - ) - ) - (set_global $hangLimit - (i32.sub - (get_global $hangLimit) - (i32.const 1) ) ) + (i32.const -4096) ) - (unreachable) ) (func $hangLimitInitializer (set_global $hangLimit From 9d31166e08ecfa7cd6437cceae3a767bfc64395b Mon Sep 17 00:00:00 2001 From: "Alon Zakai (kripken)" Date: Thu, 12 Oct 2017 16:21:47 -0700 Subject: [PATCH 07/33] atomics support in interpreter --- src/wasm-interpreter.h | 126 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 119 insertions(+), 7 deletions(-) diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h index 8f958ee42b5..acb424bf62f 100644 --- a/src/wasm-interpreter.h +++ b/src/wasm-interpreter.h @@ -853,6 +853,86 @@ class ModuleInstanceBase { return Flow(); } + Flow visitAtomicRMW(AtomicRMW *curr) { + NOTE_ENTER("AtomicRMW"); + Flow ptr = this->visit(curr->ptr); + if (ptr.breaking()) return ptr; + NOTE_EVAL1(ptr); + auto addr = instance.getFinalAddress(curr, ptr.value); + NOTE_EVAL1(addr); + auto value = this->visit(curr->value); + NOTE_EVAL1(value); + if (value.breaking()) return value; + auto loaded = instance.doAtomicLoad(addr, curr->bytes, curr->type); + NOTE_EVAL1(loaded); + auto computed = value.value; + switch (curr->op) { + case Add: computed = computed.add(value.value); break; + case Sub: computed = computed.sub(value.value); break; + case And: computed = computed.and_(value.value); break; + case Or: computed = computed.or_(value.value); break; + case Xor: computed = computed.xor_(value.value); break; + case Xchg: computed = value.value; break; + default: WASM_UNREACHABLE(); + } + instance.doAtomicStore(addr, curr->bytes, computed); + return loaded; + } + Flow visitAtomicCmpxchg(AtomicCmpxchg *curr) { + NOTE_ENTER("AtomicCmpxchg"); + Flow ptr = this->visit(curr->ptr); + if (ptr.breaking()) return ptr; + NOTE_EVAL1(ptr); + auto addr = instance.getFinalAddress(curr, ptr.value); + NOTE_EVAL1(addr); + auto expected = this->visit(curr->expected); + NOTE_EVAL1(expected); + if (expected.breaking()) return expected; + auto replacement = this->visit(curr->replacement); + NOTE_EVAL1(replacement); + if (replacement.breaking()) return replacement; + auto loaded = instance.doAtomicLoad(addr, curr->bytes, curr->type); + NOTE_EVAL1(loaded); + if (loaded == expected.value) { + instance.doAtomicStore(addr, curr->bytes, replacement.value); + } + return loaded; + } + Flow visitAtomicWait(AtomicWait *curr) { + NOTE_ENTER("AtomicWait"); + Flow ptr = this->visit(curr->ptr); + if (ptr.breaking()) return ptr; + NOTE_EVAL1(ptr); + auto addr = ptr.value.getInteger(); + NOTE_EVAL1(addr); + auto expected = this->visit(curr->expected); + NOTE_EVAL1(expected); + if (expected.breaking()) return expected; + auto timeout = this->visit(curr->timeout); + NOTE_EVAL1(timeout); + if (timeout.breaking()) return timeout; + auto loaded = instance.doAtomicLoad(addr, getWasmTypeSize(curr->expectedType), curr->expectedType); + NOTE_EVAL1(loaded); + if (loaded != expected.value) { + return Literal(int32_t(1)); // not equal + } + // TODO: add threads support! + // for now, just assume we are woken up + return Literal(int32_t(0)); // woken up + } + Flow visitAtomicWake(AtomicWake *curr) { + NOTE_ENTER("AtomicWake"); + Flow ptr = this->visit(curr->ptr); + if (ptr.breaking()) return ptr; + NOTE_EVAL1(ptr); + NOTE_EVAL1(addr); + auto count = this->visit(curr->wakeCount); + NOTE_EVAL1(count); + if (count.breaking()) return count; + // TODO: add threads support! + return Literal(int32_t(0)); // none woken up + } + Flow visitHost(Host *curr) { NOTE_ENTER("Host"); switch (curr->op) { @@ -926,15 +1006,16 @@ class ModuleInstanceBase { Address memorySize; // in pages + void trapIfGt(uint64_t lhs, uint64_t rhs, const char* msg) { + if (lhs > rhs) { + std::stringstream ss; + ss << msg << ": " << lhs << " > " << rhs; + externalInterface->trap(ss.str().c_str()); + } + } + template Address getFinalAddress(LS* curr, Literal ptr) { - auto trapIfGt = [this](uint64_t lhs, uint64_t rhs, const char* msg) { - if (lhs > rhs) { - std::stringstream ss; - ss << msg << ": " << lhs << " > " << rhs; - externalInterface->trap(ss.str().c_str()); - } - }; Address memorySizeBytes = memorySize * Memory::kPageSize; uint64_t addr = ptr.type == i32 ? ptr.geti32() : ptr.geti64(); trapIfGt(curr->offset, memorySizeBytes, "offset > memory"); @@ -945,6 +1026,37 @@ class ModuleInstanceBase { return addr; } + Literal doAtomicLoad(Address addr, Index bytes, WasmType type) { + Const ptr; + ptr.value = Literal(int32_t(addr)); + ptr.type = i32; + Load load; + load.bytes = bytes; + load.signed_ = true; + load.align = bytes; + load.isAtomic = true; // understatement + load.ptr = &ptr; + load.type = type; + return externalInterface->load(&load, addr); + } + + void doAtomicStore(Address addr, Index bytes, Literal toStore) { + Const ptr; + ptr.value = Literal(int32_t(addr)); + ptr.type = i32; + Const value; + value.value = toStore; + value.type = toStore.type; + Store store; + store.bytes = bytes; + store.align = bytes; + store.isAtomic = true; // understatement + store.ptr = &ptr; + store.value = &value; + store.valueType = value.type; + return externalInterface->store(&store, addr, toStore); + } + ExternalInterface* externalInterface; }; From d2d3d02f9326f82bc08882366bef5b6ebf6b405f Mon Sep 17 00:00:00 2001 From: "Alon Zakai (kripken)" Date: Thu, 12 Oct 2017 16:45:45 -0700 Subject: [PATCH 08/33] fixes --- src/wasm-interpreter.h | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h index acb424bf62f..d39b326086c 100644 --- a/src/wasm-interpreter.h +++ b/src/wasm-interpreter.h @@ -119,7 +119,7 @@ class ExpressionRunner : public Visitor { public: Flow visit(Expression *curr) { auto ret = Visitor::visit(curr); - if (!ret.breaking()) { + if (!ret.breaking() && (isConcreteWasmType(curr->type) || isConcreteWasmType(ret.value.type))) { assert(ret.value.type == curr->type); } return ret; @@ -1022,11 +1022,17 @@ class ModuleInstanceBase { trapIfGt(addr, memorySizeBytes - curr->offset, "final > memory"); addr += curr->offset; trapIfGt(curr->bytes, memorySizeBytes, "bytes > memory"); - trapIfGt(addr, memorySizeBytes - curr->bytes, "highest > memory"); + checkLoadAddress(addr, curr->bytes); return addr; } + void checkLoadAddress(Address addr, Index bytes) { + Address memorySizeBytes = memorySize * Memory::kPageSize; + trapIfGt(addr, memorySizeBytes - bytes, "highest > memory"); + } + Literal doAtomicLoad(Address addr, Index bytes, WasmType type) { + checkLoadAddress(addr, bytes); Const ptr; ptr.value = Literal(int32_t(addr)); ptr.type = i32; From 675b7c8bfdc539fe6ad5da0b1c285a9ba145ec5e Mon Sep 17 00:00:00 2001 From: "Alon Zakai (kripken)" Date: Thu, 12 Oct 2017 17:38:56 -0700 Subject: [PATCH 09/33] very wip --- src/ast/global-utils.h | 2 +- src/ast/import-utils.h | 6 ++--- src/passes/SafeHeap.cpp | 6 ++--- src/tools/wasm-ctor-eval.cpp | 49 ++++++++++++++++++++++-------------- src/wasm-interpreter.h | 9 ++++--- 5 files changed, 42 insertions(+), 30 deletions(-) diff --git a/src/ast/global-utils.h b/src/ast/global-utils.h index f5bebe8aa0c..96fec282bf3 100644 --- a/src/ast/global-utils.h +++ b/src/ast/global-utils.h @@ -27,7 +27,7 @@ namespace wasm { namespace GlobalUtils { // find a global initialized to the value of an import, or null if no such global - inline Global* getGlobalInitializedToImport(Module&wasm, Name module, Name base) { + inline Global* getGlobalInitializedToImport(Module& wasm, Name module, Name base) { // find the import Name imported; for (auto& import : wasm.imports) { diff --git a/src/ast/import-utils.h b/src/ast/import-utils.h index d12c2318256..ff7ca3b83b6 100644 --- a/src/ast/import-utils.h +++ b/src/ast/import-utils.h @@ -25,13 +25,13 @@ namespace wasm { namespace ImportUtils { // find an import by the module.base that is being imported. // return the internal name - inline Name getImport(Module& wasm, Name module, Name base) { + inline Import* getImport(Module& wasm, Name module, Name base) { for (auto& import : wasm.imports) { if (import->module == module && import->base == base) { - return import->name; + return import.get(); } } - return Name(); + return nullptr; } }; diff --git a/src/passes/SafeHeap.cpp b/src/passes/SafeHeap.cpp index ebaf4235847..dccc2ceaf17 100644 --- a/src/passes/SafeHeap.cpp +++ b/src/passes/SafeHeap.cpp @@ -114,7 +114,7 @@ struct SafeHeap : public Pass { void addImports(Module* module) { // imports - dynamicTopPtr = ImportUtils::getImport(*module, ENV, DYNAMICTOP_PTR_IMPORT); + dynamicTopPtr = ImportUtils::getImport(*module, ENV, DYNAMICTOP_PTR_IMPORT)->name; if (!dynamicTopPtr.is()) { auto* import = new Import; import->name = dynamicTopPtr = DYNAMICTOP_PTR_IMPORT; @@ -124,7 +124,7 @@ struct SafeHeap : public Pass { import->globalType = i32; module->addImport(import); } - segfault = ImportUtils::getImport(*module, ENV, SEGFAULT_IMPORT); + segfault = ImportUtils::getImport(*module, ENV, SEGFAULT_IMPORT)->name; if (!segfault.is()) { auto* import = new Import; import->name = segfault = SEGFAULT_IMPORT; @@ -134,7 +134,7 @@ struct SafeHeap : public Pass { import->functionType = ensureFunctionType("v", module)->name; module->addImport(import); } - alignfault = ImportUtils::getImport(*module, ENV, ALIGNFAULT_IMPORT); + alignfault = ImportUtils::getImport(*module, ENV, ALIGNFAULT_IMPORT)->name; if (!alignfault.is()) { auto* import = new Import; import->name = alignfault = ALIGNFAULT_IMPORT; diff --git a/src/tools/wasm-ctor-eval.cpp b/src/tools/wasm-ctor-eval.cpp index f3d420aac57..d0707c13e94 100644 --- a/src/tools/wasm-ctor-eval.cpp +++ b/src/tools/wasm-ctor-eval.cpp @@ -33,6 +33,7 @@ #include "wasm-builder.h" #include "ast/memory-utils.h" #include "ast/global-utils.h" +#include "ast/import-utils.h" using namespace wasm; @@ -71,6 +72,7 @@ class EvallingGlobalManager { } Literal& operator[](Name name) { +std::cout << "operator[] " << name << '\n'; if (dangerousGlobals.count(name) > 0) { std::string extra; if (name == "___dso_handle") { @@ -78,9 +80,12 @@ class EvallingGlobalManager { } throw FailToEvalException(std::string("tried to access a dangerous (import-initialized) global: ") + name.str + extra); } - if (sealed) { - if (globals.find(name) == globals.end()) { + if (globals.find(name) == globals.end()) { + if (sealed) { throw FailToEvalException(std::string("tried to access missing global: ") + name.str); + } else { + // fake a value + globals[name] = Literal(int32_t(0)); } } return globals[name]; @@ -114,6 +119,13 @@ class EvallingGlobalManager { } }; +enum { + // put the stack in some ridiculously high location + STACK_START = 0x40000000, + // use a ridiculously large stack size + STACK_SIZE = 32 * 1024 * 1024 +}; + class EvallingModuleInstance : public ModuleInstanceBase { public: EvallingModuleInstance(Module& wasm, ExternalInterface* externalInterface) : ModuleInstanceBase(wasm, externalInterface) { @@ -138,13 +150,6 @@ class EvallingModuleInstance : public ModuleInstanceBase stack; // create C stack space for us to use. We do *NOT* care about their contents, @@ -153,13 +158,6 @@ class EvallingModuleInstance : public ModuleInstanceBasename] = Literal(int32_t(STACK_START)); - } - if (auto* stackMax = GlobalUtils::getGlobalInitializedToImport(wasm, "env", "STACK_MAX")) { - globals[stackMax->name] = Literal(int32_t(STACK_START)); - } // tell the module to accept writes up to the stack end auto total = STACK_START + STACK_SIZE; memorySize = total / Memory::kPageSize; @@ -181,6 +179,19 @@ struct CtorEvalExternalInterface : EvallingModuleInstance::ExternalInterface { } void importGlobals(EvallingGlobalManager& globals, Module& wasm_) override { + // fill usable values for stack imports, and globals initialized to them + if (auto* stackTop = ImportUtils::getImport(wasm_, "env", "STACKTOP")) { + globals[stackTop->name] = Literal(int32_t(STACK_START)); + if (auto* stackTop = GlobalUtils::getGlobalInitializedToImport(wasm_, "env", "STACKTOP")) { + globals[stackTop->name] = Literal(int32_t(STACK_START)); + } + } + if (auto* stackMax = ImportUtils::getImport(wasm_, "env", "STACK_MAX")) { + globals[stackMax->name] = Literal(int32_t(STACK_START)); + if (auto* stackMax = GlobalUtils::getGlobalInitializedToImport(wasm_, "env", "STACK_MAX")) { + globals[stackMax->name] = Literal(int32_t(STACK_START)); + } + } } Literal callImport(Import *import, LiteralList& arguments) override { @@ -248,9 +259,9 @@ struct CtorEvalExternalInterface : EvallingModuleInstance::ExternalInterface { template T* getMemory(Address address) { // if memory is on the stack, use the stack - if (address >= instance->STACK_START) { - Address relative = address - instance->STACK_START; - if (relative + sizeof(T) > instance->STACK_SIZE) { + if (address >= STACK_START) { + Address relative = address - STACK_START; + if (relative + sizeof(T) > STACK_SIZE) { throw FailToEvalException("stack usage too high"); } // in range, all is good, use the stack diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h index d39b326086c..3719f9c34b1 100644 --- a/src/wasm-interpreter.h +++ b/src/wasm-interpreter.h @@ -32,9 +32,7 @@ #include "wasm.h" #include "wasm-traversal.h" -#ifdef WASM_INTERPRETER_DEBUG #include "wasm-printing.h" -#endif namespace wasm { @@ -120,6 +118,7 @@ class ExpressionRunner : public Visitor { Flow visit(Expression *curr) { auto ret = Visitor::visit(curr); if (!ret.breaking() && (isConcreteWasmType(curr->type) || isConcreteWasmType(ret.value.type))) { +std::cout << curr << " : " << ret.value << '\n'; assert(ret.value.type == curr->type); } return ret; @@ -526,7 +525,9 @@ class ConstantExpressionRunner : public ExpressionRunnername]); } + Flow visitGetGlobal(GetGlobal *curr) { + return Flow(globals[curr->name]); + } Flow visitSetGlobal(SetGlobal *curr) { WASM_UNREACHABLE(); } Flow visitLoad(Load *curr) { WASM_UNREACHABLE(); } Flow visitStore(Store *curr) { WASM_UNREACHABLE(); } @@ -814,8 +815,8 @@ class ModuleInstanceBase { NOTE_ENTER("GetGlobal"); auto name = curr->name; NOTE_EVAL1(name); - NOTE_EVAL1(instance.globals[name]); assert(instance.globals.find(name) != instance.globals.end()); + NOTE_EVAL1(instance.globals[name]); return instance.globals[name]; } Flow visitSetGlobal(SetGlobal *curr) { From 3e01950f882a399b75d5f5700081d1c46227a0ff Mon Sep 17 00:00:00 2001 From: "Alon Zakai (kripken)" Date: Fri, 13 Oct 2017 10:17:56 -0700 Subject: [PATCH 10/33] ctors fix --- src/tools/wasm-ctor-eval.cpp | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/src/tools/wasm-ctor-eval.cpp b/src/tools/wasm-ctor-eval.cpp index d0707c13e94..3f0aa1c0c0c 100644 --- a/src/tools/wasm-ctor-eval.cpp +++ b/src/tools/wasm-ctor-eval.cpp @@ -34,6 +34,7 @@ #include "ast/memory-utils.h" #include "ast/global-utils.h" #include "ast/import-utils.h" +#include "ast/literal-utils.h" using namespace wasm; @@ -72,7 +73,6 @@ class EvallingGlobalManager { } Literal& operator[](Name name) { -std::cout << "operator[] " << name << '\n'; if (dangerousGlobals.count(name) > 0) { std::string extra; if (name == "___dso_handle") { @@ -80,14 +80,6 @@ std::cout << "operator[] " << name << '\n'; } throw FailToEvalException(std::string("tried to access a dangerous (import-initialized) global: ") + name.str + extra); } - if (globals.find(name) == globals.end()) { - if (sealed) { - throw FailToEvalException(std::string("tried to access missing global: ") + name.str); - } else { - // fake a value - globals[name] = Literal(int32_t(0)); - } - } return globals[name]; } @@ -192,6 +184,19 @@ struct CtorEvalExternalInterface : EvallingModuleInstance::ExternalInterface { globals[stackMax->name] = Literal(int32_t(STACK_START)); } } + // fill in fake values for everything else, which is dangerous to use + for (auto& global : wasm_.globals) { + if (globals.find(global->name) == globals.end()) { + globals[global->name] = LiteralUtils::makeLiteralZero(global->type); + } + } + for (auto& import : wasm_.imports) { + if (import->kind == ExternalKind::Global) { + if (globals.find(import->name) == globals.end()) { + globals[import->name] = LiteralUtils::makeLiteralZero(import->globalType); + } + } + } } Literal callImport(Import *import, LiteralList& arguments) override { From 2bd219167245d9a7f2d38e9ba56da070a0dc76e2 Mon Sep 17 00:00:00 2001 From: "Alon Zakai (kripken)" Date: Fri, 13 Oct 2017 10:21:47 -0700 Subject: [PATCH 11/33] cleanup --- src/wasm-interpreter.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h index 3719f9c34b1..9f94b5db71d 100644 --- a/src/wasm-interpreter.h +++ b/src/wasm-interpreter.h @@ -118,7 +118,6 @@ class ExpressionRunner : public Visitor { Flow visit(Expression *curr) { auto ret = Visitor::visit(curr); if (!ret.breaking() && (isConcreteWasmType(curr->type) || isConcreteWasmType(ret.value.type))) { -std::cout << curr << " : " << ret.value << '\n'; assert(ret.value.type == curr->type); } return ret; From 262ccd131991ff60dba4c69a7c452bdebda54c24 Mon Sep 17 00:00:00 2001 From: "Alon Zakai (kripken)" Date: Fri, 13 Oct 2017 10:27:04 -0700 Subject: [PATCH 12/33] fix? --- src/passes/SafeHeap.cpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/passes/SafeHeap.cpp b/src/passes/SafeHeap.cpp index dccc2ceaf17..7218dd364bd 100644 --- a/src/passes/SafeHeap.cpp +++ b/src/passes/SafeHeap.cpp @@ -114,8 +114,7 @@ struct SafeHeap : public Pass { void addImports(Module* module) { // imports - dynamicTopPtr = ImportUtils::getImport(*module, ENV, DYNAMICTOP_PTR_IMPORT)->name; - if (!dynamicTopPtr.is()) { + if (ImportUtils::getImport(*module, ENV, DYNAMICTOP_PTR_IMPORT)) { auto* import = new Import; import->name = dynamicTopPtr = DYNAMICTOP_PTR_IMPORT; import->module = ENV; @@ -124,8 +123,7 @@ struct SafeHeap : public Pass { import->globalType = i32; module->addImport(import); } - segfault = ImportUtils::getImport(*module, ENV, SEGFAULT_IMPORT)->name; - if (!segfault.is()) { + if (ImportUtils::getImport(*module, ENV, SEGFAULT_IMPORT)) { auto* import = new Import; import->name = segfault = SEGFAULT_IMPORT; import->module = ENV; @@ -134,8 +132,7 @@ struct SafeHeap : public Pass { import->functionType = ensureFunctionType("v", module)->name; module->addImport(import); } - alignfault = ImportUtils::getImport(*module, ENV, ALIGNFAULT_IMPORT)->name; - if (!alignfault.is()) { + if (ImportUtils::getImport(*module, ENV, ALIGNFAULT_IMPORT)) { auto* import = new Import; import->name = alignfault = ALIGNFAULT_IMPORT; import->module = ENV; From 1fb0ea993f719309bd83463a5314e74386589dac Mon Sep 17 00:00:00 2001 From: "Alon Zakai (kripken)" Date: Fri, 13 Oct 2017 14:43:57 -0700 Subject: [PATCH 13/33] fix --- src/passes/SafeHeap.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/passes/SafeHeap.cpp b/src/passes/SafeHeap.cpp index 7218dd364bd..784bc761d73 100644 --- a/src/passes/SafeHeap.cpp +++ b/src/passes/SafeHeap.cpp @@ -114,7 +114,9 @@ struct SafeHeap : public Pass { void addImports(Module* module) { // imports - if (ImportUtils::getImport(*module, ENV, DYNAMICTOP_PTR_IMPORT)) { + if (auto* existing = ImportUtils::getImport(*module, ENV, DYNAMICTOP_PTR_IMPORT)) { + dynamicTopPtr = existing->name; + } else { auto* import = new Import; import->name = dynamicTopPtr = DYNAMICTOP_PTR_IMPORT; import->module = ENV; @@ -123,7 +125,9 @@ struct SafeHeap : public Pass { import->globalType = i32; module->addImport(import); } - if (ImportUtils::getImport(*module, ENV, SEGFAULT_IMPORT)) { + if (auto* existing = ImportUtils::getImport(*module, ENV, SEGFAULT_IMPORT)) { + dynamicTopPtr = existing->name; + } else { auto* import = new Import; import->name = segfault = SEGFAULT_IMPORT; import->module = ENV; @@ -132,7 +136,9 @@ struct SafeHeap : public Pass { import->functionType = ensureFunctionType("v", module)->name; module->addImport(import); } - if (ImportUtils::getImport(*module, ENV, ALIGNFAULT_IMPORT)) { + if (auto* existing = ImportUtils::getImport(*module, ENV, ALIGNFAULT_IMPORT)) { + dynamicTopPtr = existing->name; + } else { auto* import = new Import; import->name = alignfault = ALIGNFAULT_IMPORT; import->module = ENV; From ce49a951656e641b6114da26c518b2304647f563 Mon Sep 17 00:00:00 2001 From: "Alon Zakai (kripken)" Date: Fri, 13 Oct 2017 14:58:04 -0700 Subject: [PATCH 14/33] fixes --- src/tools/translate-to-fuzz.h | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/tools/translate-to-fuzz.h b/src/tools/translate-to-fuzz.h index 8c83ff53b6e..9adff36ca14 100644 --- a/src/tools/translate-to-fuzz.h +++ b/src/tools/translate-to-fuzz.h @@ -760,6 +760,7 @@ class TranslateToFuzzReader { Expression* makeLoad(WasmType type) { auto* ret = makeNonAtomicLoad(type); + if (type != i32 && type != i64) return ret; if (oneIn(2)) return ret; // make it atomic wasm.memory.shared = true; @@ -818,6 +819,7 @@ class TranslateToFuzzReader { Store* makeStore(WasmType type) { auto* ret = makeNonAtomicStore(type); + if (ret->value->type != i32 && ret->value->type != i64) return ret; if (oneIn(2)) return ret; // make it atomic wasm.memory.shared = true; @@ -1104,12 +1106,6 @@ class TranslateToFuzzReader { } break; } - case f32: { - bytes = pick(1, 2, 4); break; - } - case f64: { - bytes = pick(1, 2, 4, 8); break; - } default: WASM_UNREACHABLE(); } auto offset = logify(get()); From 5eb762c5893d7d5f03e662c0d195513403889637 Mon Sep 17 00:00:00 2001 From: "Alon Zakai (kripken)" Date: Fri, 13 Oct 2017 15:02:49 -0700 Subject: [PATCH 15/33] fix --- src/passes/DeadCodeElimination.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/passes/DeadCodeElimination.cpp b/src/passes/DeadCodeElimination.cpp index e5673a0cc55..85331c1efc5 100644 --- a/src/passes/DeadCodeElimination.cpp +++ b/src/passes/DeadCodeElimination.cpp @@ -254,6 +254,10 @@ struct DeadCodeElimination : public WalkerPass> case Expression::Id::HostId: DELEGATE(Host); case Expression::Id::NopId: DELEGATE(Nop); case Expression::Id::UnreachableId: break; + case Expression::Id::AtomicCmpxchgId: DELEGATE(AtomicCmpxchg); + case Expression::Id::AtomicRMWId: DELEGATE(AtomicRMW); + case Expression::Id::AtomicWaitId: DELEGATE(AtomicWait); + case Expression::Id::AtomicWakeId: DELEGATE(AtomicWake); case Expression::Id::InvalidId: default: WASM_UNREACHABLE(); } From b464816906489b944a3d3d7bd5f0486a4689b428 Mon Sep 17 00:00:00 2001 From: "Alon Zakai (kripken)" Date: Fri, 13 Oct 2017 15:42:56 -0700 Subject: [PATCH 16/33] better --- src/wasm-interpreter.h | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h index 9f94b5db71d..a266a4698d8 100644 --- a/src/wasm-interpreter.h +++ b/src/wasm-interpreter.h @@ -32,7 +32,11 @@ #include "wasm.h" #include "wasm-traversal.h" +//#define WASM_INTERPRETER_DEBUG 1 + +//#ifdef WASM_INTERPRETER_DEBUG #include "wasm-printing.h" +//#endif namespace wasm { @@ -118,6 +122,11 @@ class ExpressionRunner : public Visitor { Flow visit(Expression *curr) { auto ret = Visitor::visit(curr); if (!ret.breaking() && (isConcreteWasmType(curr->type) || isConcreteWasmType(ret.value.type))) { +#if 1 // def WASM_INTERPRETER_DEBUG + if (ret.value.type != curr->type) { + std::cerr << "expected " << printWasmType(curr->type) << ", seeing " << printWasmType(ret.value.type) << " from\n" << curr << '\n'; + } +#endif assert(ret.value.type == curr->type); } return ret; @@ -925,7 +934,6 @@ class ModuleInstanceBase { Flow ptr = this->visit(curr->ptr); if (ptr.breaking()) return ptr; NOTE_EVAL1(ptr); - NOTE_EVAL1(addr); auto count = this->visit(curr->wakeCount); NOTE_EVAL1(count); if (count.breaking()) return count; From 95d04b5f7d9c7818842e3caecbbc127fea8097f5 Mon Sep 17 00:00:00 2001 From: "Alon Zakai (kripken)" Date: Fri, 13 Oct 2017 16:40:47 -0700 Subject: [PATCH 17/33] fix --- src/passes/Precompute.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/passes/Precompute.cpp b/src/passes/Precompute.cpp index ab114fa1427..d2a7d0b9af2 100644 --- a/src/passes/Precompute.cpp +++ b/src/passes/Precompute.cpp @@ -89,6 +89,12 @@ class StandaloneExpressionRunner : public ExpressionRunner Date: Fri, 13 Oct 2017 16:51:27 -0700 Subject: [PATCH 18/33] fix --- src/passes/Print.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/passes/Print.cpp b/src/passes/Print.cpp index 8bb5175ab38..6d40034fc45 100644 --- a/src/passes/Print.cpp +++ b/src/passes/Print.cpp @@ -352,7 +352,9 @@ struct PrintSExpression : public Visitor { } static void printRMWSize(std::ostream& o, WasmType type, uint8_t bytes) { prepareColor(o) << printWasmType(type) << ".atomic.rmw"; - if (bytes != getWasmTypeSize(type)) { + if (type == unreachable) { + o << '?'; + } else if (bytes != getWasmTypeSize(type)) { if (bytes == 1) { o << '8'; } else if (bytes == 2) { From 5419aeacfbd177aec77772475cfda62dcf9c9946 Mon Sep 17 00:00:00 2001 From: "Alon Zakai (kripken)" Date: Sat, 14 Oct 2017 10:39:51 -0700 Subject: [PATCH 19/33] fix atomic store building bug --- src/ast/ExpressionManipulator.cpp | 12 ++-- src/wasm-builder.h | 2 +- test/passes/inlining-optimizing.txt | 47 +++----------- test/passes/inlining-optimizing.wast | 94 ++++------------------------ 4 files changed, 26 insertions(+), 129 deletions(-) diff --git a/src/ast/ExpressionManipulator.cpp b/src/ast/ExpressionManipulator.cpp index f5b303488fa..6c0804a4989 100644 --- a/src/ast/ExpressionManipulator.cpp +++ b/src/ast/ExpressionManipulator.cpp @@ -97,25 +97,25 @@ Expression* flexibleCopy(Expression* original, Module& wasm, CustomCopier custom } Expression* visitLoad(Load *curr) { if (curr->isAtomic) { - return builder.makeAtomicLoad(curr->bytes, curr->signed_, curr->offset, - copy(curr->ptr), curr->type); + return builder.makeAtomicLoad(curr->bytes, curr->signed_, curr->offset, + copy(curr->ptr), curr->type); } return builder.makeLoad(curr->bytes, curr->signed_, curr->offset, curr->align, copy(curr->ptr), curr->type); } Expression* visitStore(Store *curr) { if (curr->isAtomic) { - return builder.makeAtomicStore(curr->bytes, curr->offset, copy(curr->ptr), copy(curr->value), curr->valueType); + return builder.makeAtomicStore(curr->bytes, curr->offset, copy(curr->ptr), copy(curr->value), curr->valueType); } return builder.makeStore(curr->bytes, curr->offset, curr->align, copy(curr->ptr), copy(curr->value), curr->valueType); } Expression* visitAtomicRMW(AtomicRMW* curr) { return builder.makeAtomicRMW(curr->op, curr->bytes, curr->offset, - copy(curr->ptr), copy(curr->value), curr->type); + copy(curr->ptr), copy(curr->value), curr->type); } Expression* visitAtomicCmpxchg(AtomicCmpxchg* curr) { return builder.makeAtomicCmpxchg(curr->bytes, curr->offset, - copy(curr->ptr), copy(curr->expected), copy(curr->replacement), - curr->type); + copy(curr->ptr), copy(curr->expected), copy(curr->replacement), + curr->type); } Expression* visitAtomicWait(AtomicWait* curr) { return builder.makeAtomicWait(copy(curr->ptr), copy(curr->expected), copy(curr->timeout), curr->type); diff --git a/src/wasm-builder.h b/src/wasm-builder.h index cb935893380..62443372eb2 100644 --- a/src/wasm-builder.h +++ b/src/wasm-builder.h @@ -231,7 +231,7 @@ class Builder { return ret; } Store* makeAtomicStore(unsigned bytes, uint32_t offset, Expression* ptr, Expression* value, WasmType type) { - Store* store = makeStore(bytes, offset, getWasmTypeSize(type), ptr, value, type); + Store* store = makeStore(bytes, offset, bytes, ptr, value, type); store->isAtomic = true; return store; } diff --git a/test/passes/inlining-optimizing.txt b/test/passes/inlining-optimizing.txt index 19c5800636a..ca3f7da79ff 100644 --- a/test/passes/inlining-optimizing.txt +++ b/test/passes/inlining-optimizing.txt @@ -1,43 +1,12 @@ -(module - (type $0 (func)) - (type $1 (func (result i32))) - (type $2 (func (result f64))) - (type $3 (func (param f32 i64))) - (table 1 1 anyfunc) - (elem (i32.const 0) $tabled) - (memory $0 0) - (export "user" (func $user)) - (export "exported" (func $exported)) - (func $user (type $0) - (call $exported) - (call $tabled) - (call $multi) - (call $multi) - ) - (func $exported (type $0) - (nop) - ) - (func $recursive (type $0) - (call $recursive) - ) - (func $tabled (type $0) - (nop) - ) - (func $cycle1 (type $0) - (call $cycle2) - ) - (func $cycle2 (type $0) - (call $cycle1) - ) - (func $multi (type $0) - (nop) - ) -) (module (type $0 (func (result i32))) - (type $1 (func)) - (memory $0 0) - (func $main (type $0) (result i32) - (unreachable) + (type $1 (func (result i64))) + (memory $0 (shared 1 1)) + (func $1 (type $1) (result i64) + (i32.atomic.store16 + (i32.const 0) + (i32.const 0) + ) + (i64.const 0) ) ) diff --git a/test/passes/inlining-optimizing.wast b/test/passes/inlining-optimizing.wast index 4f4f348a616..80823c83292 100644 --- a/test/passes/inlining-optimizing.wast +++ b/test/passes/inlining-optimizing.wast @@ -1,88 +1,16 @@ (module - (table 1 1 anyfunc) - (elem (i32.const 0) $tabled) - (func $user (export "user") - (local $x i32) - (local $y f64) - (call $exported) - (call $tabled) - (call $multi) - (call $multi) - (call $ok) - (drop (call $int)) - (drop (call $double)) - (set_local $x (call $int2)) - (set_local $y (call $double2)) - (call $with-local) - (call $with-local2) - (drop (call $return)) - (call $multipass) - (call $param (f32.const 12.34) (i64.const 890005350012)) + (memory $0 (shared 1 1)) + (func $0 (result i32) + (i32.atomic.store16 + (i32.const 0) + (i32.const 0) ) - (func $exported (export "exported") - (nop) - ) - (func $recursive - (call $recursive) - ) - (func $tabled - (nop) - ) - (func $cycle1 - (call $cycle2) - ) - (func $cycle2 - (call $cycle1) - ) - (func $multi - (nop) - ) - (func $ok - (drop (i32.const 1)) - ) - (func $int (result i32) - (i32.const 2) - ) - (func $double (result f64) - (f64.const 3.14159) - ) - (func $int2 (result i32) - (i32.const 112) - ) - (func $double2 (result f64) - (f64.const 113.14159) - ) - (func $with-local - (local $x f32) - (set_local $x (f32.const 2.141828)) - ) - (func $with-local2 - (local $y i64) - (set_local $y (i64.const 4)) - ) - (func $return (result i32) - (return (i32.const 5)) - ) - (func $multipass - (call $multipass2) - ) - (func $multipass2 - (drop (i32.const 6)) - ) - (func $param (param $x f32) (param $y i64) - (local $z f32) - (drop (get_local $x)) - (drop (get_local $y)) - (drop (get_local $z)) - ) -) -(module - (func $main (result i32) - (call $func_51) - (i32.const 0) + (i32.const 1) ) - (func $func_51 - (unreachable) ;; void function but having unreachable body, when inlined, type must be fixed + (func $1 (result i64) + (drop + (call $0) + ) + (i64.const 0) ) ) - From fa7cec423e3cf99719f37a3c352b6e244837fc1f Mon Sep 17 00:00:00 2001 From: "Alon Zakai (kripken)" Date: Sat, 14 Oct 2017 10:39:58 -0700 Subject: [PATCH 20/33] test update --- test/passes/translate-to-fuzz.txt | 1658 ++++++++++++++--------------- 1 file changed, 792 insertions(+), 866 deletions(-) diff --git a/test/passes/translate-to-fuzz.txt b/test/passes/translate-to-fuzz.txt index 6f301689536..000ba2106a6 100644 --- a/test/passes/translate-to-fuzz.txt +++ b/test/passes/translate-to-fuzz.txt @@ -1,13 +1,15 @@ (module (type $FUNCSIG$j (func (result i64))) (type $FUNCSIG$i (func (result i32))) + (type $FUNCSIG$vff (func (param f32 f32))) + (type $FUNCSIG$fj (func (param i64) (result f32))) (global $hangLimit (mut i32) (i32.const 100)) - (table 4 anyfunc) - (elem (i32.const 0) $func_1 $func_1 $func_1 $func_1) + (table 9 9 anyfunc) + (elem (i32.const 0) $func_1 $func_1 $func_1 $func_1 $func_3 $func_3 $func_3 $func_3 $func_3) (memory $0 (shared 1 1)) (data (i32.const 0) "\00C\00[\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00") (export "func_0" (func $func_0)) - (export "func_2" (func $func_2)) + (export "func_4" (func $func_4)) (export "hangLimitInitializer" (func $hangLimitInitializer)) (func $func_0 (type $FUNCSIG$j) (result i64) (local $0 i32) @@ -62,7 +64,7 @@ ) ) ) - (func $func_2 (type $FUNCSIG$i) (result i32) + (func $func_2 (result i32) (local $0 f32) (local $1 f64) (local $2 f64) @@ -72,7 +74,7 @@ (get_global $hangLimit) ) (return - (i32.const 16) + (i32.const 269093727) ) ) (set_global $hangLimit @@ -87,198 +89,74 @@ (i32.const 274205712) (block $label$1 (drop - (f32.atomic.load offset=4 + (f32.load offset=4 align=1 (i32.const 842759483) ) ) - (loop $label$2 - (block - (if - (i32.eqz - (get_global $hangLimit) - ) - (return - (i32.const -524288) - ) - ) - (set_global $hangLimit - (i32.sub - (get_global $hangLimit) - (i32.const 1) - ) - ) - ) - (block - (block $label$3 - (i64.atomic.store32 offset=22 + (nop) + ) + (nop) + ) + (nop) + (f32.gt + (f32.load offset=2 + (i32.and + (call $func_1) + (i32.const 31) + ) + ) + (f32.load offset=4 align=2 + (i32.and + (i32.wrap/i64 + (select + (i64.atomic.rmw.and offset=22 (i32.and - (loop $label$4 (result i32) - (block - (if - (i32.eqz - (get_global $hangLimit) - ) - (return - (i32.const 65535) - ) - ) - (set_global $hangLimit - (i32.sub - (get_global $hangLimit) - (i32.const 1) - ) - ) - ) - (i32.const -128) + (call_indirect $FUNCSIG$i + (i32.const 2) ) (i32.const 31) ) - (i64.const 127) + (i64.const 36028797018963968) ) - (if - (i32.eqz - (loop $label$5 (result i32) - (block - (if - (i32.eqz - (get_global $hangLimit) - ) - (return - (i32.const -86) - ) - ) - (set_global $hangLimit - (i32.sub - (get_global $hangLimit) - (i32.const 1) - ) - ) - ) - (block (result i32) - (block $label$6 - (drop - (block $label$7 (result f64) + (call $func_0) + (i32.atomic.rmw8_u.cmpxchg offset=4 + (i32.and + (if (result i32) + (i32.eqz + (block $label$3 (result i32) + (block $label$4 + (block $label$5 (if - (br_if $label$0 - (i32.const 1091126348) - (i32.const 33554432) - ) - (drop - (call $func_0) + (i32.eqz + (i32.const 1515671579) ) - (block $label$8 - (br_if $label$5 - (i32.eqz - (i32.trunc_u/f64 - (f64.const 1652571306646628140174554e16) - ) - ) - ) - (block $label$9 - (f64.atomic.store offset=4 - (i32.and - (loop $label$10 (result i32) - (block - (if - (i32.eqz - (get_global $hangLimit) - ) - (return - (i32.const 807806537) - ) - ) - (set_global $hangLimit - (i32.sub - (get_global $hangLimit) - (i32.const 1) - ) - ) - ) - (block (result i32) - (f64.store offset=4 - (i32.and - (i64.le_u - (i64.const -1) - (i64.atomic.rmw8_u.cmpxchg offset=3 - (i32.and - (select - (i32.const -128) - (i32.const -2) - (i32.const 33554432) - ) - (i32.const 31) - ) - (block $label$11 (result i64) - (nop) - (i64.const -1) - ) - (i64.const -33554432) - ) - ) - (i32.const 31) - ) - (get_local $1) - ) - (br_if $label$10 - (i32.const -1) - ) - (i32.const -1) - ) + (block $label$6 + (loop $label$7 + (block + (if + (i32.eqz + (get_global $hangLimit) + ) + (return + (i32.const -32768) ) - (i32.const 31) ) - (get_local $1) - ) - (if - (i32.eqz - (i32.atomic.rmw16_u.cmpxchg offset=1 - (i32.and - (i32.const -16384) - (i32.const 31) - ) - (block $label$12 (result i32) - (nop) - (i32.const -82) - ) - (loop $label$13 (result i32) - (block - (if - (i32.eqz - (get_global $hangLimit) - ) - (return - (i32.const 945497692) - ) - ) - (set_global $hangLimit - (i32.sub - (get_global $hangLimit) - (i32.const 1) - ) - ) - ) - (block (result i32) - (drop - (i64.const 1949008919083353346) - ) - (br_if $label$13 - (i32.const 1091126348) - ) - (i32.atomic.load offset=4 - (i32.const 2) - ) - ) - ) + (set_global $hangLimit + (i32.sub + (get_global $hangLimit) + (i32.const 1) ) ) - (loop $label$14 + ) + (drop + (loop $label$8 (result f32) (block (if (i32.eqz (get_global $hangLimit) ) (return - (i32.const 421008146) + (i32.const -107) ) ) (set_global $hangLimit @@ -288,78 +166,89 @@ ) ) ) - (block - (nop) - (br_if $label$14 - (i32.const 2097152) + (block (result f32) + (set_local $2 + (get_local $1) ) - (set_local $0 - (if (result f32) - (i32.eqz - (if (result i32) - (i32.const 319888671) - (loop $label$15 (result i32) - (block - (if - (i32.eqz - (get_global $hangLimit) - ) - (return - (i32.const 65535) - ) - ) - (set_global $hangLimit - (i32.sub - (get_global $hangLimit) - (i32.const 1) - ) - ) - ) - (i32.const 112) - ) - (i32.const 1043932195) - ) - ) - (f32.const 521149984) - (get_local $0) + (br_if $label$8 + (i32.eqz + (i32.const 1263290954) ) ) + (get_local $0) ) ) - (nop) ) ) + (set_local $2 + (get_local $2) + ) ) - ) - (br $label$6) - ) - ) - (loop $label$16 - (block - (if - (i32.eqz - (get_global $hangLimit) - ) - (return - (i32.const 255) + (loop $label$9 + (block + (if + (i32.eqz + (get_global $hangLimit) + ) + (return + (i32.const -1) + ) + ) + (set_global $hangLimit + (i32.sub + (get_global $hangLimit) + (i32.const 1) + ) + ) + ) + (block + (set_local $1 + (f64.const 82) + ) + (br_if $label$9 + (i32.const 1073741824) + ) + (f64.store offset=22 + (i32.and + (i32.const 16) + (i32.const 31) + ) + (get_local $1) + ) + ) ) ) - (set_global $hangLimit - (i32.sub - (get_global $hangLimit) - (i32.const 1) + (set_local $0 + (if (result f32) + (i32.const -1) + (get_local $0) + (f32.const 4.5111519284546375e-05) ) ) ) - (block $label$17 - (loop $label$18 + ) + (call_indirect $FUNCSIG$i + (i32.const 3) + ) + ) + ) + (if (result i32) + (i32.eqz + (i32.const 18199) + ) + (block $label$10 (result i32) + (nop) + (call_indirect $FUNCSIG$i + (block $label$11 (result i32) + (nop) + (loop $label$12 (result i32) (block (if (i32.eqz (get_global $hangLimit) ) (return - (i32.const -32768) + (i32.const 1462849583) ) ) (set_global $hangLimit @@ -369,15 +258,28 @@ ) ) ) - (block $label$19 - (loop $label$20 + (block $label$13 (result i32) + (f32.store offset=3 align=2 + (i32.and + (i32.const 421134925) + (i32.const 31) + ) + (if (result f32) + (i32.eqz + (i32.const 255) + ) + (f32.const 304027744) + (get_local $0) + ) + ) + (loop $label$14 (result i32) (block (if (i32.eqz (get_global $hangLimit) ) (return - (i32.const 1348217658) + (i32.const -67108864) ) ) (set_global $hangLimit @@ -387,391 +289,245 @@ ) ) ) - (block $label$21 - (block $label$22 - (block $label$23 - (nop) - (nop) - ) - (if - (i32.const 255) - (set_local $1 - (f64.const 208) - ) - (nop) - ) - ) + (i32.const 72) + ) + ) + ) + ) + ) + ) + (block $label$15 (result i32) + (block $label$16 + (br_if $label$16 + (block $label$17 (result i32) + (if + (i32.eqz + (i32.const 2097152) + ) + (i32.store offset=1 align=1 + (i32.and + (i32.const 536870912) + (i32.const 31) ) + (i32.const 1073741824) ) - (if - (i32.eqz - (call_indirect $FUNCSIG$i - (i32.const 2) - ) + (nop) + ) + (if (result i32) + (i32.eqz + (i32.const -27) + ) + (i32.const 1) + (i32.const -9) + ) + ) + ) + (f32.store offset=2 align=2 + (i32.and + (if (result i32) + (i32.eqz + (br_if $label$15 + (i32.const 5) + (i32.const -2048) ) - (block $label$24 - (drop - (f64.const 1797693134862315708145274e284) - ) - (if - (i32.eqz - (if (result i32) - (i32.eqz - (i32.const -32768) - ) - (i32.const 1263160137) - (i32.const -2147483648) - ) - ) - (nop) - (br_if $label$3 + ) + (block $label$18 (result i32) + (br $label$16) + ) + (block $label$19 (result i32) + (block $label$20 + (nop) + (set_local $0 + (if (result f32) (i32.eqz - (i32.const -512) - ) - ) - ) - ) - (block $label$25 - (loop $label$26 - (block - (if - (i32.eqz - (get_global $hangLimit) - ) - (return - (i32.const 1364404325) - ) + (i32.const 1) ) - (set_global $hangLimit - (i32.sub - (get_global $hangLimit) - (i32.const 1) + (get_local $0) + (call $deNan32 + (f32.max + (f32.const 889.3024291992188) + (f32.const 4.320995515717079e-37) ) ) ) - (block - (nop) - (br_if $label$26 - (i32.const -134217728) - ) - (set_local $2 - (get_local $1) - ) - ) - ) - (if - (i32.const 29) - (nop) - (nop) ) ) + (br $label$16) ) ) + (i32.const 31) ) - (br_if $label$1 - (i32.eqz - (block $label$27 (result i32) - (return - (i32.const 2376257) + (tee_local $0 + (call $deNan32 + (select + (f32.const 6.480769254579855e-10) + (f32.const 18446744073709551615) + (select + (i32.const -1) + (i32.const 16) + (call_indirect $FUNCSIG$i + (i32.const 0) + ) ) ) ) ) ) ) + (call_indirect $FUNCSIG$i + (i32.const 0) + ) ) - (br_if $label$5 - (i32.eqz - (call $func_1) + ) + (block $label$21 (result i32) + (set_local $2 + (tee_local $2 + (get_local $1) ) ) - (br_if $label$0 - (if (result i32) + (return + (i32.const -1) + ) + ) + ) + (i32.const 31) + ) + (br_if $label$0 + (f32.ge + (call $deNan32 + (f32.demote/f64 + (call $deNan64 (select - (i32.trunc_u/f32 - (call $deNan32 - (f32.add - (get_local $0) - (f32.const 3.284356114571644e-24) - ) - ) + (get_local $1) + (tee_local $1 + (get_local $2) ) - (select - (i32.const -87) - (f32.ne - (tee_local $0 - (f32.const -16) - ) - (f32.const 3402823466385288598117041e14) + (br_if $label$0 + (i32.const 64) + (i32.eqz + (i32.const 7198) ) - (i32.const 268435456) ) - (call $func_1) ) - (block $label$33 (result i32) - (drop - (select - (i64.const 128) - (i64.const -72) - (i32.const 251725317) - ) + ) + ) + ) + (call $deNan32 + (f32.add + (get_local $0) + (if (result f32) + (i32.const 1515803219) + (f32.const -22) + (block $label$30 (result f32) + (block $label$31 + (nop) + (nop) + ) + (return + (i32.const 1296450369) ) - (i32.const 520554502) ) - (block $label$34 (result i32) - (loop $label$35 (result i32) - (block - (if - (i32.eqz - (get_global $hangLimit) - ) - (return - (i32.const 1) - ) - ) - (set_global $hangLimit - (i32.sub - (get_global $hangLimit) - (i32.const 1) - ) + ) + ) + ) + ) + (i32.eqz + (select + (i32.atomic.load16_s offset=4 + (i32.and + (if (result i32) + (i32.div_u + (call $func_2) + (i32.load16_u offset=4 align=1 + (i32.and + (i32.const 38733343) + (i32.const 31) ) ) - (block (result i32) - (block $label$36 - (block $label$37 - (loop $label$38 - (block - (if - (i32.eqz - (get_global $hangLimit) - ) - (return - (i32.const 255) - ) - ) - (set_global $hangLimit - (i32.sub - (get_global $hangLimit) - (i32.const 1) - ) - ) + ) + (block $label$23 (result i32) + (set_local $0 + (loop $label$24 (result f32) + (block + (if + (i32.eqz + (get_global $hangLimit) ) - (block $label$39 - (nop) - (nop) + (return + (i32.const 20296) ) ) - (loop $label$40 - (block - (if - (i32.eqz - (get_global $hangLimit) - ) - (return - (i32.const 1700610397) - ) - ) - (set_global $hangLimit - (i32.sub - (get_global $hangLimit) - (i32.const 1) - ) - ) - ) - (block - (br_if $label$36 - (i32.eqz - (i32.const 65535) - ) - ) - (br_if $label$40 - (i32.eqz - (i32.load8_s offset=4 - (i32.and - (call_indirect $FUNCSIG$i - (i32.const 3) - ) - (i32.const 31) - ) - ) - ) - ) - (set_local $0 - (call $deNan32 - (select - (call $deNan32 - (select - (block $label$41 (result f32) - (if - (i32.const 50529027) - (block $label$42 - (set_local $1 - (tee_local $1 - (f64.atomic.load offset=3 - (i32.and - (i32.const 84346374) - (i32.const 31) - ) - ) - ) - ) - (nop) - ) - (nop) - ) - (call $deNan32 - (f32.add - (call $deNan32 - (f32.mul - (br_if $label$41 - (f32.const 94) - (i32.const -2048) - ) - (loop $label$43 (result f32) - (block - (if - (i32.eqz - (get_global $hangLimit) - ) - (return - (i32.const -1) - ) - ) - (set_global $hangLimit - (i32.sub - (get_global $hangLimit) - (i32.const 1) - ) - ) - ) - (loop $label$44 (result f32) - (block - (if - (i32.eqz - (get_global $hangLimit) - ) - (return - (i32.const 17273) - ) - ) - (set_global $hangLimit - (i32.sub - (get_global $hangLimit) - (i32.const 1) - ) - ) - ) - (f32.const 1.1001502146955268e-22) - ) - ) - ) - ) - (get_local $0) - ) - ) - ) - (get_local $0) - (i32.const -32) - ) - ) - (get_local $0) - (i32.const 32766) - ) - ) - ) + (set_global $hangLimit + (i32.sub + (get_global $hangLimit) + (i32.const 1) ) ) ) - ) - (br_if $label$35 - (i32.load offset=4 align=1 - (i32.and - (i32.const 471341842) - (i32.const 31) - ) - ) - ) - (i32.const -2147483648) - ) - ) - ) - ) - (i64.ne - (loop $label$28 (result i64) - (block - (if - (i32.eqz - (get_global $hangLimit) - ) - (return - (i32.const 167774215) + (get_local $0) ) ) - (set_global $hangLimit - (i32.sub - (get_global $hangLimit) - (i32.const 1) - ) + (call_indirect $FUNCSIG$i + (i32.const 0) ) ) - (block $label$29 (result i64) - (drop - (tee_local $2 - (f64.atomic.load offset=3 - (i32.and - (i32.const 1578633994) - (i32.const 31) - ) + (block $label$25 (result i32) + (block $label$26 + (f64.store offset=4 + (i32.and + (i32.const 22548) + (i32.const 31) ) + (get_local $1) ) ) - (i64.const 5203425946582667613) - ) - ) - (i64.const 536870912) - ) - ) - ) - ) - ) - (block $label$45 - (drop - (i64.atomic.rmw8_u.cmpxchg offset=4 - (i32.and - (i32.trunc_s/f64 - (call $deNan64 - (select - (f64.const 4611686018427387904) - (if (result f64) + (if (result i32) (i32.eqz - (i32.const -2147483647) + (i32.const 32767) ) - (get_local $1) - (block $label$46 (result f64) - (f64.atomic.store offset=22 - (i32.and - (i32.const 13648) - (i32.const 31) + (block $label$27 (result i32) + (nop) + (if (result i32) + (i32.const -32768) + (i32.const -51) + (i32.const -1073741824) + ) + ) + (block $label$28 (result i32) + (block $label$29 + (i64.atomic.store16 offset=4 + (i32.and + (call $func_1) + (i32.const 31) + ) + (i64.const 126) + ) + (nop) + ) + (br_if $label$28 + (i32.const 255) + (i32.eqz + (i32.const 88) ) - (f64.const 2.3366969264770927e-173) ) - (br $label$3) ) ) - (call $func_1) ) ) + (i32.const 31) ) - (i32.const 31) ) - (loop $label$47 (result i64) + (call_indirect $FUNCSIG$i + (i32.const 3) + ) + (loop $label$22 (result i32) (block (if (i32.eqz (get_global $hangLimit) ) (return - (i32.const 4194304) + (i32.const -94) ) ) (set_global $hangLimit @@ -781,190 +537,168 @@ ) ) ) - (block $label$48 (result i64) - (if - (call_indirect $FUNCSIG$i - (i32.const 0) - ) - (block $label$49 - (br_if $label$2 - (i32.eqz - (i32.const 32767) - ) - ) - (nop) - ) - (block $label$50 - (set_local $0 - (f32.const -nan:0x7fffb0) - ) - (drop - (i64.const 288803243302454280) - ) - ) - ) - (br $label$45) + (i32.eqz + (call $func_1) ) ) - (i64.const 144115188075855872) ) ) - (block $label$51 - (br_if $label$3 + ) + (br_if $label$0 + (i32.load8_u offset=4 + (br_if $label$0 + (i64.le_u + (i64.const 16250) + (i64.const -2147483648) + ) (i32.eqz - (i32.trunc_u/f64 - (f64.atomic.load offset=3 - (i32.and - (if (result i32) + (br_if $label$0 + (loop $label$43 (result i32) + (block + (if (i32.eqz - (call_indirect $FUNCSIG$i - (i32.const 2) - ) + (get_global $hangLimit) ) - (block $label$52 (result i32) - (if - (i32.eqz - (i64.lt_s - (i64.const -23) - (i64.const 2147483647) - ) - ) - (drop - (f64.const -1) - ) - (nop) - ) - (br $label$1) + (return + (i32.const 32) ) - (block $label$53 (result i32) - (set_local $1 - (f64.const 9223372036854775808) - ) - (if (result i32) - (i32.eqz - (if (result i32) - (i32.const 20530187) - (block $label$54 (result i32) - (nop) - (i32.const 0) - ) - (i32.const 533) - ) - ) - (i32.const -43) - (br_if $label$53 - (if (result i32) - (block $label$55 (result i32) - (set_local $0 - (f32.const -1048576) - ) - (br $label$51) - ) - (i32.const 163) - (i32.const 4096) - ) - (i32.eqz - (i32.const -536870912) - ) + ) + (set_global $hangLimit + (i32.sub + (get_global $hangLimit) + (i32.const 1) + ) + ) + ) + (block (result i32) + (f32.store offset=22 align=1 + (i32.and + (i32.const 1549362240) + (i32.const 31) + ) + (get_local $0) + ) + (br_if $label$43 + (i32.eqz + (block $label$44 (result i32) + (nop) + (block $label$45 (result i32) + (nop) + (i32.const 52123137) ) ) ) ) - (i32.const 31) + (call $func_1) + ) + ) + (i32.trunc_u/f64 + (call $deNan64 + (select + (get_local $2) + (get_local $1) + (i32.const 8) + ) ) ) ) ) ) ) - ) - (block $label$56 - (f64.atomic.store offset=4 - (i32.and - (i32.const 1566528337) - (i32.const 31) - ) - (f64.atomic.load offset=4 - (i32.and - (i64.ge_u - (i64.const 134616423) - (i64.const 274877906944) - ) - (i32.const 31) - ) - ) - ) - (f32.store offset=22 - (i32.and - (i32.const 2048) - (i32.const 31) - ) - (f32.const 1.6651135147759403e-30) - ) - (nop) - ) - ) - (br_if $label$3 - (i32.eqz - (block $label$57 (result i32) - (drop - (f64.atomic.load offset=3 - (i32.and - (i32.atomic.rmw16_u.cmpxchg offset=4 - (i32.and - (loop $label$58 (result i32) - (block - (if - (i32.eqz - (get_global $hangLimit) - ) - (return - (i32.const 208) - ) - ) - (set_global $hangLimit - (i32.sub - (get_global $hangLimit) - (i32.const 1) - ) - ) + (i32.eqz + (f64.eq + (f64.const 274877906944) + (if (result f64) + (f64.lt + (if (result f64) + (call_indirect $FUNCSIG$i + (i32.const 1) + ) + (block $label$32 (result f64) + (drop + (if (result i32) + (i32.const 858208803) + (i32.const 30324) + (i32.const 65451) ) - (i32.gt_u - (i32.const 67108864) - (i32.atomic.rmw8_u.cmpxchg offset=3 - (i32.and - (i32.const 4) - (i32.const 31) - ) - (i32.const 2071396369) - (i32.const -47) + ) + (if (result f64) + (i32.eqz + (i32.const -268435456) + ) + (call $deNan64 + (f64.convert_u/i32 + (i32.const 65452) ) ) + (get_local $2) ) - (i32.const 31) ) - (i32.trunc_u/f32 - (call $deNan32 - (f32.neg - (f32.load offset=4 align=2 - (i32.and - (i32.const 343242608) - (i32.const 31) + (block $label$33 (result f64) + (if + (block $label$34 (result i32) + (nop) + (i32.const 437805155) + ) + (nop) + (set_local $0 + (get_local $0) + ) + ) + (call $deNan64 + (f64.min + (call $deNan64 + (f64.promote/f32 + (get_local $0) ) ) + (f64.const 7240) ) ) ) - (select - (i32.trunc_s/f32 - (loop $label$59 (result f32) + ) + (loop $label$35 (result f64) + (block + (if + (i32.eqz + (get_global $hangLimit) + ) + (return + (i32.const -90) + ) + ) + (set_global $hangLimit + (i32.sub + (get_global $hangLimit) + (i32.const 1) + ) + ) + ) + (block $label$36 (result f64) + (drop + (get_local $2) + ) + (return + (i32.const 1970369147) + ) + ) + ) + ) + (block $label$37 (result f64) + (block $label$38 + (if + (if (result i32) + (i32.eqz + (i32.const 514) + ) + (loop $label$39 (result i32) (block (if (i32.eqz (get_global $hangLimit) ) (return - (i32.const 131072) + (i32.const 0) ) ) (set_global $hangLimit @@ -974,222 +708,414 @@ ) ) ) - (block $label$60 (result f32) - (call $deNan32 - (select - (get_local $0) - (get_local $0) - (i32.const -1) + (block (result i32) + (nop) + (br_if $label$39 + (i32.eqz + (i32.const -21) ) ) + (i32.const 10) + ) + ) + (select + (i32.const 32) + (i32.const -7) + (i32.const 13) + ) + ) + (block $label$40 + (nop) + (i32.store offset=4 align=1 + (i32.and + (i32.const -1073741824) + (i32.const 31) ) + (i32.const 812988468) ) ) + (block $label$41 + (nop) + (drop + (i64.const 128) + ) + ) + ) + (br_if $label$38 (call_indirect $FUNCSIG$i (i32.const 1) ) - (i32.const 0) ) ) - (i32.const 31) + (tee_local $1 + (f64.const -nan:0xfffffffffffeb) + ) + ) + (call $deNan64 + (f64.sqrt + (block $label$42 (result f64) + (drop + (i64.const 127) + ) + (return + (i32.const -91) + ) + ) + ) ) ) ) - (br $label$2) ) ) ) ) - (br_if $label$2 - (i32.const -1048576) - ) - (if - (block $label$61 (result i32) - (set_local $0 - (f32.const 1.1754943508222875e-38) - ) - (br $label$1) - ) - (block $label$62 - (br_if $label$2 - (br_if $label$0 - (i32.load offset=4 - (i32.and - (select - (call_indirect $FUNCSIG$i - (i32.const 0) + ) + (i32.const 31) + ) + ) + ) + ) + ) + (func $func_3 (type $FUNCSIG$vff) (param $0 f32) (param $1 f32) + (local $2 f32) + (block + (if + (i32.eqz + (get_global $hangLimit) + ) + (return) + ) + (set_global $hangLimit + (i32.sub + (get_global $hangLimit) + (i32.const 1) + ) + ) + ) + (nop) + ) + (func $func_4 (type $FUNCSIG$fj) (param $0 i64) (result f32) + (local $1 f32) + (local $2 i32) + (local $3 f32) + (local $4 f64) + (local $5 i64) + (block + (if + (i32.eqz + (get_global $hangLimit) + ) + (return + (get_local $3) + ) + ) + (set_global $hangLimit + (i32.sub + (get_global $hangLimit) + (i32.const 1) + ) + ) + ) + (block $label$0 (result f32) + (block $label$1 + (call_indirect $FUNCSIG$vff + (br_if $label$0 + (f32.const 1) + (i32.eqz + (block $label$2 (result i32) + (call $func_3 + (br_if $label$0 + (f32.load offset=4 align=1 + (i32.and + (wake + (i32.and + (get_local $2) + (i32.const 31) + ) + (tee_local $2 + (block $label$17 (result i32) + (i64.le_u + (i64.const -2) + (i64.const -32768) + ) ) - (i32.const -32769) - (call $func_1) ) - (i32.const 31) ) - ) - (i32.eqz - (i32.const 127) - ) - ) - ) - (drop - (call $deNan64 - (f64.convert_s/i64 - (call $func_0) + (i32.const 31) ) ) - ) - ) - (block $label$63 - (nop) - (i64.atomic.store32 offset=3 - (i32.and - (loop $label$64 (result i32) - (block - (if - (i32.eqz - (get_global $hangLimit) - ) - (return - (i32.const 127) + (if (result i32) + (i32.eqz + (i32.trunc_s/f32 + (call $deNan32 + (f32.convert_s/i64 + (loop $label$3 (result i64) + (block + (if + (i32.eqz + (get_global $hangLimit) + ) + (return + (f32.const 1.1754943508222875e-38) + ) + ) + (set_global $hangLimit + (i32.sub + (get_global $hangLimit) + (i32.const 1) + ) + ) + ) + (i64.const 128) + ) ) ) - (set_global $hangLimit - (i32.sub - (get_global $hangLimit) - (i32.const 1) + ) + ) + (block $label$4 (result i32) + (if + (i32.eqz + (select + (br_if $label$4 + (i32.const 1) + (call_indirect $FUNCSIG$i + (i32.const 0) + ) + ) + (block $label$6 (result i32) + (set_local $4 + (f64.const 1301466880673135803265612e44) + ) + (br $label$1) + ) + (block $label$5 (result i32) + (set_local $1 + (tee_local $1 + (tee_local $1 + (get_local $1) + ) + ) + ) + (br $label$1) + ) ) ) - ) - (block $label$65 (result i32) - (drop - (loop $label$66 (result i32) - (block - (if + (block $label$7 + (i32.atomic.store16 offset=3 + (i32.and + (if (result i32) (i32.eqz - (get_global $hangLimit) + (get_local $2) ) - (return - (i32.const -27) + (i32.const 1043086128) + (i32.const -96) + ) + (i32.const 31) + ) + (i32.trunc_s/f64 + (get_local $4) + ) + ) + (block $label$8 + (call_indirect $FUNCSIG$vff + (f32.load offset=4 align=2 + (i32.and + (i32.const 343242608) + (i32.const 31) ) ) - (set_global $hangLimit - (i32.sub - (get_global $hangLimit) - (i32.const 1) + (call $deNan32 + (select + (get_local $3) + (f32.const 192.2549285888672) + (i32.const -66) ) ) + (i32.const 8) ) - (block $label$67 (result i32) - (drop - (i64.div_u - (i64.const 8073603073429087267) - (loop $label$68 (result i64) - (block - (if - (i32.eqz - (get_global $hangLimit) - ) - (return - (i32.const -262144) - ) - ) - (set_global $hangLimit - (i32.sub - (get_global $hangLimit) - (i32.const 1) - ) - ) - ) - (i64.atomic.rmw8_u.cmpxchg offset=3 - (i32.and - (i32.const 49) - (i32.const 31) - ) - (i64.const -34359738368) - (i64.const 4409085041636091956) - ) + (call_indirect $FUNCSIG$vff + (get_local $3) + (get_local $1) + (i32.const 6) + ) + ) + ) + (loop $label$9 + (block + (if + (i32.eqz + (get_global $hangLimit) + ) + (return + (f32.const 18446744073709551615) + ) + ) + (set_global $hangLimit + (i32.sub + (get_global $hangLimit) + (i32.const 1) + ) + ) + ) + (block + (loop $label$10 + (block + (if + (i32.eqz + (get_global $hangLimit) + ) + (return + (get_local $1) + ) + ) + (set_global $hangLimit + (i32.sub + (get_global $hangLimit) + (i32.const 1) ) ) ) - (br $label$1) + (set_local $2 + (wake + (i32.and + (i32.const 1094337070) + (i32.const 31) + ) + (i32.const 1) + ) + ) + ) + (br_if $label$9 + (i32.eqz + (if (result i32) + (i32.const -67108864) + (i32.const -92) + (i32.const 95) + ) + ) + ) + (call $func_3 + (get_local $3) + (block $label$11 (result f32) + (return + (get_local $1) + ) + ) ) ) ) - (call_indirect $FUNCSIG$i - (i32.const 3) + ) + (f64.gt + (block $label$12 (result f64) + (call $func_3 + (loop $label$13 (result f32) + (block + (if + (i32.eqz + (get_global $hangLimit) + ) + (return + (f32.const 15) + ) + ) + (set_global $hangLimit + (i32.sub + (get_global $hangLimit) + (i32.const 1) + ) + ) + ) + (f32.const 2251799813685248) + ) + (f32.const -nan:0x7fffef) + ) + (return + (get_local $3) + ) ) + (f64.const 268435456) ) ) - (i32.const 31) - ) - (i64.load16_s offset=4 - (i32.and - (i32.clz - (i32.atomic.load8_s offset=4 - (br_if $label$0 - (i32.const 1073741824) - (i32.eqz - (i32.const 1879902727) - ) + (block $label$14 (result i32) + (if + (br_if $label$14 + (i32.const 1195918659) + (i32.eqz + (i32.const -16) + ) + ) + (block $label$15 + (nop) + (set_local $4 + (get_local $4) + ) + ) + (block $label$16 + (nop) + (br_if $label$1 + (get_local $2) ) ) ) - (i32.const 31) + (br_if $label$2 + (tee_local $2 + (tee_local $2 + (i32.const 726283585) + ) + ) + (get_local $2) + ) ) ) ) - ) - ) - ) - ) - ) - (if - (i32.eqz - (if (result i32) - (i64.ge_s - (i64.atomic.load offset=22 - (i32.and - (i32.const -16777216) - (i32.const 31) - ) - ) - (if (result i64) - (if (result i32) - (i32.eqz - (call $func_1) - ) - (block $label$69 (result i32) - (drop - (get_local $0) + (block $label$18 (result f32) + (set_local $5 + (i64.load16_u offset=22 + (i32.and + (i32.trunc_u/f64 + (get_local $4) + ) + (i32.const 31) + ) ) - (i32.const 29) ) - (block $label$70 (result i32) - (i32.const 1073741824) + (call $deNan32 + (f32.convert_u/i32 + (if (result i32) + (i32.atomic.rmw16_u.cmpxchg offset=22 + (i32.and + (get_local $2) + (i32.const 31) + ) + (wake + (i32.and + (i32.const -7) + (i32.const 31) + ) + (get_local $2) + ) + (i32.const -32768) + ) + (block $label$19 (result i32) + (get_local $2) + ) + (block $label$20 (result i32) + (get_local $2) + ) + ) + ) ) ) - (block $label$71 (result i64) - (i64.const 6669) - ) - (block $label$72 (result i64) - (i64.const -36028797018963968) - ) ) + (i32.const 127) ) - (i32.const -1) - (i32.const 2097152) ) ) - (block $label$73 - (set_local $2 - (get_local $1) - ) - ) - (block $label$74 - (nop) - ) + (get_local $3) + (i32.const 7) ) ) - (i32.const -4096) + (get_local $1) ) ) (func $hangLimitInitializer From e439a24c720b879ffeaaefeacc46b8c9ac1c7df0 Mon Sep 17 00:00:00 2001 From: "Alon Zakai (kripken)" Date: Sat, 14 Oct 2017 17:11:20 -0700 Subject: [PATCH 21/33] validation fix --- src/wasm/wasm-validator.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp index 6d75296a4e2..f0a8473b42d 100644 --- a/src/wasm/wasm-validator.cpp +++ b/src/wasm/wasm-validator.cpp @@ -513,8 +513,8 @@ void FunctionValidator::visitAtomicCmpxchg(AtomicCmpxchg* curr) { if (curr->expected->type != unreachable && curr->replacement->type != unreachable) { shouldBeEqual(curr->expected->type, curr->replacement->type, curr, "cmpxchg operand types must match"); } - shouldBeEqualOrFirstIsUnreachable(curr->expected->type, curr->type, curr, "Cmpxchg result type must match expected"); - shouldBeEqualOrFirstIsUnreachable(curr->replacement->type, curr->type, curr, "Cmpxchg result type must match replacement"); + shouldBeEqualOrFirstIsUnreachable(curr->type, curr->expected->type, curr, "Cmpxchg result type must match expected"); + shouldBeEqualOrFirstIsUnreachable(curr->type, curr->replacement->type, curr, "Cmpxchg result type must match replacement"); shouldBeIntOrUnreachable(curr->expected->type, curr, "Atomic operations are only valid on int types"); } From 2aceca13da1813a95a23b4075d71ea6c5cc1afb7 Mon Sep 17 00:00:00 2001 From: "Alon Zakai (kripken)" Date: Sun, 15 Oct 2017 10:18:38 -0700 Subject: [PATCH 22/33] fix --- src/wasm/wasm-validator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp index f0a8473b42d..96bc0cb1d22 100644 --- a/src/wasm/wasm-validator.cpp +++ b/src/wasm/wasm-validator.cpp @@ -502,7 +502,7 @@ void FunctionValidator::visitAtomicRMW(AtomicRMW* curr) { shouldBeFalse(!getModule()->memory.shared, curr, "Atomic operation with non-shared memory"); validateMemBytes(curr->bytes, curr->type, curr); shouldBeEqualOrFirstIsUnreachable(curr->ptr->type, i32, curr, "AtomicRMW pointer type must be i32"); - shouldBeEqualOrFirstIsUnreachable(curr->value->type, curr->type, curr, "AtomicRMW result type must match operand"); + shouldBeEqualOrFirstIsUnreachable(curr->type, curr->value->type, curr, "AtomicRMW result type must match operand"); shouldBeIntOrUnreachable(curr->type, curr, "Atomic operations are only valid on int types"); } From 7c76be729bcfb01185f0326a5d8491c90bf50123 Mon Sep 17 00:00:00 2001 From: "Alon Zakai (kripken)" Date: Sun, 15 Oct 2017 13:57:28 -0700 Subject: [PATCH 23/33] fix --- src/wasm/wasm-binary.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index f7e10d39bed..8dee93a7385 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -881,6 +881,12 @@ void WasmBinaryWriter::visitAtomicRMW(AtomicRMW *curr) { recurse(curr->ptr); recurse(curr->value); + if (curr->type == unreachable) { + // don't even emit it; we don't know the right type + o << int8_t(BinaryConsts::Unreachable); + return; + } + o << int8_t(BinaryConsts::AtomicPrefix); #define CASE_FOR_OP(Op) \ @@ -927,6 +933,12 @@ void WasmBinaryWriter::visitAtomicCmpxchg(AtomicCmpxchg *curr) { recurse(curr->expected); recurse(curr->replacement); + if (curr->type == unreachable) { + // don't even emit it; we don't know the right type + o << int8_t(BinaryConsts::Unreachable); + return; + } + o << int8_t(BinaryConsts::AtomicPrefix); switch (curr->type) { case i32: From dab7d3d9d898a87673a5c79dfe9c5f5f2d7e91af Mon Sep 17 00:00:00 2001 From: "Alon Zakai (kripken)" Date: Sun, 15 Oct 2017 14:20:40 -0700 Subject: [PATCH 24/33] fix --- src/wasm/wasm-binary.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index 8dee93a7385..2f2fd98d84e 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -791,6 +791,11 @@ void WasmBinaryWriter::visitLoad(Load *curr) { default: WASM_UNREACHABLE(); } } else { + if (curr->type == unreachable) { + // don't even emit it; we don't know the right type + o << int8_t(BinaryConsts::Unreachable); + return; + } o << int8_t(BinaryConsts::AtomicPrefix); switch (curr->type) { case i32: { @@ -849,6 +854,11 @@ void WasmBinaryWriter::visitStore(Store *curr) { default: abort(); } } else { + if (curr->type == unreachable) { + // don't even emit it; we don't know the right type + o << int8_t(BinaryConsts::Unreachable); + return; + } o << int8_t(BinaryConsts::AtomicPrefix); switch (curr->valueType) { case i32: { From 1623917adb972f5678de2490507fe55713bd25a5 Mon Sep 17 00:00:00 2001 From: "Alon Zakai (kripken)" Date: Sun, 15 Oct 2017 15:36:42 -0700 Subject: [PATCH 25/33] fix --- src/wasm-interpreter.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h index a266a4698d8..067bed03cf3 100644 --- a/src/wasm-interpreter.h +++ b/src/wasm-interpreter.h @@ -866,12 +866,12 @@ class ModuleInstanceBase { NOTE_ENTER("AtomicRMW"); Flow ptr = this->visit(curr->ptr); if (ptr.breaking()) return ptr; + auto value = this->visit(curr->value); + if (value.breaking()) return value; NOTE_EVAL1(ptr); auto addr = instance.getFinalAddress(curr, ptr.value); NOTE_EVAL1(addr); - auto value = this->visit(curr->value); NOTE_EVAL1(value); - if (value.breaking()) return value; auto loaded = instance.doAtomicLoad(addr, curr->bytes, curr->type); NOTE_EVAL1(loaded); auto computed = value.value; @@ -892,14 +892,14 @@ class ModuleInstanceBase { Flow ptr = this->visit(curr->ptr); if (ptr.breaking()) return ptr; NOTE_EVAL1(ptr); - auto addr = instance.getFinalAddress(curr, ptr.value); - NOTE_EVAL1(addr); auto expected = this->visit(curr->expected); - NOTE_EVAL1(expected); if (expected.breaking()) return expected; auto replacement = this->visit(curr->replacement); - NOTE_EVAL1(replacement); if (replacement.breaking()) return replacement; + auto addr = instance.getFinalAddress(curr, ptr.value); + NOTE_EVAL1(addr); + NOTE_EVAL1(expected); + NOTE_EVAL1(replacement); auto loaded = instance.doAtomicLoad(addr, curr->bytes, curr->type); NOTE_EVAL1(loaded); if (loaded == expected.value) { From 3b5648e9eccf50fd5fe84a5a7c51adfb3496dfa9 Mon Sep 17 00:00:00 2001 From: "Alon Zakai (kripken)" Date: Sun, 15 Oct 2017 15:51:48 -0700 Subject: [PATCH 26/33] fix --- src/wasm-interpreter.h | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h index 067bed03cf3..8ffd9c497c1 100644 --- a/src/wasm-interpreter.h +++ b/src/wasm-interpreter.h @@ -912,15 +912,15 @@ class ModuleInstanceBase { Flow ptr = this->visit(curr->ptr); if (ptr.breaking()) return ptr; NOTE_EVAL1(ptr); - auto addr = ptr.value.getInteger(); - NOTE_EVAL1(addr); auto expected = this->visit(curr->expected); NOTE_EVAL1(expected); if (expected.breaking()) return expected; auto timeout = this->visit(curr->timeout); NOTE_EVAL1(timeout); if (timeout.breaking()) return timeout; - auto loaded = instance.doAtomicLoad(addr, getWasmTypeSize(curr->expectedType), curr->expectedType); + auto bytes = getWasmTypeSize(curr->expectedType); + auto addr = instance.getFinalAddress(ptr.value, bytes); + auto loaded = instance.doAtomicLoad(addr, bytes, curr->expectedType); NOTE_EVAL1(loaded); if (loaded != expected.value) { return Literal(int32_t(1)); // not equal @@ -1034,6 +1034,13 @@ class ModuleInstanceBase { return addr; } + Address getFinalAddress(Literal ptr, Index bytes) { + Address memorySizeBytes = memorySize * Memory::kPageSize; + uint64_t addr = ptr.type == i32 ? ptr.geti32() : ptr.geti64(); + trapIfGt(addr, memorySizeBytes - bytes, "highest > memory"); + return addr; + } + void checkLoadAddress(Address addr, Index bytes) { Address memorySizeBytes = memorySize * Memory::kPageSize; trapIfGt(addr, memorySizeBytes - bytes, "highest > memory"); From 260c0883691aafe9ee905e5bc97980aa87670529 Mon Sep 17 00:00:00 2001 From: "Alon Zakai (kripken)" Date: Sun, 15 Oct 2017 16:12:25 -0700 Subject: [PATCH 27/33] fix wait expectedType --- src/ast/ExpressionManipulator.cpp | 2 +- src/wasm-builder.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ast/ExpressionManipulator.cpp b/src/ast/ExpressionManipulator.cpp index 6c0804a4989..3761bc166bc 100644 --- a/src/ast/ExpressionManipulator.cpp +++ b/src/ast/ExpressionManipulator.cpp @@ -118,7 +118,7 @@ Expression* flexibleCopy(Expression* original, Module& wasm, CustomCopier custom curr->type); } Expression* visitAtomicWait(AtomicWait* curr) { - return builder.makeAtomicWait(copy(curr->ptr), copy(curr->expected), copy(curr->timeout), curr->type); + return builder.makeAtomicWait(copy(curr->ptr), copy(curr->expected), copy(curr->timeout), curr->expectedType); } Expression* visitAtomicWake(AtomicWake* curr) { return builder.makeAtomicWake(copy(curr->ptr), copy(curr->wakeCount)); diff --git a/src/wasm-builder.h b/src/wasm-builder.h index 62443372eb2..8a82dd6dbe9 100644 --- a/src/wasm-builder.h +++ b/src/wasm-builder.h @@ -206,12 +206,12 @@ class Builder { load->isAtomic = true; return load; } - AtomicWait* makeAtomicWait(Expression* ptr, Expression* expected, Expression* timeout, WasmType type) { + AtomicWait* makeAtomicWait(Expression* ptr, Expression* expected, Expression* timeout, WasmType expectedType) { auto* wait = allocator.alloc(); wait->ptr = ptr; wait->expected = expected; wait->timeout = timeout; - wait->expectedType = type; + wait->expectedType = expectedType; wait->finalize(); return wait; } From a22f66f019841437642878b72ee7d1fa05cc2687 Mon Sep 17 00:00:00 2001 From: "Alon Zakai (kripken)" Date: Sun, 15 Oct 2017 16:46:50 -0700 Subject: [PATCH 28/33] fix --- src/tools/translate-to-fuzz.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tools/translate-to-fuzz.h b/src/tools/translate-to-fuzz.h index 9adff36ca14..029b62e6382 100644 --- a/src/tools/translate-to-fuzz.h +++ b/src/tools/translate-to-fuzz.h @@ -1072,6 +1072,7 @@ class TranslateToFuzzReader { Expression* makeAtomic(WasmType type) { if (type != i32 && type != i64) return makeTrivial(type); + wasm.memory.shared = true; if (type == i32 && oneIn(2)) { if (oneIn(2)) { auto* ptr = makePointer(); From 40baf85a0b51518685ef57bee426d6e613b7b8d3 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Tue, 17 Oct 2017 13:47:03 -0700 Subject: [PATCH 29/33] atomics are unsigned --- src/tools/translate-to-fuzz.h | 10 +++++++--- src/wasm/wasm-validator.cpp | 1 + 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/tools/translate-to-fuzz.h b/src/tools/translate-to-fuzz.h index 9ef9f189022..39b183d6e8d 100644 --- a/src/tools/translate-to-fuzz.h +++ b/src/tools/translate-to-fuzz.h @@ -101,6 +101,9 @@ class TranslateToFuzzReader { // cross-VM comparisons harder) static const bool DE_NAN = true; + // Whether to emit atomics + static const bool ATOMICS = true; + // after we finish the input, we start going through it again, but xoring // so it's not identical int xorFactor = 0; @@ -799,10 +802,11 @@ class TranslateToFuzzReader { Expression* makeLoad(WasmType type) { auto* ret = makeNonAtomicLoad(type); if (type != i32 && type != i64) return ret; - if (oneIn(2)) return ret; + if (!ATOMICS || oneIn(2)) return ret; // make it atomic wasm.memory.shared = true; ret->isAtomic = true; + ret->signed_ = false; ret->align = ret->bytes; return ret; } @@ -858,7 +862,7 @@ class TranslateToFuzzReader { Store* makeStore(WasmType type) { auto* ret = makeNonAtomicStore(type); if (ret->value->type != i32 && ret->value->type != i64) return ret; - if (oneIn(2)) return ret; + if (!ATOMICS || oneIn(2)) return ret; // make it atomic wasm.memory.shared = true; ret->isAtomic = true; @@ -1109,7 +1113,7 @@ class TranslateToFuzzReader { } Expression* makeAtomic(WasmType type) { - if (type != i32 && type != i64) return makeTrivial(type); + if (!ATOMICS || (type != i32 && type != i64)) return makeTrivial(type); wasm.memory.shared = true; if (type == i32 && oneIn(2)) { if (oneIn(2)) { diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp index 96bc0cb1d22..5120eea7a77 100644 --- a/src/wasm/wasm-validator.cpp +++ b/src/wasm/wasm-validator.cpp @@ -487,6 +487,7 @@ void FunctionValidator::visitLoad(Load *curr) { validateMemBytes(curr->bytes, curr->type, curr); validateAlignment(curr->align, curr->type, curr->bytes, curr->isAtomic, curr); shouldBeEqualOrFirstIsUnreachable(curr->ptr->type, i32, curr, "load pointer type must be i32"); + if (curr->isAtomic) shouldBeFalse(curr->signed_, curr, "atomic loads must be unsigned"); } void FunctionValidator::visitStore(Store *curr) { From 1ddb2c362d3edb953f13fb716922795996d7be90 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Tue, 17 Oct 2017 15:38:05 -0700 Subject: [PATCH 30/33] fix --- src/asm2wasm.h | 8 ++++- src/ast/ExpressionManipulator.cpp | 2 +- src/ast/bits.h | 39 ++++++++++++++++++++++++ src/passes/SafeHeap.cpp | 9 +++++- src/wasm-builder.h | 4 +-- test/passes/safe-heap.txt | 50 ++++++++++++++++++++++++------- test/passes/translate-to-fuzz.txt | 4 +-- 7 files changed, 99 insertions(+), 17 deletions(-) diff --git a/src/asm2wasm.h b/src/asm2wasm.h index 8f3c771bedf..9a4305f6a35 100644 --- a/src/asm2wasm.h +++ b/src/asm2wasm.h @@ -32,6 +32,7 @@ #include "pass.h" #include "parsing.h" #include "ast_utils.h" +#include "ast/bits.h" #include "ast/branch-utils.h" #include "ast/literal-utils.h" #include "ast/trapping.h" @@ -1884,7 +1885,12 @@ Function* Asm2WasmBuilder::processFunction(Ref ast) { View& view = views[heap]; wasm.memory.shared = true; if (name == Atomics_load) { - return builder.makeAtomicLoad(view.bytes, view.signed_, 0, processUnshifted(ast[2][1], view.bytes), asmToWasmType(view.type)); + Expression* ret = builder.makeAtomicLoad(view.bytes, 0, processUnshifted(ast[2][1], view.bytes), asmToWasmType(view.type)); + if (view.signed_) { + // atomic loads are unsigned; add a signing + ret = Bits::makeSignExt(ret, view.bytes, wasm); + } + return ret; } else if (name == Atomics_store) { // asm.js stores return the value, wasm does not auto type = asmToWasmType(view.type); diff --git a/src/ast/ExpressionManipulator.cpp b/src/ast/ExpressionManipulator.cpp index 3761bc166bc..6cb0219c533 100644 --- a/src/ast/ExpressionManipulator.cpp +++ b/src/ast/ExpressionManipulator.cpp @@ -97,7 +97,7 @@ Expression* flexibleCopy(Expression* original, Module& wasm, CustomCopier custom } Expression* visitLoad(Load *curr) { if (curr->isAtomic) { - return builder.makeAtomicLoad(curr->bytes, curr->signed_, curr->offset, + return builder.makeAtomicLoad(curr->bytes, curr->offset, copy(curr->ptr), curr->type); } return builder.makeLoad(curr->bytes, curr->signed_, curr->offset, curr->align, copy(curr->ptr), curr->type); diff --git a/src/ast/bits.h b/src/ast/bits.h index 0aee50ffe00..7a86e70f4f0 100644 --- a/src/ast/bits.h +++ b/src/ast/bits.h @@ -18,6 +18,8 @@ #define wasm_ast_bits_h #include "support/bits.h" +#include "wasm-builder.h" +#include "ast/literal-utils.h" namespace wasm { @@ -60,6 +62,43 @@ struct Bits { } WASM_UNREACHABLE(); } + + static Expression* makeSignExt(Expression* value, Index bytes, Module& wasm) { + if (value->type == i32) { + if (bytes == 1 || bytes == 2) { + auto shifts = bytes == 1 ? 24 : 16; + Builder builder(wasm); + return builder.makeBinary( + ShrSInt32, + builder.makeBinary( + ShlInt32, + value, + LiteralUtils::makeFromInt32(shifts, i32, wasm) + ), + LiteralUtils::makeFromInt32(shifts, i32, wasm) + ); + } + assert(bytes == 4); + return value; // nothing to do + } else { + assert(value->type == i64); + if (bytes == 1 || bytes == 2 || bytes == 4) { + auto shifts = bytes == 1 ? 56 : (bytes == 2 ? 48 : 32); + Builder builder(wasm); + return builder.makeBinary( + ShrSInt64, + builder.makeBinary( + ShlInt64, + value, + LiteralUtils::makeFromInt32(shifts, i64, wasm) + ), + LiteralUtils::makeFromInt32(shifts, i64, wasm) + ); + } + assert(bytes == 8); + return value; // nothing to do + } + } }; } // namespace wasm diff --git a/src/passes/SafeHeap.cpp b/src/passes/SafeHeap.cpp index 784bc761d73..9b4779ee02d 100644 --- a/src/passes/SafeHeap.cpp +++ b/src/passes/SafeHeap.cpp @@ -25,6 +25,7 @@ #include "asm_v_wasm.h" #include "asmjs/shared-constants.h" #include "wasm-builder.h" +#include "ast/bits.h" #include "ast/import-utils.h" namespace wasm { @@ -229,7 +230,13 @@ struct SafeHeap : public Pass { auto* load = module->allocator.alloc(); *load = style; // basically the same as the template we are given! load->ptr = builder.makeGetLocal(2, i32); - block->list.push_back(load); + Expression* last = load; + if (load->isAtomic && load->signed_) { + // atomic loads cannot be signed, manually sign it + last = Bits::makeSignExt(load, load->bytes, *module); + load->signed_ = false; + } + block->list.push_back(last); block->finalize(style.type); func->body = block; module->addFunction(func); diff --git a/src/wasm-builder.h b/src/wasm-builder.h index f0d31d2f1e6..e5ca7984573 100644 --- a/src/wasm-builder.h +++ b/src/wasm-builder.h @@ -202,8 +202,8 @@ class Builder { ret->type = type; return ret; } - Load* makeAtomicLoad(unsigned bytes, bool signed_, uint32_t offset, Expression* ptr, WasmType type) { - Load* load = makeLoad(bytes, signed_, offset, bytes, ptr, type); + Load* makeAtomicLoad(unsigned bytes, uint32_t offset, Expression* ptr, WasmType type) { + Load* load = makeLoad(bytes, false, offset, bytes, ptr, type); load->isAtomic = true; return load; } diff --git a/test/passes/safe-heap.txt b/test/passes/safe-heap.txt index f34dd7455c6..144766f1f75 100644 --- a/test/passes/safe-heap.txt +++ b/test/passes/safe-heap.txt @@ -189,8 +189,14 @@ ) (call $segfault) ) - (i32.atomic.load8_s - (get_local $2) + (i32.shr_s + (i32.shl + (i32.atomic.load8_u + (get_local $2) + ) + (i32.const 24) + ) + (i32.const 24) ) ) (func $SAFE_HEAP_LOAD_i32_1_1 (param $0 i32) (param $1 i32) (result i32) @@ -346,8 +352,14 @@ ) (call $alignfault) ) - (i32.atomic.load16_s - (get_local $2) + (i32.shr_s + (i32.shl + (i32.atomic.load16_u + (get_local $2) + ) + (i32.const 16) + ) + (i32.const 16) ) ) (func $SAFE_HEAP_LOAD_i32_2_2 (param $0 i32) (param $1 i32) (result i32) @@ -799,8 +811,14 @@ ) (call $segfault) ) - (i64.atomic.load8_s - (get_local $2) + (i64.shr_s + (i64.shl + (i64.atomic.load8_u + (get_local $2) + ) + (i64.const 56) + ) + (i64.const 56) ) ) (func $SAFE_HEAP_LOAD_i64_1_1 (param $0 i32) (param $1 i32) (result i64) @@ -956,8 +974,14 @@ ) (call $alignfault) ) - (i64.atomic.load16_s - (get_local $2) + (i64.shr_s + (i64.shl + (i64.atomic.load16_u + (get_local $2) + ) + (i64.const 48) + ) + (i64.const 48) ) ) (func $SAFE_HEAP_LOAD_i64_2_2 (param $0 i32) (param $1 i32) (result i64) @@ -1201,8 +1225,14 @@ ) (call $alignfault) ) - (i64.atomic.load32_s - (get_local $2) + (i64.shr_s + (i64.shl + (i64.atomic.load32_u + (get_local $2) + ) + (i64.const 32) + ) + (i64.const 32) ) ) (func $SAFE_HEAP_LOAD_i64_4_4 (param $0 i32) (param $1 i32) (result i64) diff --git a/test/passes/translate-to-fuzz.txt b/test/passes/translate-to-fuzz.txt index 1374ada1f46..f088010f77b 100644 --- a/test/passes/translate-to-fuzz.txt +++ b/test/passes/translate-to-fuzz.txt @@ -502,7 +502,7 @@ ) ) ) - (i32.atomic.load16_s offset=22 + (i32.atomic.load16_u offset=22 (i32.and (if (result i32) (i32.eqz @@ -840,7 +840,7 @@ ) (block $label$0 (result f64) (drop - (i32.atomic.load8_s offset=4 + (i32.atomic.load8_u offset=4 (i32.atomic.load offset=4 (i32.and (loop $label$1 (result i32) From 8422ed7ada639d48e54a1cb3958d06a65648cf09 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Tue, 17 Oct 2017 15:46:07 -0700 Subject: [PATCH 31/33] cleanup --- src/wasm-interpreter.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h index 8ffd9c497c1..d786371e6c8 100644 --- a/src/wasm-interpreter.h +++ b/src/wasm-interpreter.h @@ -32,11 +32,10 @@ #include "wasm.h" #include "wasm-traversal.h" -//#define WASM_INTERPRETER_DEBUG 1 -//#ifdef WASM_INTERPRETER_DEBUG +#ifdef WASM_INTERPRETER_DEBUG #include "wasm-printing.h" -//#endif +#endif namespace wasm { From 691277398d48a1bbf17ef76f542ebec9b8d46a22 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Tue, 17 Oct 2017 15:48:33 -0700 Subject: [PATCH 32/33] restore --- test/passes/inlining-optimizing.txt | 43 ++++++++++++++ test/passes/inlining-optimizing.wast | 87 ++++++++++++++++++++++++++++ 2 files changed, 130 insertions(+) diff --git a/test/passes/inlining-optimizing.txt b/test/passes/inlining-optimizing.txt index ca3f7da79ff..8079d818a50 100644 --- a/test/passes/inlining-optimizing.txt +++ b/test/passes/inlining-optimizing.txt @@ -1,3 +1,46 @@ +(module + (type $0 (func)) + (type $1 (func (result i32))) + (type $2 (func (result f64))) + (type $3 (func (param f32 i64))) + (table 1 1 anyfunc) + (elem (i32.const 0) $tabled) + (memory $0 0) + (export "user" (func $user)) + (export "exported" (func $exported)) + (func $user (type $0) + (call $exported) + (call $tabled) + (call $multi) + (call $multi) + ) + (func $exported (type $0) + (nop) + ) + (func $recursive (type $0) + (call $recursive) + ) + (func $tabled (type $0) + (nop) + ) + (func $cycle1 (type $0) + (call $cycle2) + ) + (func $cycle2 (type $0) + (call $cycle1) + ) + (func $multi (type $0) + (nop) + ) +) +(module + (type $0 (func (result i32))) + (type $1 (func)) + (memory $0 0) + (func $main (type $0) (result i32) + (unreachable) + ) +) (module (type $0 (func (result i32))) (type $1 (func (result i64))) diff --git a/test/passes/inlining-optimizing.wast b/test/passes/inlining-optimizing.wast index 80823c83292..aac4706feaa 100644 --- a/test/passes/inlining-optimizing.wast +++ b/test/passes/inlining-optimizing.wast @@ -1,3 +1,90 @@ +(module + (table 1 1 anyfunc) + (elem (i32.const 0) $tabled) + (func $user (export "user") + (local $x i32) + (local $y f64) + (call $exported) + (call $tabled) + (call $multi) + (call $multi) + (call $ok) + (drop (call $int)) + (drop (call $double)) + (set_local $x (call $int2)) + (set_local $y (call $double2)) + (call $with-local) + (call $with-local2) + (drop (call $return)) + (call $multipass) + (call $param (f32.const 12.34) (i64.const 890005350012)) + ) + (func $exported (export "exported") + (nop) + ) + (func $recursive + (call $recursive) + ) + (func $tabled + (nop) + ) + (func $cycle1 + (call $cycle2) + ) + (func $cycle2 + (call $cycle1) + ) + (func $multi + (nop) + ) + (func $ok + (drop (i32.const 1)) + ) + (func $int (result i32) + (i32.const 2) + ) + (func $double (result f64) + (f64.const 3.14159) + ) + (func $int2 (result i32) + (i32.const 112) + ) + (func $double2 (result f64) + (f64.const 113.14159) + ) + (func $with-local + (local $x f32) + (set_local $x (f32.const 2.141828)) + ) + (func $with-local2 + (local $y i64) + (set_local $y (i64.const 4)) + ) + (func $return (result i32) + (return (i32.const 5)) + ) + (func $multipass + (call $multipass2) + ) + (func $multipass2 + (drop (i32.const 6)) + ) + (func $param (param $x f32) (param $y i64) + (local $z f32) + (drop (get_local $x)) + (drop (get_local $y)) + (drop (get_local $z)) + ) +) +(module + (func $main (result i32) + (call $func_51) + (i32.const 0) + ) + (func $func_51 + (unreachable) ;; void function but having unreachable body, when inlined, type must be fixed + ) +) (module (memory $0 (shared 1 1)) (func $0 (result i32) From 34a7be40c49f518e36093bb41eb8323a4ca349eb Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Tue, 17 Oct 2017 16:09:52 -0700 Subject: [PATCH 33/33] avoid unnecessary check in interpreter, the sign does not matter for a full-size load, it's just bits --- src/wasm-interpreter.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h index d786371e6c8..b3fa3f2651b 100644 --- a/src/wasm-interpreter.h +++ b/src/wasm-interpreter.h @@ -575,7 +575,7 @@ class ModuleInstanceBase { switch (load->bytes) { case 1: return load->signed_ ? Literal((int32_t)load8s(addr)) : Literal((int32_t)load8u(addr)); case 2: return load->signed_ ? Literal((int32_t)load16s(addr)) : Literal((int32_t)load16u(addr)); - case 4: return load->signed_ ? Literal((int32_t)load32s(addr)) : Literal((int32_t)load32u(addr)); + case 4: return Literal((int32_t)load32s(addr)); default: WASM_UNREACHABLE(); } break; @@ -585,7 +585,7 @@ class ModuleInstanceBase { case 1: return load->signed_ ? Literal((int64_t)load8s(addr)) : Literal((int64_t)load8u(addr)); case 2: return load->signed_ ? Literal((int64_t)load16s(addr)) : Literal((int64_t)load16u(addr)); case 4: return load->signed_ ? Literal((int64_t)load32s(addr)) : Literal((int64_t)load32u(addr)); - case 8: return load->signed_ ? Literal((int64_t)load64s(addr)) : Literal((int64_t)load64u(addr)); + case 8: return Literal((int64_t)load64s(addr)); default: WASM_UNREACHABLE(); } break;