diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/wasm-emscripten.h | 4 | ||||
-rw-r--r-- | src/wasm/wasm-emscripten.cpp | 66 |
2 files changed, 41 insertions, 29 deletions
diff --git a/src/wasm-emscripten.h b/src/wasm-emscripten.h index 686269a1c..b5673fbd3 100644 --- a/src/wasm-emscripten.h +++ b/src/wasm-emscripten.h @@ -62,10 +62,14 @@ private: Builder builder; Address stackPointerOffset; bool useStackPointerGlobal; + // Used by generateDynCallThunk to track all the dynCall functions created + // so far. + std::unordered_set<std::string> sigs; Global* getStackPointerGlobal(); Expression* generateLoadStackPointer(); Expression* generateStoreStackPointer(Expression* value); + void generateDynCallThunk(std::string sig); void generateStackSaveFunction(); void generateStackAllocFunction(); void generateStackRestoreFunction(); diff --git a/src/wasm/wasm-emscripten.cpp b/src/wasm/wasm-emscripten.cpp index 453780720..57dffb920 100644 --- a/src/wasm/wasm-emscripten.cpp +++ b/src/wasm/wasm-emscripten.cpp @@ -334,8 +334,36 @@ inline void exportFunction(Module& wasm, Name name, bool must_export) { wasm.addExport(exp); } +void EmscriptenGlueGenerator::generateDynCallThunk(std::string sig) { + auto* funcType = ensureFunctionType(sig, &wasm); + if (!sigs.insert(sig).second) { + return; // sig is already in the set + } + Name name = std::string("dynCall_") + sig; + if (wasm.getFunctionOrNull(name) || wasm.getExportOrNull(name)) { + return; // module already contains this dyncall + } + std::vector<NameType> params; + params.emplace_back("fptr", i32); // function pointer param + int p = 0; + for (const auto& ty : funcType->params) { + params.emplace_back(std::to_string(p++), ty); + } + Function* f = + builder.makeFunction(name, std::move(params), funcType->result, {}); + Expression* fptr = builder.makeGetLocal(0, i32); + std::vector<Expression*> args; + for (unsigned i = 0; i < funcType->params.size(); ++i) { + args.push_back(builder.makeGetLocal(i + 1, funcType->params[i])); + } + Expression* call = builder.makeCallIndirect(funcType, fptr, args); + f->body = call; + + wasm.addFunction(f); + exportFunction(wasm, f->name, true); +} + void EmscriptenGlueGenerator::generateDynCallThunks() { - std::unordered_set<std::string> sigs; Builder builder(wasm); std::vector<Name> tableSegmentData; if (wasm.table.segments.size() > 0) { @@ -343,32 +371,7 @@ void EmscriptenGlueGenerator::generateDynCallThunks() { } for (const auto& indirectFunc : tableSegmentData) { std::string sig = getSig(wasm.getFunction(indirectFunc)); - auto* funcType = ensureFunctionType(sig, &wasm); - if (!sigs.insert(sig).second) { - continue; // sig is already in the set - } - Name name = std::string("dynCall_") + sig; - if (wasm.getFunctionOrNull(name) || wasm.getExportOrNull(name)) { - continue; // module already contains this dyncall - } - std::vector<NameType> params; - params.emplace_back("fptr", i32); // function pointer param - int p = 0; - for (const auto& ty : funcType->params) { - params.emplace_back(std::to_string(p++), ty); - } - Function* f = - builder.makeFunction(name, std::move(params), funcType->result, {}); - Expression* fptr = builder.makeGetLocal(0, i32); - std::vector<Expression*> args; - for (unsigned i = 0; i < funcType->params.size(); ++i) { - args.push_back(builder.makeGetLocal(i + 1, funcType->params[i])); - } - Expression* call = builder.makeCallIndirect(funcType, fptr, args); - f->body = call; - - wasm.addFunction(f); - exportFunction(wasm, f->name, true); + generateDynCallThunk(sig); } } @@ -769,6 +772,7 @@ struct FixInvokeFunctionNamesWalker std::map<Name, Name> importRenames; std::vector<Name> toRemove; std::set<Name> newImports; + std::set<std::string> invokeSigs; FixInvokeFunctionNamesWalker(Module& _wasm) : wasm(_wasm) {} @@ -791,7 +795,7 @@ struct FixInvokeFunctionNamesWalker // This function converts the names of invoke wrappers based on their lowered // argument types and a return type. In the example above, the resulting new // wrapper name becomes "invoke_vii". - static Name fixEmExceptionInvoke(const Name& name, const std::string& sig) { + Name fixEmExceptionInvoke(const Name& name, const std::string& sig) { std::string nameStr = name.c_str(); if (nameStr.front() == '"' && nameStr.back() == '"') { nameStr = nameStr.substr(1, nameStr.size() - 2); @@ -800,10 +804,11 @@ struct FixInvokeFunctionNamesWalker return name; } std::string sigWoOrigFunc = sig.front() + sig.substr(2, sig.size() - 2); + invokeSigs.insert(sigWoOrigFunc); return Name("invoke_" + sigWoOrigFunc); } - static Name fixEmEHSjLjNames(const Name& name, const std::string& sig) { + Name fixEmEHSjLjNames(const Name& name, const std::string& sig) { if (name == "emscripten_longjmp_jmpbuf") { return "emscripten_longjmp"; } @@ -843,6 +848,9 @@ struct FixInvokeFunctionNamesWalker void EmscriptenGlueGenerator::fixInvokeFunctionNames() { FixInvokeFunctionNamesWalker walker(wasm); walker.walkModule(&wasm); + for (auto sig : walker.invokeSigs) { + generateDynCallThunk(sig); + } } template<class C> void printSet(std::ostream& o, C& c) { |