Skip to content

Commit a0981e5

Browse files
authored
RemoveExports pass (#8670)
Fixes #7976
1 parent d675fbf commit a0981e5

8 files changed

Lines changed: 143 additions & 0 deletions

File tree

src/passes/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ set(passes_SOURCES
105105
TraceCalls.cpp
106106
RandomizeBranchHints.cpp
107107
RedundantSetElimination.cpp
108+
RemoveExports.cpp
108109
RemoveImports.cpp
109110
RemoveMemoryInit.cpp
110111
RemoveNonJSOps.cpp

src/passes/RemoveExports.cpp

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
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+
// Remove exports using a wildcard. For example:
19+
//
20+
// --remove-exports=__*
21+
//
22+
// That will remove all exports with names like "__foo" and "__bar".
23+
//
24+
25+
#include "pass.h"
26+
#include "support/string.h"
27+
#include "wasm.h"
28+
29+
namespace wasm {
30+
31+
namespace {
32+
33+
struct RemoveExports : public Pass {
34+
void run(Module* module) override {
35+
std::string pattern =
36+
getArgument(name, "Usage usage: wasm-opt --" + name + "=WILDCARD");
37+
38+
std::vector<Name> toRemove;
39+
for (auto& exp : module->exports) {
40+
if (String::wildcardMatch(pattern, exp->name.toString())) {
41+
toRemove.push_back(exp->name);
42+
}
43+
}
44+
45+
for (auto& name : toRemove) {
46+
module->removeExport(name);
47+
}
48+
}
49+
};
50+
51+
} // anonymous namespace
52+
53+
Pass* createRemoveExportsPass() { return new RemoveExports(); }
54+
55+
} // namespace wasm

src/passes/pass.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,9 @@ void PassRegistry::registerPasses() {
412412
registerPass("remove-relaxed-simd",
413413
"replaces relaxed SIMD instructions with unreachable",
414414
createRemoveRelaxedSIMDPass);
415+
registerPass("remove-exports",
416+
"removes exports using a wildcard",
417+
createRemoveExportsPass);
415418
registerPass("remove-imports",
416419
"removes imports and replaces them with nops",
417420
createRemoveImportsPass);

src/passes/passes.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ Pass* createPropagateGlobalsGloballyPass();
135135
Pass* createRandomizeBranchHintsPass();
136136
Pass* createRemoveNonJSOpsPass();
137137
Pass* createRemoveRelaxedSIMDPass();
138+
Pass* createRemoveExportsPass();
138139
Pass* createRemoveImportsPass();
139140
Pass* createRemoveMemoryInitPass();
140141
Pass* createRemoveUnusedBrsPass();

test/lit/help/wasm-metadce.test

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,8 @@
383383
;; CHECK-NEXT: --propagate-globals-globally propagate global values to other
384384
;; CHECK-NEXT: globals (useful for tests)
385385
;; CHECK-NEXT:
386+
;; CHECK-NEXT: --remove-exports removes exports using a wildcard
387+
;; CHECK-NEXT:
386388
;; CHECK-NEXT: --remove-imports removes imports and replaces
387389
;; CHECK-NEXT: them with nops
388390
;; CHECK-NEXT:

test/lit/help/wasm-opt.test

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,8 @@
415415
;; CHECK-NEXT: --propagate-globals-globally propagate global values to other
416416
;; CHECK-NEXT: globals (useful for tests)
417417
;; CHECK-NEXT:
418+
;; CHECK-NEXT: --remove-exports removes exports using a wildcard
419+
;; CHECK-NEXT:
418420
;; CHECK-NEXT: --remove-imports removes imports and replaces
419421
;; CHECK-NEXT: them with nops
420422
;; CHECK-NEXT:

test/lit/help/wasm2js.test

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,8 @@
347347
;; CHECK-NEXT: --propagate-globals-globally propagate global values to other
348348
;; CHECK-NEXT: globals (useful for tests)
349349
;; CHECK-NEXT:
350+
;; CHECK-NEXT: --remove-exports removes exports using a wildcard
351+
;; CHECK-NEXT:
350352
;; CHECK-NEXT: --remove-imports removes imports and replaces
351353
;; CHECK-NEXT: them with nops
352354
;; CHECK-NEXT:
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited.
2+
;; NOTE: This test was ported using port_passes_tests_to_lit.py and could be cleaned up.
3+
4+
;; RUN: foreach %s %t wasm-opt "--remove-exports=__*" -all -S -o - | filecheck %s
5+
6+
;; foo and bar will be kept as exports, but __foo, __bar, and __ will not.
7+
(module
8+
;; CHECK: (type $0 (func))
9+
10+
;; CHECK: (export "foo" (func $foo))
11+
12+
;; CHECK: (export "bar" (func $bar))
13+
14+
;; CHECK: (func $foo (type $0)
15+
;; CHECK-NEXT: (drop
16+
;; CHECK-NEXT: (i32.const 1)
17+
;; CHECK-NEXT: )
18+
;; CHECK-NEXT: )
19+
(func $foo (export "foo")
20+
(drop (i32.const 1))
21+
)
22+
23+
;; CHECK: (func $__foo (type $0)
24+
;; CHECK-NEXT: (drop
25+
;; CHECK-NEXT: (i32.const 2)
26+
;; CHECK-NEXT: )
27+
;; CHECK-NEXT: )
28+
(func $__foo (export "__foo")
29+
(drop (i32.const 2))
30+
)
31+
32+
;; CHECK: (func $bar (type $0)
33+
;; CHECK-NEXT: (drop
34+
;; CHECK-NEXT: (i32.const 3)
35+
;; CHECK-NEXT: )
36+
;; CHECK-NEXT: )
37+
(func $bar (export "bar")
38+
(drop (i32.const 3))
39+
)
40+
41+
;; CHECK: (func $__bar (type $0)
42+
;; CHECK-NEXT: (drop
43+
;; CHECK-NEXT: (i32.const 4)
44+
;; CHECK-NEXT: )
45+
;; CHECK-NEXT: )
46+
(func $__bar (export "__bar")
47+
(drop (i32.const 4))
48+
)
49+
50+
;; CHECK: (func $__ (type $0)
51+
;; CHECK-NEXT: (drop
52+
;; CHECK-NEXT: (i32.const 4)
53+
;; CHECK-NEXT: )
54+
;; CHECK-NEXT: )
55+
(func $__ (export "__")
56+
(drop (i32.const 4))
57+
)
58+
)
59+
60+
;; Test non-function exports. The prefixed __mem and __table exports vanish.
61+
(module
62+
;; CHECK: (memory $memory 10 20)
63+
(memory $memory 10 20)
64+
65+
;; CHECK: (table $table 10 20 funcref)
66+
(table $table 10 20 funcref)
67+
68+
;; CHECK: (export "mem" (memory $memory))
69+
(export "mem" (memory $memory))
70+
71+
(export "__mem" (memory $memory))
72+
73+
;; CHECK: (export "tab" (table $table))
74+
(export "tab" (table $table))
75+
76+
(export "__tab" (table $table))
77+
)

0 commit comments

Comments
 (0)