summaryrefslogtreecommitdiff
path: root/test/lit/passes
diff options
context:
space:
mode:
Diffstat (limited to 'test/lit/passes')
-rw-r--r--test/lit/passes/type-merging.wast74
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