diff options
-rw-r--r-- | src/ir/subtype-exprs.h | 2 | ||||
-rw-r--r-- | src/passes/CodeFolding.cpp | 7 | ||||
-rw-r--r-- | src/passes/Flatten.cpp | 16 | ||||
-rw-r--r-- | src/passes/Print.cpp | 11 | ||||
-rw-r--r-- | src/wasm/wasm-validator.cpp | 23 | ||||
-rw-r--r-- | src/wasm/wasm.cpp | 30 | ||||
-rw-r--r-- | test/lit/passes/code-folding.wast | 44 | ||||
-rw-r--r-- | test/lit/passes/flatten_all-features.wast | 12 | ||||
-rw-r--r-- | test/lit/passes/optimize-instructions-ignore-traps.wast | 2 | ||||
-rw-r--r-- | test/lit/passes/optimize-instructions-mvp.wast | 30 | ||||
-rw-r--r-- | test/lit/passes/unsubtyping.wast | 40 | ||||
-rw-r--r-- | test/lit/wat-kitchen-sink.wast | 65 | ||||
-rw-r--r-- | test/passes/remove-unused-brs_enable-multivalue.txt | 6 | ||||
-rw-r--r-- | test/passes/remove-unused-names_code-folding.txt | 18 | ||||
-rw-r--r-- | test/spec/if.wast | 22 | ||||
-rw-r--r-- | test/wasm2js/br_table_temp.2asm.js | 2 | ||||
-rw-r--r-- | test/wasm2js/unreachable-if.2asm.js | 19 | ||||
-rw-r--r-- | test/wasm2js/unreachable-if.2asm.js.opt | 19 | ||||
-rw-r--r-- | test/wasm2js/unreachable-if.wast | 22 |
19 files changed, 282 insertions, 108 deletions
diff --git a/src/ir/subtype-exprs.h b/src/ir/subtype-exprs.h index 1895c856a..e6ee1816d 100644 --- a/src/ir/subtype-exprs.h +++ b/src/ir/subtype-exprs.h @@ -122,7 +122,7 @@ struct SubtypingDiscoverer : public OverriddenVisitor<SubType> { } } void visitIf(If* curr) { - if (curr->ifFalse) { + if (curr->ifFalse && curr->type != Type::unreachable) { self()->noteSubtype(curr->ifTrue, curr); self()->noteSubtype(curr->ifFalse, curr); } diff --git a/src/passes/CodeFolding.cpp b/src/passes/CodeFolding.cpp index 42331b747..305eb1278 100644 --- a/src/passes/CodeFolding.cpp +++ b/src/passes/CodeFolding.cpp @@ -234,6 +234,13 @@ struct CodeFolding if (!curr->ifFalse) { return; } + if (curr->condition->type == Type::unreachable) { + // If the arms are foldable and concrete, we would be replacing an + // unreachable If with a concrete block, which may or may not be valid, + // depending on the context. Leave this for DCE rather than trying to + // handle that. + return; + } // If both are blocks, look for a tail we can merge. auto* left = curr->ifTrue->dynCast<Block>(); auto* right = curr->ifFalse->dynCast<Block>(); diff --git a/src/passes/Flatten.cpp b/src/passes/Flatten.cpp index 37fa15b11..1c2cfbcd5 100644 --- a/src/passes/Flatten.cpp +++ b/src/passes/Flatten.cpp @@ -147,20 +147,24 @@ struct Flatten // arm preludes go in the arms. we must also remove an if value auto* originalIfTrue = iff->ifTrue; auto* originalIfFalse = iff->ifFalse; - auto type = iff->type; + auto type = iff->ifFalse ? Type::getLeastUpperBound(iff->ifTrue->type, + iff->ifFalse->type) + : Type::none; Expression* prelude = nullptr; if (type.isConcrete()) { Index temp = builder.addVar(getFunction(), type); if (iff->ifTrue->type.isConcrete()) { iff->ifTrue = builder.makeLocalSet(temp, iff->ifTrue); } - if (iff->ifFalse && iff->ifFalse->type.isConcrete()) { + if (iff->ifFalse->type.isConcrete()) { iff->ifFalse = builder.makeLocalSet(temp, iff->ifFalse); } - // the whole if (+any preludes from the condition) is now a prelude - prelude = rep; - // and we leave just a get of the value - rep = builder.makeLocalGet(temp, type); + if (curr->type.isConcrete()) { + // the whole if (+any preludes from the condition) is now a prelude + prelude = rep; + // and we leave just a get of the value + rep = builder.makeLocalGet(temp, type); + } } iff->ifTrue = getPreludesWithExpression(originalIfTrue, iff->ifTrue); if (iff->ifFalse) { diff --git a/src/passes/Print.cpp b/src/passes/Print.cpp index bbf5f2a6b..4ca40f35a 100644 --- a/src/passes/Print.cpp +++ b/src/passes/Print.cpp @@ -460,9 +460,16 @@ struct PrintExpressionContents } void visitIf(If* curr) { printMedium(o, "if"); - if (curr->type.isConcrete()) { + // Ifs are unreachable if their condition is unreachable, but in that case + // the arms might have some concrete type we have to account for to produce + // valid wat. + auto type = curr->type; + if (curr->condition->type == Type::unreachable && curr->ifFalse) { + type = Type::getLeastUpperBound(curr->ifTrue->type, curr->ifFalse->type); + } + if (type.isConcrete()) { o << ' '; - printBlockType(Signature(Type::none, curr->type)); + printBlockType(Signature(Type::none, type)); } } void visitLoop(Loop* curr) { diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp index 64c7fda02..e295d3931 100644 --- a/src/wasm/wasm-validator.cpp +++ b/src/wasm/wasm-validator.cpp @@ -865,7 +865,16 @@ void FunctionValidator::visitIf(If* curr) { curr, "returning if-else's false must have right type"); } else { - if (curr->condition->type != Type::unreachable) { + if (curr->condition->type == Type::unreachable) { + shouldBeTrue( + curr->ifTrue->type == Type::unreachable || + curr->ifFalse->type == Type::unreachable || + (curr->ifTrue->type == Type::none && + curr->ifFalse->type == Type::none) || + Type::hasLeastUpperBound(curr->ifTrue->type, curr->ifFalse->type), + curr, + "arms of unreachable if-else must have compatible types"); + } else { shouldBeEqual(curr->ifTrue->type, Type(Type::unreachable), curr, @@ -876,18 +885,6 @@ void FunctionValidator::visitIf(If* curr) { "unreachable if-else must have unreachable false"); } } - if (curr->ifTrue->type.isConcrete()) { - shouldBeSubType(curr->ifTrue->type, - curr->type, - curr, - "if type must match concrete ifTrue"); - } - if (curr->ifFalse->type.isConcrete()) { - shouldBeSubType(curr->ifFalse->type, - curr->type, - curr, - "if type must match concrete ifFalse"); - } } } diff --git a/src/wasm/wasm.cpp b/src/wasm/wasm.cpp index f89ef80c2..38f35411f 100644 --- a/src/wasm/wasm.cpp +++ b/src/wasm/wasm.cpp @@ -215,28 +215,20 @@ void Block::finalize(std::optional<Type> type_, Breakability breakability) { } void If::finalize(std::optional<Type> type_) { - if (type_) { - type = *type_; - if (type == Type::none && (condition->type == Type::unreachable || - (ifFalse && ifTrue->type == Type::unreachable && - ifFalse->type == Type::unreachable))) { - type = Type::unreachable; - } + // The If is unreachable if the condition is unreachable or both arms are + // unreachable. + if (condition->type == Type::unreachable || + (ifFalse && ifTrue->type == Type::unreachable && + ifFalse->type == Type::unreachable)) { + type = Type::unreachable; return; } - type = ifFalse ? Type::getLeastUpperBound(ifTrue->type, ifFalse->type) - : Type::none; - // if the arms return a value, leave it even if the condition - // is unreachable, we still mark ourselves as having that type, e.g. - // (if (result i32) - // (unreachable) - // (i32.const 10) - // (i32.const 20) - // ) - // otherwise, if the condition is unreachable, so is the if - if (type == Type::none && condition->type == Type::unreachable) { - type = Type::unreachable; + if (type_) { + type = *type_; + } else { + type = ifFalse ? Type::getLeastUpperBound(ifTrue->type, ifFalse->type) + : Type::none; } } diff --git a/test/lit/passes/code-folding.wast b/test/lit/passes/code-folding.wast index 007aa5909..b256b236c 100644 --- a/test/lit/passes/code-folding.wast +++ b/test/lit/passes/code-folding.wast @@ -743,12 +743,20 @@ ) ;; CHECK: (func $unreachable-if (type $0) - ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (if ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (then + ;; CHECK-NEXT: (nop) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (else + ;; CHECK-NEXT: (nop) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $unreachable-if @@ -773,14 +781,17 @@ ;; CHECK-NEXT: (if ;; CHECK-NEXT: (unreachable) ;; CHECK-NEXT: (then + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (else ;; CHECK-NEXT: (nop) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $unreachable-if-suffix (if @@ -800,16 +811,13 @@ ) ;; CHECK: (func $unreachable-if-concrete-arms (type $0) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (then - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (else - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (if (result i32) + ;; CHECK-NEXT: (unreachable) + ;; CHECK-NEXT: (then + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (else + ;; CHECK-NEXT: (nop) ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) diff --git a/test/lit/passes/flatten_all-features.wast b/test/lit/passes/flatten_all-features.wast index 5db45e272..b601b8a12 100644 --- a/test/lit/passes/flatten_all-features.wast +++ b/test/lit/passes/flatten_all-features.wast @@ -620,7 +620,6 @@ ;; CHECK-NEXT: (local $1 i32) ;; CHECK-NEXT: (local $2 i32) ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) ;; CHECK-NEXT: (block $x ;; CHECK-NEXT: (block ;; CHECK-NEXT: (local.set $0 @@ -646,18 +645,13 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (unreachable) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $4 + ;; CHECK-NEXT: (local.set $3 ;; CHECK-NEXT: (local.get $1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $4) + ;; CHECK-NEXT: (local.get $3) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $a13 (result i32) diff --git a/test/lit/passes/optimize-instructions-ignore-traps.wast b/test/lit/passes/optimize-instructions-ignore-traps.wast index 96ea16449..8902cbc28 100644 --- a/test/lit/passes/optimize-instructions-ignore-traps.wast +++ b/test/lit/passes/optimize-instructions-ignore-traps.wast @@ -213,7 +213,7 @@ ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 + ;; CHECK-NEXT: (local.tee $0 ;; CHECK-NEXT: (if (result i32) ;; CHECK-NEXT: (i32.or ;; CHECK-NEXT: (i32.eqz diff --git a/test/lit/passes/optimize-instructions-mvp.wast b/test/lit/passes/optimize-instructions-mvp.wast index f18c94c5c..077ecf495 100644 --- a/test/lit/passes/optimize-instructions-mvp.wast +++ b/test/lit/passes/optimize-instructions-mvp.wast @@ -5754,15 +5754,13 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.add + ;; CHECK-NEXT: (local.get $1) + ;; CHECK-NEXT: (unreachable) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) + ;; CHECK-NEXT: (block ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (local.tee $0 ;; CHECK-NEXT: (local.get $1) @@ -5775,7 +5773,7 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (if (result i32) + ;; CHECK-NEXT: (if ;; CHECK-NEXT: (unreachable) ;; CHECK-NEXT: (then ;; CHECK-NEXT: (i32.add @@ -15718,23 +15716,21 @@ ) ) ) - ;; CHECK: (func $if-dont-change-to-unreachable (param $x i32) (param $y i32) (param $z i32) (result i32) - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (then - ;; CHECK-NEXT: (return + ;; CHECK: (func $if-unreachable-return-identical (param $x i32) (param $y i32) (param $z i32) (result i32) + ;; CHECK-NEXT: (return + ;; CHECK-NEXT: (if (result i32) + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: (then ;; CHECK-NEXT: (local.get $y) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (else - ;; CHECK-NEXT: (return + ;; CHECK-NEXT: (else ;; CHECK-NEXT: (local.get $z) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - (func $if-dont-change-to-unreachable (param $x i32) (param $y i32) (param $z i32) (result i32) - ;; if we move the returns outside, we'd become unreachable; avoid that. + (func $if-unreachable-return-identical (param $x i32) (param $y i32) (param $z i32) (result i32) + ;; We can move the returns outside because we are already unreachable. (if (result i32) (local.get $x) (then diff --git a/test/lit/passes/unsubtyping.wast b/test/lit/passes/unsubtyping.wast index 97a2dd59a..149647165 100644 --- a/test/lit/passes/unsubtyping.wast +++ b/test/lit/passes/unsubtyping.wast @@ -1815,3 +1815,43 @@ ) ) ) + +;; Regression test for a crash on ifs with unreachable conditions and tuple arms. +(module + ;; CHECK: (type $0 (func (result i32 i64))) + + ;; CHECK: (func $test (type $0) (result i32 i64) + ;; CHECK-NEXT: (if (type $0) (result i32 i64) + ;; CHECK-NEXT: (unreachable) + ;; CHECK-NEXT: (then + ;; CHECK-NEXT: (tuple.make 2 + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (i64.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (else + ;; CHECK-NEXT: (tuple.make 2 + ;; CHECK-NEXT: (i32.const 2) + ;; CHECK-NEXT: (i64.const 3) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $test (result i32 i64) + (if (result i32 i64) + (unreachable) + (then + (tuple.make 2 + (i32.const 0) + (i64.const 1) + ) + ) + (else + (tuple.make 2 + (i32.const 2) + (i64.const 3) + ) + ) + ) + ) +) diff --git a/test/lit/wat-kitchen-sink.wast b/test/lit/wat-kitchen-sink.wast index 33d2e1d62..9cf7f27c5 100644 --- a/test/lit/wat-kitchen-sink.wast +++ b/test/lit/wat-kitchen-sink.wast @@ -1280,6 +1280,67 @@ end ) + ;; CHECK: (func $if-else-unreachable (type $1) (result i32) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (if (result i32) + ;; CHECK-NEXT: (unreachable) + ;; CHECK-NEXT: (then + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (else + ;; CHECK-NEXT: (i32.const 2) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $if-else-unreachable (result i32) + i32.const 0 ;; This will be dropped + unreachable + if (result i32) + i32.const 1 + else + i32.const 2 + end + ) + + ;; CHECK: (func $if-else-nested-unreachable (type $1) (result i32) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (if (result i32) + ;; CHECK-NEXT: (if (result i32) + ;; CHECK-NEXT: (unreachable) + ;; CHECK-NEXT: (then + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (else + ;; CHECK-NEXT: (i32.const 2) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (then + ;; CHECK-NEXT: (i32.const 3) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (else + ;; CHECK-NEXT: (i32.const 4) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $if-else-nested-unreachable (result i32) + i32.const 0 ;; This will be dropped + unreachable + if (result i32) + i32.const 1 + else + i32.const 2 + end + if (result i32) + i32.const 3 + else + i32.const 4 + end + ) + ;; CHECK: (func $if-else-labeled-result (type $1) (result i32) ;; CHECK-NEXT: (block $l (result i32) ;; CHECK-NEXT: (if (result i32) @@ -1607,7 +1668,7 @@ ;; CHECK: (func $if-else-brs-i32 (type $1) (result i32) ;; CHECK-NEXT: (block $label (result i32) - ;; CHECK-NEXT: (if (result i32) + ;; CHECK-NEXT: (if ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: (then ;; CHECK-NEXT: (br $label @@ -3677,7 +3738,7 @@ (func $ref-func ref.func $ref-func drop - ref.func 162 + ref.func 164 drop ) diff --git a/test/passes/remove-unused-brs_enable-multivalue.txt b/test/passes/remove-unused-brs_enable-multivalue.txt index ee6efbf4d..54780f0d9 100644 --- a/test/passes/remove-unused-brs_enable-multivalue.txt +++ b/test/passes/remove-unused-brs_enable-multivalue.txt @@ -2070,8 +2070,8 @@ (i32.const 2) ) ) - (local.set $x - (if (result i32) + (local.tee $x + (if (local.get $p) (then (br $out) @@ -2094,7 +2094,7 @@ (block $label$4 (result i64) (block $label$5 (block $label$6 - (local.set $var$1 + (local.tee $var$1 (if (result f64) (unreachable) (then diff --git a/test/passes/remove-unused-names_code-folding.txt b/test/passes/remove-unused-names_code-folding.txt index 85810131b..62d7e3405 100644 --- a/test/passes/remove-unused-names_code-folding.txt +++ b/test/passes/remove-unused-names_code-folding.txt @@ -1511,13 +1511,19 @@ ) (nop) (drop - (block (result i32) - (drop - (unreachable) + (if (result i32) + (unreachable) + (then + (i32.add + (i32.const 1) + (i32.const 2) + ) ) - (i32.add - (i32.const 1) - (i32.const 2) + (else + (i32.add + (i32.const 1) + (i32.const 2) + ) ) ) ) diff --git a/test/spec/if.wast b/test/spec/if.wast index ae7f7b385..0fef1078f 100644 --- a/test/spec/if.wast +++ b/test/spec/if.wast @@ -643,16 +643,18 @@ )) "type mismatch" ) -(assert_invalid - (module (func $type-else-value-unreached-select (result i32) - (if (result i64) - (i32.const 1) - (then (select (unreachable) (unreachable) (unreachable))) - (else (select (unreachable) (unreachable) (unreachable))) - ) - )) - "type mismatch" -) + +;; We don't pass this test because we type the `if` as unreachable. +;; (assert_invalid +;; (module (func $type-else-value-unreached-select (result i32) +;; (if (result i64) +;; (i32.const 1) +;; (then (select (unreachable) (unreachable) (unreachable))) +;; (else (select (unreachable) (unreachable) (unreachable))) +;; ) +;; )) +;; "type mismatch" +;; ) (assert_invalid (module (func $type-then-break-last-void-vs-num (result i32) diff --git a/test/wasm2js/br_table_temp.2asm.js b/test/wasm2js/br_table_temp.2asm.js index 245792eaf..704ec0687 100644 --- a/test/wasm2js/br_table_temp.2asm.js +++ b/test/wasm2js/br_table_temp.2asm.js @@ -12671,7 +12671,7 @@ function asmFunc(imports) { } function $30() { - var $1_1 = 0, $2_1 = 0; + var $1_1 = 0; block : { $1_1 = 2; switch (0 | 0) { diff --git a/test/wasm2js/unreachable-if.2asm.js b/test/wasm2js/unreachable-if.2asm.js new file mode 100644 index 000000000..f5656223c --- /dev/null +++ b/test/wasm2js/unreachable-if.2asm.js @@ -0,0 +1,19 @@ + +function asmFunc(imports) { + var Math_imul = Math.imul; + var Math_fround = Math.fround; + var Math_abs = Math.abs; + var Math_clz32 = Math.clz32; + var Math_min = Math.min; + var Math_max = Math.max; + var Math_floor = Math.floor; + var Math_ceil = Math.ceil; + var Math_trunc = Math.trunc; + var Math_sqrt = Math.sqrt; + return { + + }; +} + +var retasmFunc = asmFunc({ +}); diff --git a/test/wasm2js/unreachable-if.2asm.js.opt b/test/wasm2js/unreachable-if.2asm.js.opt new file mode 100644 index 000000000..f5656223c --- /dev/null +++ b/test/wasm2js/unreachable-if.2asm.js.opt @@ -0,0 +1,19 @@ + +function asmFunc(imports) { + var Math_imul = Math.imul; + var Math_fround = Math.fround; + var Math_abs = Math.abs; + var Math_clz32 = Math.clz32; + var Math_min = Math.min; + var Math_max = Math.max; + var Math_floor = Math.floor; + var Math_ceil = Math.ceil; + var Math_trunc = Math.trunc; + var Math_sqrt = Math.sqrt; + return { + + }; +} + +var retasmFunc = asmFunc({ +}); diff --git a/test/wasm2js/unreachable-if.wast b/test/wasm2js/unreachable-if.wast new file mode 100644 index 000000000..5bc0257c0 --- /dev/null +++ b/test/wasm2js/unreachable-if.wast @@ -0,0 +1,22 @@ +;; Regression test for bad assertion in autodrop that did not expect the if to +;; be finalized to unreachable. +(module + (func $test (result i32) + (block $l (result i32) + (drop + (br_if $l + (if (result i32) + (unreachable) + (then + (i32.const 0) + ) + (else + (i32.const 0) + ) + ) + ) + (i32.const 0) + ) + ) + ) +) |