summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/passes/Inlining.cpp4
-rw-r--r--src/wasm/wasm-validator.cpp7
-rw-r--r--test/lit/passes/inlining-unreachable.wast44
3 files changed, 48 insertions, 7 deletions
diff --git a/src/passes/Inlining.cpp b/src/passes/Inlining.cpp
index 0c95dc4b4..25993c7ec 100644
--- a/src/passes/Inlining.cpp
+++ b/src/passes/Inlining.cpp
@@ -275,7 +275,9 @@ struct Updater : public PostWalker<Updater> {
}
curr->isReturn = false;
curr->type = results;
- if (curr->type.isConcrete()) {
+ // There might still be unreachable children causing this to be unreachable.
+ curr->finalize();
+ if (results.isConcrete()) {
replaceCurrent(builder->makeBreak(returnName, curr));
} else {
replaceCurrent(builder->blockify(curr, builder->makeBreak(returnName)));
diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp
index 7a4bb6a97..ba8712d35 100644
--- a/src/wasm/wasm-validator.cpp
+++ b/src/wasm/wasm-validator.cpp
@@ -3074,8 +3074,11 @@ static void validateBinaryenIR(Module& wasm, ValidationInfo& info) {
bool validControlFlowStructureChange =
Properties::isControlFlowStructure(curr) && oldType.isConcrete() &&
newType == Type::unreachable;
- if (!Type::isSubType(newType, oldType) &&
- !validControlFlowStructureChange) {
+ // It's ok in general for types to get refined as long as they don't
+ // become unreachable.
+ bool validRefinement =
+ Type::isSubType(newType, oldType) && newType != Type::unreachable;
+ if (!validRefinement && !validControlFlowStructureChange) {
std::ostringstream ss;
ss << "stale type found in " << scope << " on " << curr
<< "\n(marked as " << oldType << ", should be " << newType
diff --git a/test/lit/passes/inlining-unreachable.wast b/test/lit/passes/inlining-unreachable.wast
index 4cec297e4..054d73545 100644
--- a/test/lit/passes/inlining-unreachable.wast
+++ b/test/lit/passes/inlining-unreachable.wast
@@ -1,6 +1,6 @@
;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited.
-;; RUN: foreach %s %t wasm-opt --inlining -S -o - | filecheck %s
+;; RUN: foreach %s %t wasm-opt -all --inlining -S -o - | filecheck %s
;; Test that we inline functions with unreachable bodies. This is important to
;; propagate the trap to the caller (where it might lead to DCE).
@@ -13,7 +13,7 @@
;; CHECK: (type $none_=>_i32 (func (result i32)))
- ;; CHECK: (func $call-trap
+ ;; CHECK: (func $call-trap (type $none_=>_none)
;; CHECK-NEXT: (block $__inlined_func$trap
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: (br $__inlined_func$trap)
@@ -31,7 +31,7 @@
(unreachable)
)
- ;; CHECK: (func $call-trap-result (result i32)
+ ;; CHECK: (func $call-trap-result (type $none_=>_i32) (result i32)
;; CHECK-NEXT: (block $__inlined_func$trap-result (result i32)
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
@@ -49,7 +49,7 @@
(nop)
(unreachable)
)
- ;; CHECK: (func $call-contents-then-trap
+ ;; CHECK: (func $call-contents-then-trap (type $none_=>_none)
;; CHECK-NEXT: (block $__inlined_func$contents-then-trap
;; CHECK-NEXT: (block
;; CHECK-NEXT: (nop)
@@ -66,3 +66,39 @@
(call $contents-then-trap)
)
)
+
+(module
+ ;; CHECK: (type $i32_=>_i32 (func (param i32) (result i32)))
+
+ ;; CHECK: (type $none_=>_none (func))
+
+ ;; CHECK: (import "env" "imported" (func $imported (param i32) (result i32)))
+ (import "env" "imported" (func $imported (param i32) (result i32)))
+
+ ;; CHECK: (func $caller (type $none_=>_none)
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (block (result i32)
+ ;; CHECK-NEXT: (block $__inlined_func$callee (result i32)
+ ;; CHECK-NEXT: (br $__inlined_func$callee
+ ;; CHECK-NEXT: (call $imported
+ ;; CHECK-NEXT: (unreachable)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $caller
+ (drop
+ (call $callee)
+ )
+ )
+
+ ;; After inlining, this return_call will turn into a call, but should still be
+ ;; unreachable. Validation will fail if it is not.
+ (func $callee (result i32)
+ (return_call $imported
+ (unreachable)
+ )
+ )
+)