Skip to content

Commit bb23d20

Browse files
authored
[Custom Descriptors] Update Unsubtyping (#7664)
When we have types A and B with descriptors A.desc and B.desc, A <: B implies A.desc <: B.desc. Update Unsubypting to preserve the implication and avoid generating invalid types.
1 parent 1c51746 commit bb23d20

File tree

3 files changed

+70
-0
lines changed

3 files changed

+70
-0
lines changed

scripts/test/fuzzing.py

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

src/passes/Unsubtyping.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,11 @@ struct Unsubtyping
290290
case HeapTypeKind::Basic:
291291
WASM_UNREACHABLE("unexpected kind");
292292
}
293+
if (auto desc = type.getDescriptorType()) {
294+
if (auto superDesc = super.getDescriptorType()) {
295+
noteSubtype(*desc, *superDesc);
296+
}
297+
}
293298
}
294299

295300
// Analyze all casts at once.

test/lit/passes/unsubtyping-desc.wast

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
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: --unsubtyping --remove-unused-types -all -S -o - | filecheck %s
4+
5+
(module
6+
(rec
7+
;; CHECK: (rec
8+
;; CHECK-NEXT: (type $A (sub (descriptor $A.desc (struct))))
9+
(type $A (sub (descriptor $A.desc (struct))))
10+
;; CHECK: (type $A.desc (sub (describes $A (struct))))
11+
(type $A.desc (sub (describes $A (struct))))
12+
;; CHECK: (type $B (sub (descriptor $B.desc (struct))))
13+
(type $B (sub $A (descriptor $B.desc (struct))))
14+
;; CHECK: (type $B.desc (sub (describes $B (struct))))
15+
(type $B.desc (sub $A.desc (describes $B (struct))))
16+
)
17+
18+
;; There is nothing requiring the subtype relationship, so we should optimize.
19+
;; CHECK: (global $A (ref null $A) (ref.null none))
20+
(global $A (ref null $A) (ref.null none))
21+
;; CHECK: (global $B (ref null $B) (ref.null none))
22+
(global $B (ref null $B) (ref.null none))
23+
)
24+
25+
(module
26+
(rec
27+
;; CHECK: (rec
28+
;; CHECK-NEXT: (type $A (sub (descriptor $A.desc (struct))))
29+
(type $A (sub (descriptor $A.desc (struct))))
30+
;; CHECK: (type $A.desc (sub (describes $A (struct))))
31+
(type $A.desc (sub (describes $A (struct))))
32+
;; CHECK: (type $B (sub $A (descriptor $B.desc (struct))))
33+
(type $B (sub $A (descriptor $B.desc (struct))))
34+
;; CHECK: (type $B.desc (sub $A.desc (describes $B (struct))))
35+
(type $B.desc (sub $A.desc (describes $B (struct))))
36+
)
37+
38+
;; Now we require B <: A, which implies B.desc <: A.desc.
39+
;; CHECK: (global $B (ref null $B) (ref.null none))
40+
(global $B (ref null $B) (ref.null none))
41+
;; CHECK: (global $A (ref null $A) (global.get $B))
42+
(global $A (ref null $A) (global.get $B))
43+
)
44+
45+
(module
46+
(rec
47+
;; CHECK: (rec
48+
;; CHECK-NEXT: (type $A (sub (descriptor $A.desc (struct))))
49+
(type $A (sub (descriptor $A.desc (struct))))
50+
;; CHECK: (type $A.desc (sub (describes $A (struct))))
51+
(type $A.desc (sub (describes $A (struct))))
52+
;; CHECK: (type $B (sub (descriptor $B.desc (struct))))
53+
(type $B (sub $A (descriptor $B.desc (struct))))
54+
;; CHECK: (type $B.desc (sub $A.desc (describes $B (struct))))
55+
(type $B.desc (sub $A.desc (describes $B (struct))))
56+
)
57+
58+
;; Now we directly require B.desc <: A.desc. This does *not* imply B <: A, so
59+
;; we can optimize $B (but not $B.desc).
60+
;; CHECK: (global $B.desc (ref null $B.desc) (ref.null none))
61+
(global $B.desc (ref null $B.desc) (ref.null none))
62+
;; CHECK: (global $A.desc (ref null $A.desc) (global.get $B.desc))
63+
(global $A.desc (ref null $A.desc) (global.get $B.desc))
64+
)

0 commit comments

Comments
 (0)