Skip to content

Commit a99e765

Browse files
authored
TypeUpdating: Fix heap type updates on heap type children (#7848)
`GlobalTypeRewriter::getTempType` had the right logic to handle a Type, which included the right logic to handle the HeapType of a Type: Look in `typeIndices` and use that mapping if it is present. We need the same thing for HeapTypes as well, which this adds in a new `getTempHeapType`. This was not noticed before because Continuations are the first thing to have a direct HeapType child which is not through a Type. So Types worked before, but not direct HeapType children, which ended up mapped to the old type before the rewriting. Changes to `wasm-type.h` are NFC but I think make it easier to read, as it makes that logic entirely parallel to the lines above it. One existing test has an update, which fixes it by removing the ref to the old type.
1 parent 344df91 commit a99e765

File tree

7 files changed

+67
-11
lines changed

7 files changed

+67
-11
lines changed

scripts/test/fuzzing.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@
121121
'cont_export_throw.wast',
122122
'type-merging-cont.wast',
123123
'remove-unused-module-elements-cont.wast',
124+
'abstract-type-refining-cont.wast',
124125
# TODO: fix split_wast() on tricky escaping situations like a string ending
125126
# in \\" (the " is not escaped - there is an escaped \ before it)
126127
'string-lifting-section.wast',

src/ir/type-updating.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -359,9 +359,10 @@ Type GlobalTypeRewriter::getTempType(Type type) {
359359
}
360360
if (type.isRef()) {
361361
auto heapType = type.getHeapType();
362-
if (auto it = typeIndices.find(heapType); it != typeIndices.end()) {
362+
auto tempHeapType = getTempHeapType(heapType);
363+
if (tempHeapType != heapType) {
363364
return typeBuilder.getTempRefType(
364-
typeBuilder[it->second], type.getNullability(), type.getExactness());
365+
tempHeapType, type.getNullability(), type.getExactness());
365366
}
366367
// This type is not one that is eligible for optimizing. That is fine; just
367368
// use it unmodified.
@@ -377,6 +378,13 @@ Type GlobalTypeRewriter::getTempType(Type type) {
377378
WASM_UNREACHABLE("bad type");
378379
}
379380

381+
HeapType GlobalTypeRewriter::getTempHeapType(HeapType type) {
382+
if (auto it = typeIndices.find(type); it != typeIndices.end()) {
383+
return typeBuilder[it->second];
384+
}
385+
return type;
386+
}
387+
380388
Type GlobalTypeRewriter::getTempTupleType(Tuple tuple) {
381389
return typeBuilder.getTempTupleType(tuple);
382390
}

src/ir/type-updating.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -404,6 +404,7 @@ class GlobalTypeRewriter {
404404
// so that they can use a proper temp type of the TypeBuilder while modifying
405405
// things.
406406
Type getTempType(Type type);
407+
HeapType getTempHeapType(HeapType type);
407408
Type getTempTupleType(Tuple tuple);
408409

409410
using SignatureUpdates = std::unordered_map<HeapType, Signature>;
@@ -496,7 +497,7 @@ class TypeMapper : public GlobalTypeRewriter {
496497
if (iter != mapping.end()) {
497498
return iter->second;
498499
}
499-
return type;
500+
return getTempHeapType(type);
500501
}
501502

502503
Type getNewType(Type type) {

src/wasm-type.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -805,9 +805,12 @@ struct TypeBuilder {
805805
setHeapType(i, wasm::Array(elem));
806806
return;
807807
}
808-
case HeapTypeKind::Cont:
809-
setHeapType(i, Continuation(map(type.getContinuation().type)));
808+
case HeapTypeKind::Cont: {
809+
auto cont = type.getContinuation();
810+
cont.type = map(cont.type);
811+
setHeapType(i, cont);
810812
return;
813+
}
811814
case HeapTypeKind::Basic:
812815
WASM_UNREACHABLE("unexpected kind");
813816
}

src/wasm/wasm-type.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1324,6 +1324,9 @@ FeatureSet HeapType::getFeatures() const {
13241324

13251325
// In addition, scan their non-ref children, to add dependencies on
13261326
// things like SIMD.
1327+
// XXX This will not scan HeapType children that are not also children of
1328+
// Type children, which happens with Continuation (has a HeapType
1329+
// child that is not a Type).
13271330
for (auto child : heapType.getTypeChildren()) {
13281331
if (!child.isRef()) {
13291332
feats |= child.getFeatures();
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited.
2+
3+
;; RUN: foreach %s %t wasm-opt --abstract-type-refining -all --closed-world -S -o - | filecheck %s
4+
5+
;; $uncreated is never created, so we optimize and rebuild types. While doing
6+
;; so we should not get confused as we copy the continuation type, which
7+
;; should end up referring properly to the corresponding func type.
8+
9+
(module
10+
(rec
11+
;; CHECK: (rec
12+
;; CHECK-NEXT: (type $cont (cont $func))
13+
14+
;; CHECK: (type $func (func))
15+
(type $func (func))
16+
(type $cont (cont $func))
17+
18+
(type $uncreated (struct))
19+
)
20+
21+
;; CHECK: (elem declare func $func)
22+
23+
;; CHECK: (func $func (type $func)
24+
;; CHECK-NEXT: )
25+
(func $func (type $func)
26+
)
27+
28+
;; CHECK: (func $test (type $func)
29+
;; CHECK-NEXT: (drop
30+
;; CHECK-NEXT: (cont.new $cont
31+
;; CHECK-NEXT: (ref.func $func)
32+
;; CHECK-NEXT: )
33+
;; CHECK-NEXT: )
34+
;; CHECK-NEXT: )
35+
(func $test (type $func)
36+
(drop
37+
(cont.new $cont
38+
(ref.func $func)
39+
)
40+
)
41+
)
42+
)
43+

test/lit/passes/type-merging-cont.wast

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,12 @@
1010
;; CHECK: (rec
1111
;; CHECK-NEXT: (type $f (func))
1212
(type $f (func))
13-
;; CHECK: (type $f_0 (func))
14-
15-
;; CHECK: (type $k (cont $f_0))
13+
;; CHECK: (type $k (cont $f))
1614
(type $k (cont $f))
1715

16+
;; CHECK: (type $f-i32 (func (result i32)))
1817
(type $f-i32 (func (result i32)))
19-
;; CHECK: (type $f-i32_0 (func (result i32)))
20-
21-
;; CHECK: (type $k-i32 (cont $f-i32_0))
18+
;; CHECK: (type $k-i32 (cont $f-i32))
2219
(type $k-i32 (cont $f-i32))
2320

2421
(rec

0 commit comments

Comments
 (0)