123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194 |
- From b43807a835fc878e5eefcb8b4a18aff62d7f4540 Mon Sep 17 00:00:00 2001
- From: Alon Zakai <azakai@google.com>
- Date: Wed, 19 Aug 2020 14:55:46 -0700
- Subject: [PATCH] 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
- ---
- src/tools/wasm-emscripten-finalize.cpp | 11 +++++++
- src/wasm-emscripten.h | 4 +++
- src/wasm/wasm-emscripten.cpp | 40 +++++++++++++++++---------
- 3 files changed, 42 insertions(+), 13 deletions(-)
- diff --git a/src/tools/wasm-emscripten-finalize.cpp b/src/tools/wasm-emscripten-finalize.cpp
- index ce1da4c9e1..960c6870cf 100644
- --- a/src/tools/wasm-emscripten-finalize.cpp
- +++ b/src/tools/wasm-emscripten-finalize.cpp
- @@ -56,6 +56,7 @@ int main(int argc, const char* argv[]) {
- bool checkStackOverflow = false;
- uint64_t globalBase = INVALID_BASE;
- bool standaloneWasm = false;
- + bool minimizeWasmChanges = false;
-
- ToolOptions options("wasm-emscripten-finalize",
- "Performs Emscripten-specific transforms on .wasm files");
- @@ -163,6 +164,15 @@ int main(int argc, const char* argv[]) {
- [&standaloneWasm](Options* o, const std::string&) {
- standaloneWasm = true;
- })
- + .add("--minimize-wasm-changes",
- + "",
- + "Modify the wasm as little as possible. This is useful during "
- + "development as we reduce the number of changes to the wasm, as it "
- + "lets emscripten control how much modifications to do.",
- + Options::Arguments::Zero,
- + [&minimizeWasmChanges](Options* o, const std::string&) {
- + minimizeWasmChanges = true;
- + })
- .add_positional("INFILE",
- Options::Arguments::One,
- [&infile](Options* o, const std::string& argument) {
- @@ -222,6 +232,7 @@ int main(int argc, const char* argv[]) {
- EmscriptenGlueGenerator generator(wasm);
- generator.setStandalone(standaloneWasm);
- generator.setSideModule(sideModule);
- + generator.setMinimizeWasmChanges(minimizeWasmChanges);
-
- generator.fixInvokeFunctionNames();
-
- diff --git a/src/wasm-emscripten.h b/src/wasm-emscripten.h
- index 395c76a160..fe8b8ed36a 100644
- --- a/src/wasm-emscripten.h
- +++ b/src/wasm-emscripten.h
- @@ -35,6 +35,9 @@ class EmscriptenGlueGenerator {
-
- void setStandalone(bool standalone_) { standalone = standalone_; }
- void setSideModule(bool sideModule_) { sideModule = sideModule_; }
- + void setMinimizeWasmChanges(bool minimizeWasmChanges_) {
- + minimizeWasmChanges = minimizeWasmChanges_;
- + }
-
- Function* generateMemoryGrowthFunction();
- Function* generateAssignGOTEntriesFunction();
- @@ -71,6 +74,7 @@ class EmscriptenGlueGenerator {
- bool useStackPointerGlobal;
- bool standalone;
- bool sideModule;
- + bool minimizeWasmChanges;
- // Used by generateDynCallThunk to track all the dynCall functions created
- // so far.
- std::unordered_set<Signature> sigs;
- diff --git a/src/wasm/wasm-emscripten.cpp b/src/wasm/wasm-emscripten.cpp
- index e4664e645c..f4da0e6e7a 100644
- --- a/src/wasm/wasm-emscripten.cpp
- +++ b/src/wasm/wasm-emscripten.cpp
- @@ -320,6 +320,7 @@ std::string proxyingSuffix(Proxying proxy) {
-
- struct AsmConstWalker : public LinearExecutionWalker<AsmConstWalker> {
- Module& wasm;
- + bool minimizeWasmChanges;
- std::vector<Address> segmentOffsets; // segment index => address offset
-
- struct AsmConst {
- @@ -334,8 +335,9 @@ struct AsmConstWalker : public LinearExecutionWalker<AsmConstWalker> {
- // last sets in the current basic block, per index
- std::map<Index, LocalSet*> sets;
-
- - AsmConstWalker(Module& _wasm)
- - : wasm(_wasm), segmentOffsets(getSegmentOffsets(wasm)) {}
- + AsmConstWalker(Module& _wasm, bool minimizeWasmChanges)
- + : wasm(_wasm), minimizeWasmChanges(minimizeWasmChanges),
- + segmentOffsets(getSegmentOffsets(wasm)) {}
-
- void noteNonLinear(Expression* curr);
-
- @@ -426,7 +428,9 @@ void AsmConstWalker::visitCall(Call* curr) {
- int32_t address = value->value.geti32();
- auto code = codeForConstAddr(wasm, segmentOffsets, address);
- auto& asmConst = createAsmConst(address, code, sig, importName);
- - fixupName(curr->target, baseSig, asmConst.proxy);
- + if (!minimizeWasmChanges) {
- + fixupName(curr->target, baseSig, asmConst.proxy);
- + }
- }
-
- Proxying AsmConstWalker::proxyType(Name name) {
- @@ -439,6 +443,9 @@ Proxying AsmConstWalker::proxyType(Name name) {
- }
-
- void AsmConstWalker::visitTable(Table* curr) {
- + if (minimizeWasmChanges) {
- + return;
- + }
- for (auto& segment : curr->segments) {
- for (auto& name : segment.data) {
- auto* func = wasm.getFunction(name);
- @@ -515,24 +522,30 @@ void AsmConstWalker::addImports() {
- }
- }
-
- -AsmConstWalker fixEmAsmConstsAndReturnWalker(Module& wasm) {
- +static AsmConstWalker fixEmAsmConstsAndReturnWalker(Module& wasm,
- + bool minimizeWasmChanges) {
- // Collect imports to remove
- // This would find our generated functions if we ran it later
- std::vector<Name> toRemove;
- - for (auto& import : wasm.functions) {
- - if (import->imported() && import->base.hasSubstring(EM_ASM_PREFIX)) {
- - toRemove.push_back(import->name);
- + if (!minimizeWasmChanges) {
- + for (auto& import : wasm.functions) {
- + if (import->imported() && import->base.hasSubstring(EM_ASM_PREFIX)) {
- + toRemove.push_back(import->name);
- + }
- }
- }
-
- // Walk the module, generate _sig versions of EM_ASM functions
- - AsmConstWalker walker(wasm);
- + AsmConstWalker walker(wasm, minimizeWasmChanges);
- walker.process();
-
- - // Remove the base functions that we didn't generate
- - for (auto importName : toRemove) {
- - wasm.removeFunction(importName);
- + if (!minimizeWasmChanges) {
- + // Remove the base functions that we didn't generate
- + for (auto importName : toRemove) {
- + wasm.removeFunction(importName);
- + }
- }
- +
- return walker;
- }
-
- @@ -754,7 +767,8 @@ std::string EmscriptenGlueGenerator::generateEmscriptenMetadata(
- std::stringstream meta;
- meta << "{\n";
-
- - AsmConstWalker emAsmWalker = fixEmAsmConstsAndReturnWalker(wasm);
- + AsmConstWalker emAsmWalker =
- + fixEmAsmConstsAndReturnWalker(wasm, minimizeWasmChanges);
-
- // print
- commaFirst = true;
- @@ -810,7 +824,7 @@ std::string EmscriptenGlueGenerator::generateEmscriptenMetadata(
- commaFirst = true;
- ModuleUtils::iterImportedFunctions(wasm, [&](Function* import) {
- if (emJsWalker.codeByName.count(import->base.str) == 0 &&
- - !import->base.startsWith(EM_ASM_PREFIX.str) &&
- + (minimizeWasmChanges || !import->base.startsWith(EM_ASM_PREFIX.str)) &&
- !import->base.startsWith("invoke_")) {
- if (declares.insert(import->base.str).second) {
- meta << nextElement() << '"' << import->base.str << '"';
|