From ba4582d6a422e2ea8fec876e9cc2314278e06c35 Mon Sep 17 00:00:00 2001 From: stevenfontanella Date: Tue, 25 Aug 2026 18:33:54 +0000 Subject: [PATCH 1/2] Fix depth map for waitqueues --- src/ir/subtypes.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/ir/subtypes.h b/src/ir/subtypes.h index 74263839379..36f178b3804 100644 --- a/src/ir/subtypes.h +++ b/src/ir/subtypes.h @@ -158,6 +158,9 @@ struct SubTypes { depths[HeapTypes::nofunc.getBasic(share)] = 0; depths[HeapTypes::nocont.getBasic(share)] = 0; depths[HeapTypes::noexn.getBasic(share)] = 0; + depths[HeapTypes::sharedNowaitqueue.getBasic(share)] = 0; + + depths[HeapTypes::sharedWaitqueue.getBasic(share)] = 1; // func would appear already if we saw function types, but if not, ensure // it exists here. Ditto for cont. From 06cf8f2dd7bd6fe4c17cf49ce62710cff11233a1 Mon Sep 17 00:00:00 2001 From: stevenfontanella Date: Tue, 25 Aug 2026 20:36:20 +0000 Subject: [PATCH 2/2] Add test --- test/lit/passes/gufa-waitqueue.wast | 46 +++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 test/lit/passes/gufa-waitqueue.wast diff --git a/test/lit/passes/gufa-waitqueue.wast b/test/lit/passes/gufa-waitqueue.wast new file mode 100644 index 00000000000..d1d9a826164 --- /dev/null +++ b/test/lit/passes/gufa-waitqueue.wast @@ -0,0 +1,46 @@ +;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. +;; RUN: wasm-opt %s -all --gufa -S -o - | filecheck %s + +(module + ;; CHECK: (type $struct (shared (struct (field (ref null (shared waitqueue)))))) + (type $struct (shared (struct (field (ref null (shared waitqueue)))))) + + ;; CHECK: (func $flows-null (type $1) (result (ref null (shared waitqueue))) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (call $helper + ;; CHECK-NEXT: (ref.null (shared nowaitqueue)) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (ref.null (shared nowaitqueue)) + ;; CHECK-NEXT: ) + (func $flows-null (export "test") (result (ref null (shared waitqueue))) + ;; GUFA can figure out that this function always returns null + ;; even though it flows through a struct. + (call $helper (ref.null (shared nowaitqueue))) + ) + + ;; CHECK: (func $helper (type $2) (param $w (ref null (shared waitqueue))) (result (ref null (shared waitqueue))) + ;; CHECK-NEXT: (local $s (ref null $struct)) + ;; CHECK-NEXT: (local.set $s + ;; CHECK-NEXT: (struct.new $struct + ;; CHECK-NEXT: (ref.null (shared nowaitqueue)) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (block (result (ref null (shared nowaitqueue))) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (struct.get $struct 0 + ;; CHECK-NEXT: (local.get $s) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (ref.null (shared nowaitqueue)) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (ref.null (shared nowaitqueue)) + ;; CHECK-NEXT: ) + (func $helper (param $w (ref null (shared waitqueue))) (result (ref null (shared waitqueue))) + (local $s (ref null $struct)) + (local.set $s (struct.new $struct (local.get $w))) + (struct.get $struct 0 (local.get $s)) + ) +)