Skip to content

Commit f202450

Browse files
authored
Heap2Local: Handle unreachable code inside ref.is_null (#8038)
We must not force the type to be i32, but leave it unreachable (parallel to ref.eq, below it). Fixes #8035
1 parent 8ccb3f6 commit f202450

File tree

2 files changed

+67
-0
lines changed

2 files changed

+67
-0
lines changed

src/passes/Heap2Local.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -795,6 +795,12 @@ struct Struct2Local : PostWalker<Struct2Local> {
795795
return;
796796
}
797797

798+
if (curr->type == Type::unreachable) {
799+
// The result does not matter. Leave things as they are (and let DCE
800+
// handle it).
801+
return;
802+
}
803+
798804
// The result must be 0, since the allocation is not null. Drop the RefIs
799805
// and append that.
800806
replaceCurrent(builder.makeSequence(

test/lit/passes/heap2local-desc.wast

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1218,3 +1218,64 @@
12181218
)
12191219
)
12201220

1221+
(module
1222+
(rec
1223+
;; CHECK: (rec
1224+
;; CHECK-NEXT: (type $struct (sub (descriptor $desc (struct))))
1225+
(type $struct (sub (descriptor $desc (struct))))
1226+
;; CHECK: (type $desc (describes $struct (struct)))
1227+
(type $desc (sub final (describes $struct (struct))))
1228+
)
1229+
1230+
;; CHECK: (type $2 (func (result i32)))
1231+
1232+
;; CHECK: (func $test (type $2) (result i32)
1233+
;; CHECK-NEXT: (local $desc (ref $desc))
1234+
;; CHECK-NEXT: (local $1 (ref (exact $desc)))
1235+
;; CHECK-NEXT: (local $2 (ref (exact $desc)))
1236+
;; CHECK-NEXT: (drop
1237+
;; CHECK-NEXT: (block (result nullref)
1238+
;; CHECK-NEXT: (ref.null none)
1239+
;; CHECK-NEXT: )
1240+
;; CHECK-NEXT: )
1241+
;; CHECK-NEXT: (ref.is_null
1242+
;; CHECK-NEXT: (block
1243+
;; CHECK-NEXT: (drop
1244+
;; CHECK-NEXT: (block (result nullref)
1245+
;; CHECK-NEXT: (local.set $2
1246+
;; CHECK-NEXT: (struct.new_default $desc)
1247+
;; CHECK-NEXT: )
1248+
;; CHECK-NEXT: (local.set $1
1249+
;; CHECK-NEXT: (local.get $2)
1250+
;; CHECK-NEXT: )
1251+
;; CHECK-NEXT: (ref.null none)
1252+
;; CHECK-NEXT: )
1253+
;; CHECK-NEXT: )
1254+
;; CHECK-NEXT: (drop
1255+
;; CHECK-NEXT: (ref.null none)
1256+
;; CHECK-NEXT: )
1257+
;; CHECK-NEXT: (unreachable)
1258+
;; CHECK-NEXT: )
1259+
;; CHECK-NEXT: )
1260+
;; CHECK-NEXT: )
1261+
(func $test (result i32)
1262+
(local $desc (ref $desc))
1263+
(local.set $desc
1264+
(struct.new_default $desc)
1265+
)
1266+
;; After we optimize the struct.new above, the local.get below will get
1267+
;; removed, and we will see that the ref.cast_desc traps (the input
1268+
;; descriptor differs from the one we test, the allocation we just
1269+
;; removed). When optimizing that, we should not emit invalid IR for the
1270+
;; ref.is_null: It has an i32 result normally, but in unreachable code it
1271+
;; must remain unreachable.
1272+
(ref.is_null
1273+
(ref.cast_desc (ref $struct)
1274+
(struct.new_default $struct
1275+
(struct.new_default $desc)
1276+
)
1277+
(local.get $desc)
1278+
)
1279+
)
1280+
)
1281+
)

0 commit comments

Comments
 (0)