diff --git a/emsdk/binary/src/passes/FuncCastEmulation.cpp b/src/passes/FuncCastEmulation.cpp index 9d232c9..60d3990 100644 --- a/emsdk/binaryen/src/passes/FuncCastEmulation.cpp +++ b/emsdk/binaryen/src/passes/FuncCastEmulation.cpp @@ -170,20 +170,86 @@ struct FuncCastEmulation : public Pass { std::stoul(runner->options.getArgumentOrDefault("max-func-params", "16")); // we just need the one ABI function type for all indirect calls Signature ABIType(Type(std::vector(numParams, Type::i64)), Type::i64); - // Add a thunk for each function in the table, and do the call through it. + + // make sure everything in exports has a thunk + // so dlsym works std::unordered_map funcThunks; + std::unordered_map exportThunks; + for(auto& function: module->exports) + { + auto& exportName=function->name; + auto& exportValue=function->value; + // don't create FPCAST emulation for javascript legalizer stubs + // (used when javascript doesn't have 64 bit support, so + // can't use fpcast emulation calls which need 64 bit support) + if(module->getFunctionOrNull(exportValue) && strncmp(exportValue.str,"legalstub$",10)!=0 ) + { + Name exportThunkName = std::string("byn$fpcast-emu$") + exportName.str; + auto iter = funcThunks.find(exportValue); + if (iter == funcThunks.end()) + { + // an export without a thunk yet - make it and export it + auto thunk = makeThunk(exportValue, module, numParams); + funcThunks[exportValue] = thunk; + exportThunks[exportThunkName]=thunk; + }else + { + // just export existing thunk + exportThunks[exportThunkName]=iter->second; + } + } + } + int exportCount=0; + // Add a thunk for each function in the table, and do the call through it. for (auto& segment : module->table.segments) { for (auto& name : segment.data) { - auto iter = funcThunks.find(name); - if (iter == funcThunks.end()) { - auto thunk = makeThunk(name, module, numParams); - funcThunks[name] = thunk; - name = thunk; - } else { - name = iter->second; + // don't create FPCAST emulation for javascript legalizer stubs + // (used when javascript doesn't have 64 bit support, so + // can't use fpcast emulation calls which need 64 bit support) + if(strncmp(name.str,"legalstub$",10)!=0) + { + auto iter = funcThunks.find(name); + if (iter == funcThunks.end()) { + // we've already made thunks for exported funcionts so + // this is a static function - make the thunk and make an anon export + // to it so that it can be called by pyodide + Name orig_name(name); + auto thunk = makeThunk(name, module, numParams); + funcThunks[name] = thunk; + exportCount+=1; + char buffer[256]; + snprintf(buffer,256,"byn$fpcast-emu$__static_%d",exportCount); + // first make the fpcast version of the function + auto* export_ = new Export; + export_->name = buffer; + export_->value = thunk; + export_->kind = ExternalKind::Function; + module->addExport(export_); + // now make the non-fpcast version + snprintf(buffer,256,"__static_%d",exportCount); + auto* export2_ = new Export; + export2_->name = buffer; + export2_->value = orig_name; + export2_->kind = ExternalKind::Function; + module->addExport(export2_); + name = thunk; + } else { + name = iter->second; + } } } } + // make exports for all export thunks + for(auto& thunk: exportThunks) + { + auto* export_ = new Export; + export_->name = thunk.first; + export_->value = thunk.second; + export_->kind = ExternalKind::Function; + module->addExport(export_); + } + + // update call_indirects ParallelFuncCastEmulation(ABIType, numParams).run(runner, module); }