summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Lively <7121787+tlively@users.noreply.github.com>2021-06-01 12:15:24 -0400
committerGitHub <noreply@github.com>2021-06-01 09:15:24 -0700
commit028f47368fe844130f52ad7811c8028ebd18a38e (patch)
tree7c6b2a68a55f922d70f534abd594d900079139b3
parent88606f75b97ef3014edb74484125534c2040095b (diff)
downloadbinaryen-028f47368fe844130f52ad7811c8028ebd18a38e.tar.gz
binaryen-028f47368fe844130f52ad7811c8028ebd18a38e.tar.bz2
binaryen-028f47368fe844130f52ad7811c8028ebd18a38e.zip
[wasm-split] Minimize names of newly created exports (#3905)
wasm-split would previously use internal function names to create the external names of the functions that are newly exported from the primary module to be imported into the secondary module. When the input module contains full function names (as is commonly the case when emitting symbol maps), this caused the function names to be preserved as the export names, even when names are otherwise being stripped. To save on code size and properly anonymize functions, generate minimal export names when debuginfo is disabled instead.
-rw-r--r--src/ir/module-splitting.cpp12
-rw-r--r--src/ir/module-splitting.h4
-rw-r--r--src/tools/wasm-split.cpp1
-rw-r--r--test/example/module-splitting.cpp44
-rw-r--r--test/example/module-splitting.txt72
-rw-r--r--test/lit/wasm-split/basic.wast88
-rw-r--r--test/lit/wasm-split/minimized-exports.wast38
7 files changed, 213 insertions, 46 deletions
diff --git a/src/ir/module-splitting.cpp b/src/ir/module-splitting.cpp
index 5f9ba0aad..d6dca8994 100644
--- a/src/ir/module-splitting.cpp
+++ b/src/ir/module-splitting.cpp
@@ -266,6 +266,8 @@ struct ModuleSplitter {
TableSlotManager tableManager;
+ Names::MinifiedNameGenerator minified;
+
// Map from internal function names to (one of) their corresponding export
// names.
std::map<Name, Name> exportedPrimaryFuncs;
@@ -344,8 +346,14 @@ void ModuleSplitter::exportImportFunction(Name funcName) {
if (exportIt != exportedPrimaryFuncs.end()) {
exportName = exportIt->second;
} else {
- exportName = Names::getValidExportName(
- primary, config.newExportPrefix + funcName.c_str());
+ if (config.minimizeNewExportNames) {
+ do {
+ exportName = config.newExportPrefix + minified.getName();
+ } while (primary.getExportOrNull(exportName) != nullptr);
+ } else {
+ exportName = Names::getValidExportName(
+ primary, config.newExportPrefix + funcName.c_str());
+ }
primary.addExport(
Builder::makeExport(exportName, funcName, ExternalKind::Function));
exportedPrimaryFuncs[funcName] = exportName;
diff --git a/src/ir/module-splitting.h b/src/ir/module-splitting.h
index 9a2597067..479fba148 100644
--- a/src/ir/module-splitting.h
+++ b/src/ir/module-splitting.h
@@ -62,6 +62,10 @@ struct Config {
// used to differentiate between "real" exports of the module and exports that
// should only be consumed by the secondary module.
std::string newExportPrefix = "";
+ // Whether the export names of newly created exports should be minimized. If
+ // false, the original function names will be used (after `newExportPrefix`)
+ // as the new export names.
+ bool minimizeNewExportNames = false;
};
// Returns the new secondary module and modifies the `primary` module in place.
diff --git a/src/tools/wasm-split.cpp b/src/tools/wasm-split.cpp
index 3ac8b2c45..7f3fe65c4 100644
--- a/src/tools/wasm-split.cpp
+++ b/src/tools/wasm-split.cpp
@@ -676,6 +676,7 @@ void splitModule(Module& wasm, const WasmSplitOptions& options) {
if (options.exportPrefix.size()) {
config.newExportPrefix = options.exportPrefix;
}
+ config.minimizeNewExportNames = !options.passOptions.debugInfo;
std::unique_ptr<Module> secondary =
ModuleSplitting::splitFunctions(wasm, config);
diff --git a/test/example/module-splitting.cpp b/test/example/module-splitting.cpp
index 5391fe584..2aa67d6d5 100644
--- a/test/example/module-splitting.cpp
+++ b/test/example/module-splitting.cpp
@@ -64,6 +64,8 @@ void do_test(const std::set<Name>& keptFuncs, std::string&& module) {
assert(valid && "secondary invalid!");
}
+void test_minimized_exports();
+
int main() {
// Trivial module
do_test({}, "(module)");
@@ -437,4 +439,46 @@ int main() {
(export "foo2" (func $foo))
(func $foo)
))");
+
+ test_minimized_exports();
+}
+
+void test_minimized_exports() {
+ Module primary;
+ primary.features = FeatureSet::All;
+
+ std::set<Name> keep;
+ Expression* callBody = nullptr;
+
+ Builder builder(primary);
+
+ for (size_t i = 0; i < 10; ++i) {
+ Name name = std::to_string(i);
+ primary.addFunction(Builder::makeFunction(name, {}, {}, builder.makeNop()));
+ keep.insert(name);
+ callBody =
+ builder.blockify(callBody, builder.makeCall(name, {}, Type::none));
+
+ if (i == 3) {
+ primary.addExport(
+ Builder::makeExport("already_exported", name, ExternalKind::Function));
+ }
+ if (i == 7) {
+ primary.addExport(
+ Builder::makeExport("%b", name, ExternalKind::Function));
+ }
+ }
+
+ primary.addFunction(Builder::makeFunction("call", {}, {}, callBody));
+
+ ModuleSplitting::Config config;
+ config.primaryFuncs = std::move(keep);
+ config.newExportPrefix = "%";
+ config.minimizeNewExportNames = true;
+
+ auto secondary = splitFunctions(primary, config);
+ std::cout << "Minimized names primary:\n";
+ std::cout << primary << "\n";
+ std::cout << "Minimized names secondary:\n";
+ std::cout << *secondary << "\n";
}
diff --git a/test/example/module-splitting.txt b/test/example/module-splitting.txt
index 5c3728cde..2b92e9dd6 100644
--- a/test/example/module-splitting.txt
+++ b/test/example/module-splitting.txt
@@ -1107,3 +1107,75 @@ Secondary:
)
+Minimized names primary:
+(module
+ (type $none_=>_none (func))
+ (export "already_exported" (func $3))
+ (export "%b" (func $7))
+ (export "%a" (func $0))
+ (export "%c" (func $1))
+ (export "%d" (func $2))
+ (export "%e" (func $4))
+ (export "%f" (func $5))
+ (export "%g" (func $6))
+ (export "%h" (func $8))
+ (export "%i" (func $9))
+ (func $0
+ (nop)
+ )
+ (func $1
+ (nop)
+ )
+ (func $2
+ (nop)
+ )
+ (func $3
+ (nop)
+ )
+ (func $4
+ (nop)
+ )
+ (func $5
+ (nop)
+ )
+ (func $6
+ (nop)
+ )
+ (func $7
+ (nop)
+ )
+ (func $8
+ (nop)
+ )
+ (func $9
+ (nop)
+ )
+)
+
+Minimized names secondary:
+(module
+ (type $none_=>_none (func))
+ (import "primary" "%a" (func $0))
+ (import "primary" "%c" (func $1))
+ (import "primary" "%d" (func $2))
+ (import "primary" "already_exported" (func $3))
+ (import "primary" "%e" (func $4))
+ (import "primary" "%f" (func $5))
+ (import "primary" "%g" (func $6))
+ (import "primary" "%b" (func $7))
+ (import "primary" "%h" (func $8))
+ (import "primary" "%i" (func $9))
+ (func $call
+ (call $0)
+ (call $1)
+ (call $2)
+ (call $3)
+ (call $4)
+ (call $5)
+ (call $6)
+ (call $7)
+ (call $8)
+ (call $9)
+ )
+)
+
diff --git a/test/lit/wasm-split/basic.wast b/test/lit/wasm-split/basic.wast
index 98fe433f3..7bbc14b49 100644
--- a/test/lit/wasm-split/basic.wast
+++ b/test/lit/wasm-split/basic.wast
@@ -1,19 +1,19 @@
-;; RUN: wasm-split %s --export-prefix='%' -o1 %t.none.1.wasm -o2 %t.none.2.wasm -v 2>&1 \
+;; RUN: wasm-split %s --export-prefix='%' -g -o1 %t.none.1.wasm -o2 %t.none.2.wasm -v 2>&1 \
;; RUN: | filecheck %s --check-prefix KEEP-NONE
;; RUN: wasm-dis %t.none.1.wasm | filecheck %s --check-prefix KEEP-NONE-PRIMARY
;; RUN: wasm-dis %t.none.2.wasm | filecheck %s --check-prefix KEEP-NONE-SECONDARY
-;; RUN: wasm-split %s --export-prefix='%' -o1 %t.foo.1.wasm -o2 %t.foo.2.wasm --keep-funcs=foo -v 2>&1 \
+;; RUN: wasm-split %s --export-prefix='%' -g -o1 %t.foo.1.wasm -o2 %t.foo.2.wasm --keep-funcs=foo -v 2>&1 \
;; RUN: | filecheck %s --check-prefix KEEP-FOO
;; RUN: wasm-dis %t.foo.1.wasm | filecheck %s --check-prefix KEEP-FOO-PRIMARY
;; RUN: wasm-dis %t.foo.2.wasm | filecheck %s --check-prefix KEEP-FOO-SECONDARY
-;; RUN: wasm-split %s --export-prefix='%' -o1 %t.bar.1.wasm -o2 %t.bar.2.wasm --keep-funcs=bar -v 2>&1 \
+;; RUN: wasm-split %s --export-prefix='%' -g -o1 %t.bar.1.wasm -o2 %t.bar.2.wasm --keep-funcs=bar -v 2>&1 \
;; RUN: | filecheck %s --check-prefix KEEP-BAR
;; RUN: wasm-dis %t.bar.1.wasm | filecheck %s --check-prefix KEEP-BAR-PRIMARY
;; RUN: wasm-dis %t.bar.2.wasm | filecheck %s --check-prefix KEEP-BAR-SECONDARY
-;; RUN: wasm-split %s --export-prefix='%' -o1 %t.both.1.wasm -o2 %t.both.2.wasm --keep-funcs=foo,bar -v 2>&1 \
+;; RUN: wasm-split %s --export-prefix='%' -g -o1 %t.both.1.wasm -o2 %t.both.2.wasm --keep-funcs=foo,bar -v 2>&1 \
;; RUN: | filecheck %s --check-prefix KEEP-BOTH
;; RUN: wasm-dis %t.both.1.wasm | filecheck %s --check-prefix KEEP-BOTH-PRIMARY
;; RUN: wasm-dis %t.both.2.wasm | filecheck %s --check-prefix KEEP-BOTH-SECONDARY
@@ -33,23 +33,23 @@
;; KEEP-NONE-PRIMARY: (module
;; KEEP-NONE-PRIMARY-NEXT: (type $i32_=>_i32 (func (param i32) (result i32)))
-;; KEEP-NONE-PRIMARY-NEXT: (import "placeholder" "0" (func $fimport$0 (param i32) (result i32)))
-;; KEEP-NONE-PRIMARY-NEXT: (table $0 1 1 funcref)
-;; KEEP-NONE-PRIMARY-NEXT: (elem (i32.const 0) $fimport$0)
-;; KEEP-NONE-PRIMARY-NEXT: (export "%table" (table $0))
+;; KEEP-NONE-PRIMARY-NEXT: (import "placeholder" "0" (func $placeholder_0 (param i32) (result i32)))
+;; KEEP-NONE-PRIMARY-NEXT: (table $table 1 1 funcref)
+;; KEEP-NONE-PRIMARY-NEXT: (elem (i32.const 0) $placeholder_0)
+;; KEEP-NONE-PRIMARY-NEXT: (export "%table" (table $table))
;; KEEP-NONE-PRIMARY-NEXT: )
;; KEEP-NONE-SECONDARY: (module
;; KEEP-NONE-SECONDARY-NEXT: (type $i32_=>_i32 (func (param i32) (result i32)))
-;; KEEP-NONE-SECONDARY-NEXT: (import "primary" "%table" (table $timport$0 1 1 funcref))
-;; KEEP-NONE-SECONDARY-NEXT: (elem (i32.const 0) $1)
-;; KEEP-NONE-SECONDARY-NEXT: (func $0 (param $0 i32) (result i32)
-;; KEEP-NONE-SECONDARY-NEXT: (call $1
+;; KEEP-NONE-SECONDARY-NEXT: (import "primary" "%table" (table $table 1 1 funcref))
+;; KEEP-NONE-SECONDARY-NEXT: (elem (i32.const 0) $foo)
+;; KEEP-NONE-SECONDARY-NEXT: (func $bar (param $0 i32) (result i32)
+;; KEEP-NONE-SECONDARY-NEXT: (call $foo
;; KEEP-NONE-SECONDARY-NEXT: (i32.const 1)
;; KEEP-NONE-SECONDARY-NEXT: )
;; KEEP-NONE-SECONDARY-NEXT: )
-;; KEEP-NONE-SECONDARY-NEXT: (func $1 (param $0 i32) (result i32)
-;; KEEP-NONE-SECONDARY-NEXT: (call $0
+;; KEEP-NONE-SECONDARY-NEXT: (func $foo (param $0 i32) (result i32)
+;; KEEP-NONE-SECONDARY-NEXT: (call $bar
;; KEEP-NONE-SECONDARY-NEXT: (i32.const 0)
;; KEEP-NONE-SECONDARY-NEXT: )
;; KEEP-NONE-SECONDARY-NEXT: )
@@ -60,12 +60,12 @@
;; KEEP-FOO-PRIMARY: (module
;; KEEP-FOO-PRIMARY-NEXT: (type $i32_=>_i32 (func (param i32) (result i32)))
-;; KEEP-FOO-PRIMARY-NEXT: (import "placeholder" "1" (func $fimport$0 (param i32) (result i32)))
-;; KEEP-FOO-PRIMARY-NEXT: (table $0 2 2 funcref)
-;; KEEP-FOO-PRIMARY-NEXT: (elem (i32.const 0) $0 $fimport$0)
-;; KEEP-FOO-PRIMARY-NEXT: (export "%foo" (func $0))
-;; KEEP-FOO-PRIMARY-NEXT: (export "%table" (table $0))
-;; KEEP-FOO-PRIMARY-NEXT: (func $0 (param $0 i32) (result i32)
+;; KEEP-FOO-PRIMARY-NEXT: (import "placeholder" "1" (func $placeholder_1 (param i32) (result i32)))
+;; KEEP-FOO-PRIMARY-NEXT: (table $table 2 2 funcref)
+;; KEEP-FOO-PRIMARY-NEXT: (elem (i32.const 0) $foo $placeholder_1)
+;; KEEP-FOO-PRIMARY-NEXT: (export "%foo" (func $foo))
+;; KEEP-FOO-PRIMARY-NEXT: (export "%table" (table $table))
+;; KEEP-FOO-PRIMARY-NEXT: (func $foo (param $0 i32) (result i32)
;; KEEP-FOO-PRIMARY-NEXT: (call_indirect (type $i32_=>_i32)
;; KEEP-FOO-PRIMARY-NEXT: (i32.const 0)
;; KEEP-FOO-PRIMARY-NEXT: (i32.const 1)
@@ -75,11 +75,11 @@
;; KEEP-FOO-SECONDARY: (module
;; KEEP-FOO-SECONDARY-NEXT: (type $i32_=>_i32 (func (param i32) (result i32)))
-;; KEEP-FOO-SECONDARY-NEXT: (import "primary" "%table" (table $timport$0 2 2 funcref))
-;; KEEP-FOO-SECONDARY-NEXT: (import "primary" "%foo" (func $fimport$0 (param i32) (result i32)))
-;; KEEP-FOO-SECONDARY-NEXT: (elem (i32.const 1) $0)
-;; KEEP-FOO-SECONDARY-NEXT: (func $0 (param $0 i32) (result i32)
-;; KEEP-FOO-SECONDARY-NEXT: (call $fimport$0
+;; KEEP-FOO-SECONDARY-NEXT: (import "primary" "%table" (table $table 2 2 funcref))
+;; KEEP-FOO-SECONDARY-NEXT: (import "primary" "%foo" (func $foo (param i32) (result i32)))
+;; KEEP-FOO-SECONDARY-NEXT: (elem (i32.const 1) $bar)
+;; KEEP-FOO-SECONDARY-NEXT: (func $bar (param $0 i32) (result i32)
+;; KEEP-FOO-SECONDARY-NEXT: (call $foo
;; KEEP-FOO-SECONDARY-NEXT: (i32.const 1)
;; KEEP-FOO-SECONDARY-NEXT: )
;; KEEP-FOO-SECONDARY-NEXT: )
@@ -90,12 +90,12 @@
;; KEEP-BAR-PRIMARY: (module
;; KEEP-BAR-PRIMARY-NEXT: (type $i32_=>_i32 (func (param i32) (result i32)))
-;; KEEP-BAR-PRIMARY-NEXT: (import "placeholder" "0" (func $fimport$0 (param i32) (result i32)))
-;; KEEP-BAR-PRIMARY-NEXT: (table $0 1 1 funcref)
-;; KEEP-BAR-PRIMARY-NEXT: (elem (i32.const 0) $fimport$0)
-;; KEEP-BAR-PRIMARY-NEXT: (export "%bar" (func $0))
-;; KEEP-BAR-PRIMARY-NEXT: (export "%table" (table $0))
-;; KEEP-BAR-PRIMARY-NEXT: (func $0 (param $0 i32) (result i32)
+;; KEEP-BAR-PRIMARY-NEXT: (import "placeholder" "0" (func $placeholder_0 (param i32) (result i32)))
+;; KEEP-BAR-PRIMARY-NEXT: (table $table 1 1 funcref)
+;; KEEP-BAR-PRIMARY-NEXT: (elem (i32.const 0) $placeholder_0)
+;; KEEP-BAR-PRIMARY-NEXT: (export "%bar" (func $bar))
+;; KEEP-BAR-PRIMARY-NEXT: (export "%table" (table $table))
+;; KEEP-BAR-PRIMARY-NEXT: (func $bar (param $0 i32) (result i32)
;; KEEP-BAR-PRIMARY-NEXT: (call_indirect (type $i32_=>_i32)
;; KEEP-BAR-PRIMARY-NEXT: (i32.const 1)
;; KEEP-BAR-PRIMARY-NEXT: (i32.const 0)
@@ -105,11 +105,11 @@
;; KEEP-BAR-SECONDARY: (module
;; KEEP-BAR-SECONDARY-NEXT: (type $i32_=>_i32 (func (param i32) (result i32)))
-;; KEEP-BAR-SECONDARY-NEXT: (import "primary" "%table" (table $timport$0 1 1 funcref))
-;; KEEP-BAR-SECONDARY-NEXT: (import "primary" "%bar" (func $fimport$0 (param i32) (result i32)))
-;; KEEP-BAR-SECONDARY-NEXT: (elem (i32.const 0) $0)
-;; KEEP-BAR-SECONDARY-NEXT: (func $0 (param $0 i32) (result i32)
-;; KEEP-BAR-SECONDARY-NEXT: (call $fimport$0
+;; KEEP-BAR-SECONDARY-NEXT: (import "primary" "%table" (table $table 1 1 funcref))
+;; KEEP-BAR-SECONDARY-NEXT: (import "primary" "%bar" (func $bar (param i32) (result i32)))
+;; KEEP-BAR-SECONDARY-NEXT: (elem (i32.const 0) $foo)
+;; KEEP-BAR-SECONDARY-NEXT: (func $foo (param $0 i32) (result i32)
+;; KEEP-BAR-SECONDARY-NEXT: (call $bar
;; KEEP-BAR-SECONDARY-NEXT: (i32.const 0)
;; KEEP-BAR-SECONDARY-NEXT: )
;; KEEP-BAR-SECONDARY-NEXT: )
@@ -121,21 +121,21 @@
;; KEEP-BOTH-PRIMARY: (module
;; KEEP-BOTH-PRIMARY-NEXT: (type $i32_=>_i32 (func (param i32) (result i32)))
-;; KEEP-BOTH-PRIMARY-NEXT: (table $0 1 1 funcref)
-;; KEEP-BOTH-PRIMARY-NEXT: (elem (i32.const 0) $0)
-;; KEEP-BOTH-PRIMARY-NEXT: (export "%table" (table $0))
-;; KEEP-BOTH-PRIMARY-NEXT: (func $0 (param $0 i32) (result i32)
-;; KEEP-BOTH-PRIMARY-NEXT: (call $1
+;; KEEP-BOTH-PRIMARY-NEXT: (table $table 1 1 funcref)
+;; KEEP-BOTH-PRIMARY-NEXT: (elem (i32.const 0) $foo)
+;; KEEP-BOTH-PRIMARY-NEXT: (export "%table" (table $table))
+;; KEEP-BOTH-PRIMARY-NEXT: (func $foo (param $0 i32) (result i32)
+;; KEEP-BOTH-PRIMARY-NEXT: (call $bar
;; KEEP-BOTH-PRIMARY-NEXT: (i32.const 0)
;; KEEP-BOTH-PRIMARY-NEXT: )
;; KEEP-BOTH-PRIMARY-NEXT: )
-;; KEEP-BOTH-PRIMARY-NEXT: (func $1 (param $0 i32) (result i32)
-;; KEEP-BOTH-PRIMARY-NEXT: (call $0
+;; KEEP-BOTH-PRIMARY-NEXT: (func $bar (param $0 i32) (result i32)
+;; KEEP-BOTH-PRIMARY-NEXT: (call $foo
;; KEEP-BOTH-PRIMARY-NEXT: (i32.const 1)
;; KEEP-BOTH-PRIMARY-NEXT: )
;; KEEP-BOTH-PRIMARY-NEXT: )
;; KEEP-BOTH-PRIMARY-NEXT: )
;; KEEP-BOTH-SECONDARY: (module
-;; KEEP-BOTH-SECONDARY-NEXT: (import "primary" "%table" (table $timport$0 1 1 funcref))
+;; KEEP-BOTH-SECONDARY-NEXT: (import "primary" "%table" (table $table 1 1 funcref))
;; KEEP-BOTH-SECONDARY-NEXT: )
diff --git a/test/lit/wasm-split/minimized-exports.wast b/test/lit/wasm-split/minimized-exports.wast
new file mode 100644
index 000000000..a7c225550
--- /dev/null
+++ b/test/lit/wasm-split/minimized-exports.wast
@@ -0,0 +1,38 @@
+;; RUN: wasm-split %s --keep-funcs=foo,bar --export-prefix='%' -o1 %t.1.wasm -o2 %t.2.wasm
+;; RUN: wasm-dis %t.1.wasm | filecheck %s --check-prefix PRIMARY
+;; RUN: wasm-dis %t.2.wasm | filecheck %s --check-prefix SECONDARY
+
+;; PRIMARY: (module
+;; PRIMARY-NEXT: (type $none_=>_none (func))
+;; PRIMARY-NEXT: (export "%a" (func $1))
+;; PRIMARY-NEXT: (export "%b" (func $0))
+;; PRIMARY-NEXT: (func $0
+;; PRIMARY-NEXT: (nop)
+;; PRIMARY-NEXT: )
+;; PRIMARY-NEXT: (func $1
+;; PRIMARY-NEXT: (nop)
+;; PRIMARY-NEXT: )
+;; PRIMARY-NEXT: )
+
+;; SECONDARY: (module
+;; SECONDARY-NEXT: (type $none_=>_none (func))
+;; SECONDARY-NEXT: (import "primary" "%a" (func $fimport$0))
+;; SECONDARY-NEXT: (import "primary" "%b" (func $fimport$1))
+;; SECONDARY-NEXT: (func $0
+;; SECONDARY-NEXT: (call $fimport$1)
+;; SECONDARY-NEXT: (call $fimport$0)
+;; SECONDARY-NEXT: )
+;; SECONDARY-NEXT: )
+
+(module
+ (func $foo
+ (nop)
+ )
+ (func $bar
+ (nop)
+ )
+ (func $baz
+ (call $foo)
+ (call $bar)
+ )
+)