diff options
-rw-r--r-- | src/passes/Inlining.cpp | 4 | ||||
-rw-r--r-- | src/wasm/wasm-validator.cpp | 7 | ||||
-rw-r--r-- | test/lit/passes/inlining-unreachable.wast | 44 |
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) + ) + ) +) |