/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 |