Fix crash in MinimizeRecGroups (#8685)
We previously did not store type indices for public types. This caused a
crash when the logic for comparing rec groups came across references to
public types and assumed there would be indices to compare them by.
Fixes #8682.
diff --git a/src/passes/MinimizeRecGroups.cpp b/src/passes/MinimizeRecGroups.cpp
index 306426a..a4d5e82 100644
--- a/src/passes/MinimizeRecGroups.cpp
+++ b/src/passes/MinimizeRecGroups.cpp
@@ -311,10 +311,10 @@
// generate new groups with the same shape.
std::unordered_set<RecGroup> publicGroups;
for (auto& [type, info] : typeInfo) {
+ typeIndices.insert({type, typeIndices.size()});
if (info.visibility == ModuleUtils::Visibility::Private) {
// We can optimize private types.
types.push_back(type);
- typeIndices.insert({type, typeIndices.size()});
} else {
publicGroups.insert(type.getRecGroup());
}
diff --git a/test/lit/passes/minimize-rec-groups.wast b/test/lit/passes/minimize-rec-groups.wast
index 3483d1c..963f655 100644
--- a/test/lit/passes/minimize-rec-groups.wast
+++ b/test/lit/passes/minimize-rec-groups.wast
@@ -563,4 +563,44 @@
;; CHECK: (global $privateB (ref null $privateB) (ref.null none))
(global $privateB (ref null $privateB) (ref.null none))
)
+
+;; Regression test for a bug where we crashed when comparing rec groups with
+;; references to public types because we did not store type indices for public
+;; types.
;; CHECK: (export "g" (global $public))
+(module
+ (rec
+ ;; CHECK: (rec
+ ;; CHECK-NEXT: (type $public (sub (descriptor $desc) (struct)))
+ (type $public (sub (descriptor $desc) (struct)))
+ ;; CHECK: (type $desc (sub (describes $public) (struct)))
+ (type $desc (sub (describes $public) (struct)))
+ )
+
+ ;; We should not crash when comparing these identical connected components.
+ (rec
+ ;; CHECK: (rec
+ ;; CHECK-NEXT: (type $private1 (sub $public (descriptor $desc1) (struct)))
+ (type $private1 (sub $public (descriptor $desc1) (struct)))
+ ;; CHECK: (type $desc1 (sub $desc (describes $private1) (struct)))
+
+ ;; CHECK: (rec
+ ;; CHECK-NEXT: (type $4 (struct))
+
+ ;; CHECK: (type $private2 (sub $public (descriptor $desc2) (struct)))
+ (type $private2 (sub $public (descriptor $desc2) (struct)))
+ (type $desc1 (sub $desc (describes $private1) (struct)))
+ ;; CHECK: (type $desc2 (sub $desc (describes $private2) (struct)))
+ (type $desc2 (sub $desc (describes $private2) (struct)))
+ )
+
+ ;; CHECK: (global $use1 (ref null $private1) (ref.null none))
+ (global $use1 (ref null $private1) (ref.null none))
+ ;; CHECK: (global $use2 (ref null $private2) (ref.null none))
+ (global $use2 (ref null $private2) (ref.null none))
+ ;; CHECK: (global $public (ref null $public) (ref.null none))
+ (global $public (ref null $public) (ref.null none))
+ ;; CHECK: (export "public" (global $public))
+ (export "public" (global $public))
+)
+