| /* | |
| * Copyright 2020 WebAssembly Community Group participants | |
| * | |
| * Licensed under the Apache License, Version 2.0 (the "License"); | |
| * you may not use this file except in compliance with the License. | |
| * You may obtain a copy of the License at | |
| * | |
| * http://www.apache.org/licenses/LICENSE-2.0 | |
| * | |
| * Unless required by applicable law or agreed to in writing, software | |
| * distributed under the License is distributed on an "AS IS" BASIS, | |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| * See the License for the specific language governing permissions and | |
| * limitations under the License. | |
| */ | |
| // module-splitting.h: Provides an interface for decomposing WebAssembly modules | |
| // into multiple modules that can be loaded independently. This works by moving | |
| // functions to a new secondary module and rewriting the primary module to call | |
| // them indirectly. Until the secondary module is instantiated, those indirect | |
| // calls will go to placeholder functions newly imported into the primary | |
| // module. If the primary module has a single segment with a non-constant | |
| // offset, the placeholder function import names are the offsets from that base | |
| // global of the corresponding functions in the table. Otherwise, the | |
| // placeholder import names are the absolute table indices of the corresponding | |
| // functions. The secondary module imports all of its dependencies from the | |
| // primary module. | |
| // | |
| // This code currently makes a few assumptions about the modules that will be | |
| // split and will fail assertions if those assumptions are not true. | |
| // | |
| // 1) It assumes that mutable-globals are allowed. | |
| // | |
| // 2) It assumes that either all segment offsets are constants or there is | |
| // exactly one segment that may have a non-constant offset. | |
| // | |
| // 3) It assumes that exact function references are only required for validity | |
| // if custom descriptors (and its exact function import feature) are | |
| // allowed. | |
| // | |
| // These requirements will be relaxed as necessary in the future, but for now | |
| // this code should be considered experimental and used with care. | |
| #ifndef wasm_ir_module_splitting_h | |
| #define wasm_ir_module_splitting_h | |
| #include "pass.h" | |
| #include "wasm.h" | |
| namespace wasm::ModuleSplitting { | |
| struct Config { | |
| // Pass options to use for effects analysis | |
| PassOptions passOptions; | |
| // A vector of set of functions to split into that secondary. Each function | |
| // set belongs to a single secondary module. All others are kept in the | |
| // primary module. Must not include the start function if it exists. May or | |
| // may not include imported functions, which are always kept in the primary | |
| // module regardless. | |
| std::vector<std::set<Name>> secondaryFuncs; | |
| // A vector of names of the secondary modules. | |
| std::vector<Name> secondaryNames; | |
| // Whether to import placeholder functions into the primary module that will | |
| // be called when a secondary function is called before the secondary module | |
| // has been loaded. | |
| bool usePlaceholders = true; | |
| // The namespace from which to import primary functions into the secondary | |
| // module. | |
| Name importNamespace = "primary"; | |
| // The prefix of the namespaces from which to import placeholder functions | |
| // into the primary module. Ignored if `usePlaceholders` is false. | |
| Name placeholderNamespacePrefix = "placeholder"; | |
| // The prefix to attach to the name of any newly created exports. This can be | |
| // used to differentiate between "real" exports of the module and exports that | |
| // should only be consumed by the secondary module. | |
| std::string newExportPrefix = ""; | |
| // Whether the export names of newly created exports should be minimized. If | |
| // false, the original function names will be used (after `newExportPrefix`) | |
| // as the new export names. | |
| bool minimizeNewExportNames = false; | |
| }; | |
| struct Results { | |
| std::vector<std::unique_ptr<Module>> secondaries; | |
| std::unordered_map<Name, std::map<size_t, Name>> placeholderMap; | |
| }; | |
| // Returns the new secondary module and modifies the `primary` module in place. | |
| Results splitFunctions(Module& primary, const Config& config); | |
| } // namespace wasm::ModuleSplitting | |
| #endif // wasm_ir_module_splitting_h |