11819edbaSAlex Crichton /**
21819edbaSAlex Crichton  * \file wasmtime/module.hh
31819edbaSAlex Crichton  */
41819edbaSAlex Crichton 
51819edbaSAlex Crichton #ifndef WASMTIME_MODULE_HH
61819edbaSAlex Crichton #define WASMTIME_MODULE_HH
71819edbaSAlex Crichton 
81819edbaSAlex Crichton #include <memory>
91819edbaSAlex Crichton #include <string_view>
101819edbaSAlex Crichton #include <wasmtime/engine.hh>
11311d023aSAlex Crichton #include <wasmtime/helpers.hh>
121819edbaSAlex Crichton #include <wasmtime/module.h>
131819edbaSAlex Crichton #include <wasmtime/span.hh>
141819edbaSAlex Crichton #include <wasmtime/types/export.hh>
151819edbaSAlex Crichton #include <wasmtime/types/import.hh>
161819edbaSAlex Crichton #include <wasmtime/wat.hh>
171819edbaSAlex Crichton 
181819edbaSAlex Crichton namespace wasmtime {
191819edbaSAlex Crichton 
201819edbaSAlex Crichton /**
211819edbaSAlex Crichton  * \brief Representation of a compiled WebAssembly module.
221819edbaSAlex Crichton  *
231819edbaSAlex Crichton  * This type contains JIT code of a compiled WebAssembly module. A `Module` is
241819edbaSAlex Crichton  * connected to an `Engine` and can only be instantiated within that `Engine`.
251819edbaSAlex Crichton  * You can inspect a `Module` for its type information. This is passed as an
261819edbaSAlex Crichton  * argument to other APIs to instantiate it.
271819edbaSAlex Crichton  */
281819edbaSAlex Crichton class Module {
29311d023aSAlex Crichton   WASMTIME_CLONE_WRAPPER(Module, wasmtime_module);
301819edbaSAlex Crichton 
311819edbaSAlex Crichton #ifdef WASMTIME_FEATURE_COMPILER
32*7a4f53a3SPiotr Sikora 
33*7a4f53a3SPiotr Sikora #ifdef WASMTIME_FEATURE_WAT
341819edbaSAlex Crichton   /**
351819edbaSAlex Crichton    * \brief Compiles a module from the WebAssembly text format.
361819edbaSAlex Crichton    *
371819edbaSAlex Crichton    * This function will automatically use `wat2wasm` on the input and then
381819edbaSAlex Crichton    * delegate to the #compile function.
391819edbaSAlex Crichton    */
compile(Engine & engine,std::string_view wat)401819edbaSAlex Crichton   static Result<Module> compile(Engine &engine, std::string_view wat) {
411819edbaSAlex Crichton     auto wasm = wat2wasm(wat);
421819edbaSAlex Crichton     if (!wasm) {
431819edbaSAlex Crichton       return wasm.err();
441819edbaSAlex Crichton     }
451819edbaSAlex Crichton     auto bytes = wasm.ok();
461819edbaSAlex Crichton     return compile(engine, bytes);
471819edbaSAlex Crichton   }
48*7a4f53a3SPiotr Sikora #endif // WASMTIME_FEATURE_WAT
491819edbaSAlex Crichton 
501819edbaSAlex Crichton   /**
511819edbaSAlex Crichton    * \brief Compiles a module from the WebAssembly binary format.
521819edbaSAlex Crichton    *
531819edbaSAlex Crichton    * This function compiles the provided WebAssembly binary specified by `wasm`
541819edbaSAlex Crichton    * within the compilation settings configured by `engine`. This method is
551819edbaSAlex Crichton    * synchronous and will not return until the module has finished compiling.
561819edbaSAlex Crichton    *
571819edbaSAlex Crichton    * This function can fail if the WebAssembly binary is invalid or doesn't
581819edbaSAlex Crichton    * validate (or similar).
591819edbaSAlex Crichton    */
compile(Engine & engine,Span<uint8_t> wasm)601819edbaSAlex Crichton   static Result<Module> compile(Engine &engine, Span<uint8_t> wasm) {
611819edbaSAlex Crichton     wasmtime_module_t *ret = nullptr;
621819edbaSAlex Crichton     auto *error =
63311d023aSAlex Crichton         wasmtime_module_new(engine.capi(), wasm.data(), wasm.size(), &ret);
641819edbaSAlex Crichton     if (error != nullptr) {
651819edbaSAlex Crichton       return Error(error);
661819edbaSAlex Crichton     }
671819edbaSAlex Crichton     return Module(ret);
681819edbaSAlex Crichton   }
691819edbaSAlex Crichton 
701819edbaSAlex Crichton   /**
711819edbaSAlex Crichton    * \brief Validates the provided WebAssembly binary without compiling it.
721819edbaSAlex Crichton    *
731819edbaSAlex Crichton    * This function will validate whether the provided binary is indeed valid
741819edbaSAlex Crichton    * within the compilation settings of the `engine` provided.
751819edbaSAlex Crichton    */
validate(Engine & engine,Span<uint8_t> wasm)761819edbaSAlex Crichton   static Result<std::monostate> validate(Engine &engine, Span<uint8_t> wasm) {
771819edbaSAlex Crichton     auto *error =
78311d023aSAlex Crichton         wasmtime_module_validate(engine.capi(), wasm.data(), wasm.size());
791819edbaSAlex Crichton     if (error != nullptr) {
801819edbaSAlex Crichton       return Error(error);
811819edbaSAlex Crichton     }
821819edbaSAlex Crichton     return std::monostate();
831819edbaSAlex Crichton   }
841819edbaSAlex Crichton #endif // WASMTIME_FEATURE_COMPILER
851819edbaSAlex Crichton 
861819edbaSAlex Crichton   /**
871819edbaSAlex Crichton    * \brief Deserializes a previous list of bytes created with `serialize`.
881819edbaSAlex Crichton    *
891819edbaSAlex Crichton    * This function is intended to be much faster than `compile` where it uses
901819edbaSAlex Crichton    * the artifacts of a previous compilation to quickly create an in-memory
911819edbaSAlex Crichton    * module ready for instantiation.
921819edbaSAlex Crichton    *
931819edbaSAlex Crichton    * It is not safe to pass arbitrary input to this function, it is only safe to
941819edbaSAlex Crichton    * pass in output from previous calls to `serialize`. For more information see
951819edbaSAlex Crichton    * the Rust documentation -
961819edbaSAlex Crichton    * https://docs.wasmtime.dev/api/wasmtime/struct.Module.html#method.deserialize
971819edbaSAlex Crichton    */
deserialize(Engine & engine,Span<uint8_t> wasm)981819edbaSAlex Crichton   static Result<Module> deserialize(Engine &engine, Span<uint8_t> wasm) {
991819edbaSAlex Crichton     wasmtime_module_t *ret = nullptr;
100311d023aSAlex Crichton     auto *error = wasmtime_module_deserialize(engine.capi(), wasm.data(),
1011819edbaSAlex Crichton                                               wasm.size(), &ret);
1021819edbaSAlex Crichton     if (error != nullptr) {
1031819edbaSAlex Crichton       return Error(error);
1041819edbaSAlex Crichton     }
1051819edbaSAlex Crichton     return Module(ret);
1061819edbaSAlex Crichton   }
1071819edbaSAlex Crichton 
1081819edbaSAlex Crichton   /**
1091819edbaSAlex Crichton    * \brief Deserializes a module from an on-disk file.
1101819edbaSAlex Crichton    *
1111819edbaSAlex Crichton    * This function is the same as `deserialize` except that it reads the data
1121819edbaSAlex Crichton    * for the serialized module from the path on disk. This can be faster than
1131819edbaSAlex Crichton    * the alternative which may require copying the data around.
1141819edbaSAlex Crichton    *
1151819edbaSAlex Crichton    * It is not safe to pass arbitrary input to this function, it is only safe to
1161819edbaSAlex Crichton    * pass in output from previous calls to `serialize`. For more information see
1171819edbaSAlex Crichton    * the Rust documentation -
1181819edbaSAlex Crichton    * https://docs.wasmtime.dev/api/wasmtime/struct.Module.html#method.deserialize
1191819edbaSAlex Crichton    */
deserialize_file(Engine & engine,const std::string & path)1201819edbaSAlex Crichton   static Result<Module> deserialize_file(Engine &engine,
1211819edbaSAlex Crichton                                          const std::string &path) {
1221819edbaSAlex Crichton     wasmtime_module_t *ret = nullptr;
1231819edbaSAlex Crichton     auto *error =
124311d023aSAlex Crichton         wasmtime_module_deserialize_file(engine.capi(), path.c_str(), &ret);
1251819edbaSAlex Crichton     if (error != nullptr) {
1261819edbaSAlex Crichton       return Error(error);
1271819edbaSAlex Crichton     }
1281819edbaSAlex Crichton     return Module(ret);
1291819edbaSAlex Crichton   }
1301819edbaSAlex Crichton 
1311819edbaSAlex Crichton   /// Returns the list of types imported by this module.
imports() const1321819edbaSAlex Crichton   ImportType::List imports() const {
1331819edbaSAlex Crichton     ImportType::List list;
1341819edbaSAlex Crichton     wasmtime_module_imports(ptr.get(), &list.list);
1351819edbaSAlex Crichton     return list;
1361819edbaSAlex Crichton   }
1371819edbaSAlex Crichton 
1381819edbaSAlex Crichton   /// Returns the list of types exported by this module.
exports() const1391819edbaSAlex Crichton   ExportType::List exports() const {
1401819edbaSAlex Crichton     ExportType::List list;
1411819edbaSAlex Crichton     wasmtime_module_exports(ptr.get(), &list.list);
1421819edbaSAlex Crichton     return list;
1431819edbaSAlex Crichton   }
1441819edbaSAlex Crichton 
1451819edbaSAlex Crichton #ifdef WASMTIME_FEATURE_COMPILER
1461819edbaSAlex Crichton   /**
1471819edbaSAlex Crichton    * \brief Serializes this module to a list of bytes.
1481819edbaSAlex Crichton    *
1491819edbaSAlex Crichton    * The returned bytes can then be used to later pass to `deserialize` to
1501819edbaSAlex Crichton    * quickly recreate this module in a different process perhaps.
1511819edbaSAlex Crichton    */
serialize() const1521819edbaSAlex Crichton   Result<std::vector<uint8_t>> serialize() const {
1531819edbaSAlex Crichton     wasm_byte_vec_t bytes;
1541819edbaSAlex Crichton     auto *error = wasmtime_module_serialize(ptr.get(), &bytes);
1551819edbaSAlex Crichton     if (error != nullptr) {
1561819edbaSAlex Crichton       return Error(error);
1571819edbaSAlex Crichton     }
1581819edbaSAlex Crichton     std::vector<uint8_t> ret;
1591819edbaSAlex Crichton     // NOLINTNEXTLINE TODO can this be done without triggering lints?
1601819edbaSAlex Crichton     Span<uint8_t> raw(reinterpret_cast<uint8_t *>(bytes.data), bytes.size);
1611819edbaSAlex Crichton     ret.assign(raw.begin(), raw.end());
1621819edbaSAlex Crichton     wasm_byte_vec_delete(&bytes);
1631819edbaSAlex Crichton     return ret;
1641819edbaSAlex Crichton   }
1651819edbaSAlex Crichton #endif // WASMTIME_FEATURE_COMPILER
1661819edbaSAlex Crichton };
1671819edbaSAlex Crichton 
1681819edbaSAlex Crichton } // namespace wasmtime
1691819edbaSAlex Crichton 
1701819edbaSAlex Crichton #endif // WASMTIME_MODULE_HH
171