Skip to content

Commit 3a717cf

Browse files
authored
GlobalRefining: Do not refine exported globals if their type cannot be public (#7973)
1 parent d43c40d commit 3a717cf

File tree

2 files changed

+47
-6
lines changed

2 files changed

+47
-6
lines changed

src/passes/GlobalRefining.cpp

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "ir/find_all.h"
2323
#include "ir/lubs.h"
2424
#include "ir/module-utils.h"
25+
#include "ir/public-type-validator.h"
2526
#include "ir/utils.h"
2627
#include "pass.h"
2728
#include "wasm-type.h"
@@ -75,13 +76,17 @@ struct GlobalRefining : public Pass {
7576
// fields in subtypes - the types must match exactly, or else a write in
7677
// one place could store a type considered in valid in another place).
7778
std::unordered_set<Name> unoptimizable;
78-
for (auto* global : ExportUtils::getExportedGlobals(*module)) {
79+
auto exportedGlobalsVec = ExportUtils::getExportedGlobals(*module);
80+
std::unordered_set<Global*> exportedGlobals(exportedGlobalsVec.begin(),
81+
exportedGlobalsVec.end());
82+
for (auto* global : exportedGlobalsVec) {
7983
if (getPassOptions().closedWorld || global->mutable_) {
8084
unoptimizable.insert(global->name);
8185
}
8286
}
8387

8488
bool optimized = false;
89+
PublicTypeValidator publicTypeValidator(module->features);
8590

8691
for (auto& global : module->globals) {
8792
if (global->imported() || unoptimizable.count(global->name)) {
@@ -102,12 +107,20 @@ struct GlobalRefining : public Pass {
102107

103108
auto oldType = global->type;
104109
auto newType = lub.getLUB();
105-
if (newType != oldType) {
106-
// We found an improvement!
107-
assert(Type::isSubType(newType, oldType));
108-
global->type = newType;
109-
optimized = true;
110+
if (newType == oldType) {
111+
continue;
110112
}
113+
114+
// Do not make invalid types public.
115+
if (exportedGlobals.count(global.get()) &&
116+
!publicTypeValidator.isValidPublicType(newType)) {
117+
continue;
118+
}
119+
120+
// We found an improvement!
121+
assert(Type::isSubType(newType, oldType));
122+
global->type = newType;
123+
optimized = true;
111124
}
112125

113126
if (!optimized) {
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited.
2+
3+
;; RUN: foreach %s %t wasm-opt --global-refining -all --disable-custom-descriptors -S -o - | filecheck %s
4+
5+
;; We cannot refine $global's type, as then it would make the rec group
6+
;; public, and that includes an exact type, which is invalid without custom
7+
;; descriptors.
8+
;;
9+
;; We can refine $unexported, though, as it makes nothing public.
10+
(module
11+
(rec
12+
;; CHECK: (rec
13+
;; CHECK-NEXT: (type $array (array i8))
14+
(type $array (array i8))
15+
;; CHECK: (type $struct (struct (field (ref (exact $array)))))
16+
(type $struct (struct (field (ref (exact $array)))))
17+
)
18+
19+
;; CHECK: (global $global (ref eq) (array.new_fixed $array 0))
20+
(global $global (ref eq) (array.new_fixed $array 0))
21+
22+
;; CHECK: (global $unexported (ref (exact $array)) (array.new_fixed $array 0))
23+
(global $unexported (ref eq) (array.new_fixed $array 0))
24+
25+
;; CHECK: (export "global" (global $global))
26+
(export "global" (global $global))
27+
)
28+

0 commit comments

Comments
 (0)