Skip to content

Commit ec6d7ef

Browse files
authored
Add a pass to remove toolchain annotations (#8301)
Toolchains should remove these annotations before shipping, using --strip-toolchain-annotations
1 parent bc4838e commit ec6d7ef

File tree

10 files changed

+165
-5
lines changed

10 files changed

+165
-5
lines changed

src/passes/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ set(passes_SOURCES
100100
StringLowering.cpp
101101
Strip.cpp
102102
StripTargetFeatures.cpp
103+
StripToolchainAnnotations.cpp
103104
TraceCalls.cpp
104105
RandomizeBranchHints.cpp
105106
RedundantSetElimination.cpp
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/*
2+
* Copyright 2026 WebAssembly Community Group participants
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
//
18+
// Removes toolchain-specific annotations from the IR. Typically this should be
19+
// done after toolchain optimizations no longer need the annotations, and before
20+
// shipping the final wasm (VMs do not need these toolchain annotations).
21+
//
22+
23+
#include "pass.h"
24+
#include "wasm-binary.h"
25+
#include "wasm.h"
26+
27+
namespace wasm {
28+
29+
struct StripToolchainAnnotations
30+
: public WalkerPass<PostWalker<StripToolchainAnnotations>> {
31+
bool isFunctionParallel() override { return true; }
32+
33+
bool requiresNonNullableLocalFixups() override { return false; }
34+
35+
std::unique_ptr<Pass> create() override {
36+
return std::make_unique<StripToolchainAnnotations>();
37+
}
38+
39+
void doWalkFunction(Function* func) {
40+
auto& annotations = func->codeAnnotations;
41+
auto iter = annotations.begin();
42+
while (iter != annotations.end()) {
43+
// Remove the toolchain-specific annotations.
44+
auto& annotation = iter->second;
45+
annotation.removableIfUnused = false;
46+
47+
// If nothing remains, remove the entire annotation.
48+
if (annotation == CodeAnnotation()) {
49+
iter = annotations.erase(iter);
50+
} else {
51+
++iter;
52+
}
53+
}
54+
}
55+
};
56+
57+
Pass* createStripToolchainAnnotationsPass() {
58+
return new StripToolchainAnnotations();
59+
}
60+
61+
} // namespace wasm

src/passes/pass.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -551,6 +551,9 @@ void PassRegistry::registerPasses() {
551551
registerPass("strip-target-features",
552552
"strip the wasm target features section",
553553
createStripTargetFeaturesPass);
554+
registerPass("strip-toolchain-annotations",
555+
"strip all toolchain-specific code annotations",
556+
createStripToolchainAnnotationsPass);
554557
registerPass("translate-to-new-eh",
555558
"deprecated; same as translate-to-exnref",
556559
createTranslateToExnrefPass);

src/passes/passes.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,9 @@ Pass* createSimplifyLocalsNoNestingPass();
164164
Pass* createSimplifyLocalsNoTeePass();
165165
Pass* createSimplifyLocalsNoStructurePass();
166166
Pass* createSimplifyLocalsNoTeeNoStructurePass();
167+
Pass* createSouperifyPass();
168+
Pass* createSouperifySingleUsePass();
169+
Pass* createSpillPointersPass();
167170
Pass* createStackCheckPass();
168171
Pass* createStringGatheringPass();
169172
Pass* createStringLiftingPass();
@@ -172,12 +175,10 @@ Pass* createStringLoweringMagicImportPass();
172175
Pass* createStringLoweringMagicImportAssertPass();
173176
Pass* createStripDebugPass();
174177
Pass* createStripDWARFPass();
178+
Pass* createStripEHPass();
175179
Pass* createStripProducersPass();
176180
Pass* createStripTargetFeaturesPass();
177-
Pass* createSouperifyPass();
178-
Pass* createSouperifySingleUsePass();
179-
Pass* createSpillPointersPass();
180-
Pass* createStripEHPass();
181+
Pass* createStripToolchainAnnotationsPass();
181182
Pass* createStubUnsupportedJSOpsPass();
182183
Pass* createSSAifyPass();
183184
Pass* createSSAifyNoMergePass();

test/lit/help/wasm-metadce.test

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -522,6 +522,9 @@
522522
;; CHECK-NEXT: --strip-target-features strip the wasm target features
523523
;; CHECK-NEXT: section
524524
;; CHECK-NEXT:
525+
;; CHECK-NEXT: --strip-toolchain-annotations strip all toolchain-specific
526+
;; CHECK-NEXT: code annotations
527+
;; CHECK-NEXT:
525528
;; CHECK-NEXT: --stub-unsupported-js stub out unsupported JS
526529
;; CHECK-NEXT: operations
527530
;; CHECK-NEXT:

test/lit/help/wasm-opt.test

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -554,6 +554,9 @@
554554
;; CHECK-NEXT: --strip-target-features strip the wasm target features
555555
;; CHECK-NEXT: section
556556
;; CHECK-NEXT:
557+
;; CHECK-NEXT: --strip-toolchain-annotations strip all toolchain-specific
558+
;; CHECK-NEXT: code annotations
559+
;; CHECK-NEXT:
557560
;; CHECK-NEXT: --stub-unsupported-js stub out unsupported JS
558561
;; CHECK-NEXT: operations
559562
;; CHECK-NEXT:

test/lit/help/wasm2js.test

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -486,6 +486,9 @@
486486
;; CHECK-NEXT: --strip-target-features strip the wasm target features
487487
;; CHECK-NEXT: section
488488
;; CHECK-NEXT:
489+
;; CHECK-NEXT: --strip-toolchain-annotations strip all toolchain-specific
490+
;; CHECK-NEXT: code annotations
491+
;; CHECK-NEXT:
489492
;; CHECK-NEXT: --stub-unsupported-js stub out unsupported JS
490493
;; CHECK-NEXT: operations
491494
;; CHECK-NEXT:

test/lit/lit.cfg.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,10 @@
2525
for tool in ('not', 'foreach'):
2626
tool_file = config.binaryen_src_root + '/scripts/' + tool + '.py'
2727
python = sys.executable.replace('\\', '/')
28-
config.substitutions.append((tool, python + ' ' + tool_file))
28+
# Add spaces to avoid replacing every 'not' in the command (like in
29+
# "--strip-anNOTations"; capitalization for emphasis).
30+
config.substitutions.append((' ' + tool + ' ',
31+
' ' + python + ' ' + tool_file + ' '))
2932

3033
if 'linux' in sys.platform:
3134
config.available_features.add('linux')
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
;; RUN: wasm-opt -all --strip-toolchain-annotations %s -S -o - | filecheck %s
2+
3+
(module
4+
(@metadata.code.inline "\00")
5+
(func $test-func-a
6+
;; This VM annotation is kept.
7+
)
8+
9+
(@binaryen.removable.if.unused)
10+
(func $test-func-b
11+
;; Toolchain one is removed.
12+
)
13+
14+
(@metadata.code.inline "\00")
15+
(@binaryen.removable.if.unused)
16+
(func $test-func-c
17+
;; Toolchain one is removed, VM one is kept.
18+
)
19+
20+
(@binaryen.removable.if.unused)
21+
(@metadata.code.inline "\00")
22+
(func $test-func-d
23+
;; Reverse order of above.
24+
)
25+
)
26+
27+
;; CHECK: (module
28+
;; CHECK-NEXT: (type $0 (func))
29+
;; CHECK-NEXT: (@metadata.code.inline "\00")
30+
;; CHECK-NEXT: (func $test-func-a (type $0)
31+
;; CHECK-NEXT: )
32+
;; CHECK-NEXT: (func $test-func-b (type $0)
33+
;; CHECK-NEXT: )
34+
;; CHECK-NEXT: (@metadata.code.inline "\00")
35+
;; CHECK-NEXT: (func $test-func-c (type $0)
36+
;; CHECK-NEXT: )
37+
;; CHECK-NEXT: (@metadata.code.inline "\00")
38+
;; CHECK-NEXT: (func $test-func-d (type $0)
39+
;; CHECK-NEXT: )
40+
;; CHECK-NEXT: )
41+
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited.
2+
3+
;; RUN: wasm-opt %s -all --strip-toolchain-annotations -S -o - | filecheck %s
4+
5+
(module
6+
;; CHECK: (func $test (type $0) (param $0 i32)
7+
;; CHECK-NEXT: (@metadata.code.inline "\00")
8+
;; CHECK-NEXT: (call $test
9+
;; CHECK-NEXT: (i32.const 0)
10+
;; CHECK-NEXT: )
11+
;; CHECK-NEXT: (call $test
12+
;; CHECK-NEXT: (i32.const 1)
13+
;; CHECK-NEXT: )
14+
;; CHECK-NEXT: (@metadata.code.inline "\00")
15+
;; CHECK-NEXT: (call $test
16+
;; CHECK-NEXT: (i32.const 2)
17+
;; CHECK-NEXT: )
18+
;; CHECK-NEXT: (@metadata.code.inline "\00")
19+
;; CHECK-NEXT: (call $test
20+
;; CHECK-NEXT: (i32.const 3)
21+
;; CHECK-NEXT: )
22+
;; CHECK-NEXT: )
23+
(func $test (param i32)
24+
;; Inlining hints are not removed, as they are for the VM too.
25+
(@metadata.code.inline "\00")
26+
(call $test (i32.const 0))
27+
28+
;; Toolchain hints are removed.
29+
(@binaryen.removable.if.unused)
30+
(call $test (i32.const 1))
31+
32+
;; When both are present, remove the toolchain one, in either order.
33+
(@binaryen.removable.if.unused)
34+
(@metadata.code.inline "\00")
35+
(call $test (i32.const 2))
36+
37+
(@metadata.code.inline "\00")
38+
(@binaryen.removable.if.unused)
39+
(call $test (i32.const 3))
40+
)
41+
)

0 commit comments

Comments
 (0)