From c136076b339de072b98bcb62be6166083c74dcc6 Mon Sep 17 00:00:00 2001 From: stevenfontanella Date: Thu, 1 Jan 2026 01:08:10 +0000 Subject: [PATCH 1/4] Try allowing globals to be imported in ctor eval --- src/tools/wasm-ctor-eval.cpp | 11 ++++++++++- test/ctor-eval/global-get-init.wast | 16 ++++++++++++---- test/ctor-eval/global-get-init.wast.ctors | 2 +- test/ctor-eval/global-get-init.wast.out | 9 +++++---- 4 files changed, 28 insertions(+), 10 deletions(-) diff --git a/src/tools/wasm-ctor-eval.cpp b/src/tools/wasm-ctor-eval.cpp index 4ce09e4479e..0ee49d0eb7f 100644 --- a/src/tools/wasm-ctor-eval.cpp +++ b/src/tools/wasm-ctor-eval.cpp @@ -73,9 +73,15 @@ class EvallingImportResolver : public ImportResolver { public: EvallingImportResolver() = default; + // We throw FailToEvalException on reading these. Provide a stub value that + // passes import validation. Literals* getGlobalOrNull(ImportNames name, Type type) const override { - throw FailToEvalException("Accessed imported global"); + auto [it, _] = stubLiterals.try_emplace(type, Literals({Literal(type)})); + return &it->second; } + +private: + mutable std::unordered_map stubLiterals; }; class EvallingModuleRunner : public ModuleRunnerBase { @@ -557,6 +563,9 @@ struct CtorEvalExternalInterface : EvallingModuleRunner::ExternalInterface { wasm->updateMaps(); for (auto& oldGlobal : oldGlobals) { + if (oldGlobal->imported()) { + continue; + } // Serialize the global's value. While doing so, pass in the name of this // global, as we may be able to reuse the global as the defining global // for the value. See getSerialization() for more details. diff --git a/test/ctor-eval/global-get-init.wast b/test/ctor-eval/global-get-init.wast index 125e672d6c5..e52867fa240 100644 --- a/test/ctor-eval/global-get-init.wast +++ b/test/ctor-eval/global-get-init.wast @@ -1,8 +1,16 @@ (module + ;; an imported global that isn't accessed doesn't stop us from optimizing (import "import" "global" (global $imported i32)) - (func $test1 (export "test1") - ;; This should be safe to eval in theory, but the imported global stops us, - ;; so this function will not be optimized out. - ;; TODO: perhaps if we never use that global that is ok? + (global $g (mut i32) (i32.const 0)) + (func $setg (export "setg") + (drop (i32.const 1)) + (global.set $g + (i32.add (i32.const 1) (i32.const 2)) + ) + ) + + (func $keepalive (export "keepalive") (result i32) + ;; Keep the global alive so we can see its value. + (global.get $g) ) ) diff --git a/test/ctor-eval/global-get-init.wast.ctors b/test/ctor-eval/global-get-init.wast.ctors index a5bce3fd256..9b1821d1b2d 100644 --- a/test/ctor-eval/global-get-init.wast.ctors +++ b/test/ctor-eval/global-get-init.wast.ctors @@ -1 +1 @@ -test1 +setg diff --git a/test/ctor-eval/global-get-init.wast.out b/test/ctor-eval/global-get-init.wast.out index 519e96dbabd..89271eee388 100644 --- a/test/ctor-eval/global-get-init.wast.out +++ b/test/ctor-eval/global-get-init.wast.out @@ -1,7 +1,8 @@ (module - (type $0 (func)) - (export "test1" (func $test1)) - (func $test1 (type $0) - (nop) + (type $0 (func (result i32))) + (global $g (mut i32) (i32.const 3)) + (export "keepalive" (func $keepalive)) + (func $keepalive (type $0) (result i32) + (global.get $g) ) ) From 1626aeca171fa89e035d48b3f5f12fb7f0a0393b Mon Sep 17 00:00:00 2001 From: stevenfontanella Date: Mon, 12 Jan 2026 19:28:38 +0000 Subject: [PATCH 2/4] PR update --- src/tools/wasm-ctor-eval.cpp | 12 ++++++------ test/ctor-eval/global-get-init.wast | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/tools/wasm-ctor-eval.cpp b/src/tools/wasm-ctor-eval.cpp index 0ee49d0eb7f..bafea4b620d 100644 --- a/src/tools/wasm-ctor-eval.cpp +++ b/src/tools/wasm-ctor-eval.cpp @@ -71,17 +71,17 @@ class EvallingModuleRunner; class EvallingImportResolver : public ImportResolver { public: - EvallingImportResolver() = default; + EvallingImportResolver() : stubLiteral({Literal(0)}) {}; - // We throw FailToEvalException on reading these. Provide a stub value that - // passes import validation. + // Return an unused stub value. We throw FailToEvalException on reading any + // imported globals. We ignore the type and return an i32 literal since some + // types can't be created anyway (e.g. ref none). Literals* getGlobalOrNull(ImportNames name, Type type) const override { - auto [it, _] = stubLiterals.try_emplace(type, Literals({Literal(type)})); - return &it->second; + return &stubLiteral; } private: - mutable std::unordered_map stubLiterals; + mutable Literals stubLiteral; }; class EvallingModuleRunner : public ModuleRunnerBase { diff --git a/test/ctor-eval/global-get-init.wast b/test/ctor-eval/global-get-init.wast index e52867fa240..a7a1aff8615 100644 --- a/test/ctor-eval/global-get-init.wast +++ b/test/ctor-eval/global-get-init.wast @@ -1,6 +1,6 @@ (module ;; an imported global that isn't accessed doesn't stop us from optimizing - (import "import" "global" (global $imported i32)) + (import "import" "global" (global $imported (ref i31))) (global $g (mut i32) (i32.const 0)) (func $setg (export "setg") (drop (i32.const 1)) From 5cd7eeedb0e28f334dbf62d18cdda0def9f82a25 Mon Sep 17 00:00:00 2001 From: stevenfontanella Date: Mon, 12 Jan 2026 19:31:32 +0000 Subject: [PATCH 3/4] Formatting fix From ec60cfdb05c6f9edf8648f27b98615e15ea45780 Mon Sep 17 00:00:00 2001 From: stevenfontanella Date: Mon, 12 Jan 2026 19:36:30 +0000 Subject: [PATCH 4/4] Formatting fix --- src/tools/wasm-ctor-eval.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/wasm-ctor-eval.cpp b/src/tools/wasm-ctor-eval.cpp index bafea4b620d..1407682faf9 100644 --- a/src/tools/wasm-ctor-eval.cpp +++ b/src/tools/wasm-ctor-eval.cpp @@ -71,7 +71,7 @@ class EvallingModuleRunner; class EvallingImportResolver : public ImportResolver { public: - EvallingImportResolver() : stubLiteral({Literal(0)}) {}; + EvallingImportResolver() : stubLiteral({Literal(0)}){}; // Return an unused stub value. We throw FailToEvalException on reading any // imported globals. We ignore the type and return an i32 literal since some