Skip to content

Commit 819a39f

Browse files
authored
[wasm-split] Support --placeholdermap for --multi-split (#7792)
This adds support for `--placeholdermap` for `--multi-split`. Because there can be multiple tables where placeholders are placed, this modifies the placeholder file format slightly by adding table indices for each table.
1 parent 5dae9f4 commit 819a39f

File tree

8 files changed

+115
-21
lines changed

8 files changed

+115
-21
lines changed

CHANGELOG.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,11 @@ Current Trunk
1717

1818
- `wasm-split`'s `--multi-split` mode now supports more options:
1919
`--no-placeholders`, `--import-namespace`, `--emit-module-names`,
20-
`--emit-text`, and `--symbolmap`. Because `--no-placeholders` is false by
21-
default and until now `--multi-split` didn't use placeholders at all, this is
22-
a breaking change. If you want to continue to do multi-split without
23-
placeholders, you need to explicitly specify `--no-placeholders`.
20+
`--emit-text`, `--symbolmap`, and `--placeholdermap`. Because
21+
`--no-placeholders` is false by default and until now `--multi-split` didn't
22+
use placeholders at all, this is a breaking change. If you want to continue
23+
to do multi-split without placeholders, you need to explicitly specify
24+
`--no-placeholders`.
2425
- Add a `--string-lifting` pass that raises imported string operations and
2526
constants into stringref in Binaryen IR (which can then be fully optimized,
2627
and typically lowered back down with `--string-lowering`).

src/ir/module-splitting.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -302,8 +302,9 @@ struct ModuleSplitter {
302302
// names.
303303
std::map<Name, Name> exportedPrimaryFuncs;
304304

305-
// Map placeholder indices to the names of the functions they replace.
306-
std::map<size_t, Name> placeholderMap;
305+
// For each table, map placeholder indices to the names of the functions they
306+
// replace.
307+
std::unordered_map<Name, std::map<size_t, Name>> placeholderMap;
307308

308309
// Internal name of the LOAD_SECONDARY_MODULE function.
309310
Name internalLoadSecondaryModule;
@@ -723,7 +724,7 @@ void ModuleSplitter::setupTablePatching() {
723724
}
724725
assert(table == tableManager.activeTable->name);
725726

726-
placeholderMap[index] = ref->func;
727+
placeholderMap[table][index] = ref->func;
727728
auto* secondaryFunc = secondary.getFunction(ref->func);
728729
replacedElems[index] = secondaryFunc;
729730
if (!config.usePlaceholders) {

src/ir/module-splitting.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ struct Config {
7777

7878
struct Results {
7979
std::unique_ptr<Module> secondary;
80-
std::map<size_t, Name> placeholderMap;
80+
std::unordered_map<Name, std::map<size_t, Name>> placeholderMap;
8181
};
8282

8383
// Returns the new secondary module and modifies the `primary` module in place.

src/tools/wasm-split/split-options.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ WasmSplitOptions::WasmSplitOptions()
221221
"",
222222
"Write a file mapping placeholder indices to the function names.",
223223
WasmSplitOption,
224-
{Mode::Split},
224+
{Mode::Split, Mode::MultiSplit},
225225
Options::Arguments::Zero,
226226
[&](Options* o, const std::string& argument) { placeholderMap = true; })
227227
.add("--import-namespace",

src/tools/wasm-split/wasm-split.cpp

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,11 @@
2020
#include <fstream>
2121

2222
#include "ir/module-splitting.h"
23-
#include "ir/names.h"
2423
#include "support/file.h"
2524
#include "support/name.h"
2625
#include "support/path.h"
2726
#include "support/utilities.h"
2827
#include "wasm-binary.h"
29-
#include "wasm-builder.h"
3028
#include "wasm-io.h"
3129
#include "wasm-validator.h"
3230

@@ -203,12 +201,24 @@ void writeSymbolMap(Module& wasm, std::string filename) {
203201
runner.run();
204202
}
205203

206-
void writePlaceholderMap(const std::map<size_t, Name> placeholderMap,
207-
std::string filename) {
204+
void writePlaceholderMap(
205+
Module& wasm,
206+
const std::unordered_map<Name, std::map<size_t, Name>>& placeholderMap,
207+
std::string filename) {
208208
Output output(filename, Flags::Text);
209209
auto& o = output.getStream();
210-
for (auto& [index, func] : placeholderMap) {
211-
o << index << ':' << func << '\n';
210+
for (Index i = 0; i < wasm.tables.size(); i++) {
211+
const auto& table = wasm.tables[i];
212+
auto it = placeholderMap.find(table->name);
213+
if (it != placeholderMap.end()) {
214+
o << "table " << i << "\n";
215+
for (auto& [index, func] : it->second) {
216+
o << index << ':' << func << '\n';
217+
}
218+
if (i < wasm.tables.size() - 1) {
219+
o << "\n";
220+
}
221+
}
212222
}
213223
}
214224

@@ -344,7 +354,8 @@ void splitModule(const WasmSplitOptions& options) {
344354
}
345355

346356
if (options.placeholderMap) {
347-
writePlaceholderMap(splitResults.placeholderMap,
357+
writePlaceholderMap(wasm,
358+
splitResults.placeholderMap,
348359
options.primaryOutput + ".placeholders");
349360
}
350361

@@ -422,6 +433,7 @@ void multiSplitModule(const WasmSplitOptions& options) {
422433
wasm.name = Path::getBaseName(options.output);
423434
}
424435

436+
std::unordered_map<Name, std::map<size_t, Name>> placeholderMap;
425437
for (auto& [mod, funcs] : moduleFuncs) {
426438
if (options.verbose) {
427439
std::cerr << "Splitting module " << mod << '\n';
@@ -431,12 +443,14 @@ void multiSplitModule(const WasmSplitOptions& options) {
431443
}
432444
config.secondaryFuncs = std::set<Name>(funcs.begin(), funcs.end());
433445
auto splitResults = ModuleSplitting::splitFunctions(wasm, config);
434-
// TODO: placeholderMap
435446
auto moduleName =
436447
options.outPrefix + mod + (options.emitBinary ? ".wasm" : ".wast");
437448
if (options.symbolMap) {
438449
writeSymbolMap(*splitResults.secondary, moduleName + ".symbols");
439450
}
451+
if (options.placeholderMap) {
452+
placeholderMap.merge(splitResults.placeholderMap);
453+
}
440454
if (options.emitModuleNames) {
441455
splitResults.secondary->name = Path::getBaseName(moduleName);
442456
}
@@ -445,7 +459,9 @@ void multiSplitModule(const WasmSplitOptions& options) {
445459
if (options.symbolMap) {
446460
writeSymbolMap(wasm, options.output + ".symbols");
447461
}
448-
462+
if (options.placeholderMap) {
463+
writePlaceholderMap(wasm, placeholderMap, options.output + ".placeholders");
464+
}
449465
writeModule(wasm, options.output, options);
450466
}
451467

test/lit/help/wasm-split.test

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,9 @@
7272
;; CHECK-NEXT: functions will fail before the secondary
7373
;; CHECK-NEXT: module has been instantiated.
7474
;; CHECK-NEXT:
75-
;; CHECK-NEXT: --placeholdermap [split] Write a file mapping placeholder
76-
;; CHECK-NEXT: indices to the function names.
75+
;; CHECK-NEXT: --placeholdermap [split, multi-split] Write a file mapping
76+
;; CHECK-NEXT: placeholder indices to the function
77+
;; CHECK-NEXT: names.
7778
;; CHECK-NEXT:
7879
;; CHECK-NEXT: --import-namespace [split, instrument, multi-split] When
7980
;; CHECK-NEXT: provided as an option for module
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
;; RUN: wasm-split -all --multi-split %s --manifest %S/multi-split.wast.manifest --out-prefix=%t --placeholdermap -o %t.wasm
2+
;; RUN: filecheck %s --check-prefix MAP < %t.wasm.placeholders
3+
4+
;; MAP: table 0
5+
;; MAP-NEXT: 0:A
6+
;; MAP-NEXT:
7+
;; MAP-NEXT: table 1
8+
;; MAP-NEXT: 0:B
9+
;; MAP-NEXT:
10+
;; MAP-NEXT: table 2
11+
;; MAP-NEXT: 0:C
12+
13+
(module
14+
(type $ret-i32 (func (result i32)))
15+
(type $ret-i64 (func (result i64)))
16+
(type $ret-f32 (func (result f32)))
17+
18+
(func $A (type $ret-i32) (result i32)
19+
(drop
20+
(call_ref $ret-i32
21+
(ref.func $A)
22+
)
23+
)
24+
(drop
25+
(call_ref $ret-i64
26+
(ref.func $B)
27+
)
28+
)
29+
(drop
30+
(call_ref $ret-f32
31+
(ref.func $C)
32+
)
33+
)
34+
(i32.const 0)
35+
)
36+
37+
(func $B (type $ret-i64) (result i64)
38+
(drop
39+
(call_ref $ret-i32
40+
(ref.func $A)
41+
)
42+
)
43+
(drop
44+
(call_ref $ret-i64
45+
(ref.func $B)
46+
)
47+
)
48+
(drop
49+
(call_ref $ret-f32
50+
(ref.func $C)
51+
)
52+
)
53+
(i64.const 0)
54+
)
55+
56+
(func $C (type $ret-f32) (result f32)
57+
(drop
58+
(call_ref $ret-i32
59+
(ref.func $A)
60+
)
61+
)
62+
(drop
63+
(call_ref $ret-i64
64+
(ref.func $B)
65+
)
66+
)
67+
(drop
68+
(call_ref $ret-f32
69+
(ref.func $C)
70+
)
71+
)
72+
(f32.const 0)
73+
)
74+
)

test/lit/wasm-split/placeholdermap.wast

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
;; RUN: filecheck %s --check-prefix MAP < %t.1.wasm.placeholders
33
;; RUN: wasm-dis %t.1.wasm | filecheck %s --check-prefix PRIMARY
44

5-
;; MAP: 0:foo
5+
;; MAP: table 0
6+
;; MAP-NEXT: 0:foo
67
;; MAP-NEXT: 2:baz
78
;; MAP-NOT: bar
89

0 commit comments

Comments
 (0)