diff options
Diffstat (limited to 'src/s2wasm.h')
-rw-r--r-- | src/s2wasm.h | 36 |
1 files changed, 23 insertions, 13 deletions
diff --git a/src/s2wasm.h b/src/s2wasm.h index 2963af2fe..b78da8cfe 100644 --- a/src/s2wasm.h +++ b/src/s2wasm.h @@ -1249,20 +1249,28 @@ class S2WasmBuilder { wasm.addExport(exp); } - void getDyncallThunk(const std::string& sig) { - // hard-code the sig for testing for now. vi is the signature for static destructors - assert(sig == "vi"); - auto* targetType = ensureFunctionType(sig, &wasm, wasm.allocator); + void makeDynCallThunks() { + std::unordered_set<std::string> sigs; wasm::Builder wasmBuilder(wasm); - std::vector<NameType> params {{"$0", i32}, {"$1", i32}}; - Function* f = wasmBuilder.makeFunction(std::string("dynCall_") + sig, std::move(params), none, {}); - auto* call = wasmBuilder.makeCallIndirect( - targetType, - wasmBuilder.makeGetLocal(params[0].name, params[0].type), - {wasmBuilder.makeGetLocal(params[1].name, params[1].type)}); - auto* ret = wasmBuilder.makeReturn(call); - f->body = ret; - wasm.addFunction(f); + for (const auto& indirectFunc : wasm.table.names) { + std::string sig(getSig(wasm.getFunction(indirectFunc))); + auto* funcType = ensureFunctionType(sig, &wasm, wasm.allocator); + if (!sigs.insert(sig).second) continue; // Sig is already in the set + 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 = wasmBuilder.makeFunction(std::string("dynCall_") + sig, std::move(params), funcType->result, {}); + Expression* fptr = wasmBuilder.makeGetLocal("fptr", i32); + std::vector<Expression*> args; + for (unsigned i = 0; i < funcType->params.size(); ++i) { + args.push_back(wasmBuilder.makeGetLocal("$" + std::to_string(i), funcType->params[i])); + } + Expression* call = wasmBuilder.makeCallIndirect(funcType, fptr, std::move(args)); + f->body = funcType->result == none ? call : wasmBuilder.makeReturn(call); + wasm.addFunction(f); + exportFunction(f->name, true); + } } void fix() { @@ -1383,6 +1391,8 @@ public: wasm.removeImport(EMSCRIPTEN_ASM_CONST); // we create _sig versions + makeDynCallThunks(); + o << ";; METADATA: { "; // find asmConst calls, and emit their metadata struct AsmConstWalker : public PostWalker<AsmConstWalker> { |