diff options
author | Brendan Dahl <brendan.dahl@gmail.com> | 2023-01-20 10:37:36 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-01-20 10:37:36 -0800 |
commit | ed3bf4f0613a66496342720d82f4100eccf39403 (patch) | |
tree | 0b779ca1a4b8f92bd9905ccb860eb7c8e1296ed2 /src/passes/JSPI.cpp | |
parent | 992584fadfdd1714aeb8ff64e7e8cd7ca3ff3326 (diff) | |
download | binaryen-ed3bf4f0613a66496342720d82f4100eccf39403.tar.gz binaryen-ed3bf4f0613a66496342720d82f4100eccf39403.tar.bz2 binaryen-ed3bf4f0613a66496342720d82f4100eccf39403.zip |
Support using JSPI to load the secondary wasm split module. (#5431)
When using JSPI with wasm-split, any calls to secondary module functions
will now first check a global to see if the module is loaded. If not
loaded it will call a JSPI'ed function that will handle loading module.
The setup is split into the JSPI pass and wasm-split tool since the JSPI
pass is first run by emscripten and we need to JSPI'ify the load secondary
module function. wasm-split then injects all the checks and calls to the
load function.
Diffstat (limited to 'src/passes/JSPI.cpp')
-rw-r--r-- | src/passes/JSPI.cpp | 39 |
1 files changed, 37 insertions, 2 deletions
diff --git a/src/passes/JSPI.cpp b/src/passes/JSPI.cpp index aa1546984..01532bb38 100644 --- a/src/passes/JSPI.cpp +++ b/src/passes/JSPI.cpp @@ -18,6 +18,7 @@ #include "ir/element-utils.h" #include "ir/import-utils.h" #include "ir/literal-utils.h" +#include "ir/module-splitting.h" #include "ir/names.h" #include "ir/utils.h" #include "pass.h" @@ -49,6 +50,12 @@ // Wrap each export in the comma-separated list. Similar to jspi-imports, // wildcards and separate files are supported. // +// --pass-arg=jspi-split-module +// +// Enables integration with wasm-split. A JSPI'ed function named +// `__load_secondary_module` will be injected that is used by wasm-split to +// load a secondary module. +// namespace wasm { @@ -87,6 +94,22 @@ struct JSPI : public Pass { options.getArgumentOrDefault("jspi-exports", ""))); String::Split listedExports(stateChangingExports, ","); + bool wasmSplit = options.hasArgument("jspi-split-module"); + if (wasmSplit) { + // Make an import for the load secondary module function so a JSPI wrapper + // version will be created. + auto import = + Builder::makeFunction(ModuleSplitting::LOAD_SECONDARY_MODULE, + Signature(Type::none, Type::none), + {}); + import->module = ENV; + import->base = ModuleSplitting::LOAD_SECONDARY_MODULE; + module->addFunction(std::move(import)); + listedImports.push_back( + ENV.toString() + "." + + ModuleSplitting::LOAD_SECONDARY_MODULE.toString()); + } + // Create a global to store the suspender that is passed into exported // functions and will then need to be passed out to the imported functions. Name suspender = Names::getValidGlobalName(*module, "suspender"); @@ -128,7 +151,7 @@ struct JSPI : public Pass { if (im->imported() && canChangeState(getFullFunctionName(im->module, im->base), listedImports)) { - makeWrapperForImport(im, module, suspender); + makeWrapperForImport(im, module, suspender, wasmSplit); } } } @@ -181,7 +204,10 @@ private: return module->addFunction(std::move(wrapperFunc))->name; } - void makeWrapperForImport(Function* im, Module* module, Name suspender) { + void makeWrapperForImport(Function* im, + Module* module, + Name suspender, + bool wasmSplit) { Builder builder(*module); auto wrapperIm = make_unique<Function>(); wrapperIm->name = Names::getValidFunctionName( @@ -234,6 +260,15 @@ private: stub->body = block; wrapperIm->type = Signature(Type(params), call->type); + if (wasmSplit && im->name == ModuleSplitting::LOAD_SECONDARY_MODULE) { + // In non-debug builds the name of the JSPI wrapper function for loading + // the secondary module will be removed. Create an export of it so that + // wasm-split can find it. + module->addExport( + builder.makeExport(ModuleSplitting::LOAD_SECONDARY_MODULE, + ModuleSplitting::LOAD_SECONDARY_MODULE, + ExternalKind::Function)); + } module->removeFunction(im->name); module->addFunction(std::move(stub)); module->addFunction(std::move(wrapperIm)); |