Skip to content

Commit 3db6220

Browse files
authored
[Custom Descriptors] Fix bug optimizing struct.new (#7701)
When all of the non-descriptor operands to struct.new have default values, we can optimize the struct.new to struct.new_default in OptimizeInstructions. When we do this, we drop all the children with side effects. This previously included the descriptor operand, even though we did not clear the descriptor operand from the StructNew parent expression, causing the descriptor operand to appear twice in the IR. This is invalid and could lead to assertion failures elsewhere. To avoid the problem, clear the descriptor operand while we call the utility to drop the StructNew children and restore it afterward. This is somewhat ugly, but better than duplicating the functionality of the utility, except ignoring the descriptor.
1 parent 7f642c9 commit 3db6220

File tree

2 files changed

+43
-4
lines changed

2 files changed

+43
-4
lines changed

src/passes/OptimizeInstructions.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1863,9 +1863,15 @@ struct OptimizeInstructions
18631863
}
18641864
}
18651865

1866-
// Success! Drop the children and return a struct.new_with_default.
1866+
// Success! Drop the children and return a struct.new_with_default. We don't
1867+
// want the descriptor to be dropped, however, so temporarily remove it
1868+
// while we drop the other children. If the descriptor is null, this makes
1869+
// no difference.
1870+
auto* desc = curr->desc;
1871+
curr->desc = nullptr;
18671872
auto* rep = getDroppedChildrenAndAppend(curr, curr);
18681873
curr->operands.clear();
1874+
curr->desc = desc;
18691875
assert(curr->isWithDefault());
18701876
replaceCurrent(rep);
18711877
}

test/lit/passes/optimize-instructions-desc.wast

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,18 @@
1111
(type $desc (describes $struct (struct)))
1212
)
1313

14-
;; CHECK: (func $trap-null-desc (type $2) (result (ref (exact $struct)))
14+
(rec
15+
;; CHECK: (rec
16+
;; CHECK-NEXT: (type $struct-i32 (descriptor $struct-i32.desc (struct (field i32))))
17+
(type $struct-i32 (descriptor $struct-i32.desc (struct (field i32))))
18+
;; CHECK: (type $struct-i32.desc (describes $struct-i32 (struct)))
19+
(type $struct-i32.desc (describes $struct-i32 (struct)))
20+
)
21+
22+
;; CHECK: (import "" "" (func $effect (type $5)))
23+
(import "" "" (func $effect))
24+
25+
;; CHECK: (func $trap-null-desc (type $4) (result (ref (exact $struct)))
1526
;; CHECK-NEXT: (unreachable)
1627
;; CHECK-NEXT: )
1728
(func $trap-null-desc (result (ref (exact $struct)))
@@ -20,7 +31,7 @@
2031
)
2132
)
2233

23-
;; CHECK: (func $trap-null-desc-fallthrough (type $2) (result (ref (exact $struct)))
34+
;; CHECK: (func $trap-null-desc-fallthrough (type $4) (result (ref (exact $struct)))
2435
;; CHECK-NEXT: (local $desc (ref null (exact $desc)))
2536
;; CHECK-NEXT: (drop
2637
;; CHECK-NEXT: (local.tee $desc
@@ -38,7 +49,7 @@
3849
)
3950
)
4051

41-
;; CHECK: (func $nonnull-cast-desc (type $3) (param $desc (ref null (exact $desc))) (result (ref (exact $struct)))
52+
;; CHECK: (func $nonnull-cast-desc (type $6) (param $desc (ref null (exact $desc))) (result (ref (exact $struct)))
4253
;; CHECK-NEXT: (struct.new_default $struct
4354
;; CHECK-NEXT: (local.get $desc)
4455
;; CHECK-NEXT: )
@@ -50,4 +61,26 @@
5061
)
5162
)
5263
)
64+
65+
;; Test that when we optimize a struct.new to a struct.new_default, we drop
66+
;; the field operands but keep the descriptor.
67+
;; CHECK: (func $new-default-keep-desc (type $7) (result anyref)
68+
;; CHECK-NEXT: (struct.new_default $struct-i32
69+
;; CHECK-NEXT: (block (result (ref (exact $struct-i32.desc)))
70+
;; CHECK-NEXT: (call $effect)
71+
;; CHECK-NEXT: (struct.new_default $struct-i32.desc)
72+
;; CHECK-NEXT: )
73+
;; CHECK-NEXT: )
74+
;; CHECK-NEXT: )
75+
(func $new-default-keep-desc (result anyref)
76+
(struct.new $struct-i32
77+
(i32.const 0)
78+
(block (result (ref (exact $struct-i32.desc)))
79+
;; This would cause the descriptor to be dropped if it were dropped with
80+
;; the other children.
81+
(call $effect)
82+
(struct.new_default $struct-i32.desc)
83+
)
84+
)
85+
)
5386
)

0 commit comments

Comments
 (0)