diff --git a/src/passes/GlobalRefining.cpp b/src/passes/GlobalRefining.cpp index 4ef6252b5ac..1cb4aed7c29 100644 --- a/src/passes/GlobalRefining.cpp +++ b/src/passes/GlobalRefining.cpp @@ -22,6 +22,7 @@ #include "ir/find_all.h" #include "ir/lubs.h" #include "ir/module-utils.h" +#include "ir/public-type-validator.h" #include "ir/utils.h" #include "pass.h" #include "wasm-type.h" @@ -75,13 +76,17 @@ struct GlobalRefining : public Pass { // fields in subtypes - the types must match exactly, or else a write in // one place could store a type considered in valid in another place). std::unordered_set unoptimizable; - for (auto* global : ExportUtils::getExportedGlobals(*module)) { + auto exportedGlobalsVec = ExportUtils::getExportedGlobals(*module); + std::unordered_set exportedGlobals(exportedGlobalsVec.begin(), + exportedGlobalsVec.end()); + for (auto* global : exportedGlobalsVec) { if (getPassOptions().closedWorld || global->mutable_) { unoptimizable.insert(global->name); } } bool optimized = false; + PublicTypeValidator publicTypeValidator(module->features); for (auto& global : module->globals) { if (global->imported() || unoptimizable.count(global->name)) { @@ -102,12 +107,20 @@ struct GlobalRefining : public Pass { auto oldType = global->type; auto newType = lub.getLUB(); - if (newType != oldType) { - // We found an improvement! - assert(Type::isSubType(newType, oldType)); - global->type = newType; - optimized = true; + if (newType == oldType) { + continue; } + + // Do not make invalid types public. + if (exportedGlobals.count(global.get()) && + !publicTypeValidator.isValidPublicType(newType)) { + continue; + } + + // We found an improvement! + assert(Type::isSubType(newType, oldType)); + global->type = newType; + optimized = true; } if (!optimized) { diff --git a/test/lit/passes/global-refining_no-cd.wast b/test/lit/passes/global-refining_no-cd.wast new file mode 100644 index 00000000000..ff1a8590760 --- /dev/null +++ b/test/lit/passes/global-refining_no-cd.wast @@ -0,0 +1,28 @@ +;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. + +;; RUN: foreach %s %t wasm-opt --global-refining -all --disable-custom-descriptors -S -o - | filecheck %s + +;; We cannot refine $global's type, as then it would make the rec group +;; public, and that includes an exact type, which is invalid without custom +;; descriptors. +;; +;; We can refine $unexported, though, as it makes nothing public. +(module + (rec + ;; CHECK: (rec + ;; CHECK-NEXT: (type $array (array i8)) + (type $array (array i8)) + ;; CHECK: (type $struct (struct (field (ref (exact $array))))) + (type $struct (struct (field (ref (exact $array))))) + ) + + ;; CHECK: (global $global (ref eq) (array.new_fixed $array 0)) + (global $global (ref eq) (array.new_fixed $array 0)) + + ;; CHECK: (global $unexported (ref (exact $array)) (array.new_fixed $array 0)) + (global $unexported (ref eq) (array.new_fixed $array 0)) + + ;; CHECK: (export "global" (global $global)) + (export "global" (global $global)) +) +