From 91191d43eb3e0c744e4a2d76d7e411d274c2de92 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Wed, 11 Feb 2026 14:58:42 -0800 Subject: [PATCH 01/12] work --- src/passes/CMakeLists.txt | 1 + src/passes/StripToolchainAnnotations.cpp | 57 ++++++++++++++++++++++++ src/passes/pass.cpp | 3 ++ src/passes/passes.h | 9 ++-- 4 files changed, 66 insertions(+), 4 deletions(-) create mode 100644 src/passes/StripToolchainAnnotations.cpp diff --git a/src/passes/CMakeLists.txt b/src/passes/CMakeLists.txt index a763006ab66..0aa64c5f418 100644 --- a/src/passes/CMakeLists.txt +++ b/src/passes/CMakeLists.txt @@ -100,6 +100,7 @@ set(passes_SOURCES StringLowering.cpp Strip.cpp StripTargetFeatures.cpp + StripToolchainAnnotations.cpp TraceCalls.cpp RandomizeBranchHints.cpp RedundantSetElimination.cpp diff --git a/src/passes/StripToolchainAnnotations.cpp b/src/passes/StripToolchainAnnotations.cpp new file mode 100644 index 00000000000..6c12d88230d --- /dev/null +++ b/src/passes/StripToolchainAnnotations.cpp @@ -0,0 +1,57 @@ +/* + * Copyright 2026 WebAssembly Community Group participants + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// +// Removes toolchain-specific annotations from the IR. This is useful after all +// toolchain work is complete, because those annotations will not be used by +// VMs later, so they just waste space.annotations +// + +#include "pass.h" +#include "wasm-binary.h" +#include "wasm.h" + +namespace wasm { + +struct StripToolchainAnnotations : public WalkerPass> { + bool isFunctionParallel() override { return true; } + + bool requiresNonNullableLocalFixups() override { return false; } + + void doWalkFunction(Function* func) { + auto& annotations = annotations; + auto iter = func->codeAnnotations.begin(); + while (iter != func->codeAnnotations.end()) { + // Remove the toolchain-specific annotations. + auto& annotation = iter->second; + annotation.deadIfUnused = false; + + // If nothing remains, remove the entire annotation. + if (annotation == CodeAnnotation()) { + iter = annotations.erase(it); + } else { + ++iter; + // TODO test + } + } + } +}; + +Pass* createStripToolchainAnnotationsPass() { + return new StripToolchainAnnotations(); +} + +} // namespace wasm diff --git a/src/passes/pass.cpp b/src/passes/pass.cpp index 0f83013b8ab..a09f383a23b 100644 --- a/src/passes/pass.cpp +++ b/src/passes/pass.cpp @@ -548,6 +548,9 @@ void PassRegistry::registerPasses() { registerPass("strip-target-features", "strip the wasm target features section", createStripTargetFeaturesPass); + registerPass("strip-toolchain-annotations", + "strip all toolchain-specific code annotations", + createStripToolchainAnnotationsPass); registerPass("translate-to-new-eh", "deprecated; same as translate-to-exnref", createTranslateToExnrefPass); diff --git a/src/passes/passes.h b/src/passes/passes.h index 6481e062c6d..00bbdc23754 100644 --- a/src/passes/passes.h +++ b/src/passes/passes.h @@ -163,6 +163,9 @@ Pass* createSimplifyLocalsNoNestingPass(); Pass* createSimplifyLocalsNoTeePass(); Pass* createSimplifyLocalsNoStructurePass(); Pass* createSimplifyLocalsNoTeeNoStructurePass(); +Pass* createSouperifyPass(); +Pass* createSouperifySingleUsePass(); +Pass* createSpillPointersPass(); Pass* createStackCheckPass(); Pass* createStringGatheringPass(); Pass* createStringLiftingPass(); @@ -171,12 +174,10 @@ Pass* createStringLoweringMagicImportPass(); Pass* createStringLoweringMagicImportAssertPass(); Pass* createStripDebugPass(); Pass* createStripDWARFPass(); +Pass* createStripEHPass(); Pass* createStripProducersPass(); Pass* createStripTargetFeaturesPass(); -Pass* createSouperifyPass(); -Pass* createSouperifySingleUsePass(); -Pass* createSpillPointersPass(); -Pass* createStripEHPass(); +Pass* createStripToolchainAnnotationsPass(); Pass* createStubUnsupportedJSOpsPass(); Pass* createSSAifyPass(); Pass* createSSAifyNoMergePass(); From 4454eb107b332b9c5a950ef8cae0ec53262721c5 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Wed, 11 Feb 2026 14:59:50 -0800 Subject: [PATCH 02/12] fix --- src/passes/StripToolchainAnnotations.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/passes/StripToolchainAnnotations.cpp b/src/passes/StripToolchainAnnotations.cpp index 6c12d88230d..90f208408db 100644 --- a/src/passes/StripToolchainAnnotations.cpp +++ b/src/passes/StripToolchainAnnotations.cpp @@ -37,7 +37,7 @@ struct StripToolchainAnnotations : public WalkerPasscodeAnnotations.end()) { // Remove the toolchain-specific annotations. auto& annotation = iter->second; - annotation.deadIfUnused = false; + annotation.removableIfUnused = false; // If nothing remains, remove the entire annotation. if (annotation == CodeAnnotation()) { From 20c9a58b0b5753dd424d91f856400ecf87c292d9 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Wed, 11 Feb 2026 15:02:35 -0800 Subject: [PATCH 03/12] work --- src/passes/StripToolchainAnnotations.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/passes/StripToolchainAnnotations.cpp b/src/passes/StripToolchainAnnotations.cpp index 90f208408db..cdac97acf5c 100644 --- a/src/passes/StripToolchainAnnotations.cpp +++ b/src/passes/StripToolchainAnnotations.cpp @@ -15,9 +15,9 @@ */ // -// Removes toolchain-specific annotations from the IR. This is useful after all -// toolchain work is complete, because those annotations will not be used by -// VMs later, so they just waste space.annotations +// Removes toolchain-specific annotations from the IR. Typically this should be +// done after toolchain optimizations no longer need the annotations, and before +// shipping the final wasm (VMs do not need these toolchain annotations). // #include "pass.h" From c41fa9c373062644dbd9046cf5d307f850b03651 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Wed, 11 Feb 2026 15:04:34 -0800 Subject: [PATCH 04/12] work --- src/passes/StripToolchainAnnotations.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/passes/StripToolchainAnnotations.cpp b/src/passes/StripToolchainAnnotations.cpp index cdac97acf5c..1748ba4b585 100644 --- a/src/passes/StripToolchainAnnotations.cpp +++ b/src/passes/StripToolchainAnnotations.cpp @@ -32,19 +32,18 @@ struct StripToolchainAnnotations : public WalkerPasscodeAnnotations.begin(); - while (iter != func->codeAnnotations.end()) { + auto& annotations = func->codeAnnotations; + auto iter = annotations.begin(); + while (iter != annotations.end()) { // Remove the toolchain-specific annotations. auto& annotation = iter->second; annotation.removableIfUnused = false; // If nothing remains, remove the entire annotation. if (annotation == CodeAnnotation()) { - iter = annotations.erase(it); + iter = annotations.erase(iter); } else { ++iter; - // TODO test } } } From c8f58866c8d4b62f92f7134d1648e189efa61003 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Wed, 11 Feb 2026 15:07:25 -0800 Subject: [PATCH 05/12] work --- src/passes/StripToolchainAnnotations.cpp | 2 ++ .../passes/strip-toolchain-annotations.wast | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+) create mode 100644 test/lit/passes/strip-toolchain-annotations.wast diff --git a/src/passes/StripToolchainAnnotations.cpp b/src/passes/StripToolchainAnnotations.cpp index 1748ba4b585..4d312b47eea 100644 --- a/src/passes/StripToolchainAnnotations.cpp +++ b/src/passes/StripToolchainAnnotations.cpp @@ -31,6 +31,8 @@ struct StripToolchainAnnotations : public WalkerPass create() override { return std::make_unique(); } + void doWalkFunction(Function* func) { auto& annotations = func->codeAnnotations; auto iter = annotations.begin(); diff --git a/test/lit/passes/strip-toolchain-annotations.wast b/test/lit/passes/strip-toolchain-annotations.wast new file mode 100644 index 00000000000..71ac7a7acff --- /dev/null +++ b/test/lit/passes/strip-toolchain-annotations.wast @@ -0,0 +1,18 @@ +;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. +;; RUN: wasm-opt %s -all --strip-toolchain-annotations -S -o - | filecheck %s + +(module + ;; CHECK: (func $test (type $0) + ;; CHECK-NEXT: (@metadata.code.inline "\00") + ;; CHECK-NEXT: (call $test) + ;; CHECK-NEXT: (call $test) + ;; CHECK-NEXT: ) + (func $test + ;; Inlining hints are not removed, as they are for the VM too. + (@metadata.code.inline "\00") + (call $test) + ;; Toolchain hints are removed. + (@binaryen.removable.if.unused) + (call $test) + ) +) From 2364d5f3cf9528ef59d6d4769ecb4b5565af1407 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Wed, 11 Feb 2026 15:07:44 -0800 Subject: [PATCH 06/12] fmr --- src/passes/StripToolchainAnnotations.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/passes/StripToolchainAnnotations.cpp b/src/passes/StripToolchainAnnotations.cpp index 4d312b47eea..6118998eabf 100644 --- a/src/passes/StripToolchainAnnotations.cpp +++ b/src/passes/StripToolchainAnnotations.cpp @@ -26,12 +26,15 @@ namespace wasm { -struct StripToolchainAnnotations : public WalkerPass> { +struct StripToolchainAnnotations + : public WalkerPass> { bool isFunctionParallel() override { return true; } bool requiresNonNullableLocalFixups() override { return false; } - std::unique_ptr create() override { return std::make_unique(); } + std::unique_ptr create() override { + return std::make_unique(); + } void doWalkFunction(Function* func) { auto& annotations = func->codeAnnotations; From a8f310594480c29d50403065178da537911877f2 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Wed, 11 Feb 2026 15:09:36 -0800 Subject: [PATCH 07/12] test --- .../passes/strip-toolchain-annotations.wast | 34 +++++++++++++++---- 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/test/lit/passes/strip-toolchain-annotations.wast b/test/lit/passes/strip-toolchain-annotations.wast index 71ac7a7acff..71547e057fa 100644 --- a/test/lit/passes/strip-toolchain-annotations.wast +++ b/test/lit/passes/strip-toolchain-annotations.wast @@ -2,17 +2,39 @@ ;; RUN: wasm-opt %s -all --strip-toolchain-annotations -S -o - | filecheck %s (module - ;; CHECK: (func $test (type $0) + ;; CHECK: (func $test (type $0) (param $0 i32) ;; CHECK-NEXT: (@metadata.code.inline "\00") - ;; CHECK-NEXT: (call $test) - ;; CHECK-NEXT: (call $test) + ;; CHECK-NEXT: (call $test + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (call $test + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (@metadata.code.inline "\00") + ;; CHECK-NEXT: (call $test + ;; CHECK-NEXT: (i32.const 2) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (@metadata.code.inline "\00") + ;; CHECK-NEXT: (call $test + ;; CHECK-NEXT: (i32.const 3) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - (func $test + (func $test (param i32) ;; Inlining hints are not removed, as they are for the VM too. (@metadata.code.inline "\00") - (call $test) + (call $test (i32.const 0)) + ;; Toolchain hints are removed. (@binaryen.removable.if.unused) - (call $test) + (call $test (i32.const 1)) + + ;; When both are present, remove the toolchain one, in either order. + (@binaryen.removable.if.unused) + (@metadata.code.inline "\00") + (call $test (i32.const 2)) + + (@metadata.code.inline "\00") + (@binaryen.removable.if.unused) + (call $test (i32.const 3)) ) ) From 9c5dbd269c630106c0044abe49385096b647935c Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Wed, 11 Feb 2026 15:19:49 -0800 Subject: [PATCH 08/12] test --- test/lit/help/wasm-metadce.test | 3 +++ test/lit/help/wasm-opt.test | 3 +++ test/lit/help/wasm2js.test | 3 +++ 3 files changed, 9 insertions(+) diff --git a/test/lit/help/wasm-metadce.test b/test/lit/help/wasm-metadce.test index 98785fda862..53a8c729fda 100644 --- a/test/lit/help/wasm-metadce.test +++ b/test/lit/help/wasm-metadce.test @@ -519,6 +519,9 @@ ;; CHECK-NEXT: --strip-target-features strip the wasm target features ;; CHECK-NEXT: section ;; CHECK-NEXT: +;; CHECK-NEXT: --strip-toolchain-annotations strip all toolchain-specific +;; CHECK-NEXT: code annotations +;; CHECK-NEXT: ;; CHECK-NEXT: --stub-unsupported-js stub out unsupported JS ;; CHECK-NEXT: operations ;; CHECK-NEXT: diff --git a/test/lit/help/wasm-opt.test b/test/lit/help/wasm-opt.test index 4c0f4f67047..6ffd6950662 100644 --- a/test/lit/help/wasm-opt.test +++ b/test/lit/help/wasm-opt.test @@ -551,6 +551,9 @@ ;; CHECK-NEXT: --strip-target-features strip the wasm target features ;; CHECK-NEXT: section ;; CHECK-NEXT: +;; CHECK-NEXT: --strip-toolchain-annotations strip all toolchain-specific +;; CHECK-NEXT: code annotations +;; CHECK-NEXT: ;; CHECK-NEXT: --stub-unsupported-js stub out unsupported JS ;; CHECK-NEXT: operations ;; CHECK-NEXT: diff --git a/test/lit/help/wasm2js.test b/test/lit/help/wasm2js.test index 3c201f79ac4..c75f9b7bdc3 100644 --- a/test/lit/help/wasm2js.test +++ b/test/lit/help/wasm2js.test @@ -483,6 +483,9 @@ ;; CHECK-NEXT: --strip-target-features strip the wasm target features ;; CHECK-NEXT: section ;; CHECK-NEXT: +;; CHECK-NEXT: --strip-toolchain-annotations strip all toolchain-specific +;; CHECK-NEXT: code annotations +;; CHECK-NEXT: ;; CHECK-NEXT: --stub-unsupported-js stub out unsupported JS ;; CHECK-NEXT: operations ;; CHECK-NEXT: From 6f547fd55986927cb218402288f82a071144d73b Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Wed, 11 Feb 2026 15:24:54 -0800 Subject: [PATCH 09/12] test --- .../strip-toolchain-annotations-func.wast | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 test/lit/passes/strip-toolchain-annotations-func.wast diff --git a/test/lit/passes/strip-toolchain-annotations-func.wast b/test/lit/passes/strip-toolchain-annotations-func.wast new file mode 100644 index 00000000000..b42de3b63ef --- /dev/null +++ b/test/lit/passes/strip-toolchain-annotations-func.wast @@ -0,0 +1,41 @@ +;; RUN: wasm-opt -all --strip-toolchain-annotations %s -S -o - | filecheck %s + +(module + (@metadata.code.inline "\00") + (func $test-func-a + ;; This VM annotation is kept. + ) + + (@binaryen.removable.if.unused) + (func $test-func-b + ;; Toolchain one is removed. + ) + + (@metadata.code.inline "\00") + (@binaryen.removable.if.unused) + (func $test-func-c + ;; Toolchain one is removed, VM one is kept. + ) + + (@binaryen.removable.if.unused) + (@metadata.code.inline "\00") + (func $test-func-d + ;; Reverse order of above. + ) +) + +;; CHECK: (module +;; CHECK-NEXT: (type $0 (func)) +;; CHECK-NEXT: (@metadata.code.inline "\00") +;; CHECK-NEXT: (func $test-func-a (type $0) +;; CHECK-NEXT: ) +;; CHECK-NEXT: (func $test-func-b (type $0) +;; CHECK-NEXT: ) +;; CHECK-NEXT: (@metadata.code.inline "\00") +;; CHECK-NEXT: (func $test-func-c (type $0) +;; CHECK-NEXT: ) +;; CHECK-NEXT: (@metadata.code.inline "\00") +;; CHECK-NEXT: (func $test-func-d (type $0) +;; CHECK-NEXT: ) +;; CHECK-NEXT: ) + From acfcff2b0ef15d40f2c79dde737cd2e54969fcba Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Wed, 11 Feb 2026 15:26:51 -0800 Subject: [PATCH 10/12] test --- test/lit/passes/strip-toolchain-annotations.wast | 1 + 1 file changed, 1 insertion(+) diff --git a/test/lit/passes/strip-toolchain-annotations.wast b/test/lit/passes/strip-toolchain-annotations.wast index 71547e057fa..8e51cc993be 100644 --- a/test/lit/passes/strip-toolchain-annotations.wast +++ b/test/lit/passes/strip-toolchain-annotations.wast @@ -1,4 +1,5 @@ ;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. + ;; RUN: wasm-opt %s -all --strip-toolchain-annotations -S -o - | filecheck %s (module From f38b61d386243bc301815171c55a6dd8deda2c88 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Wed, 11 Feb 2026 15:32:39 -0800 Subject: [PATCH 11/12] like fix / yikes --- test/lit/lit.cfg.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/lit/lit.cfg.py b/test/lit/lit.cfg.py index be80ea4fc98..f593e4f948b 100644 --- a/test/lit/lit.cfg.py +++ b/test/lit/lit.cfg.py @@ -25,7 +25,9 @@ for tool in ('not', 'foreach'): tool_file = config.binaryen_src_root + '/scripts/' + tool + '.py' python = sys.executable.replace('\\', '/') - config.substitutions.append((tool, python + ' ' + tool_file)) + # Add a space after, to avoid replacing every 'not' in the command (like in + # "--strip-anNOTations"; capitalization for emphasis). + config.substitutions.append((tool + ' ', python + ' ' + tool_file + ' ')) if 'linux' in sys.platform: config.available_features.add('linux') From 35b42b989c4fa446cbe9d84454939012c3569346 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 12 Feb 2026 13:21:48 -0800 Subject: [PATCH 12/12] space on other side too --- test/lit/lit.cfg.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/lit/lit.cfg.py b/test/lit/lit.cfg.py index f593e4f948b..148e89e9031 100644 --- a/test/lit/lit.cfg.py +++ b/test/lit/lit.cfg.py @@ -25,9 +25,10 @@ for tool in ('not', 'foreach'): tool_file = config.binaryen_src_root + '/scripts/' + tool + '.py' python = sys.executable.replace('\\', '/') - # Add a space after, to avoid replacing every 'not' in the command (like in + # Add spaces to avoid replacing every 'not' in the command (like in # "--strip-anNOTations"; capitalization for emphasis). - config.substitutions.append((tool + ' ', python + ' ' + tool_file + ' ')) + config.substitutions.append((' ' + tool + ' ', + ' ' + python + ' ' + tool_file + ' ')) if 'linux' in sys.platform: config.available_features.add('linux')