Skip to content

Commit 8a12ceb

Browse files
authored
Heap2Local: Fix unreachability handling in visitRefGetDesc (#8283)
1 parent 5f91ba9 commit 8a12ceb

2 files changed

Lines changed: 91 additions & 5 deletions

File tree

src/passes/Heap2Local.cpp

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -958,6 +958,15 @@ struct Struct2Local : PostWalker<Struct2Local> {
958958
return;
959959
}
960960

961+
if (curr->type == Type::unreachable) {
962+
// We must not modify unreachable code here, as we will replace it with a
963+
// local.get, which has a concrete type (another option could be to run
964+
// DCE and not only ReFinalize - DCE will propagate an unreachable out of
965+
// a concrete block, like we emit here - but we can just ignore such
966+
// code).
967+
return;
968+
}
969+
961970
auto descIndex = localIndexes[fields.size()];
962971
Expression* value = builder.makeLocalGet(descIndex, descType);
963972
replaceCurrent(builder.blockify(builder.makeDrop(curr->ref), value));
@@ -990,11 +999,7 @@ struct Struct2Local : PostWalker<Struct2Local> {
990999
}
9911000

9921001
if (curr->type == Type::unreachable) {
993-
// We must not modify unreachable code here, as we will replace it with a
994-
// local.get, which has a concrete type (another option could be to run
995-
// DCE and not only ReFinalize - DCE will propagate an unreachable out of
996-
// a concrete block, like we emit here - but we can just ignore such
997-
// code).
1002+
// As with RefGetDesc, above.
9981003
return;
9991004
}
10001005

test/lit/passes/heap2local-desc.wast

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1279,3 +1279,84 @@
12791279
)
12801280
)
12811281
)
1282+
1283+
(module
1284+
(rec
1285+
;; CHECK: (rec
1286+
;; CHECK-NEXT: (type $struct (descriptor $desc) (struct))
1287+
(type $struct (descriptor $desc) (struct))
1288+
;; CHECK: (type $desc (sub (describes $struct) (struct (field funcref))))
1289+
(type $desc (sub (describes $struct) (struct (field funcref))))
1290+
)
1291+
1292+
;; CHECK: (type $2 (func))
1293+
1294+
;; CHECK: (func $test (type $2)
1295+
;; CHECK-NEXT: (local $desc (ref $desc))
1296+
;; CHECK-NEXT: (local $func funcref)
1297+
;; CHECK-NEXT: (local $2 funcref)
1298+
;; CHECK-NEXT: (local $3 (ref (exact $desc)))
1299+
;; CHECK-NEXT: (local $4 (ref (exact $desc)))
1300+
;; CHECK-NEXT: (drop
1301+
;; CHECK-NEXT: (block (result nullref)
1302+
;; CHECK-NEXT: (local.set $2
1303+
;; CHECK-NEXT: (ref.null nofunc)
1304+
;; CHECK-NEXT: )
1305+
;; CHECK-NEXT: (ref.null none)
1306+
;; CHECK-NEXT: )
1307+
;; CHECK-NEXT: )
1308+
;; CHECK-NEXT: (local.tee $func
1309+
;; CHECK-NEXT: (block ;; (replaces unreachable StructGet we can't emit)
1310+
;; CHECK-NEXT: (drop
1311+
;; CHECK-NEXT: (block ;; (replaces unreachable RefGetDesc we can't emit)
1312+
;; CHECK-NEXT: (drop
1313+
;; CHECK-NEXT: (block
1314+
;; CHECK-NEXT: (drop
1315+
;; CHECK-NEXT: (block (result nullref)
1316+
;; CHECK-NEXT: (local.set $4
1317+
;; CHECK-NEXT: (struct.new_default $desc)
1318+
;; CHECK-NEXT: )
1319+
;; CHECK-NEXT: (local.set $3
1320+
;; CHECK-NEXT: (local.get $4)
1321+
;; CHECK-NEXT: )
1322+
;; CHECK-NEXT: (ref.null none)
1323+
;; CHECK-NEXT: )
1324+
;; CHECK-NEXT: )
1325+
;; CHECK-NEXT: (drop
1326+
;; CHECK-NEXT: (ref.null none)
1327+
;; CHECK-NEXT: )
1328+
;; CHECK-NEXT: (unreachable)
1329+
;; CHECK-NEXT: )
1330+
;; CHECK-NEXT: )
1331+
;; CHECK-NEXT: (unreachable)
1332+
;; CHECK-NEXT: )
1333+
;; CHECK-NEXT: )
1334+
;; CHECK-NEXT: (unreachable)
1335+
;; CHECK-NEXT: )
1336+
;; CHECK-NEXT: )
1337+
;; CHECK-NEXT: )
1338+
(func $test
1339+
(local $desc (ref $desc))
1340+
(local $func funcref)
1341+
1342+
(local.set $desc
1343+
(struct.new_default $desc)
1344+
)
1345+
1346+
(local.set $func
1347+
(struct.get $desc 0
1348+
;; This ref.get_desc will become unreachable (as the desc does not
1349+
;; match, after expanding locals). We should not generate invalid code
1350+
;; from that point - it is unreachable, and we can leave it as is.
1351+
(ref.get_desc $struct
1352+
(ref.cast_desc_eq (ref $struct)
1353+
(struct.new_default_desc $struct
1354+
(struct.new_default $desc)
1355+
)
1356+
(local.get $desc)
1357+
)
1358+
)
1359+
)
1360+
)
1361+
)
1362+
)

0 commit comments

Comments
 (0)