Skip to content

Commit 4360007

Browse files
authored
[Custom Descriptors] Update TypeMerging (#7666)
Update type merging to consider the existence of descriptor and described types as part of the top-level structure of a type. This prevents types with and without descriptors from incorrectly being merged together.
1 parent 02338c9 commit 4360007

File tree

3 files changed

+86
-0
lines changed

3 files changed

+86
-0
lines changed

scripts/test/fuzzing.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@
120120
'struct.new-desc.wast',
121121
'remove-unused-types-descriptors.wast',
122122
'unsubtyping-desc.wast',
123+
'type-merging-desc.wast',
123124
# TODO: fix split_wast() on tricky escaping situations like a string ending
124125
# in \\" (the " is not escaped - there is an escaped \ before it)
125126
'string-lifting-section.wast',

src/passes/TypeMerging.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -591,6 +591,13 @@ bool shapeEq(HeapType a, HeapType b) {
591591
if (a.isShared() != b.isShared()) {
592592
return false;
593593
}
594+
// Ignore supertype because we want to be able to merge into parents.
595+
if (!!a.getDescriptorType() != !!b.getDescriptorType()) {
596+
return false;
597+
}
598+
if (!!a.getDescribedType() != !!b.getDescribedType()) {
599+
return false;
600+
}
594601
auto aKind = a.getKind();
595602
auto bKind = b.getKind();
596603
if (aKind != bKind) {
@@ -614,6 +621,9 @@ bool shapeEq(HeapType a, HeapType b) {
614621
size_t shapeHash(HeapType a) {
615622
size_t digest = hash(a.isOpen());
616623
rehash(digest, a.isShared());
624+
// Ignore supertype because we want to be able to merge into parents.
625+
rehash(digest, !!a.getDescriptorType());
626+
rehash(digest, !!a.getDescribedType());
617627
auto kind = a.getKind();
618628
rehash(digest, kind);
619629
switch (kind) {
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited.
2+
;; RUN: foreach %s %t wasm-opt -all --closed-world --preserve-type-order \
3+
;; RUN: --type-merging --remove-unused-types -S -o - | filecheck %s
4+
5+
(module
6+
(rec
7+
;; CHECK: (rec
8+
;; CHECK-NEXT: (type $A (struct))
9+
(type $A (struct))
10+
;; CHECK: (type $B (descriptor $C (struct)))
11+
(type $B (descriptor $C (struct)))
12+
;; CHECK: (type $C (describes $B (struct)))
13+
(type $C (describes $B (struct)))
14+
)
15+
16+
;; The types have different shapes and should not be merged.
17+
;; CHECK: (global $A (ref null $A) (ref.null none))
18+
(global $A (ref null $A) (ref.null none))
19+
;; CHECK: (global $B (ref null $B) (ref.null none))
20+
(global $B (ref null $B) (ref.null none))
21+
;; CHECK: (global $C (ref null $C) (ref.null none))
22+
(global $C (ref null $C) (ref.null none))
23+
)
24+
25+
(module
26+
(rec
27+
;; CHECK: (rec
28+
;; CHECK-NEXT: (type $A (descriptor $A.desc (struct (field i32))))
29+
(type $A (descriptor $A.desc (struct (field i32))))
30+
;; CHECK: (type $A.desc (describes $A (struct)))
31+
(type $A.desc (describes $A (struct)))
32+
33+
;; CHECK: (type $B (descriptor $B.desc (struct (field f64))))
34+
(type $B (descriptor $B.desc (struct (field f64))))
35+
;; CHECK: (type $B.desc (describes $B (struct)))
36+
(type $B.desc (describes $B (struct)))
37+
)
38+
39+
;; $A and $B have different shapes and should not be merged, so therefore
40+
;; $A.desc and $B.desc should not be merged.
41+
;; CHECK: (global $A (ref null $A) (ref.null none))
42+
(global $A (ref null $A) (ref.null none))
43+
;; CHECK: (global $A.desc (ref null $A.desc) (ref.null none))
44+
(global $A.desc (ref null $A.desc) (ref.null none))
45+
;; CHECK: (global $B (ref null $B) (ref.null none))
46+
(global $B (ref null $B) (ref.null none))
47+
;; CHECK: (global $B.desc (ref null $A.desc) (ref.null none))
48+
(global $B.desc (ref null $B.desc) (ref.null none))
49+
)
50+
51+
(module
52+
(rec
53+
;; CHECK: (rec
54+
;; CHECK-NEXT: (type $A (descriptor $A.desc (struct)))
55+
(type $A (descriptor $A.desc (struct)))
56+
;; CHECK: (type $A.desc (describes $A (struct (field i32))))
57+
(type $A.desc (describes $A (struct (field i32))))
58+
59+
;; CHECK: (type $B (descriptor $B.desc (struct)))
60+
(type $B (descriptor $B.desc (struct)))
61+
;; CHECK: (type $B.desc (describes $B (struct (field f64))))
62+
(type $B.desc (describes $B (struct (field f64))))
63+
)
64+
65+
;; $A.desc and $B.desc have different shapes and should not be merged, so
66+
;; therefore $A and $B should not be merged.
67+
;; CHECK: (global $A (ref null $A) (ref.null none))
68+
(global $A (ref null $A) (ref.null none))
69+
;; CHECK: (global $A.desc (ref null $A.desc) (ref.null none))
70+
(global $A.desc (ref null $A.desc) (ref.null none))
71+
;; CHECK: (global $B (ref null $A) (ref.null none))
72+
(global $B (ref null $B) (ref.null none))
73+
;; CHECK: (global $B.desc (ref null $B.desc) (ref.null none))
74+
(global $B.desc (ref null $B.desc) (ref.null none))
75+
)

0 commit comments

Comments
 (0)