1 /** 2 * \file wasmtime/module.hh 3 */ 4 5 #ifndef WASMTIME_MODULE_HH 6 #define WASMTIME_MODULE_HH 7 8 #include <memory> 9 #include <string_view> 10 #include <wasmtime/engine.hh> 11 #include <wasmtime/helpers.hh> 12 #include <wasmtime/module.h> 13 #include <wasmtime/span.hh> 14 #include <wasmtime/types/export.hh> 15 #include <wasmtime/types/import.hh> 16 #include <wasmtime/wat.hh> 17 18 namespace wasmtime { 19 20 /** 21 * \brief Representation of a compiled WebAssembly module. 22 * 23 * This type contains JIT code of a compiled WebAssembly module. A `Module` is 24 * connected to an `Engine` and can only be instantiated within that `Engine`. 25 * You can inspect a `Module` for its type information. This is passed as an 26 * argument to other APIs to instantiate it. 27 */ 28 class Module { 29 WASMTIME_CLONE_WRAPPER(Module, wasmtime_module); 30 31 #ifdef WASMTIME_FEATURE_COMPILER 32 33 #ifdef WASMTIME_FEATURE_WAT 34 /** 35 * \brief Compiles a module from the WebAssembly text format. 36 * 37 * This function will automatically use `wat2wasm` on the input and then 38 * delegate to the #compile function. 39 */ compile(Engine & engine,std::string_view wat)40 static Result<Module> compile(Engine &engine, std::string_view wat) { 41 auto wasm = wat2wasm(wat); 42 if (!wasm) { 43 return wasm.err(); 44 } 45 auto bytes = wasm.ok(); 46 return compile(engine, bytes); 47 } 48 #endif // WASMTIME_FEATURE_WAT 49 50 /** 51 * \brief Compiles a module from the WebAssembly binary format. 52 * 53 * This function compiles the provided WebAssembly binary specified by `wasm` 54 * within the compilation settings configured by `engine`. This method is 55 * synchronous and will not return until the module has finished compiling. 56 * 57 * This function can fail if the WebAssembly binary is invalid or doesn't 58 * validate (or similar). 59 */ compile(Engine & engine,Span<uint8_t> wasm)60 static Result<Module> compile(Engine &engine, Span<uint8_t> wasm) { 61 wasmtime_module_t *ret = nullptr; 62 auto *error = 63 wasmtime_module_new(engine.capi(), wasm.data(), wasm.size(), &ret); 64 if (error != nullptr) { 65 return Error(error); 66 } 67 return Module(ret); 68 } 69 70 /** 71 * \brief Validates the provided WebAssembly binary without compiling it. 72 * 73 * This function will validate whether the provided binary is indeed valid 74 * within the compilation settings of the `engine` provided. 75 */ validate(Engine & engine,Span<uint8_t> wasm)76 static Result<std::monostate> validate(Engine &engine, Span<uint8_t> wasm) { 77 auto *error = 78 wasmtime_module_validate(engine.capi(), wasm.data(), wasm.size()); 79 if (error != nullptr) { 80 return Error(error); 81 } 82 return std::monostate(); 83 } 84 #endif // WASMTIME_FEATURE_COMPILER 85 86 /** 87 * \brief Deserializes a previous list of bytes created with `serialize`. 88 * 89 * This function is intended to be much faster than `compile` where it uses 90 * the artifacts of a previous compilation to quickly create an in-memory 91 * module ready for instantiation. 92 * 93 * It is not safe to pass arbitrary input to this function, it is only safe to 94 * pass in output from previous calls to `serialize`. For more information see 95 * the Rust documentation - 96 * https://docs.wasmtime.dev/api/wasmtime/struct.Module.html#method.deserialize 97 */ deserialize(Engine & engine,Span<uint8_t> wasm)98 static Result<Module> deserialize(Engine &engine, Span<uint8_t> wasm) { 99 wasmtime_module_t *ret = nullptr; 100 auto *error = wasmtime_module_deserialize(engine.capi(), wasm.data(), 101 wasm.size(), &ret); 102 if (error != nullptr) { 103 return Error(error); 104 } 105 return Module(ret); 106 } 107 108 /** 109 * \brief Deserializes a module from an on-disk file. 110 * 111 * This function is the same as `deserialize` except that it reads the data 112 * for the serialized module from the path on disk. This can be faster than 113 * the alternative which may require copying the data around. 114 * 115 * It is not safe to pass arbitrary input to this function, it is only safe to 116 * pass in output from previous calls to `serialize`. For more information see 117 * the Rust documentation - 118 * https://docs.wasmtime.dev/api/wasmtime/struct.Module.html#method.deserialize 119 */ deserialize_file(Engine & engine,const std::string & path)120 static Result<Module> deserialize_file(Engine &engine, 121 const std::string &path) { 122 wasmtime_module_t *ret = nullptr; 123 auto *error = 124 wasmtime_module_deserialize_file(engine.capi(), path.c_str(), &ret); 125 if (error != nullptr) { 126 return Error(error); 127 } 128 return Module(ret); 129 } 130 131 /// Returns the list of types imported by this module. imports() const132 ImportType::List imports() const { 133 ImportType::List list; 134 wasmtime_module_imports(ptr.get(), &list.list); 135 return list; 136 } 137 138 /// Returns the list of types exported by this module. exports() const139 ExportType::List exports() const { 140 ExportType::List list; 141 wasmtime_module_exports(ptr.get(), &list.list); 142 return list; 143 } 144 145 #ifdef WASMTIME_FEATURE_COMPILER 146 /** 147 * \brief Serializes this module to a list of bytes. 148 * 149 * The returned bytes can then be used to later pass to `deserialize` to 150 * quickly recreate this module in a different process perhaps. 151 */ serialize() const152 Result<std::vector<uint8_t>> serialize() const { 153 wasm_byte_vec_t bytes; 154 auto *error = wasmtime_module_serialize(ptr.get(), &bytes); 155 if (error != nullptr) { 156 return Error(error); 157 } 158 std::vector<uint8_t> ret; 159 // NOLINTNEXTLINE TODO can this be done without triggering lints? 160 Span<uint8_t> raw(reinterpret_cast<uint8_t *>(bytes.data), bytes.size); 161 ret.assign(raw.begin(), raw.end()); 162 wasm_byte_vec_delete(&bytes); 163 return ret; 164 } 165 #endif // WASMTIME_FEATURE_COMPILER 166 }; 167 168 } // namespace wasmtime 169 170 #endif // WASMTIME_MODULE_HH 171