Skip to content

Commit b43807a

Browse files
authored
wasm-emscripten-finalize: Make EM_ASM modifications optional (#3044)
wasm-emscripten-finalize renames EM_ASM calls to have the signature in the name. This isn't actually useful - emscripten doesn't benefit from that. I think it was optimized in fastcomp, and in upstream we copied the general form but not the optimizations, and then EM_JS came along which is easier to optimize anyhow. This PR makes those changes optional: when not doing them, it just leaves the calls as they are. Emscripten will need some changes to handle that, but those are simple. For convenience this adds a flag to "minimize wasm changes". The idea is that this flag avoids needing a double-roll or other inconvenience as the changes need to happen in tandem on the emscripten side. The same flag can be reused for later changes similar to this one. When they are all done we can remove the flag. (Note how the code ifdefed by the flag can be removed once we no longer need the old way of doing things - that is, the new approach is simpler on the binaryen side). See #3043
1 parent 11ec7c5 commit b43807a

File tree

3 files changed

+42
-13
lines changed

3 files changed

+42
-13
lines changed

src/tools/wasm-emscripten-finalize.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ int main(int argc, const char* argv[]) {
5656
bool checkStackOverflow = false;
5757
uint64_t globalBase = INVALID_BASE;
5858
bool standaloneWasm = false;
59+
bool minimizeWasmChanges = false;
5960

6061
ToolOptions options("wasm-emscripten-finalize",
6162
"Performs Emscripten-specific transforms on .wasm files");
@@ -163,6 +164,15 @@ int main(int argc, const char* argv[]) {
163164
[&standaloneWasm](Options* o, const std::string&) {
164165
standaloneWasm = true;
165166
})
167+
.add("--minimize-wasm-changes",
168+
"",
169+
"Modify the wasm as little as possible. This is useful during "
170+
"development as we reduce the number of changes to the wasm, as it "
171+
"lets emscripten control how much modifications to do.",
172+
Options::Arguments::Zero,
173+
[&minimizeWasmChanges](Options* o, const std::string&) {
174+
minimizeWasmChanges = true;
175+
})
166176
.add_positional("INFILE",
167177
Options::Arguments::One,
168178
[&infile](Options* o, const std::string& argument) {
@@ -222,6 +232,7 @@ int main(int argc, const char* argv[]) {
222232
EmscriptenGlueGenerator generator(wasm);
223233
generator.setStandalone(standaloneWasm);
224234
generator.setSideModule(sideModule);
235+
generator.setMinimizeWasmChanges(minimizeWasmChanges);
225236

226237
generator.fixInvokeFunctionNames();
227238

src/wasm-emscripten.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ class EmscriptenGlueGenerator {
3535

3636
void setStandalone(bool standalone_) { standalone = standalone_; }
3737
void setSideModule(bool sideModule_) { sideModule = sideModule_; }
38+
void setMinimizeWasmChanges(bool minimizeWasmChanges_) {
39+
minimizeWasmChanges = minimizeWasmChanges_;
40+
}
3841

3942
Function* generateMemoryGrowthFunction();
4043
Function* generateAssignGOTEntriesFunction();
@@ -71,6 +74,7 @@ class EmscriptenGlueGenerator {
7174
bool useStackPointerGlobal;
7275
bool standalone;
7376
bool sideModule;
77+
bool minimizeWasmChanges;
7478
// Used by generateDynCallThunk to track all the dynCall functions created
7579
// so far.
7680
std::unordered_set<Signature> sigs;

src/wasm/wasm-emscripten.cpp

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,7 @@ std::string proxyingSuffix(Proxying proxy) {
320320

321321
struct AsmConstWalker : public LinearExecutionWalker<AsmConstWalker> {
322322
Module& wasm;
323+
bool minimizeWasmChanges;
323324
std::vector<Address> segmentOffsets; // segment index => address offset
324325

325326
struct AsmConst {
@@ -334,8 +335,9 @@ struct AsmConstWalker : public LinearExecutionWalker<AsmConstWalker> {
334335
// last sets in the current basic block, per index
335336
std::map<Index, LocalSet*> sets;
336337

337-
AsmConstWalker(Module& _wasm)
338-
: wasm(_wasm), segmentOffsets(getSegmentOffsets(wasm)) {}
338+
AsmConstWalker(Module& _wasm, bool minimizeWasmChanges)
339+
: wasm(_wasm), minimizeWasmChanges(minimizeWasmChanges),
340+
segmentOffsets(getSegmentOffsets(wasm)) {}
339341

340342
void noteNonLinear(Expression* curr);
341343

@@ -426,7 +428,9 @@ void AsmConstWalker::visitCall(Call* curr) {
426428
int32_t address = value->value.geti32();
427429
auto code = codeForConstAddr(wasm, segmentOffsets, address);
428430
auto& asmConst = createAsmConst(address, code, sig, importName);
429-
fixupName(curr->target, baseSig, asmConst.proxy);
431+
if (!minimizeWasmChanges) {
432+
fixupName(curr->target, baseSig, asmConst.proxy);
433+
}
430434
}
431435

432436
Proxying AsmConstWalker::proxyType(Name name) {
@@ -439,6 +443,9 @@ Proxying AsmConstWalker::proxyType(Name name) {
439443
}
440444

441445
void AsmConstWalker::visitTable(Table* curr) {
446+
if (minimizeWasmChanges) {
447+
return;
448+
}
442449
for (auto& segment : curr->segments) {
443450
for (auto& name : segment.data) {
444451
auto* func = wasm.getFunction(name);
@@ -515,24 +522,30 @@ void AsmConstWalker::addImports() {
515522
}
516523
}
517524

518-
AsmConstWalker fixEmAsmConstsAndReturnWalker(Module& wasm) {
525+
static AsmConstWalker fixEmAsmConstsAndReturnWalker(Module& wasm,
526+
bool minimizeWasmChanges) {
519527
// Collect imports to remove
520528
// This would find our generated functions if we ran it later
521529
std::vector<Name> toRemove;
522-
for (auto& import : wasm.functions) {
523-
if (import->imported() && import->base.hasSubstring(EM_ASM_PREFIX)) {
524-
toRemove.push_back(import->name);
530+
if (!minimizeWasmChanges) {
531+
for (auto& import : wasm.functions) {
532+
if (import->imported() && import->base.hasSubstring(EM_ASM_PREFIX)) {
533+
toRemove.push_back(import->name);
534+
}
525535
}
526536
}
527537

528538
// Walk the module, generate _sig versions of EM_ASM functions
529-
AsmConstWalker walker(wasm);
539+
AsmConstWalker walker(wasm, minimizeWasmChanges);
530540
walker.process();
531541

532-
// Remove the base functions that we didn't generate
533-
for (auto importName : toRemove) {
534-
wasm.removeFunction(importName);
542+
if (!minimizeWasmChanges) {
543+
// Remove the base functions that we didn't generate
544+
for (auto importName : toRemove) {
545+
wasm.removeFunction(importName);
546+
}
535547
}
548+
536549
return walker;
537550
}
538551

@@ -754,7 +767,8 @@ std::string EmscriptenGlueGenerator::generateEmscriptenMetadata(
754767
std::stringstream meta;
755768
meta << "{\n";
756769

757-
AsmConstWalker emAsmWalker = fixEmAsmConstsAndReturnWalker(wasm);
770+
AsmConstWalker emAsmWalker =
771+
fixEmAsmConstsAndReturnWalker(wasm, minimizeWasmChanges);
758772

759773
// print
760774
commaFirst = true;
@@ -810,7 +824,7 @@ std::string EmscriptenGlueGenerator::generateEmscriptenMetadata(
810824
commaFirst = true;
811825
ModuleUtils::iterImportedFunctions(wasm, [&](Function* import) {
812826
if (emJsWalker.codeByName.count(import->base.str) == 0 &&
813-
!import->base.startsWith(EM_ASM_PREFIX.str) &&
827+
(minimizeWasmChanges || !import->base.startsWith(EM_ASM_PREFIX.str)) &&
814828
!import->base.startsWith("invoke_")) {
815829
if (declares.insert(import->base.str).second) {
816830
meta << nextElement() << '"' << import->base.str << '"';

0 commit comments

Comments
 (0)