diff options
Diffstat (limited to 'test/lit/passes')
-rw-r--r-- | test/lit/passes/type-merging.wast | 74 |
1 files changed, 74 insertions, 0 deletions
diff --git a/test/lit/passes/type-merging.wast b/test/lit/passes/type-merging.wast index f7cae2a42..b3cc45bd2 100644 --- a/test/lit/passes/type-merging.wast +++ b/test/lit/passes/type-merging.wast @@ -953,6 +953,80 @@ ) ) +;; Regression test for a bug where we were over-aggressive in merging during the +;; supertype phase. Types A, B, C, D1, and D2 will all start out in the same +;; supertype merging partition, but partition refinement will show that A, B, +;; and C are distinct. We previously continued to merge D1 and D2, but that is +;; incorrect, as such a merge will either make g1 or g2 invalid below. The fix +;; was to manually split partitions that end up containing separate type trees. +(module + ;; CHECK: (rec + ;; CHECK-NEXT: (type $I (struct (field anyref))) + (type $I (sub (struct (field anyref)))) + ;; CHECK: (type $J (sub $I (struct (field eqref)))) + (type $J (sub $I (struct (field eqref)))) + ;; CHECK: (type $K (sub $J (struct (field i31ref)))) + (type $K (sub $J (struct (field i31ref)))) + (rec + ;; CHECK: (type $A (struct (field (ref null $A)) (field (ref null $I)))) + (type $A (sub (struct (ref null $A) (ref null $I)))) + ;; CHECK: (type $C (sub $A (struct (field (ref null $A)) (field (ref null $K))))) + + ;; CHECK: (type $D2 (sub $C (struct (field (ref null $B)) (field (ref null $K))))) + + ;; CHECK: (type $B (sub $A (struct (field (ref null $B)) (field (ref null $J))))) + (type $B (sub $A (struct (ref null $B) (ref null $J)))) + (type $C (sub $A (struct (ref null $A) (ref null $K)))) + ;; CHECK: (type $D1 (sub $B (struct (field (ref null $B)) (field (ref null $K))))) + (type $D1 (sub $B (struct (ref null $B) (ref null $K)))) + (type $D2 (sub $C (struct (ref null $B) (ref null $K)))) + ) + + ;; CHECK: (global $g1 (ref $B) (struct.new_default $D1)) + (global $g1 (ref $B) (struct.new_default $D1)) + ;; CHECK: (global $g2 (ref $C) (struct.new_default $D2)) + (global $g2 (ref $C) (struct.new_default $D2)) +) + +;; Same as above, but with some additional types that can be merged. +(module + ;; CHECK: (rec + ;; CHECK-NEXT: (type $I (struct (field anyref))) + (type $I (sub (struct (field anyref)))) + ;; CHECK: (type $J (sub $I (struct (field eqref)))) + (type $J (sub $I (struct (field eqref)))) + ;; CHECK: (type $K (sub $J (struct (field i31ref)))) + (type $K (sub $J (struct (field i31ref)))) + (rec + ;; CHECK: (type $A (struct (field (ref null $A)) (field (ref null $I)))) + (type $A (sub (struct (ref null $A) (ref null $I)))) + (type $A' (sub $A (struct (ref null $A) (ref null $I)))) + ;; CHECK: (type $C (sub $A (struct (field (ref null $A)) (field (ref null $K))))) + + ;; CHECK: (type $D2 (sub $C (struct (field (ref null $B)) (field (ref null $K))))) + + ;; CHECK: (type $B (sub $A (struct (field (ref null $B)) (field (ref null $J))))) + (type $B (sub $A' (struct (ref null $B) (ref null $J)))) + (type $B' (sub $B (struct (ref null $B) (ref null $J)))) + (type $C (sub $A' (struct (ref null $A) (ref null $K)))) + (type $C' (sub $C (struct (ref null $A) (ref null $K)))) + ;; CHECK: (type $D1 (sub $B (struct (field (ref null $B)) (field (ref null $K))))) + (type $D1 (sub $B' (struct (ref null $B) (ref null $K)))) + (type $D1' (sub $D1 (struct (ref null $B) (ref null $K)))) + (type $D2 (sub $C' (struct (ref null $B) (ref null $K)))) + (type $D2' (sub $D2 (struct (ref null $B) (ref null $K)))) + ) + + ;; CHECK: (global $g1 (ref $B) (struct.new_default $D1)) + (global $g1 (ref $B') (struct.new_default $D1')) + ;; CHECK: (global $g2 (ref $C) (struct.new_default $D2)) + (global $g2 (ref $C') (struct.new_default $D2')) +) + + (global $g1 (ref $B) (struct.new_default $D1)) + (global $g2 (ref $C) (struct.new_default $D2)) +) + ;; Check that a ref.test inhibits merging (ref.cast is already checked above). (module ;; CHECK: (rec |