diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/s2wasm-main.cpp | 13 | ||||
-rw-r--r-- | src/s2wasm.h | 36 |
2 files changed, 34 insertions, 15 deletions
diff --git a/src/s2wasm-main.cpp b/src/s2wasm-main.cpp index d26ef3f1c..f22116978 100644 --- a/src/s2wasm-main.cpp +++ b/src/s2wasm-main.cpp @@ -29,6 +29,7 @@ using namespace wasm; int main(int argc, const char *argv[]) { bool ignoreUnknownSymbols = false; + bool generateEmscriptenGlue = false; std::string startFunction; Options options("s2wasm", "Link .s file into .wast"); options @@ -68,6 +69,11 @@ int main(int argc, const char *argv[]) { [](Options *o, const std::string &argument) { o->extra["max-memory"] = argument; }) + .add("--emscripten-glue", "-e", "Generate emscripten glue", + Options::Arguments::Zero, + [&generateEmscriptenGlue](Options *, const std::string &) { + generateEmscriptenGlue = true; + }) .add_positional("INFILE", Options::Arguments::One, [](Options *o, const std::string &argument) { o->extra["infile"] = argument; @@ -98,9 +104,12 @@ int main(int argc, const char *argv[]) { stackAllocation, initialMem, maxMem, ignoreUnknownSymbols, startFunction); - if (options.debug) std::cerr << "Emscripten gluing..." << std::endl; std::stringstream meta; - s2wasm.emscriptenGlue(meta); + if (generateEmscriptenGlue) { + if (options.debug) std::cerr << "Emscripten gluing..." << std::endl; + // dyncall thunks + s2wasm.emscriptenGlue(meta); + } if (options.debug) std::cerr << "Printing..." << std::endl; Output output(options.extra["output"], Flags::Text, options.debug ? Flags::Debug : Flags::Release); 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> { |