Coverage Report

Created: 2025-07-01 06:18

/src/WasmEdge/lib/vm/vm.cpp
Line
Count
Source (jump to first uncovered line)
1
// SPDX-License-Identifier: Apache-2.0
2
// SPDX-FileCopyrightText: 2019-2024 Second State INC
3
4
#include "vm/vm.h"
5
6
#include "ast/module.h"
7
#include "common/errcode.h"
8
#include "common/types.h"
9
#include "host/wasi/wasimodule.h"
10
#include "plugin/plugin.h"
11
#include "llvm/compiler.h"
12
#include "llvm/jit.h"
13
14
#include "host/mock/wasi_crypto_module.h"
15
#include "host/mock/wasi_logging_module.h"
16
#include "host/mock/wasi_nn_module.h"
17
#include "host/mock/wasmedge_image_module.h"
18
#include "host/mock/wasmedge_process_module.h"
19
#include "host/mock/wasmedge_stablediffusion_module.h"
20
#include "host/mock/wasmedge_tensorflow_module.h"
21
#include "host/mock/wasmedge_tensorflowlite_module.h"
22
#include "validator/validator.h"
23
#include <memory>
24
#include <variant>
25
26
namespace WasmEdge {
27
namespace VM {
28
29
namespace {
30
31
template <typename T> struct VisitUnit {
32
  using MT = std::function<T(std::unique_ptr<AST::Module> &)>;
33
  using CT = std::function<T(std::unique_ptr<AST::Component::Component> &)>;
34
35
0
  VisitUnit(MT F, CT G) : VisitMod{F}, VisitComp{G} {}
Unexecuted instantiation: vm.cpp:WasmEdge::VM::(anonymous namespace)::VisitUnit<cxx20::expected<std::__1::vector<std::__1::pair<WasmEdge::Variant<unsigned int, int, unsigned long, long, float, double, unsigned __int128, __int128, unsigned long __vector(2), long __vector(2), unsigned int __vector(4), int __vector(4), unsigned short __vector(8), short __vector(8), unsigned char __vector(16), signed char __vector(16), float __vector(4), double __vector(2), WasmEdge::RefVariant>, WasmEdge::ValType>, std::__1::allocator<std::__1::pair<WasmEdge::Variant<unsigned int, int, unsigned long, long, float, double, unsigned __int128, __int128, unsigned long __vector(2), long __vector(2), unsigned int __vector(4), int __vector(4), unsigned short __vector(8), short __vector(8), unsigned char __vector(16), signed char __vector(16), float __vector(4), double __vector(2), WasmEdge::RefVariant>, WasmEdge::ValType> > >, WasmEdge::ErrCode> >::VisitUnit(std::__1::function<cxx20::expected<std::__1::vector<std::__1::pair<WasmEdge::Variant<unsigned int, int, unsigned long, long, float, double, unsigned __int128, __int128, unsigned long __vector(2), long __vector(2), unsigned int __vector(4), int __vector(4), unsigned short __vector(8), short __vector(8), unsigned char __vector(16), signed char __vector(16), float __vector(4), double __vector(2), WasmEdge::RefVariant>, WasmEdge::ValType>, std::__1::allocator<std::__1::pair<WasmEdge::Variant<unsigned int, int, unsigned long, long, float, double, unsigned __int128, __int128, unsigned long __vector(2), long __vector(2), unsigned int __vector(4), int __vector(4), unsigned short __vector(8), short __vector(8), unsigned char __vector(16), signed char __vector(16), float __vector(4), double __vector(2), WasmEdge::RefVariant>, WasmEdge::ValType> > >, WasmEdge::ErrCode> (std::__1::unique_ptr<WasmEdge::AST::Module, std::__1::default_delete<WasmEdge::AST::Module> >&)>, std::__1::function<cxx20::expected<std::__1::vector<std::__1::pair<WasmEdge::Variant<unsigned int, int, unsigned long, long, float, double, unsigned __int128, __int128, unsigned long __vector(2), long __vector(2), unsigned int __vector(4), int __vector(4), unsigned short __vector(8), short __vector(8), unsigned char __vector(16), signed char __vector(16), float __vector(4), double __vector(2), WasmEdge::RefVariant>, WasmEdge::ValType>, std::__1::allocator<std::__1::pair<WasmEdge::Variant<unsigned int, int, unsigned long, long, float, double, unsigned __int128, __int128, unsigned long __vector(2), long __vector(2), unsigned int __vector(4), int __vector(4), unsigned short __vector(8), short __vector(8), unsigned char __vector(16), signed char __vector(16), float __vector(4), double __vector(2), WasmEdge::RefVariant>, WasmEdge::ValType> > >, WasmEdge::ErrCode> (std::__1::unique_ptr<WasmEdge::AST::Component::Component, std::__1::default_delete<WasmEdge::AST::Component::Component> >&)>)
Unexecuted instantiation: vm.cpp:WasmEdge::VM::(anonymous namespace)::VisitUnit<void>::VisitUnit(std::__1::function<void (std::__1::unique_ptr<WasmEdge::AST::Module, std::__1::default_delete<WasmEdge::AST::Module> >&)>, std::__1::function<void (std::__1::unique_ptr<WasmEdge::AST::Component::Component, std::__1::default_delete<WasmEdge::AST::Component::Component> >&)>)
36
0
  T operator()(std::unique_ptr<AST::Module> &Mod) const {
37
0
    return VisitMod(Mod);
38
0
  }
Unexecuted instantiation: vm.cpp:WasmEdge::VM::(anonymous namespace)::VisitUnit<cxx20::expected<std::__1::vector<std::__1::pair<WasmEdge::Variant<unsigned int, int, unsigned long, long, float, double, unsigned __int128, __int128, unsigned long __vector(2), long __vector(2), unsigned int __vector(4), int __vector(4), unsigned short __vector(8), short __vector(8), unsigned char __vector(16), signed char __vector(16), float __vector(4), double __vector(2), WasmEdge::RefVariant>, WasmEdge::ValType>, std::__1::allocator<std::__1::pair<WasmEdge::Variant<unsigned int, int, unsigned long, long, float, double, unsigned __int128, __int128, unsigned long __vector(2), long __vector(2), unsigned int __vector(4), int __vector(4), unsigned short __vector(8), short __vector(8), unsigned char __vector(16), signed char __vector(16), float __vector(4), double __vector(2), WasmEdge::RefVariant>, WasmEdge::ValType> > >, WasmEdge::ErrCode> >::operator()(std::__1::unique_ptr<WasmEdge::AST::Module, std::__1::default_delete<WasmEdge::AST::Module> >&) const
Unexecuted instantiation: vm.cpp:WasmEdge::VM::(anonymous namespace)::VisitUnit<void>::operator()(std::__1::unique_ptr<WasmEdge::AST::Module, std::__1::default_delete<WasmEdge::AST::Module> >&) const
39
0
  T operator()(std::unique_ptr<AST::Component::Component> &Comp) const {
40
0
    return VisitComp(Comp);
41
0
  }
Unexecuted instantiation: vm.cpp:WasmEdge::VM::(anonymous namespace)::VisitUnit<cxx20::expected<std::__1::vector<std::__1::pair<WasmEdge::Variant<unsigned int, int, unsigned long, long, float, double, unsigned __int128, __int128, unsigned long __vector(2), long __vector(2), unsigned int __vector(4), int __vector(4), unsigned short __vector(8), short __vector(8), unsigned char __vector(16), signed char __vector(16), float __vector(4), double __vector(2), WasmEdge::RefVariant>, WasmEdge::ValType>, std::__1::allocator<std::__1::pair<WasmEdge::Variant<unsigned int, int, unsigned long, long, float, double, unsigned __int128, __int128, unsigned long __vector(2), long __vector(2), unsigned int __vector(4), int __vector(4), unsigned short __vector(8), short __vector(8), unsigned char __vector(16), signed char __vector(16), float __vector(4), double __vector(2), WasmEdge::RefVariant>, WasmEdge::ValType> > >, WasmEdge::ErrCode> >::operator()(std::__1::unique_ptr<WasmEdge::AST::Component::Component, std::__1::default_delete<WasmEdge::AST::Component::Component> >&) const
Unexecuted instantiation: vm.cpp:WasmEdge::VM::(anonymous namespace)::VisitUnit<void>::operator()(std::__1::unique_ptr<WasmEdge::AST::Component::Component, std::__1::default_delete<WasmEdge::AST::Component::Component> >&) const
42
43
private:
44
  MT VisitMod;
45
  CT VisitComp;
46
};
47
48
template <typename T>
49
std::unique_ptr<Runtime::Instance::ModuleInstance>
50
0
createPluginModule(std::string_view PName, std::string_view MName) {
51
0
  using namespace std::literals::string_view_literals;
52
0
  if (const auto *Plugin = Plugin::Plugin::find(PName)) {
53
0
    if (const auto *Module = Plugin->findModule(MName)) {
54
0
      return Module->create();
55
0
    }
56
0
  }
57
0
  spdlog::debug("Plugin: {} , module name: {} not found. Mock instead."sv,
58
0
                PName, MName);
59
0
  return std::make_unique<T>();
60
0
}
Unexecuted instantiation: vm.cpp:std::__1::unique_ptr<WasmEdge::Runtime::Instance::ModuleInstance, std::__1::default_delete<WasmEdge::Runtime::Instance::ModuleInstance> > WasmEdge::VM::(anonymous namespace)::createPluginModule<WasmEdge::Host::WasiNNModuleMock>(std::__1::basic_string_view<char, std::__1::char_traits<char> >, std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Unexecuted instantiation: vm.cpp:std::__1::unique_ptr<WasmEdge::Runtime::Instance::ModuleInstance, std::__1::default_delete<WasmEdge::Runtime::Instance::ModuleInstance> > WasmEdge::VM::(anonymous namespace)::createPluginModule<WasmEdge::Host::WasiCryptoCommonModuleMock>(std::__1::basic_string_view<char, std::__1::char_traits<char> >, std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Unexecuted instantiation: vm.cpp:std::__1::unique_ptr<WasmEdge::Runtime::Instance::ModuleInstance, std::__1::default_delete<WasmEdge::Runtime::Instance::ModuleInstance> > WasmEdge::VM::(anonymous namespace)::createPluginModule<WasmEdge::Host::WasiCryptoAsymmetricCommonModuleMock>(std::__1::basic_string_view<char, std::__1::char_traits<char> >, std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Unexecuted instantiation: vm.cpp:std::__1::unique_ptr<WasmEdge::Runtime::Instance::ModuleInstance, std::__1::default_delete<WasmEdge::Runtime::Instance::ModuleInstance> > WasmEdge::VM::(anonymous namespace)::createPluginModule<WasmEdge::Host::WasiCryptoKxModuleMock>(std::__1::basic_string_view<char, std::__1::char_traits<char> >, std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Unexecuted instantiation: vm.cpp:std::__1::unique_ptr<WasmEdge::Runtime::Instance::ModuleInstance, std::__1::default_delete<WasmEdge::Runtime::Instance::ModuleInstance> > WasmEdge::VM::(anonymous namespace)::createPluginModule<WasmEdge::Host::WasiCryptoSignaturesModuleMock>(std::__1::basic_string_view<char, std::__1::char_traits<char> >, std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Unexecuted instantiation: vm.cpp:std::__1::unique_ptr<WasmEdge::Runtime::Instance::ModuleInstance, std::__1::default_delete<WasmEdge::Runtime::Instance::ModuleInstance> > WasmEdge::VM::(anonymous namespace)::createPluginModule<WasmEdge::Host::WasiCryptoSymmetricModuleMock>(std::__1::basic_string_view<char, std::__1::char_traits<char> >, std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Unexecuted instantiation: vm.cpp:std::__1::unique_ptr<WasmEdge::Runtime::Instance::ModuleInstance, std::__1::default_delete<WasmEdge::Runtime::Instance::ModuleInstance> > WasmEdge::VM::(anonymous namespace)::createPluginModule<WasmEdge::Host::WasmEdgeProcessModuleMock>(std::__1::basic_string_view<char, std::__1::char_traits<char> >, std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Unexecuted instantiation: vm.cpp:std::__1::unique_ptr<WasmEdge::Runtime::Instance::ModuleInstance, std::__1::default_delete<WasmEdge::Runtime::Instance::ModuleInstance> > WasmEdge::VM::(anonymous namespace)::createPluginModule<WasmEdge::Host::WasiLoggingModuleMock>(std::__1::basic_string_view<char, std::__1::char_traits<char> >, std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Unexecuted instantiation: vm.cpp:std::__1::unique_ptr<WasmEdge::Runtime::Instance::ModuleInstance, std::__1::default_delete<WasmEdge::Runtime::Instance::ModuleInstance> > WasmEdge::VM::(anonymous namespace)::createPluginModule<WasmEdge::Host::WasmEdgeTensorflowModuleMock>(std::__1::basic_string_view<char, std::__1::char_traits<char> >, std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Unexecuted instantiation: vm.cpp:std::__1::unique_ptr<WasmEdge::Runtime::Instance::ModuleInstance, std::__1::default_delete<WasmEdge::Runtime::Instance::ModuleInstance> > WasmEdge::VM::(anonymous namespace)::createPluginModule<WasmEdge::Host::WasmEdgeTensorflowLiteModuleMock>(std::__1::basic_string_view<char, std::__1::char_traits<char> >, std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Unexecuted instantiation: vm.cpp:std::__1::unique_ptr<WasmEdge::Runtime::Instance::ModuleInstance, std::__1::default_delete<WasmEdge::Runtime::Instance::ModuleInstance> > WasmEdge::VM::(anonymous namespace)::createPluginModule<WasmEdge::Host::WasmEdgeImageModuleMock>(std::__1::basic_string_view<char, std::__1::char_traits<char> >, std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Unexecuted instantiation: vm.cpp:std::__1::unique_ptr<WasmEdge::Runtime::Instance::ModuleInstance, std::__1::default_delete<WasmEdge::Runtime::Instance::ModuleInstance> > WasmEdge::VM::(anonymous namespace)::createPluginModule<WasmEdge::Host::WasmEdgeStableDiffusionModuleMock>(std::__1::basic_string_view<char, std::__1::char_traits<char> >, std::__1::basic_string_view<char, std::__1::char_traits<char> >)
61
} // namespace
62
63
VM::VM(const Configure &Conf)
64
0
    : Conf(Conf), Stage(VMStage::Inited),
65
0
      LoaderEngine(Conf, &Executor::Executor::Intrinsics),
66
0
      ValidatorEngine(Conf), ExecutorEngine(Conf, &Stat),
67
0
      Store(std::make_unique<Runtime::StoreManager>()), StoreRef(*Store.get()) {
68
0
  unsafeInitVM();
69
0
}
70
71
VM::VM(const Configure &Conf, Runtime::StoreManager &S)
72
0
    : Conf(Conf), Stage(VMStage::Inited),
73
0
      LoaderEngine(Conf, &Executor::Executor::Intrinsics),
74
0
      ValidatorEngine(Conf), ExecutorEngine(Conf, &Stat), StoreRef(S) {
75
0
  unsafeInitVM();
76
0
}
77
78
0
void VM::unsafeInitVM() {
79
  // Load the built-in modules and the plug-ins.
80
0
  unsafeLoadBuiltInHosts();
81
0
  unsafeLoadPlugInHosts();
82
83
  // Register all module instances.
84
0
  unsafeRegisterBuiltInHosts();
85
0
  unsafeRegisterPlugInHosts();
86
0
}
87
88
0
void VM::unsafeLoadBuiltInHosts() {
89
  // Load the built-in host modules from configuration.
90
  // TODO: This will be extended for the versionlized WASI in the future.
91
0
  BuiltInModInsts.clear();
92
0
  if (Conf.hasHostRegistration(HostRegistration::Wasi)) {
93
0
    std::unique_ptr<Runtime::Instance::ModuleInstance> WasiMod =
94
0
        std::make_unique<Host::WasiModule>();
95
0
    BuiltInModInsts.insert({HostRegistration::Wasi, std::move(WasiMod)});
96
0
  }
97
0
}
98
99
0
void VM::unsafeLoadPlugInHosts() {
100
  // Load the plugins and mock them if not found.
101
0
  using namespace std::literals::string_view_literals;
102
0
  PlugInModInsts.clear();
103
104
0
  PlugInModInsts.push_back(
105
0
      createPluginModule<Host::WasiNNModuleMock>("wasi_nn"sv, "wasi_nn"sv));
106
0
  PlugInModInsts.push_back(createPluginModule<Host::WasiCryptoCommonModuleMock>(
107
0
      "wasi_crypto"sv, "wasi_crypto_common"sv));
108
0
  PlugInModInsts.push_back(
109
0
      createPluginModule<Host::WasiCryptoAsymmetricCommonModuleMock>(
110
0
          "wasi_crypto"sv, "wasi_crypto_asymmetric_common"sv));
111
0
  PlugInModInsts.push_back(createPluginModule<Host::WasiCryptoKxModuleMock>(
112
0
      "wasi_crypto"sv, "wasi_crypto_kx"sv));
113
0
  PlugInModInsts.push_back(
114
0
      createPluginModule<Host::WasiCryptoSignaturesModuleMock>(
115
0
          "wasi_crypto"sv, "wasi_crypto_signatures"sv));
116
0
  PlugInModInsts.push_back(
117
0
      createPluginModule<Host::WasiCryptoSymmetricModuleMock>(
118
0
          "wasi_crypto"sv, "wasi_crypto_symmetric"sv));
119
0
  PlugInModInsts.push_back(createPluginModule<Host::WasmEdgeProcessModuleMock>(
120
0
      "wasmedge_process"sv, "wasmedge_process"sv));
121
0
  PlugInModInsts.push_back(createPluginModule<Host::WasiLoggingModuleMock>(
122
0
      "wasi_logging"sv, "wasi:logging/logging"sv));
123
0
  PlugInModInsts.push_back(
124
0
      createPluginModule<Host::WasmEdgeTensorflowModuleMock>(
125
0
          "wasmedge_tensorflow"sv, "wasmedge_tensorflow"sv));
126
0
  PlugInModInsts.push_back(
127
0
      createPluginModule<Host::WasmEdgeTensorflowLiteModuleMock>(
128
0
          "wasmedge_tensorflowlite"sv, "wasmedge_tensorflowlite"sv));
129
0
  PlugInModInsts.push_back(createPluginModule<Host::WasmEdgeImageModuleMock>(
130
0
      "wasmedge_image"sv, "wasmedge_image"sv));
131
0
  PlugInModInsts.push_back(
132
0
      createPluginModule<Host::WasmEdgeStableDiffusionModuleMock>(
133
0
          "wasmedge_stablediffusion"sv, "wasmedge_stablediffusion"sv));
134
135
  // Load the other non-official plugins.
136
0
  for (const auto &Plugin : Plugin::Plugin::plugins()) {
137
0
    if (Conf.isForbiddenPlugins(Plugin.name())) {
138
0
      continue;
139
0
    }
140
    // Skip wasi_crypto, wasi_nn, wasi_logging, WasmEdge_Process,
141
    // WasmEdge_Tensorflow, WasmEdge_TensorflowLite, and WasmEdge_Image.
142
0
    if (Plugin.name() == "wasi_crypto"sv || Plugin.name() == "wasi_nn"sv ||
143
0
        Plugin.name() == "wasi_logging"sv ||
144
0
        Plugin.name() == "wasmedge_process"sv ||
145
0
        Plugin.name() == "wasmedge_tensorflow"sv ||
146
0
        Plugin.name() == "wasmedge_tensorflowlite"sv ||
147
0
        Plugin.name() == "wasmedge_image"sv ||
148
0
        Plugin.name() == "wasmedge_stablediffusion"sv) {
149
0
      continue;
150
0
    }
151
0
    for (const auto &Module : Plugin.modules()) {
152
0
      PlugInModInsts.push_back(Module.create());
153
0
    }
154
0
    for (const auto &Component : Plugin.components()) {
155
0
      PlugInCompInsts.push_back(Component.create());
156
0
    }
157
0
  }
158
0
}
159
160
0
void VM::unsafeRegisterBuiltInHosts() {
161
  // Register all created WASI host modules.
162
0
  for (auto &It : BuiltInModInsts) {
163
0
    ExecutorEngine.registerModule(StoreRef, *(It.second.get()));
164
0
  }
165
0
}
166
167
0
void VM::unsafeRegisterPlugInHosts() {
168
  // Register all created module instances from plugins.
169
0
  for (auto &It : PlugInModInsts) {
170
0
    ExecutorEngine.registerModule(StoreRef, *(It.get()));
171
0
  }
172
0
  for (auto &It : PlugInCompInsts) {
173
0
    ExecutorEngine.registerComponent(StoreRef, *(It.get()));
174
0
  }
175
0
}
176
177
Expect<void> VM::unsafeRegisterModule(std::string_view Name,
178
0
                                      const std::filesystem::path &Path) {
179
0
  if (Stage == VMStage::Instantiated) {
180
    // When registering module, instantiated module in store will be reset.
181
    // Therefore the instantiation should restart.
182
0
    Stage = VMStage::Validated;
183
0
  }
184
  // Load module.
185
0
  EXPECTED_TRY(auto Module, LoaderEngine.parseModule(Path));
186
0
  return unsafeRegisterModule(Name, *Module.get());
187
0
}
188
189
Expect<void> VM::unsafeRegisterModule(std::string_view Name,
190
0
                                      Span<const Byte> Code) {
191
0
  if (Stage == VMStage::Instantiated) {
192
    // When registering module, instantiated module in store will be reset.
193
    // Therefore the instantiation should restart.
194
0
    Stage = VMStage::Validated;
195
0
  }
196
  // Load module.
197
0
  EXPECTED_TRY(auto Module, LoaderEngine.parseModule(Code));
198
0
  return unsafeRegisterModule(Name, *Module.get());
199
0
}
200
201
Expect<void> VM::unsafeRegisterModule(std::string_view Name,
202
0
                                      const AST::Module &Module) {
203
0
  if (Stage == VMStage::Instantiated) {
204
    // When registering module, instantiated module in store will be reset.
205
    // Therefore the instantiation should restart.
206
0
    Stage = VMStage::Validated;
207
0
  }
208
  // Validate module.
209
0
  EXPECTED_TRY(ValidatorEngine.validate(Module));
210
  // Instantiate and register module.
211
0
  EXPECTED_TRY(auto ModInst,
212
0
               ExecutorEngine.registerModule(StoreRef, Module, Name));
213
0
  RegModInsts.push_back(std::move(ModInst));
214
0
  return {};
215
0
}
216
217
Expect<void>
218
0
VM::unsafeRegisterModule(const Runtime::Instance::ModuleInstance &ModInst) {
219
0
  if (Stage == VMStage::Instantiated) {
220
    // When registering module, instantiated module in store will be reset.
221
    // Therefore the instantiation should restart.
222
0
    Stage = VMStage::Validated;
223
0
  }
224
0
  return ExecutorEngine.registerModule(StoreRef, ModInst);
225
0
}
226
227
Expect<std::vector<std::pair<ValVariant, ValType>>>
228
VM::unsafeRunWasmFile(const std::filesystem::path &Path, std::string_view Func,
229
                      Span<const ValVariant> Params,
230
0
                      Span<const ValType> ParamTypes) {
231
0
  if (Stage == VMStage::Instantiated) {
232
    // When running another module, instantiated module in store will be reset.
233
    // Therefore the instantiation should restart.
234
0
    Stage = VMStage::Validated;
235
0
  }
236
  // Load wasm unit.
237
0
  EXPECTED_TRY(auto ComponentOrModule, LoaderEngine.parseWasmUnit(Path));
238
0
  return std::visit(
239
0
      VisitUnit<Expect<std::vector<std::pair<ValVariant, ValType>>>>(
240
0
          [&](auto &M) -> Expect<std::vector<std::pair<ValVariant, ValType>>> {
241
0
            Mod = std::move(M);
242
0
            return unsafeRunWasmFile(*Mod, Func, Params, ParamTypes);
243
0
          },
244
0
          [&](auto &C) -> Expect<std::vector<std::pair<ValVariant, ValType>>> {
245
0
            Comp = std::move(C);
246
0
            return unsafeRunWasmFile(*Comp, Func, Params, ParamTypes);
247
0
          }),
248
0
      ComponentOrModule);
249
0
}
250
251
Expect<std::vector<std::pair<ValVariant, ValType>>>
252
VM::unsafeRunWasmFile(Span<const Byte> Code, std::string_view Func,
253
                      Span<const ValVariant> Params,
254
0
                      Span<const ValType> ParamTypes) {
255
0
  if (Stage == VMStage::Instantiated) {
256
    // When running another module, instantiated module in store will be reset.
257
    // Therefore the instantiation should restart.
258
0
    Stage = VMStage::Validated;
259
0
  }
260
  // Load wasm unit.
261
0
  EXPECTED_TRY(auto ComponentOrModule, LoaderEngine.parseWasmUnit(Code));
262
0
  return std::visit(
263
0
      VisitUnit<Expect<std::vector<std::pair<ValVariant, ValType>>>>(
264
0
          [&](auto &M) -> Expect<std::vector<std::pair<ValVariant, ValType>>> {
265
0
            Mod = std::move(M);
266
0
            return unsafeRunWasmFile(*Mod, Func, Params, ParamTypes);
267
0
          },
268
0
          [&](auto &C) -> Expect<std::vector<std::pair<ValVariant, ValType>>> {
269
0
            Comp = std::move(C);
270
0
            return unsafeRunWasmFile(*Comp, Func, Params, ParamTypes);
271
0
          }),
272
0
      ComponentOrModule);
273
0
}
274
275
Expect<std::vector<std::pair<ValVariant, ValType>>>
276
VM::unsafeRunWasmFile(const AST::Component::Component &Component,
277
                      std::string_view, Span<const ValVariant>,
278
0
                      Span<const ValType>) {
279
0
  if (Stage == VMStage::Instantiated) {
280
    // When running another module, instantiated module in store will be reset.
281
    // Therefore the instantiation should restart.
282
0
    Stage = VMStage::Validated;
283
0
  }
284
0
  EXPECTED_TRY(ValidatorEngine.validate(Component));
285
0
  spdlog::error("component execution is not done yet."sv);
286
0
  return Unexpect(ErrCode::Value::RuntimeError);
287
0
}
288
289
Expect<std::vector<std::pair<ValVariant, ValType>>>
290
VM::unsafeRunWasmFile(const AST::Module &Module, std::string_view Func,
291
                      Span<const ValVariant> Params,
292
0
                      Span<const ValType> ParamTypes) {
293
0
  if (Stage == VMStage::Instantiated) {
294
    // When running another module, instantiated module in store will be reset.
295
    // Therefore the instantiation should restart.
296
0
    Stage = VMStage::Validated;
297
0
  }
298
0
  EXPECTED_TRY(ValidatorEngine.validate(Module));
299
0
  EXPECTED_TRY(ActiveModInst,
300
0
               ExecutorEngine.instantiateModule(StoreRef, Module));
301
302
  // Get module instance.
303
0
  if (ActiveModInst) {
304
    // Execute function and return values with the module instance.
305
0
    return unsafeExecute(ActiveModInst.get(), Func, Params, ParamTypes);
306
0
  }
307
0
  spdlog::error(ErrCode::Value::WrongInstanceAddress);
308
0
  spdlog::error(ErrInfo::InfoExecuting(""sv, Func));
309
0
  return Unexpect(ErrCode::Value::WrongInstanceAddress);
310
0
}
311
312
Expect<std::vector<std::pair<ValInterface, ValType>>>
313
VM::unsafeExecute(const Runtime::Instance::ComponentInstance *CompInst,
314
                  std::string_view Func, Span<const ValInterface> Params,
315
0
                  Span<const ValType> ParamTypes) {
316
  // Find exported function by name.
317
0
  Runtime::Instance::Component::FunctionInstance *FuncInst =
318
0
      CompInst->findFuncExports(Func);
319
320
  // Execute function.
321
0
  return ExecutorEngine.invoke(FuncInst, Params, ParamTypes)
322
0
      .map_error([&CompInst, &Func](auto E) {
323
0
        if (E != ErrCode::Value::Terminated) {
324
0
          spdlog::error(
325
0
              ErrInfo::InfoExecuting(CompInst->getComponentName(), Func));
326
0
        }
327
0
        return E;
328
0
      });
329
0
}
330
331
Async<Expect<std::vector<std::pair<ValVariant, ValType>>>>
332
VM::asyncRunWasmFile(const std::filesystem::path &Path, std::string_view Func,
333
                     Span<const ValVariant> Params,
334
0
                     Span<const ValType> ParamTypes) {
335
0
  Expect<std::vector<std::pair<ValVariant, ValType>>> (VM::*FPtr)(
336
0
      const std::filesystem::path &, std::string_view, Span<const ValVariant>,
337
0
      Span<const ValType>) = &VM::runWasmFile;
338
0
  return {FPtr,
339
0
          *this,
340
0
          std::filesystem::path(Path),
341
0
          std::string(Func),
342
0
          std::vector(Params.begin(), Params.end()),
343
0
          std::vector(ParamTypes.begin(), ParamTypes.end())};
344
0
}
345
346
Async<Expect<std::vector<std::pair<ValVariant, ValType>>>>
347
VM::asyncRunWasmFile(Span<const Byte> Code, std::string_view Func,
348
                     Span<const ValVariant> Params,
349
0
                     Span<const ValType> ParamTypes) {
350
0
  Expect<std::vector<std::pair<ValVariant, ValType>>> (VM::*FPtr)(
351
0
      Span<const Byte>, std::string_view, Span<const ValVariant>,
352
0
      Span<const ValType>) = &VM::runWasmFile;
353
0
  return {FPtr,
354
0
          *this,
355
0
          Code,
356
0
          std::string(Func),
357
0
          std::vector(Params.begin(), Params.end()),
358
0
          std::vector(ParamTypes.begin(), ParamTypes.end())};
359
0
}
360
361
Async<Expect<std::vector<std::pair<ValVariant, ValType>>>>
362
VM::asyncRunWasmFile(const AST::Module &Module, std::string_view Func,
363
                     Span<const ValVariant> Params,
364
0
                     Span<const ValType> ParamTypes) {
365
0
  Expect<std::vector<std::pair<ValVariant, ValType>>> (VM::*FPtr)(
366
0
      const AST::Module &, std::string_view, Span<const ValVariant>,
367
0
      Span<const ValType>) = &VM::runWasmFile;
368
0
  return {FPtr,
369
0
          *this,
370
0
          Module,
371
0
          std::string(Func),
372
0
          std::vector(Params.begin(), Params.end()),
373
0
          std::vector(ParamTypes.begin(), ParamTypes.end())};
374
0
}
375
376
0
Expect<void> VM::unsafeLoadWasm(const std::filesystem::path &Path) {
377
  // If not load successfully, the previous status will be reserved.
378
0
  EXPECTED_TRY(auto ComponentOrModule, LoaderEngine.parseWasmUnit(Path));
379
380
0
  std::visit(VisitUnit<void>([&](auto &M) -> void { Mod = std::move(M); },
381
0
                             [&](auto &C) -> void { Comp = std::move(C); }),
382
0
             ComponentOrModule);
383
0
  Stage = VMStage::Loaded;
384
0
  return {};
385
0
}
386
387
0
Expect<void> VM::unsafeLoadWasm(Span<const Byte> Code) {
388
  // If not load successfully, the previous status will be reserved.
389
0
  EXPECTED_TRY(auto ComponentOrModule, LoaderEngine.parseWasmUnit(Code));
390
391
0
  std::visit(VisitUnit<void>([&](auto &M) -> void { Mod = std::move(M); },
392
0
                             [&](auto &C) -> void { Comp = std::move(C); }),
393
0
             ComponentOrModule);
394
0
  Stage = VMStage::Loaded;
395
0
  return {};
396
0
}
397
398
0
Expect<void> VM::unsafeLoadWasm(const AST::Module &Module) {
399
0
  Mod = std::make_unique<AST::Module>(Module);
400
0
  Stage = VMStage::Loaded;
401
0
  return {};
402
0
}
403
404
struct Validate {
405
  // borrow validator to pass control to it
406
0
  Validate(Validator::Validator &Engine) : ValidatorEngine(Engine) {}
407
0
  Expect<void> operator()(const std::unique_ptr<AST::Module> &Mod) const {
408
0
    return ValidatorEngine.validate(*Mod.get());
409
0
  }
410
  Expect<void>
411
0
  operator()(const std::unique_ptr<AST::Component::Component> &Comp) const {
412
0
    return ValidatorEngine.validate(*Comp.get());
413
0
  }
414
415
private:
416
  Validator::Validator &ValidatorEngine;
417
};
418
419
0
Expect<void> VM::unsafeValidate() {
420
0
  if (Stage < VMStage::Loaded) {
421
    // When module is not loaded, not validate.
422
0
    spdlog::error(ErrCode::Value::WrongVMWorkflow);
423
0
    return Unexpect(ErrCode::Value::WrongVMWorkflow);
424
0
  }
425
426
0
  if (Mod) {
427
0
    EXPECTED_TRY(ValidatorEngine.validate(*Mod.get()));
428
0
  } else if (Comp) {
429
0
    EXPECTED_TRY(ValidatorEngine.validate(*Comp.get()));
430
0
  } else {
431
0
    spdlog::error(ErrCode::Value::WrongVMWorkflow);
432
0
    return Unexpect(ErrCode::Value::WrongVMWorkflow);
433
0
  }
434
0
  Stage = VMStage::Validated;
435
0
  return {};
436
0
}
437
438
0
Expect<void> VM::unsafeInstantiate() {
439
0
  if (Stage < VMStage::Validated) {
440
    // When module is not validated, not instantiate.
441
0
    spdlog::error(ErrCode::Value::WrongVMWorkflow);
442
0
    return Unexpect(ErrCode::Value::WrongVMWorkflow);
443
0
  }
444
445
0
  if (Mod) {
446
0
    if (Conf.getRuntimeConfigure().isEnableJIT() && !Mod->getSymbol()) {
447
0
#ifdef WASMEDGE_USE_LLVM
448
0
      LLVM::Compiler Compiler(Conf);
449
0
      Compiler.checkConfigure()
450
0
          .map_error([](uint32_t Err) {
451
0
            if (Err != ErrCode::Value::Success) {
452
0
              spdlog::error("Compiler Configure failed. Error code: {}, use "
453
0
                            "interpreter mode instead."sv,
454
0
                            Err);
455
0
            }
456
0
            return ErrCode::Value::Success;
457
0
          })
458
0
          .and_then([&]() { return Compiler.compile(*Mod); })
459
0
          .map_error([](uint32_t Err) {
460
0
            if (Err != ErrCode::Value::Success) {
461
0
              spdlog::error("Compilation failed. Error code: {}, use "
462
0
                            "interpreter mode instead."sv,
463
0
                            Err);
464
0
            }
465
0
            return ErrCode::Value::Success;
466
0
          })
467
0
          .and_then([&](auto LLModule) {
468
0
            LLVM::JIT JIT(Conf);
469
0
            return JIT.load(std::move(LLModule));
470
0
          })
471
0
          .map_error([](uint32_t Err) {
472
0
            if (Err != ErrCode::Value::Success) {
473
0
              spdlog::warn(
474
0
                  "JIT failed. Error code: {}, use interpreter mode instead."sv,
475
0
                  Err);
476
0
            }
477
0
            return ErrCode::Value::Success;
478
0
          })
479
0
          .and_then([&](auto Module) {
480
0
            return LoaderEngine.loadExecutable(*Mod, std::move(Module));
481
0
          })
482
0
          .map_error([](uint32_t Err) {
483
0
            if (Err != ErrCode::Value::Success) {
484
0
              spdlog::warn("Loader failed. Error code: {}, use interpreter "
485
0
                           "mode instead."sv,
486
0
                           Err);
487
0
            }
488
0
            return ErrCode::Value::Success;
489
0
          });
490
#else
491
      spdlog::error("LLVM disabled, JIT is unsupported!"sv);
492
#endif
493
0
    }
494
495
0
    EXPECTED_TRY(ActiveModInst,
496
0
                 ExecutorEngine.instantiateModule(StoreRef, *Mod));
497
0
    Stage = VMStage::Instantiated;
498
0
    return {};
499
0
  } else if (Comp) {
500
0
    EXPECTED_TRY(ActiveCompInst,
501
0
                 ExecutorEngine.instantiateComponent(StoreRef, *Comp));
502
0
    Stage = VMStage::Instantiated;
503
0
    return {};
504
0
  } else {
505
0
    spdlog::error(ErrCode::Value::WrongVMWorkflow);
506
0
    return Unexpect(ErrCode::Value::WrongVMWorkflow);
507
0
  }
508
0
}
509
510
Expect<std::vector<std::pair<ValVariant, ValType>>>
511
VM::unsafeExecute(std::string_view Func, Span<const ValVariant> Params,
512
0
                  Span<const ValType> ParamTypes) {
513
0
  if (unlikely(!ActiveModInst)) {
514
0
    spdlog::error(ErrCode::Value::WrongInstanceAddress);
515
0
    spdlog::error(ErrInfo::InfoExecuting("When invoking"sv, Func));
516
0
    return Unexpect(ErrCode::Value::WrongInstanceAddress);
517
0
  }
518
  // Execute function and return values with the module instance.
519
0
  return unsafeExecute(ActiveModInst.get(), Func, Params, ParamTypes);
520
0
}
521
522
Expect<std::vector<std::pair<ValInterface, ValType>>>
523
VM::unsafeExecute(std::string_view Func, Span<const ValInterface> Params,
524
0
                  Span<const ValType> ParamTypes) {
525
0
  if (unlikely(!ActiveCompInst)) {
526
0
    spdlog::error(ErrCode::Value::WrongInstanceAddress);
527
0
    spdlog::error(ErrInfo::InfoExecuting("When invoking"sv, Func));
528
0
    return Unexpect(ErrCode::Value::WrongInstanceAddress);
529
0
  }
530
0
  return unsafeExecute(ActiveCompInst.get(), Func, Params, ParamTypes);
531
0
}
532
533
Expect<std::vector<std::pair<ValInterface, ValType>>>
534
VM::unsafeExecute(std::string_view CompName, std::string_view Func,
535
                  Span<const ValInterface> Params,
536
0
                  Span<const ValType> ParamTypes) {
537
  // Find module instance by name.
538
0
  const auto *FindCompInst = StoreRef.findComponent(CompName);
539
0
  if (unlikely(!FindCompInst)) {
540
0
    spdlog::error(ErrCode::Value::WrongInstanceAddress);
541
0
    spdlog::error(ErrInfo::InfoExecuting(CompName, Func));
542
0
    return Unexpect(ErrCode::Value::WrongInstanceAddress);
543
0
  }
544
  // Execute function and return values with the component instance.
545
0
  return unsafeExecute(FindCompInst, Func, Params, ParamTypes);
546
0
}
547
548
Expect<std::vector<std::pair<ValVariant, ValType>>>
549
VM::unsafeExecute(std::string_view ModName, std::string_view Func,
550
                  Span<const ValVariant> Params,
551
0
                  Span<const ValType> ParamTypes) {
552
  // Find module instance by name.
553
0
  const auto *FindModInst = StoreRef.findModule(ModName);
554
0
  if (unlikely(!FindModInst)) {
555
0
    spdlog::error(ErrCode::Value::WrongInstanceAddress);
556
0
    spdlog::error(ErrInfo::InfoExecuting(ModName, Func));
557
0
    return Unexpect(ErrCode::Value::WrongInstanceAddress);
558
0
  }
559
  // Execute function and return values with the module instance.
560
0
  return unsafeExecute(FindModInst, Func, Params, ParamTypes);
561
0
}
562
563
Expect<std::vector<std::pair<ValVariant, ValType>>>
564
VM::unsafeExecute(const Runtime::Instance::ModuleInstance *ModInst,
565
                  std::string_view Func, Span<const ValVariant> Params,
566
0
                  Span<const ValType> ParamTypes) {
567
  // Find exported function by name.
568
0
  Runtime::Instance::FunctionInstance *FuncInst =
569
0
      ModInst->findFuncExports(Func);
570
571
  // Execute function.
572
0
  return ExecutorEngine.invoke(FuncInst, Params, ParamTypes)
573
0
      .map_error([&ModInst, &Func](auto E) {
574
0
        if (E != ErrCode::Value::Terminated) {
575
0
          spdlog::error(ErrInfo::InfoExecuting(ModInst->getModuleName(), Func));
576
0
        }
577
0
        return E;
578
0
      });
579
0
}
580
581
Async<Expect<std::vector<std::pair<ValVariant, ValType>>>>
582
VM::asyncExecute(std::string_view Func, Span<const ValVariant> Params,
583
0
                 Span<const ValType> ParamTypes) {
584
0
  Expect<std::vector<std::pair<ValVariant, ValType>>> (VM::*FPtr)(
585
0
      std::string_view, Span<const ValVariant>, Span<const ValType>) =
586
0
      &VM::execute;
587
0
  return {FPtr, *this, std::string(Func),
588
0
          std::vector(Params.begin(), Params.end()),
589
0
          std::vector(ParamTypes.begin(), ParamTypes.end())};
590
0
}
591
592
Async<Expect<std::vector<std::pair<ValVariant, ValType>>>>
593
VM::asyncExecute(std::string_view ModName, std::string_view Func,
594
                 Span<const ValVariant> Params,
595
0
                 Span<const ValType> ParamTypes) {
596
0
  Expect<std::vector<std::pair<ValVariant, ValType>>> (VM::*FPtr)(
597
0
      std::string_view, std::string_view, Span<const ValVariant>,
598
0
      Span<const ValType>) = &VM::execute;
599
0
  return {FPtr,
600
0
          *this,
601
0
          std::string(ModName),
602
0
          std::string(Func),
603
0
          std::vector(Params.begin(), Params.end()),
604
0
          std::vector(ParamTypes.begin(), ParamTypes.end())};
605
0
}
606
607
Async<Expect<std::vector<std::pair<ValInterface, ValType>>>>
608
VM::asyncExecute(std::string_view Func, Span<const ValInterface> Params,
609
0
                 Span<const ValType> ParamTypes) {
610
0
  Expect<std::vector<std::pair<ValInterface, ValType>>> (VM::*FPtr)(
611
0
      std::string_view, Span<const ValInterface>, Span<const ValType>) =
612
0
      &VM::execute;
613
0
  return {FPtr, *this, std::string(Func),
614
0
          std::vector(Params.begin(), Params.end()),
615
0
          std::vector(ParamTypes.begin(), ParamTypes.end())};
616
0
}
617
618
Async<Expect<std::vector<std::pair<ValInterface, ValType>>>>
619
VM::asyncExecute(std::string_view CompName, std::string_view Func,
620
                 Span<const ValInterface> Params,
621
0
                 Span<const ValType> ParamTypes) {
622
0
  Expect<std::vector<std::pair<ValInterface, ValType>>> (VM::*FPtr)(
623
0
      std::string_view, std::string_view, Span<const ValInterface>,
624
0
      Span<const ValType>) = &VM::execute;
625
0
  return {FPtr,
626
0
          *this,
627
0
          std::string(CompName),
628
0
          std::string(Func),
629
0
          std::vector(Params.begin(), Params.end()),
630
0
          std::vector(ParamTypes.begin(), ParamTypes.end())};
631
0
}
632
633
0
void VM::unsafeCleanup() {
634
0
  if (Mod) {
635
0
    Mod.reset();
636
0
  }
637
0
  if (Comp) {
638
0
    Comp.reset();
639
0
  }
640
0
  if (ActiveModInst) {
641
0
    ActiveModInst.reset();
642
0
  }
643
0
  if (ActiveCompInst) {
644
0
    ActiveCompInst.reset();
645
0
  }
646
0
  StoreRef.reset();
647
0
  RegModInsts.clear();
648
0
  Stat.clear();
649
0
  unsafeLoadBuiltInHosts();
650
0
  unsafeLoadPlugInHosts();
651
0
  unsafeRegisterBuiltInHosts();
652
0
  unsafeRegisterPlugInHosts();
653
0
  LoaderEngine.reset();
654
0
  Stage = VMStage::Inited;
655
0
}
656
657
std::vector<std::pair<std::string, const AST::FunctionType &>>
658
0
VM::unsafeGetFunctionList() const {
659
0
  std::vector<std::pair<std::string, const AST::FunctionType &>> Map;
660
0
  if (ActiveModInst) {
661
0
    ActiveModInst->getFuncExports([&](const auto &FuncExports) {
662
0
      Map.reserve(FuncExports.size());
663
0
      for (auto &&Func : FuncExports) {
664
0
        const auto &FuncType = (Func.second)->getFuncType();
665
0
        Map.emplace_back(Func.first, FuncType);
666
0
      }
667
0
    });
668
0
  } else if (ActiveCompInst) {
669
0
    return ActiveCompInst->getFuncExports();
670
0
  }
671
0
  return Map;
672
0
}
673
674
Runtime::Instance::ModuleInstance *
675
0
VM::unsafeGetImportModule(const HostRegistration Type) const {
676
0
  if (auto Iter = BuiltInModInsts.find(Type); Iter != BuiltInModInsts.cend()) {
677
0
    return Iter->second.get();
678
0
  }
679
0
  return nullptr;
680
0
}
681
682
0
const Runtime::Instance::ModuleInstance *VM::unsafeGetActiveModule() const {
683
0
  if (ActiveModInst) {
684
0
    return ActiveModInst.get();
685
0
  }
686
0
  return nullptr;
687
0
};
688
689
} // namespace VM
690
} // namespace WasmEdge