diff --git a/src/ir/module-splitting.cpp b/src/ir/module-splitting.cpp index 6ae18645128..2ef7eaaf63c 100644 --- a/src/ir/module-splitting.cpp +++ b/src/ir/module-splitting.cpp @@ -353,10 +353,10 @@ struct ModuleSplitter { classifyFunctions(); moveSecondaryFunctions(); thunkExportedSecondaryFunctions(); - shareImportableItems(); indirectReferencesToSecondaryFunctions(); indirectCallsToSecondaryFunctions(); exportImportCalledPrimaryFunctions(); + shareImportableItems(); setupTablePatching(); } }; @@ -432,11 +432,11 @@ void ModuleSplitter::classifyFunctions() { configSecondaryFuncs.insert(funcs.begin(), funcs.end()); } for (auto& func : primary.functions) { + // The start function must always be kept in the primary module. if (func->imported() || !configSecondaryFuncs.contains(func->name) || - segmentReferrers.contains(func->name)) { + segmentReferrers.contains(func->name) || func->name == primary.start) { primaryFuncs.insert(func->name); } else { - assert(func->name != primary.start && "The start function must be kept"); allSecondaryFuncs.insert(func->name); } } diff --git a/src/tools/wasm-split/wasm-split.cpp b/src/tools/wasm-split/wasm-split.cpp index fd53dd18b5e..20e6243a241 100644 --- a/src/tools/wasm-split/wasm-split.cpp +++ b/src/tools/wasm-split/wasm-split.cpp @@ -296,6 +296,13 @@ void splitModule(const WasmSplitOptions& options) { } continue; } + if (function->name == wasm.start) { + if (!options.quiet) { + std::cerr << "warning: cannot split out start function " << func + << "\n"; + } + continue; + } if (!options.quiet && options.keepFuncs.contains(func)) { std::cerr << "warning: function " << func << " was to be both kept and split. It will be split.\n"; diff --git a/test/lit/wasm-split/active-table-base-global-used-elsewhere.wast b/test/lit/wasm-split/active-table-base-global-used-elsewhere.wast index 6c68499e732..04d078dbe07 100644 --- a/test/lit/wasm-split/active-table-base-global-used-elsewhere.wast +++ b/test/lit/wasm-split/active-table-base-global-used-elsewhere.wast @@ -40,7 +40,7 @@ (func $keep (call $split) ) - ;; SECONDARY: (import "primary" "table" (table $table 1 funcref)) + ;; SECONDARY: (import "primary" "table" (table $table 2 funcref)) ;; SECONDARY: (import "primary" "global" (global $base i32)) diff --git a/test/lit/wasm-split/multi-split-start.wast b/test/lit/wasm-split/multi-split-start.wast new file mode 100644 index 00000000000..a02f30383ef --- /dev/null +++ b/test/lit/wasm-split/multi-split-start.wast @@ -0,0 +1,86 @@ +;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. + +;; RUN: wasm-split -all -g --multi-split %s --manifest %s.manifest --out-prefix=%t -o %t.wasm +;; RUN: wasm-dis %t.wasm | filecheck %s --check-prefix=PRIMARY +;; RUN: wasm-dis %t1.wasm | filecheck %s --check-prefix=MOD1 +;; RUN: wasm-dis %t2.wasm | filecheck %s --check-prefix=MOD2 +;; RUN: wasm-dis %t3.wasm | filecheck %s --check-prefix=MOD3 + +;; The start function, $C, cannot be split it, and will remain in the primary. + +(module + ;; PRIMARY: (type $0 (func)) + + ;; PRIMARY: (import "placeholder.2" "0" (func $placeholder_0)) + + ;; PRIMARY: (table $0 1 funcref) + + ;; PRIMARY: (elem $0 (i32.const 0) $placeholder_0) + + ;; PRIMARY: (export "C" (func $C)) + + ;; PRIMARY: (export "table" (table $0)) + + ;; PRIMARY: (start $C) + (start $C) + + ;; MOD1: (type $0 (func)) + + ;; MOD1: (import "primary" "table" (table $timport$0 1 funcref)) + + ;; MOD1: (import "primary" "C" (func $C (exact))) + + ;; MOD1: (func $A + ;; MOD1-NEXT: (call $A) + ;; MOD1-NEXT: (call_indirect (type $0) + ;; MOD1-NEXT: (i32.const 0) + ;; MOD1-NEXT: ) + ;; MOD1-NEXT: (call $C) + ;; MOD1-NEXT: ) + (func $A + (call $A) + (call $B) + (call $C) + ) + + ;; MOD2: (type $0 (func)) + + ;; MOD2: (import "primary" "table" (table $timport$0 1 funcref)) + + ;; MOD2: (elem $0 (i32.const 0) $B) + + ;; MOD2: (func $B + ;; MOD2-NEXT: (drop + ;; MOD2-NEXT: (i32.const 42) + ;; MOD2-NEXT: ) + ;; MOD2-NEXT: ) + (func $B + (drop + (i32.const 42) + ) + ) + + ;; PRIMARY: (func $C + ;; PRIMARY-NEXT: (drop + ;; PRIMARY-NEXT: (i32.const 1337) + ;; PRIMARY-NEXT: ) + ;; PRIMARY-NEXT: ) + (func $C + (drop + (i32.const 1337) + ) + ) + + ;; MOD3: (type $0 (func)) + + ;; MOD3: (func $D + ;; MOD3-NEXT: (drop + ;; MOD3-NEXT: (i32.const 999999) + ;; MOD3-NEXT: ) + ;; MOD3-NEXT: ) + (func $D + (drop + (i32.const 999999) + ) + ) +) diff --git a/test/lit/wasm-split/multi-split-start.wast.manifest b/test/lit/wasm-split/multi-split-start.wast.manifest new file mode 100644 index 00000000000..ae2c2b78c5a --- /dev/null +++ b/test/lit/wasm-split/multi-split-start.wast.manifest @@ -0,0 +1,9 @@ +1: +A + +2: +B + +3: +C +D diff --git a/test/lit/wasm-split/split-module-items.wast b/test/lit/wasm-split/split-module-items.wast index fdca4737a28..09ac6cd8873 100644 --- a/test/lit/wasm-split/split-module-items.wast +++ b/test/lit/wasm-split/split-module-items.wast @@ -34,11 +34,11 @@ ;; PRIMARY: (tag $keep-tag (type $1) (param i32)) ;; PRIMARY-NEXT: (tag $shared-tag (type $1) (param i32)) - ;; PRIMARY: (export "memory" (memory $shared-memory)) + ;; PRIMARY: (export "keep" (func $keep)) + ;; PRIMARY-NEXT: (export "memory" (memory $shared-memory)) ;; PRIMARY-NEXT: (export "table" (table $shared-table)) ;; PRIMARY-NEXT: (export "global" (global $shared-global)) ;; PRIMARY-NEXT: (export "tag" (tag $shared-tag)) - ;; PRIMARY-NEXT: (export "keep" (func $keep)) ;; PRIMARY-NEXT: (export "table_5" (table $2)) ;; SECONDARY: (import "primary" "memory" (memory $shared-memory 1 1)) diff --git a/test/lit/wasm-split/start.wast b/test/lit/wasm-split/start.wast new file mode 100644 index 00000000000..381a1e8707a --- /dev/null +++ b/test/lit/wasm-split/start.wast @@ -0,0 +1,28 @@ +;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. + +;; RUN: wasm-split %s --split-funcs=start_func,other -o1 %t.1.wasm -o2 %t.2.wasm -g 2>&1 +;; RUN: wasm-dis -all %t.1.wasm | filecheck %s --check-prefix PRIMARY +;; RUN: wasm-dis -all %t.2.wasm | filecheck %s --check-prefix SECONDARY + +;; Do not error on trying to split out the start function. It cannot be +;; split out, keep it in the primary module. + +(module + ;; PRIMARY: (type $0 (func)) + + ;; PRIMARY: (start $start_func) + + ;; PRIMARY: (func $start_func (type $0) + ;; PRIMARY-NEXT: ) + (func $start_func) + + (start $start_func) + + ;; SECONDARY: (type $0 (func)) + + ;; SECONDARY: (func $other (type $0) + ;; SECONDARY-NEXT: ) + (func $other) +) + +