@@ -334,41 +334,44 @@ inline void exportFunction(Module& wasm, Name name, bool must_export) {
334334 wasm.addExport (exp);
335335}
336336
337+ void EmscriptenGlueGenerator::generateDynCallThunk (std::string sig) {
338+ auto * funcType = ensureFunctionType (sig, &wasm);
339+ if (!sigs.insert (sig).second ) {
340+ return ; // sig is already in the set
341+ }
342+ Name name = std::string (" dynCall_" ) + sig;
343+ if (wasm.getFunctionOrNull (name) || wasm.getExportOrNull (name)) {
344+ return ; // module already contains this dyncall
345+ }
346+ std::vector<NameType> params;
347+ params.emplace_back (" fptr" , i32 ); // function pointer param
348+ int p = 0 ;
349+ for (const auto & ty : funcType->params ) {
350+ params.emplace_back (std::to_string (p++), ty);
351+ }
352+ Function* f =
353+ builder.makeFunction (name, std::move (params), funcType->result , {});
354+ Expression* fptr = builder.makeGetLocal (0 , i32 );
355+ std::vector<Expression*> args;
356+ for (unsigned i = 0 ; i < funcType->params .size (); ++i) {
357+ args.push_back (builder.makeGetLocal (i + 1 , funcType->params [i]));
358+ }
359+ Expression* call = builder.makeCallIndirect (funcType, fptr, args);
360+ f->body = call;
361+
362+ wasm.addFunction (f);
363+ exportFunction (wasm, f->name , true );
364+ }
365+
337366void EmscriptenGlueGenerator::generateDynCallThunks () {
338- std::unordered_set<std::string> sigs;
339367 Builder builder (wasm);
340368 std::vector<Name> tableSegmentData;
341369 if (wasm.table .segments .size () > 0 ) {
342370 tableSegmentData = wasm.table .segments [0 ].data ;
343371 }
344372 for (const auto & indirectFunc : tableSegmentData) {
345373 std::string sig = getSig (wasm.getFunction (indirectFunc));
346- auto * funcType = ensureFunctionType (sig, &wasm);
347- if (!sigs.insert (sig).second ) {
348- continue ; // sig is already in the set
349- }
350- Name name = std::string (" dynCall_" ) + sig;
351- if (wasm.getFunctionOrNull (name) || wasm.getExportOrNull (name)) {
352- continue ; // module already contains this dyncall
353- }
354- std::vector<NameType> params;
355- params.emplace_back (" fptr" , i32 ); // function pointer param
356- int p = 0 ;
357- for (const auto & ty : funcType->params ) {
358- params.emplace_back (std::to_string (p++), ty);
359- }
360- Function* f =
361- builder.makeFunction (name, std::move (params), funcType->result , {});
362- Expression* fptr = builder.makeGetLocal (0 , i32 );
363- std::vector<Expression*> args;
364- for (unsigned i = 0 ; i < funcType->params .size (); ++i) {
365- args.push_back (builder.makeGetLocal (i + 1 , funcType->params [i]));
366- }
367- Expression* call = builder.makeCallIndirect (funcType, fptr, args);
368- f->body = call;
369-
370- wasm.addFunction (f);
371- exportFunction (wasm, f->name , true );
374+ generateDynCallThunk (sig);
372375 }
373376}
374377
@@ -769,6 +772,7 @@ struct FixInvokeFunctionNamesWalker
769772 std::map<Name, Name> importRenames;
770773 std::vector<Name> toRemove;
771774 std::set<Name> newImports;
775+ std::set<std::string> invokeSigs;
772776
773777 FixInvokeFunctionNamesWalker (Module& _wasm) : wasm(_wasm) {}
774778
@@ -791,7 +795,7 @@ struct FixInvokeFunctionNamesWalker
791795 // This function converts the names of invoke wrappers based on their lowered
792796 // argument types and a return type. In the example above, the resulting new
793797 // wrapper name becomes "invoke_vii".
794- static Name fixEmExceptionInvoke (const Name& name, const std::string& sig) {
798+ Name fixEmExceptionInvoke (const Name& name, const std::string& sig) {
795799 std::string nameStr = name.c_str ();
796800 if (nameStr.front () == ' "' && nameStr.back () == ' "' ) {
797801 nameStr = nameStr.substr (1 , nameStr.size () - 2 );
@@ -800,10 +804,11 @@ struct FixInvokeFunctionNamesWalker
800804 return name;
801805 }
802806 std::string sigWoOrigFunc = sig.front () + sig.substr (2 , sig.size () - 2 );
807+ invokeSigs.insert (sigWoOrigFunc);
803808 return Name (" invoke_" + sigWoOrigFunc);
804809 }
805810
806- static Name fixEmEHSjLjNames (const Name& name, const std::string& sig) {
811+ Name fixEmEHSjLjNames (const Name& name, const std::string& sig) {
807812 if (name == " emscripten_longjmp_jmpbuf" ) {
808813 return " emscripten_longjmp" ;
809814 }
@@ -843,6 +848,9 @@ struct FixInvokeFunctionNamesWalker
843848void EmscriptenGlueGenerator::fixInvokeFunctionNames () {
844849 FixInvokeFunctionNamesWalker walker (wasm);
845850 walker.walkModule (&wasm);
851+ for (auto sig : walker.invokeSigs ) {
852+ generateDynCallThunk (sig);
853+ }
846854}
847855
848856template <class C > void printSet (std::ostream& o, C& c) {
0 commit comments