Skip to content

Commit ea98200

Browse files
authored
Heap2Local: Handle unreachable ref.test replacement (#8605)
As with `local.get` in other cases, here we replace with something concrete (a `const`), and we can't do that if we became unreachable.
1 parent 95d8876 commit ea98200

File tree

2 files changed

+75
-0
lines changed

2 files changed

+75
-0
lines changed

src/passes/Heap2Local.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -862,6 +862,13 @@ struct Struct2Local : PostWalker<Struct2Local> {
862862
return;
863863
}
864864

865+
if (curr->type == Type::unreachable) {
866+
// We must not modify unreachable code here, as we will replace it with a
867+
// const, which has a concrete type (similar to the situation with
868+
// local.get in other cases in this pass).
869+
return;
870+
}
871+
865872
// This test operates on the allocation, which means we can compute whether
866873
// it will succeed statically. We do not even need
867874
// GCTypeUtils::evaluateCastCheck because we know the allocation's type

test/lit/passes/heap2local-desc.wast

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1360,3 +1360,71 @@
13601360
)
13611361
)
13621362
)
1363+
1364+
(module
1365+
(rec
1366+
;; CHECK: (rec
1367+
;; CHECK-NEXT: (type $struct (descriptor $desc) (struct))
1368+
(type $struct (descriptor $desc) (struct))
1369+
;; CHECK: (type $desc (sub (describes $struct) (struct)))
1370+
(type $desc (sub (describes $struct) (struct)))
1371+
)
1372+
1373+
;; CHECK: (type $2 (func))
1374+
1375+
;; CHECK: (func $test (type $2)
1376+
;; CHECK-NEXT: (local $temp (ref $desc))
1377+
;; CHECK-NEXT: (local $1 (ref none))
1378+
;; CHECK-NEXT: (local $2 (ref none))
1379+
;; CHECK-NEXT: (drop
1380+
;; CHECK-NEXT: (block (result nullref)
1381+
;; CHECK-NEXT: (ref.null none)
1382+
;; CHECK-NEXT: )
1383+
;; CHECK-NEXT: )
1384+
;; CHECK-NEXT: (drop
1385+
;; CHECK-NEXT: (ref.test (ref none)
1386+
;; CHECK-NEXT: (block
1387+
;; CHECK-NEXT: (drop
1388+
;; CHECK-NEXT: (block (result nullref)
1389+
;; CHECK-NEXT: (local.set $2
1390+
;; CHECK-NEXT: (ref.as_non_null
1391+
;; CHECK-NEXT: (ref.null none)
1392+
;; CHECK-NEXT: )
1393+
;; CHECK-NEXT: )
1394+
;; CHECK-NEXT: (local.set $1
1395+
;; CHECK-NEXT: (local.get $2)
1396+
;; CHECK-NEXT: )
1397+
;; CHECK-NEXT: (ref.null none)
1398+
;; CHECK-NEXT: )
1399+
;; CHECK-NEXT: )
1400+
;; CHECK-NEXT: (drop
1401+
;; CHECK-NEXT: (ref.null none)
1402+
;; CHECK-NEXT: )
1403+
;; CHECK-NEXT: (unreachable)
1404+
;; CHECK-NEXT: )
1405+
;; CHECK-NEXT: )
1406+
;; CHECK-NEXT: )
1407+
;; CHECK-NEXT: )
1408+
(func $test
1409+
(local $temp (ref $desc))
1410+
(local.set $temp
1411+
(struct.new_default $desc)
1412+
)
1413+
;; The ref.test's input will become unreachable after we optimize. We should
1414+
;; not emit a const for the test result, even though we know it, as this is
1415+
;; unreachable code which would not validate.
1416+
(drop
1417+
(ref.test (ref none)
1418+
(ref.cast_desc_eq (ref $struct)
1419+
(struct.new_default_desc $struct
1420+
(ref.as_non_null
1421+
(ref.null none)
1422+
)
1423+
)
1424+
(local.get $temp)
1425+
)
1426+
)
1427+
)
1428+
)
1429+
)
1430+

0 commit comments

Comments
 (0)