/src/WasmEdge/include/executor/executor.h
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 | | //===-- wasmedge/executor/executor.h - Executor class definition ----------===// |
5 | | // |
6 | | // Part of the WasmEdge Project. |
7 | | // |
8 | | //===----------------------------------------------------------------------===// |
9 | | /// |
10 | | /// \file |
11 | | /// This file contains the declaration of the Executor class, which instantiate |
12 | | /// and run Wasm modules. |
13 | | /// |
14 | | //===----------------------------------------------------------------------===// |
15 | | #pragma once |
16 | | |
17 | | #include "ast/module.h" |
18 | | #include "common/async.h" |
19 | | #include "common/configure.h" |
20 | | #include "common/defines.h" |
21 | | #include "common/errcode.h" |
22 | | #include "common/statistics.h" |
23 | | #include "runtime/callingframe.h" |
24 | | #include "runtime/instance/module.h" |
25 | | #include "runtime/stackmgr.h" |
26 | | #include "runtime/storemgr.h" |
27 | | |
28 | | #include <atomic> |
29 | | #include <condition_variable> |
30 | | #include <csignal> |
31 | | #include <cstdint> |
32 | | #include <functional> |
33 | | #include <memory> |
34 | | #include <mutex> |
35 | | #include <optional> |
36 | | #include <shared_mutex> |
37 | | #include <string_view> |
38 | | #include <type_traits> |
39 | | #include <utility> |
40 | | #include <vector> |
41 | | |
42 | | namespace WasmEdge { |
43 | | namespace Executor { |
44 | | |
45 | | namespace { |
46 | | |
47 | | // Template return type aliasing |
48 | | /// Accept unsigned integer types. (uint32_t, uint64_t) |
49 | | template <typename T> |
50 | | using TypeU = typename std::enable_if_t<IsWasmUnsignV<T>, Expect<void>>; |
51 | | /// Accept integer types. (uint32_t, int32_t, uint64_t, int64_t) |
52 | | template <typename T> |
53 | | using TypeI = typename std::enable_if_t<IsWasmIntV<T>, Expect<void>>; |
54 | | /// Accept floating types. (float, double) |
55 | | template <typename T> |
56 | | using TypeF = typename std::enable_if_t<IsWasmFloatV<T>, Expect<void>>; |
57 | | /// Accept all num types. (uint32_t, int32_t, uint64_t, int64_t, float, double) |
58 | | template <typename T> |
59 | | using TypeT = typename std::enable_if_t<IsWasmNumV<T>, Expect<void>>; |
60 | | /// Accept Wasm built-in num types. (uint32_t, uint64_t, float, double) |
61 | | template <typename T> |
62 | | using TypeN = typename std::enable_if_t<IsWasmNativeNumV<T>, Expect<void>>; |
63 | | |
64 | | /// Accept (unsigned integer types, unsigned integer types). |
65 | | template <typename T1, typename T2> |
66 | | using TypeUU = typename std::enable_if_t<IsWasmUnsignV<T1> && IsWasmUnsignV<T2>, |
67 | | Expect<void>>; |
68 | | /// Accept (integer types, unsigned integer types). |
69 | | template <typename T1, typename T2> |
70 | | using TypeIU = typename std::enable_if_t<IsWasmIntV<T1> && IsWasmUnsignV<T2>, |
71 | | Expect<void>>; |
72 | | /// Accept (floating types, floating types). |
73 | | template <typename T1, typename T2> |
74 | | using TypeFF = typename std::enable_if_t<IsWasmFloatV<T1> && IsWasmFloatV<T2>, |
75 | | Expect<void>>; |
76 | | /// Accept (integer types, floating types). |
77 | | template <typename T1, typename T2> |
78 | | using TypeIF = |
79 | | typename std::enable_if_t<IsWasmIntV<T1> && IsWasmFloatV<T2>, Expect<void>>; |
80 | | /// Accept (floating types, integer types). |
81 | | template <typename T1, typename T2> |
82 | | using TypeFI = |
83 | | typename std::enable_if_t<IsWasmFloatV<T1> && IsWasmIntV<T2>, Expect<void>>; |
84 | | /// Accept (Wasm built-in num types, Wasm built-in num types). |
85 | | template <typename T1, typename T2> |
86 | | using TypeNN = |
87 | | typename std::enable_if_t<IsWasmNativeNumV<T1> && IsWasmNativeNumV<T2> && |
88 | | sizeof(T1) == sizeof(T2), |
89 | | Expect<void>>; |
90 | | |
91 | | } // namespace |
92 | | |
93 | | /// Helper class for handling the pre- and post- host functions |
94 | | class HostFuncHandler { |
95 | | public: |
96 | 0 | void setPreHost(void *HostData, std::function<void(void *)> HostFunc) { |
97 | 0 | std::unique_lock Lock(Mutex); |
98 | 0 | PreHostData = HostData; |
99 | 0 | PreHostFunc = HostFunc; |
100 | 0 | } |
101 | 0 | void setPostHost(void *HostData, std::function<void(void *)> HostFunc) { |
102 | 0 | std::unique_lock Lock(Mutex); |
103 | 0 | PostHostData = HostData; |
104 | 0 | PostHostFunc = HostFunc; |
105 | 0 | } |
106 | 0 | void invokePreHostFunc() { |
107 | 0 | if (PreHostFunc.operator bool()) { |
108 | 0 | PreHostFunc(PreHostData); |
109 | 0 | } |
110 | 0 | } |
111 | 0 | void invokePostHostFunc() { |
112 | 0 | if (PostHostFunc.operator bool()) { |
113 | 0 | PostHostFunc(PostHostData); |
114 | 0 | } |
115 | 0 | } |
116 | | |
117 | | private: |
118 | | void *PreHostData = nullptr; |
119 | | void *PostHostData = nullptr; |
120 | | std::function<void(void *)> PreHostFunc = {}; |
121 | | std::function<void(void *)> PostHostFunc = {}; |
122 | | mutable std::shared_mutex Mutex; |
123 | | }; |
124 | | |
125 | | /// Executor flow control class. |
126 | | class Executor { |
127 | | public: |
128 | | Executor(const Configure &Conf, Statistics::Statistics *S = nullptr) noexcept |
129 | 0 | : Conf(Conf) { |
130 | 0 | if (Conf.getStatisticsConfigure().isInstructionCounting() || |
131 | 0 | Conf.getStatisticsConfigure().isCostMeasuring() || |
132 | 0 | Conf.getStatisticsConfigure().isTimeMeasuring()) { |
133 | 0 | Stat = S; |
134 | 0 | } else { |
135 | 0 | Stat = nullptr; |
136 | 0 | } |
137 | 0 | if (Stat) { |
138 | 0 | Stat->setCostLimit(Conf.getStatisticsConfigure().getCostLimit()); |
139 | 0 | } |
140 | 0 | } |
141 | | |
142 | | /// Getter of Configure |
143 | 0 | const Configure &getConfigure() const { return Conf; } |
144 | | |
145 | | /// Instantiate a WASM Module into an anonymous module instance. |
146 | | Expect<std::unique_ptr<Runtime::Instance::ModuleInstance>> |
147 | | instantiateModule(Runtime::StoreManager &StoreMgr, const AST::Module &Mod); |
148 | | |
149 | | Expect<std::unique_ptr<Runtime::Instance::ComponentInstance>> |
150 | | instantiateComponent(Runtime::StoreManager &StoreMgr, |
151 | | const AST::Component::Component &Comp); |
152 | | Expect<std::unique_ptr<Runtime::Instance::ComponentInstance>> |
153 | | instantiateComponent(Runtime::StoreManager &StoreMgr, |
154 | | const AST::Component::Component &Comp, |
155 | | std::string_view Name); |
156 | | |
157 | | /// Instantiate and register a WASM module into a named module instance. |
158 | | Expect<std::unique_ptr<Runtime::Instance::ModuleInstance>> |
159 | | registerModule(Runtime::StoreManager &StoreMgr, const AST::Module &Mod, |
160 | | std::string_view Name); |
161 | | |
162 | | /// Register an instantiated module into a named module instance. |
163 | | Expect<void> registerModule(Runtime::StoreManager &StoreMgr, |
164 | | const Runtime::Instance::ModuleInstance &ModInst); |
165 | | Expect<void> |
166 | | registerComponent(Runtime::StoreManager &StoreMgr, |
167 | | const Runtime::Instance::ComponentInstance &CompInst); |
168 | | |
169 | | /// Register a host function which will be invoked before calling a |
170 | | /// host function. |
171 | | Expect<void> registerPreHostFunction(void *HostData, |
172 | | std::function<void(void *)> HostFunc); |
173 | | |
174 | | /// Register a host function which will be invoked after calling a |
175 | | /// host function. |
176 | | Expect<void> registerPostHostFunction(void *HostData, |
177 | | std::function<void(void *)> HostFunc); |
178 | | |
179 | | /// Invoke a WASM function by function instance. |
180 | | Expect<std::vector<std::pair<ValVariant, ValType>>> |
181 | | invoke(const Runtime::Instance::FunctionInstance *FuncInst, |
182 | | Span<const ValVariant> Params, Span<const ValType> ParamTypes); |
183 | | |
184 | | /// Invoke a Component function by function instance. |
185 | | Expect<std::vector<std::pair<ValInterface, ValType>>> |
186 | | invoke(const Runtime::Instance::Component::FunctionInstance *FuncInst, |
187 | | Span<const ValInterface> Params, Span<const ValType> ParamTypes); |
188 | | |
189 | | /// Asynchronous invoke a WASM function by function instance. |
190 | | Async<Expect<std::vector<std::pair<ValVariant, ValType>>>> |
191 | | asyncInvoke(const Runtime::Instance::FunctionInstance *FuncInst, |
192 | | Span<const ValVariant> Params, Span<const ValType> ParamTypes); |
193 | | |
194 | | /// Stop execution |
195 | 0 | void stop() noexcept { |
196 | 0 | StopToken.store(1, std::memory_order_relaxed); |
197 | 0 | atomicNotifyAll(); |
198 | 0 | } |
199 | | |
200 | | private: |
201 | | /// Run Wasm bytecode expression for initialization. |
202 | | Expect<void> runExpression(Runtime::StackManager &StackMgr, |
203 | | AST::InstrView Instrs); |
204 | | |
205 | | /// Run Wasm function. |
206 | | Expect<void> runFunction(Runtime::StackManager &StackMgr, |
207 | | const Runtime::Instance::FunctionInstance &Func, |
208 | | Span<const ValVariant> Params); |
209 | | |
210 | | /// Execute instructions. |
211 | | Expect<void> execute(Runtime::StackManager &StackMgr, |
212 | | const AST::InstrView::iterator Start, |
213 | | const AST::InstrView::iterator End); |
214 | | |
215 | | /// \name Functions for instantiation. |
216 | | /// @{ |
217 | | /// Instantiation of Module Instance. |
218 | | Expect<std::unique_ptr<Runtime::Instance::ModuleInstance>> |
219 | | instantiate(Runtime::StoreManager &StoreMgr, const AST::Module &Mod, |
220 | | std::optional<std::string_view> Name = std::nullopt); |
221 | | |
222 | | /// Instantiation of Imports. |
223 | | Expect<void> instantiate(Runtime::StoreManager &StoreMgr, |
224 | | Runtime::Instance::ModuleInstance &ModInst, |
225 | | const AST::ImportSection &ImportSec); |
226 | | |
227 | | /// Instantiation of Function Instances. |
228 | | Expect<void> instantiate(Runtime::Instance::ModuleInstance &ModInst, |
229 | | const AST::FunctionSection &FuncSec, |
230 | | const AST::CodeSection &CodeSec); |
231 | | |
232 | | /// Instantiation of Table Instances. |
233 | | Expect<void> instantiate(Runtime::StackManager &StackMgr, |
234 | | Runtime::Instance::ModuleInstance &ModInst, |
235 | | const AST::TableSection &TabSec); |
236 | | |
237 | | /// Instantiation of Memory Instances. |
238 | | Expect<void> instantiate(Runtime::Instance::ModuleInstance &ModInst, |
239 | | const AST::MemorySection &MemSec); |
240 | | |
241 | | /// Instantiateion of Tag Instances. |
242 | | Expect<void> instantiate(Runtime::Instance::ModuleInstance &ModInst, |
243 | | const AST::TagSection &TagSec); |
244 | | |
245 | | /// Instantiation of Global Instances. |
246 | | Expect<void> instantiate(Runtime::StackManager &StackMgr, |
247 | | Runtime::Instance::ModuleInstance &ModInst, |
248 | | const AST::GlobalSection &GlobSec); |
249 | | |
250 | | /// Instantiation of Element Instances. |
251 | | Expect<void> instantiate(Runtime::StackManager &StackMgr, |
252 | | Runtime::Instance::ModuleInstance &ModInst, |
253 | | const AST::ElementSection &ElemSec); |
254 | | |
255 | | /// Initialize table with Element Instances. |
256 | | Expect<void> initTable(Runtime::StackManager &StackMgr, |
257 | | const AST::ElementSection &ElemSec); |
258 | | |
259 | | /// Instantiation of Data Instances. |
260 | | Expect<void> instantiate(Runtime::StackManager &StackMgr, |
261 | | Runtime::Instance::ModuleInstance &ModInst, |
262 | | const AST::DataSection &DataSec); |
263 | | |
264 | | /// Initialize memory with Data Instances. |
265 | | Expect<void> initMemory(Runtime::StackManager &StackMgr, |
266 | | const AST::DataSection &DataSec); |
267 | | |
268 | | /// Instantiation of Exports. |
269 | | Expect<void> instantiate(Runtime::Instance::ModuleInstance &ModInst, |
270 | | const AST::ExportSection &ExportSec); |
271 | | /// @} |
272 | | |
273 | | /// @{ |
274 | | /// Instantiation of Component Instance. |
275 | | Expect<std::unique_ptr<Runtime::Instance::ComponentInstance>> |
276 | | instantiate(Runtime::StoreManager &StoreMgr, |
277 | | const AST::Component::Component &Comp, |
278 | | std::optional<std::string_view> Name = std::nullopt); |
279 | | |
280 | | Expect<void> instantiate(Runtime::StoreManager &StoreMgr, |
281 | | Runtime::Instance::ComponentInstance &CompInst, |
282 | | const AST::Component::CoreInstanceSection &); |
283 | | Expect<void> instantiate(Runtime::StoreManager &StoreMgr, |
284 | | Runtime::Instance::ComponentInstance &CompInst, |
285 | | const AST::Component::CoreTypeSection &); |
286 | | Expect<void> instantiate(Runtime::StoreManager &StoreMgr, |
287 | | Runtime::Instance::ComponentInstance &CompInst, |
288 | | const AST::Component::InstanceSection &); |
289 | | Expect<void> instantiate(Runtime::StoreManager &StoreMgr, |
290 | | Runtime::Instance::ComponentInstance &CompInst, |
291 | | const AST::Component::AliasSection &); |
292 | | Expect<void> instantiate(Runtime::StoreManager &StoreMgr, |
293 | | Runtime::Instance::ComponentInstance &CompInst, |
294 | | const AST::Component::TypeSection &); |
295 | | Expect<void> instantiate(Runtime::StoreManager &StoreMgr, |
296 | | Runtime::Instance::ComponentInstance &CompInst, |
297 | | const AST::Component::CanonSection &); |
298 | | Expect<void> instantiate(Runtime::StoreManager &StoreMgr, |
299 | | Runtime::Instance::ComponentInstance &CompInst, |
300 | | const AST::Component::StartSection &); |
301 | | Expect<void> instantiate(Runtime::StoreManager &StoreMgr, |
302 | | Runtime::Instance::ComponentInstance &CompInst, |
303 | | const AST::Component::ImportSection &); |
304 | | Expect<void> instantiate(Runtime::StoreManager &StoreMgr, |
305 | | Runtime::Instance::ComponentInstance &CompInst, |
306 | | const AST::Component::ExportSection &); |
307 | | /// @} |
308 | | |
309 | | /// \name Helper Functions for canonical ABI |
310 | | /// @{ |
311 | | std::unique_ptr<Runtime::Instance::Component::FunctionInstance> |
312 | | lifting(Runtime::Instance::ComponentInstance &Comp, |
313 | | const WasmEdge::AST::Component::FuncType &FuncType, |
314 | | Runtime::Instance::FunctionInstance *F, |
315 | | Runtime::Instance::MemoryInstance *Memory, |
316 | | Runtime::Instance::FunctionInstance *Realloc); |
317 | | |
318 | | std::unique_ptr<Runtime::Instance::FunctionInstance> |
319 | | lowering(Runtime::Instance::Component::FunctionInstance *F, |
320 | | Runtime::Instance::MemoryInstance *Memory, |
321 | | Runtime::Instance::FunctionInstance *Realloc); |
322 | | /// @} |
323 | | |
324 | | /// \name Helper Functions for block controls. |
325 | | /// @{ |
326 | | /// Helper function for calling functions. Return the continuation iterator. |
327 | | Expect<AST::InstrView::iterator> |
328 | | enterFunction(Runtime::StackManager &StackMgr, |
329 | | const Runtime::Instance::FunctionInstance &Func, |
330 | | const AST::InstrView::iterator RetIt, bool IsTailCall = false); |
331 | | |
332 | | /// Helper function for branching to label. |
333 | | Expect<void> branchToLabel(Runtime::StackManager &StackMgr, |
334 | | const AST::Instruction::JumpDescriptor &JumpDesc, |
335 | | AST::InstrView::iterator &PC) noexcept; |
336 | | |
337 | | /// Helper function for throwing an exception. |
338 | | Expect<void> throwException(Runtime::StackManager &StackMgr, |
339 | | Runtime::Instance::TagInstance &TagInst, |
340 | | AST::InstrView::iterator &PC) noexcept; |
341 | | /// @} |
342 | | |
343 | | /// \name Helper Functions for GC instructions. |
344 | | /// @{ |
345 | | Expect<RefVariant> structNew(Runtime::StackManager &StackMgr, |
346 | | const uint32_t TypeIdx, |
347 | | Span<const ValVariant> Args = {}) const noexcept; |
348 | | Expect<ValVariant> structGet(Runtime::StackManager &StackMgr, |
349 | | const RefVariant Ref, const uint32_t TypeIdx, |
350 | | const uint32_t Off, |
351 | | const bool IsSigned = false) const noexcept; |
352 | | Expect<void> structSet(Runtime::StackManager &StackMgr, const RefVariant Ref, |
353 | | const ValVariant Val, const uint32_t TypeIdx, |
354 | | const uint32_t Off) const noexcept; |
355 | | Expect<RefVariant> arrayNew(Runtime::StackManager &StackMgr, |
356 | | const uint32_t TypeIdx, const uint32_t Length, |
357 | | Span<const ValVariant> Args = {}) const noexcept; |
358 | | Expect<RefVariant> arrayNewData(Runtime::StackManager &StackMgr, |
359 | | const uint32_t TypeIdx, |
360 | | const uint32_t DataIdx, const uint32_t Start, |
361 | | const uint32_t Length) const noexcept; |
362 | | Expect<RefVariant> arrayNewElem(Runtime::StackManager &StackMgr, |
363 | | const uint32_t TypeIdx, |
364 | | const uint32_t ElemIdx, const uint32_t Start, |
365 | | const uint32_t Length) const noexcept; |
366 | | Expect<ValVariant> arrayGet(Runtime::StackManager &StackMgr, |
367 | | const RefVariant &Ref, const uint32_t TypeIdx, |
368 | | const uint32_t Idx, |
369 | | const bool IsSigned = false) const noexcept; |
370 | | Expect<void> arraySet(Runtime::StackManager &StackMgr, const RefVariant &Ref, |
371 | | const ValVariant &Val, const uint32_t TypeIdx, |
372 | | const uint32_t Idx) const noexcept; |
373 | | Expect<void> arrayFill(Runtime::StackManager &StackMgr, const RefVariant &Ref, |
374 | | const ValVariant &Val, const uint32_t TypeIdx, |
375 | | const uint32_t Idx, const uint32_t Cnt) const noexcept; |
376 | | Expect<void> arrayInitData(Runtime::StackManager &StackMgr, |
377 | | const RefVariant &Ref, const uint32_t TypeIdx, |
378 | | const uint32_t DataIdx, const uint32_t DstIdx, |
379 | | const uint32_t SrcIdx, |
380 | | const uint32_t Cnt) const noexcept; |
381 | | Expect<void> arrayInitElem(Runtime::StackManager &StackMgr, |
382 | | const RefVariant &Ref, const uint32_t TypeIdx, |
383 | | const uint32_t ElemIdx, const uint32_t DstIdx, |
384 | | const uint32_t SrcIdx, |
385 | | const uint32_t Cnt) const noexcept; |
386 | | Expect<void> arrayCopy(Runtime::StackManager &StackMgr, |
387 | | const RefVariant &DstRef, const uint32_t DstTypeIdx, |
388 | | const uint32_t DstIdx, const RefVariant &SrcRef, |
389 | | const uint32_t SrcTypeIdx, const uint32_t SrcIdx, |
390 | | const uint32_t Cnt) const noexcept; |
391 | | /// @} |
392 | | |
393 | | /// \name Helper Functions for atomic operations. |
394 | | /// @{ |
395 | | template <typename T> |
396 | | Expect<uint32_t> atomicWait(Runtime::Instance::MemoryInstance &MemInst, |
397 | | uint32_t Address, T Expected, |
398 | | int64_t Timeout) noexcept; |
399 | | Expect<uint32_t> atomicNotify(Runtime::Instance::MemoryInstance &MemInst, |
400 | | uint32_t Address, uint32_t Count) noexcept; |
401 | | void atomicNotifyAll() noexcept; |
402 | | /// @} |
403 | | |
404 | | /// \name Helper Functions for getting instances or types. |
405 | | /// @{ |
406 | | /// Helper function for getting defined type by index. |
407 | | const AST::SubType *getDefTypeByIdx(Runtime::StackManager &StackMgr, |
408 | | const uint32_t Idx) const; |
409 | | |
410 | | /// Helper function for getting composite type by index. Assuming validated. |
411 | | const WasmEdge::AST::CompositeType & |
412 | | getCompositeTypeByIdx(Runtime::StackManager &StackMgr, |
413 | | const uint32_t Idx) const noexcept; |
414 | | |
415 | | /// Helper function for getting struct storage type by index. |
416 | | const ValType &getStructStorageTypeByIdx(Runtime::StackManager &StackMgr, |
417 | | const uint32_t Idx, |
418 | | const uint32_t Off) const noexcept; |
419 | | |
420 | | /// Helper function for getting array storage type by index. |
421 | | const ValType &getArrayStorageTypeByIdx(Runtime::StackManager &StackMgr, |
422 | | const uint32_t Idx) const noexcept; |
423 | | |
424 | | /// Helper function for getting function instance by index. |
425 | | Runtime::Instance::FunctionInstance * |
426 | | getFuncInstByIdx(Runtime::StackManager &StackMgr, const uint32_t Idx) const; |
427 | | |
428 | | /// Helper function for getting table instance by index. |
429 | | Runtime::Instance::TableInstance * |
430 | | getTabInstByIdx(Runtime::StackManager &StackMgr, const uint32_t Idx) const; |
431 | | |
432 | | /// Helper function for getting memory instance by index. |
433 | | Runtime::Instance::MemoryInstance * |
434 | | getMemInstByIdx(Runtime::StackManager &StackMgr, const uint32_t Idx) const; |
435 | | |
436 | | /// Helper function for getting tag instance by index. |
437 | | Runtime::Instance::TagInstance * |
438 | | getTagInstByIdx(Runtime::StackManager &StackMgr, const uint32_t Idx) const; |
439 | | |
440 | | /// Helper function for getting global instance by index. |
441 | | Runtime::Instance::GlobalInstance * |
442 | | getGlobInstByIdx(Runtime::StackManager &StackMgr, const uint32_t Idx) const; |
443 | | |
444 | | /// Helper function for getting element instance by index. |
445 | | Runtime::Instance::ElementInstance * |
446 | | getElemInstByIdx(Runtime::StackManager &StackMgr, const uint32_t Idx) const; |
447 | | |
448 | | /// Helper function for getting data instance by index. |
449 | | Runtime::Instance::DataInstance * |
450 | | getDataInstByIdx(Runtime::StackManager &StackMgr, const uint32_t Idx) const; |
451 | | |
452 | | /// Helper function for converting into bottom abstract heap type. |
453 | | TypeCode toBottomType(Runtime::StackManager &StackMgr, |
454 | | const ValType &Type) const; |
455 | | |
456 | | /// Helper function for cleaning unused bits of numeric values in ValVariant. |
457 | | void cleanNumericVal(ValVariant &Val, const ValType &Type) const noexcept; |
458 | | |
459 | | /// Helper function for packing ValVariant for packed type. |
460 | | ValVariant packVal(const ValType &Type, const ValVariant &Val) const noexcept; |
461 | | |
462 | | /// Helper function for packing ValVariant vector for packed type. |
463 | | std::vector<ValVariant> |
464 | | packVals(const ValType &Type, std::vector<ValVariant> &&Vals) const noexcept; |
465 | | |
466 | | /// Helper function for unpacking ValVariant for packed type. |
467 | | ValVariant unpackVal(const ValType &Type, const ValVariant &Val, |
468 | | bool IsSigned = false) const noexcept; |
469 | | /// @} |
470 | | |
471 | | /// \name Interpreter - Run instructions functions |
472 | | /// @{ |
473 | | /// ======= Control instructions ======= |
474 | | Expect<void> runIfElseOp(Runtime::StackManager &StackMgr, |
475 | | const AST::Instruction &Instr, |
476 | | AST::InstrView::iterator &PC) noexcept; |
477 | | Expect<void> runThrowOp(Runtime::StackManager &StackMgr, |
478 | | const AST::Instruction &Instr, |
479 | | AST::InstrView::iterator &PC) noexcept; |
480 | | Expect<void> runThrowRefOp(Runtime::StackManager &StackMgr, |
481 | | const AST::Instruction &Instr, |
482 | | AST::InstrView::iterator &PC) noexcept; |
483 | | Expect<void> runBrOp(Runtime::StackManager &StackMgr, |
484 | | const AST::Instruction &Instr, |
485 | | AST::InstrView::iterator &PC) noexcept; |
486 | | Expect<void> runBrIfOp(Runtime::StackManager &StackMgr, |
487 | | const AST::Instruction &Instr, |
488 | | AST::InstrView::iterator &PC) noexcept; |
489 | | Expect<void> runBrOnNullOp(Runtime::StackManager &StackMgr, |
490 | | const AST::Instruction &Instr, |
491 | | AST::InstrView::iterator &PC) noexcept; |
492 | | Expect<void> runBrOnNonNullOp(Runtime::StackManager &StackMgr, |
493 | | const AST::Instruction &Instr, |
494 | | AST::InstrView::iterator &PC) noexcept; |
495 | | Expect<void> runBrTableOp(Runtime::StackManager &StackMgr, |
496 | | const AST::Instruction &Instr, |
497 | | AST::InstrView::iterator &PC) noexcept; |
498 | | Expect<void> runBrOnCastOp(Runtime::StackManager &StackMgr, |
499 | | const AST::Instruction &Instr, |
500 | | AST::InstrView::iterator &PC, |
501 | | bool IsReverse = false) noexcept; |
502 | | Expect<void> runReturnOp(Runtime::StackManager &StackMgr, |
503 | | AST::InstrView::iterator &PC) noexcept; |
504 | | Expect<void> runCallOp(Runtime::StackManager &StackMgr, |
505 | | const AST::Instruction &Instr, |
506 | | AST::InstrView::iterator &PC, |
507 | | bool IsTailCall = false) noexcept; |
508 | | Expect<void> runCallRefOp(Runtime::StackManager &StackMgr, |
509 | | const AST::Instruction &Instr, |
510 | | AST::InstrView::iterator &PC, |
511 | | bool IsTailCall = false) noexcept; |
512 | | Expect<void> runCallIndirectOp(Runtime::StackManager &StackMgr, |
513 | | const AST::Instruction &Instr, |
514 | | AST::InstrView::iterator &PC, |
515 | | bool IsTailCall = false) noexcept; |
516 | | Expect<void> runTryTableOp(Runtime::StackManager &StackMgr, |
517 | | const AST::Instruction &Instr, |
518 | | AST::InstrView::iterator &PC) noexcept; |
519 | | /// ======= Variable instructions ======= |
520 | | Expect<void> runLocalGetOp(Runtime::StackManager &StackMgr, |
521 | | uint32_t StackOffset) const noexcept; |
522 | | Expect<void> runLocalSetOp(Runtime::StackManager &StackMgr, |
523 | | uint32_t StackOffset) const noexcept; |
524 | | Expect<void> runLocalTeeOp(Runtime::StackManager &StackMgr, |
525 | | uint32_t StackOffset) const noexcept; |
526 | | Expect<void> runGlobalGetOp(Runtime::StackManager &StackMgr, |
527 | | uint32_t Idx) const noexcept; |
528 | | Expect<void> runGlobalSetOp(Runtime::StackManager &StackMgr, |
529 | | uint32_t Idx) const noexcept; |
530 | | /// ======= Reference instructions ======= |
531 | | Expect<void> runRefNullOp(Runtime::StackManager &StackMgr, |
532 | | const ValType &Type) const noexcept; |
533 | | Expect<void> runRefIsNullOp(ValVariant &Val) const noexcept; |
534 | | Expect<void> runRefFuncOp(Runtime::StackManager &StackMgr, |
535 | | uint32_t Idx) const noexcept; |
536 | | Expect<void> runRefEqOp(ValVariant &Val1, |
537 | | const ValVariant &Val2) const noexcept; |
538 | | Expect<void> runRefAsNonNullOp(RefVariant &Val, |
539 | | const AST::Instruction &Instr) const noexcept; |
540 | | Expect<void> runStructNewOp(Runtime::StackManager &StackMgr, |
541 | | const uint32_t TypeIdx, |
542 | | const bool IsDefault = false) const noexcept; |
543 | | Expect<void> runStructGetOp(Runtime::StackManager &StackMgr, |
544 | | const uint32_t TypeIdx, const uint32_t Off, |
545 | | const AST::Instruction &Instr, |
546 | | const bool IsSigned = false) const noexcept; |
547 | | Expect<void> runStructSetOp(Runtime::StackManager &StackMgr, |
548 | | const ValVariant &Val, const uint32_t TypeIdx, |
549 | | const uint32_t Off, |
550 | | const AST::Instruction &Instr) const noexcept; |
551 | | Expect<void> runArrayNewOp(Runtime::StackManager &StackMgr, |
552 | | const uint32_t TypeIdx, const uint32_t InitCnt, |
553 | | uint32_t Length) const noexcept; |
554 | | Expect<void> runArrayNewDataOp(Runtime::StackManager &StackMgr, |
555 | | const uint32_t TypeIdx, const uint32_t DataIdx, |
556 | | const AST::Instruction &Instr) const noexcept; |
557 | | Expect<void> runArrayNewElemOp(Runtime::StackManager &StackMgr, |
558 | | const uint32_t TypeIdx, const uint32_t ElemIdx, |
559 | | const AST::Instruction &Instr) const noexcept; |
560 | | Expect<void> runArrayGetOp(Runtime::StackManager &StackMgr, |
561 | | const uint32_t TypeIdx, |
562 | | const AST::Instruction &Instr, |
563 | | const bool IsSigned = false) const noexcept; |
564 | | Expect<void> runArraySetOp(Runtime::StackManager &StackMgr, |
565 | | const ValVariant &Val, const uint32_t TypeIdx, |
566 | | const AST::Instruction &Instr) const noexcept; |
567 | | Expect<void> runArrayLenOp(ValVariant &Val, |
568 | | const AST::Instruction &Instr) const noexcept; |
569 | | Expect<void> runArrayFillOp(Runtime::StackManager &StackMgr, |
570 | | const uint32_t Cnt, const ValVariant &Val, |
571 | | const uint32_t TypeIdx, |
572 | | const AST::Instruction &Instr) const noexcept; |
573 | | Expect<void> runArrayCopyOp(Runtime::StackManager &StackMgr, |
574 | | const uint32_t Cnt, const uint32_t DstTypeIdx, |
575 | | const uint32_t SrcTypeIdx, |
576 | | const AST::Instruction &Instr) const noexcept; |
577 | | Expect<void> runArrayInitDataOp(Runtime::StackManager &StackMgr, |
578 | | const uint32_t Cnt, const uint32_t TypeIdx, |
579 | | const uint32_t DataIdx, |
580 | | const AST::Instruction &Instr) const noexcept; |
581 | | Expect<void> runArrayInitElemOp(Runtime::StackManager &StackMgr, |
582 | | const uint32_t Cnt, const uint32_t TypeIdx, |
583 | | const uint32_t ElemIdx, |
584 | | const AST::Instruction &Instr) const noexcept; |
585 | | Expect<void> runRefTestOp(const Runtime::Instance::ModuleInstance *ModInst, |
586 | | ValVariant &Val, const AST::Instruction &Instr, |
587 | | const bool IsCast = false) const noexcept; |
588 | | Expect<void> runRefConvOp(RefVariant &Val, TypeCode TCode) const noexcept; |
589 | | Expect<void> runRefI31Op(ValVariant &Val) const noexcept; |
590 | | Expect<void> runI31GetOp(ValVariant &Val, const AST::Instruction &Instr, |
591 | | const bool IsSigned = false) const noexcept; |
592 | | /// ======= Table instructions ======= |
593 | | Expect<void> runTableGetOp(Runtime::StackManager &StackMgr, |
594 | | Runtime::Instance::TableInstance &TabInst, |
595 | | const AST::Instruction &Instr); |
596 | | Expect<void> runTableSetOp(Runtime::StackManager &StackMgr, |
597 | | Runtime::Instance::TableInstance &TabInst, |
598 | | const AST::Instruction &Instr); |
599 | | Expect<void> runTableInitOp(Runtime::StackManager &StackMgr, |
600 | | Runtime::Instance::TableInstance &TabInst, |
601 | | Runtime::Instance::ElementInstance &ElemInst, |
602 | | const AST::Instruction &Instr); |
603 | | Expect<void> runElemDropOp(Runtime::Instance::ElementInstance &ElemInst); |
604 | | Expect<void> runTableCopyOp(Runtime::StackManager &StackMgr, |
605 | | Runtime::Instance::TableInstance &TabInstDst, |
606 | | Runtime::Instance::TableInstance &TabInstSrc, |
607 | | const AST::Instruction &Instr); |
608 | | Expect<void> runTableGrowOp(Runtime::StackManager &StackMgr, |
609 | | Runtime::Instance::TableInstance &TabInst); |
610 | | Expect<void> runTableSizeOp(Runtime::StackManager &StackMgr, |
611 | | Runtime::Instance::TableInstance &TabInst); |
612 | | Expect<void> runTableFillOp(Runtime::StackManager &StackMgr, |
613 | | Runtime::Instance::TableInstance &TabInst, |
614 | | const AST::Instruction &Instr); |
615 | | /// ======= Memory instructions ======= |
616 | | template <typename T, uint32_t BitWidth = sizeof(T) * 8> |
617 | | TypeT<T> runLoadOp(Runtime::StackManager &StackMgr, |
618 | | Runtime::Instance::MemoryInstance &MemInst, |
619 | | const AST::Instruction &Instr); |
620 | | template <typename T, uint32_t BitWidth = sizeof(T) * 8> |
621 | | TypeN<T> runStoreOp(Runtime::StackManager &StackMgr, |
622 | | Runtime::Instance::MemoryInstance &MemInst, |
623 | | const AST::Instruction &Instr); |
624 | | Expect<void> runMemorySizeOp(Runtime::StackManager &StackMgr, |
625 | | Runtime::Instance::MemoryInstance &MemInst); |
626 | | Expect<void> runMemoryGrowOp(Runtime::StackManager &StackMgr, |
627 | | Runtime::Instance::MemoryInstance &MemInst); |
628 | | Expect<void> runMemoryInitOp(Runtime::StackManager &StackMgr, |
629 | | Runtime::Instance::MemoryInstance &MemInst, |
630 | | Runtime::Instance::DataInstance &DataInst, |
631 | | const AST::Instruction &Instr); |
632 | | Expect<void> runDataDropOp(Runtime::Instance::DataInstance &DataInst); |
633 | | Expect<void> runMemoryCopyOp(Runtime::StackManager &StackMgr, |
634 | | Runtime::Instance::MemoryInstance &MemInstDst, |
635 | | Runtime::Instance::MemoryInstance &MemInstSrc, |
636 | | const AST::Instruction &Instr); |
637 | | Expect<void> runMemoryFillOp(Runtime::StackManager &StackMgr, |
638 | | Runtime::Instance::MemoryInstance &MemInst, |
639 | | const AST::Instruction &Instr); |
640 | | /// ======= Test and Relation Numeric instructions ======= |
641 | | template <typename T> TypeU<T> runEqzOp(ValVariant &Val) const; |
642 | | template <typename T> |
643 | | TypeT<T> runEqOp(ValVariant &Val1, const ValVariant &Val2) const; |
644 | | template <typename T> |
645 | | TypeT<T> runNeOp(ValVariant &Val1, const ValVariant &Val2) const; |
646 | | template <typename T> |
647 | | TypeT<T> runLtOp(ValVariant &Val1, const ValVariant &Val2) const; |
648 | | template <typename T> |
649 | | TypeT<T> runGtOp(ValVariant &Val1, const ValVariant &Val2) const; |
650 | | template <typename T> |
651 | | TypeT<T> runLeOp(ValVariant &Val1, const ValVariant &Val2) const; |
652 | | template <typename T> |
653 | | TypeT<T> runGeOp(ValVariant &Val1, const ValVariant &Val2) const; |
654 | | /// ======= Unary Numeric instructions ======= |
655 | | template <typename T> TypeU<T> runClzOp(ValVariant &Val) const; |
656 | | template <typename T> TypeU<T> runCtzOp(ValVariant &Val) const; |
657 | | template <typename T> TypeU<T> runPopcntOp(ValVariant &Val) const; |
658 | | template <typename T> TypeF<T> runAbsOp(ValVariant &Val) const; |
659 | | template <typename T> TypeF<T> runNegOp(ValVariant &Val) const; |
660 | | template <typename T> TypeF<T> runCeilOp(ValVariant &Val) const; |
661 | | template <typename T> TypeF<T> runFloorOp(ValVariant &Val) const; |
662 | | template <typename T> TypeF<T> runTruncOp(ValVariant &Val) const; |
663 | | template <typename T> TypeF<T> runNearestOp(ValVariant &Val) const; |
664 | | template <typename T> TypeF<T> runSqrtOp(ValVariant &Val) const; |
665 | | /// ======= Binary Numeric instructions ======= |
666 | | template <typename T> |
667 | | TypeN<T> runAddOp(ValVariant &Val1, const ValVariant &Val2) const; |
668 | | template <typename T> |
669 | | TypeN<T> runSubOp(ValVariant &Val1, const ValVariant &Val2) const; |
670 | | template <typename T> |
671 | | TypeN<T> runMulOp(ValVariant &Val1, const ValVariant &Val2) const; |
672 | | template <typename T> |
673 | | TypeT<T> runDivOp(const AST::Instruction &Instr, ValVariant &Val1, |
674 | | const ValVariant &Val2) const; |
675 | | template <typename T> |
676 | | TypeI<T> runRemOp(const AST::Instruction &Instr, ValVariant &Val1, |
677 | | const ValVariant &Val2) const; |
678 | | template <typename T> |
679 | | TypeU<T> runAndOp(ValVariant &Val1, const ValVariant &Val2) const; |
680 | | template <typename T> |
681 | | TypeU<T> runOrOp(ValVariant &Val1, const ValVariant &Val2) const; |
682 | | template <typename T> |
683 | | TypeU<T> runXorOp(ValVariant &Val1, const ValVariant &Val2) const; |
684 | | template <typename T> |
685 | | TypeU<T> runShlOp(ValVariant &Val1, const ValVariant &Val2) const; |
686 | | template <typename T> |
687 | | TypeI<T> runShrOp(ValVariant &Val1, const ValVariant &Val2) const; |
688 | | template <typename T> |
689 | | TypeU<T> runRotlOp(ValVariant &Val1, const ValVariant &Val2) const; |
690 | | template <typename T> |
691 | | TypeU<T> runRotrOp(ValVariant &Val1, const ValVariant &Val2) const; |
692 | | template <typename T> |
693 | | TypeF<T> runMinOp(ValVariant &Val1, const ValVariant &Val2) const; |
694 | | template <typename T> |
695 | | TypeF<T> runMaxOp(ValVariant &Val1, const ValVariant &Val2) const; |
696 | | template <typename T> |
697 | | TypeF<T> runCopysignOp(ValVariant &Val1, const ValVariant &Val2) const; |
698 | | /// ======= Cast Numeric instructions ======= |
699 | | template <typename TIn, typename TOut> |
700 | | TypeUU<TIn, TOut> runWrapOp(ValVariant &Val) const; |
701 | | template <typename TIn, typename TOut> |
702 | | TypeFI<TIn, TOut> runTruncateOp(const AST::Instruction &Instr, |
703 | | ValVariant &Val) const; |
704 | | template <typename TIn, typename TOut> |
705 | | TypeFI<TIn, TOut> runTruncateSatOp(ValVariant &Val) const; |
706 | | template <typename TIn, typename TOut, size_t B = sizeof(TIn) * 8> |
707 | | TypeIU<TIn, TOut> runExtendOp(ValVariant &Val) const; |
708 | | template <typename TIn, typename TOut> |
709 | | TypeIF<TIn, TOut> runConvertOp(ValVariant &Val) const; |
710 | | template <typename TIn, typename TOut> |
711 | | TypeFF<TIn, TOut> runDemoteOp(ValVariant &Val) const; |
712 | | template <typename TIn, typename TOut> |
713 | | TypeFF<TIn, TOut> runPromoteOp(ValVariant &Val) const; |
714 | | template <typename TIn, typename TOut> |
715 | | TypeNN<TIn, TOut> runReinterpretOp(ValVariant &Val) const; |
716 | | /// ======= SIMD Memory instructions ======= |
717 | | template <typename TIn, typename TOut> |
718 | | Expect<void> runLoadExpandOp(Runtime::StackManager &StackMgr, |
719 | | Runtime::Instance::MemoryInstance &MemInst, |
720 | | const AST::Instruction &Instr); |
721 | | template <typename T> |
722 | | Expect<void> runLoadSplatOp(Runtime::StackManager &StackMgr, |
723 | | Runtime::Instance::MemoryInstance &MemInst, |
724 | | const AST::Instruction &Instr); |
725 | | template <typename T> |
726 | | Expect<void> runLoadLaneOp(Runtime::StackManager &StackMgr, |
727 | | Runtime::Instance::MemoryInstance &MemInst, |
728 | | const AST::Instruction &Instr); |
729 | | template <typename T> |
730 | | Expect<void> runStoreLaneOp(Runtime::StackManager &StackMgr, |
731 | | Runtime::Instance::MemoryInstance &MemInst, |
732 | | const AST::Instruction &Instr); |
733 | | /// ======= SIMD Lane instructions ======= |
734 | | template <typename TIn, typename TOut = TIn> |
735 | | Expect<void> runExtractLaneOp(ValVariant &Val, const uint8_t Index) const; |
736 | | template <typename TIn, typename TOut = TIn> |
737 | | Expect<void> runReplaceLaneOp(ValVariant &Val1, const ValVariant &Val2, |
738 | | const uint8_t Index) const; |
739 | | /// ======= SIMD Numeric instructions ======= |
740 | | template <typename TIn, typename TOut = TIn> |
741 | | Expect<void> runSplatOp(ValVariant &Val) const; |
742 | | template <typename T> |
743 | | Expect<void> runVectorEqOp(ValVariant &Val1, const ValVariant &Val2) const; |
744 | | template <typename T> |
745 | | Expect<void> runVectorNeOp(ValVariant &Val1, const ValVariant &Val2) const; |
746 | | template <typename T> |
747 | | Expect<void> runVectorLtOp(ValVariant &Val1, const ValVariant &Val2) const; |
748 | | template <typename T> |
749 | | Expect<void> runVectorGtOp(ValVariant &Val1, const ValVariant &Val2) const; |
750 | | template <typename T> |
751 | | Expect<void> runVectorLeOp(ValVariant &Val1, const ValVariant &Val2) const; |
752 | | template <typename T> |
753 | | Expect<void> runVectorGeOp(ValVariant &Val1, const ValVariant &Val2) const; |
754 | | template <typename T> Expect<void> runVectorAbsOp(ValVariant &Val) const; |
755 | | template <typename T> Expect<void> runVectorNegOp(ValVariant &Val) const; |
756 | | inline Expect<void> runVectorPopcntOp(ValVariant &Val) const; |
757 | | template <typename T> Expect<void> runVectorSqrtOp(ValVariant &Val) const; |
758 | | template <typename TIn, typename TOut> |
759 | | Expect<void> runVectorTruncSatOp(ValVariant &Val) const; |
760 | | template <typename TIn, typename TOut> |
761 | | Expect<void> runVectorConvertOp(ValVariant &Val) const; |
762 | | inline Expect<void> runVectorDemoteOp(ValVariant &Val) const; |
763 | | inline Expect<void> runVectorPromoteOp(ValVariant &Val) const; |
764 | | inline Expect<void> runVectorAnyTrueOp(ValVariant &Val) const; |
765 | | template <typename T> Expect<void> runVectorAllTrueOp(ValVariant &Val) const; |
766 | | template <typename T> Expect<void> runVectorBitMaskOp(ValVariant &Val) const; |
767 | | template <typename TIn, typename TOut> |
768 | | Expect<void> runVectorNarrowOp(ValVariant &Val1, |
769 | | const ValVariant &Val2) const; |
770 | | template <typename TIn, typename TOut> |
771 | | Expect<void> runVectorExtendLowOp(ValVariant &Val) const; |
772 | | template <typename TIn, typename TOut> |
773 | | Expect<void> runVectorExtendHighOp(ValVariant &Val) const; |
774 | | template <typename TIn, typename TOut> |
775 | | Expect<void> runVectorExtAddPairwiseOp(ValVariant &Val) const; |
776 | | template <typename TIn, typename TOut> |
777 | | Expect<void> runVectorExtMulLowOp(ValVariant &Val1, |
778 | | const ValVariant &Val2) const; |
779 | | template <typename TIn, typename TOut> |
780 | | Expect<void> runVectorExtMulHighOp(ValVariant &Val1, |
781 | | const ValVariant &Val2) const; |
782 | | inline Expect<void> runVectorQ15MulSatOp(ValVariant &Val1, |
783 | | const ValVariant &Val2) const; |
784 | | template <typename T> |
785 | | Expect<void> runVectorShlOp(ValVariant &Val1, const ValVariant &Val2) const; |
786 | | template <typename T> |
787 | | Expect<void> runVectorShrOp(ValVariant &Val1, const ValVariant &Val2) const; |
788 | | template <typename T> |
789 | | Expect<void> runVectorAddOp(ValVariant &Val1, const ValVariant &Val2) const; |
790 | | template <typename T> |
791 | | Expect<void> runVectorAddSatOp(ValVariant &Val1, |
792 | | const ValVariant &Val2) const; |
793 | | template <typename T> |
794 | | Expect<void> runVectorSubOp(ValVariant &Val1, const ValVariant &Val2) const; |
795 | | template <typename T> |
796 | | Expect<void> runVectorSubSatOp(ValVariant &Val1, |
797 | | const ValVariant &Val2) const; |
798 | | template <typename T> |
799 | | Expect<void> runVectorMulOp(ValVariant &Val1, const ValVariant &Val2) const; |
800 | | template <typename T> |
801 | | Expect<void> runVectorDivOp(ValVariant &Val1, const ValVariant &Val2) const; |
802 | | template <typename T> |
803 | | Expect<void> runVectorMinOp(ValVariant &Val1, const ValVariant &Val2) const; |
804 | | template <typename T> |
805 | | Expect<void> runVectorMaxOp(ValVariant &Val1, const ValVariant &Val2) const; |
806 | | template <typename T> |
807 | | Expect<void> runVectorFMinOp(ValVariant &Val1, const ValVariant &Val2) const; |
808 | | template <typename T> |
809 | | Expect<void> runVectorFMaxOp(ValVariant &Val1, const ValVariant &Val2) const; |
810 | | template <typename T, typename ET> |
811 | | Expect<void> runVectorAvgrOp(ValVariant &Val1, const ValVariant &Val2) const; |
812 | | template <typename T> Expect<void> runVectorCeilOp(ValVariant &Val) const; |
813 | | template <typename T> Expect<void> runVectorFloorOp(ValVariant &Val) const; |
814 | | template <typename T> Expect<void> runVectorTruncOp(ValVariant &Val) const; |
815 | | template <typename T> Expect<void> runVectorNearestOp(ValVariant &Val) const; |
816 | | /// ======= Relaxed SIMD instructions ======= |
817 | | template <typename T> |
818 | | Expect<void> runVectorRelaxedLaneselectOp(ValVariant &Val1, |
819 | | const ValVariant &Val2, |
820 | | const ValVariant &Mask) const; |
821 | | inline Expect<void> |
822 | | runVectorRelaxedIntegerDotProductOp(ValVariant &Val1, |
823 | | const ValVariant &Val2) const; |
824 | | inline Expect<void> runVectorRelaxedIntegerDotProductOpAdd( |
825 | | ValVariant &Val1, const ValVariant &Val2, const ValVariant &C) const; |
826 | | /// ======= Atomic instructions ======= |
827 | | Expect<void> runAtomicNotifyOp(Runtime::StackManager &StackMgr, |
828 | | Runtime::Instance::MemoryInstance &MemInst, |
829 | | const AST::Instruction &Instr); |
830 | | Expect<void> runMemoryFenceOp(); |
831 | | template <typename T> |
832 | | TypeT<T> runAtomicWaitOp(Runtime::StackManager &StackMgr, |
833 | | Runtime::Instance::MemoryInstance &MemInst, |
834 | | const AST::Instruction &Instr); |
835 | | template <typename T, typename I> |
836 | | TypeT<T> runAtomicLoadOp(Runtime::StackManager &StackMgr, |
837 | | Runtime::Instance::MemoryInstance &MemInst, |
838 | | const AST::Instruction &Instr); |
839 | | template <typename T, typename I> |
840 | | TypeT<T> runAtomicStoreOp(Runtime::StackManager &StackMgr, |
841 | | Runtime::Instance::MemoryInstance &MemInst, |
842 | | const AST::Instruction &Instr); |
843 | | template <typename T, typename I> |
844 | | TypeT<T> runAtomicAddOp(Runtime::StackManager &StackMgr, |
845 | | Runtime::Instance::MemoryInstance &MemInst, |
846 | | const AST::Instruction &Instr); |
847 | | template <typename T, typename I> |
848 | | TypeT<T> runAtomicSubOp(Runtime::StackManager &StackMgr, |
849 | | Runtime::Instance::MemoryInstance &MemInst, |
850 | | const AST::Instruction &Instr); |
851 | | template <typename T, typename I> |
852 | | TypeT<T> runAtomicOrOp(Runtime::StackManager &StackMgr, |
853 | | Runtime::Instance::MemoryInstance &MemInst, |
854 | | const AST::Instruction &Instr); |
855 | | template <typename T, typename I> |
856 | | TypeT<T> runAtomicAndOp(Runtime::StackManager &StackMgr, |
857 | | Runtime::Instance::MemoryInstance &MemInst, |
858 | | const AST::Instruction &Instr); |
859 | | template <typename T, typename I> |
860 | | TypeT<T> runAtomicXorOp(Runtime::StackManager &StackMgr, |
861 | | Runtime::Instance::MemoryInstance &MemInst, |
862 | | const AST::Instruction &Instr); |
863 | | template <typename T, typename I> |
864 | | TypeT<T> runAtomicExchangeOp(Runtime::StackManager &StackMgr, |
865 | | Runtime::Instance::MemoryInstance &MemInst, |
866 | | const AST::Instruction &Instr); |
867 | | template <typename T, typename I> |
868 | | TypeT<T> |
869 | | runAtomicCompareExchangeOp(Runtime::StackManager &StackMgr, |
870 | | Runtime::Instance::MemoryInstance &MemInst, |
871 | | const AST::Instruction &Instr); |
872 | | /// @} |
873 | | |
874 | | public: |
875 | | /// \name AOT/JIT - Run compiled functions |
876 | | /// @{ |
877 | | Expect<void> proxyTrap(Runtime::StackManager &StackMgr, |
878 | | const uint32_t Code) noexcept; |
879 | | Expect<void> proxyCall(Runtime::StackManager &StackMgr, |
880 | | const uint32_t FuncIdx, const ValVariant *Args, |
881 | | ValVariant *Rets) noexcept; |
882 | | Expect<void> proxyCallIndirect(Runtime::StackManager &StackMgr, |
883 | | const uint32_t TableIdx, |
884 | | const uint32_t FuncTypeIdx, |
885 | | const uint32_t FuncIdx, const ValVariant *Args, |
886 | | ValVariant *Rets) noexcept; |
887 | | Expect<void> proxyCallRef(Runtime::StackManager &StackMgr, |
888 | | const RefVariant Ref, const ValVariant *Args, |
889 | | ValVariant *Rets) noexcept; |
890 | | Expect<RefVariant> proxyRefFunc(Runtime::StackManager &StackMgr, |
891 | | const uint32_t FuncIdx) noexcept; |
892 | | Expect<RefVariant> proxyStructNew(Runtime::StackManager &StackMgr, |
893 | | const uint32_t TypeIdx, |
894 | | const ValVariant *Args, |
895 | | const uint32_t ArgSize) noexcept; |
896 | | Expect<void> proxyStructGet(Runtime::StackManager &StackMgr, |
897 | | const RefVariant Ref, const uint32_t TypeIdx, |
898 | | const uint32_t Off, const bool IsSigned, |
899 | | ValVariant *Ret) noexcept; |
900 | | Expect<void> proxyStructSet(Runtime::StackManager &StackMgr, |
901 | | const RefVariant Ref, const uint32_t TypeIdx, |
902 | | const uint32_t Off, |
903 | | const ValVariant *Val) noexcept; |
904 | | Expect<RefVariant> proxyArrayNew(Runtime::StackManager &StackMgr, |
905 | | const uint32_t TypeIdx, |
906 | | const uint32_t Length, |
907 | | const ValVariant *Args, |
908 | | const uint32_t ArgSize) noexcept; |
909 | | Expect<RefVariant> proxyArrayNewData(Runtime::StackManager &StackMgr, |
910 | | const uint32_t TypeIdx, |
911 | | const uint32_t DataIdx, |
912 | | const uint32_t Start, |
913 | | const uint32_t Length) noexcept; |
914 | | Expect<RefVariant> proxyArrayNewElem(Runtime::StackManager &StackMgr, |
915 | | const uint32_t TypeIdx, |
916 | | const uint32_t ElemIdx, |
917 | | const uint32_t Start, |
918 | | const uint32_t Length) noexcept; |
919 | | Expect<void> proxyArrayGet(Runtime::StackManager &StackMgr, |
920 | | const RefVariant Ref, const uint32_t TypeIdx, |
921 | | const uint32_t Idx, const bool IsSigned, |
922 | | ValVariant *Ret) noexcept; |
923 | | Expect<void> proxyArraySet(Runtime::StackManager &StackMgr, |
924 | | const RefVariant Ref, const uint32_t TypeIdx, |
925 | | const uint32_t Idx, |
926 | | const ValVariant *Val) noexcept; |
927 | | Expect<uint32_t> proxyArrayLen(Runtime::StackManager &StackMgr, |
928 | | const RefVariant Ref) noexcept; |
929 | | Expect<void> proxyArrayFill(Runtime::StackManager &StackMgr, |
930 | | const RefVariant Ref, const uint32_t TypeIdx, |
931 | | const uint32_t Idx, const uint32_t Cnt, |
932 | | const ValVariant *Val) noexcept; |
933 | | Expect<void> proxyArrayCopy(Runtime::StackManager &StackMgr, |
934 | | const RefVariant DstRef, |
935 | | const uint32_t DstTypeIdx, const uint32_t DstIdx, |
936 | | const RefVariant SrcRef, |
937 | | const uint32_t SrcTypeIdx, const uint32_t SrcIdx, |
938 | | const uint32_t Cnt) noexcept; |
939 | | Expect<void> proxyArrayInitData(Runtime::StackManager &StackMgr, |
940 | | const RefVariant Ref, const uint32_t TypeIdx, |
941 | | const uint32_t DataIdx, const uint32_t DstIdx, |
942 | | const uint32_t SrcIdx, |
943 | | const uint32_t Cnt) noexcept; |
944 | | Expect<void> proxyArrayInitElem(Runtime::StackManager &StackMgr, |
945 | | const RefVariant Ref, const uint32_t TypeIdx, |
946 | | const uint32_t ElemIdx, const uint32_t DstIdx, |
947 | | const uint32_t SrcIdx, |
948 | | const uint32_t Cnt) noexcept; |
949 | | Expect<uint32_t> proxyRefTest(Runtime::StackManager &StackMgr, |
950 | | const RefVariant Ref, ValType VTTest) noexcept; |
951 | | Expect<RefVariant> proxyRefCast(Runtime::StackManager &StackMgr, |
952 | | const RefVariant Ref, |
953 | | ValType VTCast) noexcept; |
954 | | Expect<RefVariant> proxyTableGet(Runtime::StackManager &StackMgr, |
955 | | const uint32_t TableIdx, |
956 | | const uint32_t Off) noexcept; |
957 | | Expect<void> proxyTableSet(Runtime::StackManager &StackMgr, |
958 | | const uint32_t TableIdx, const uint32_t Off, |
959 | | const RefVariant Ref) noexcept; |
960 | | Expect<void> proxyTableInit(Runtime::StackManager &StackMgr, |
961 | | const uint32_t TableIdx, const uint32_t ElemIdx, |
962 | | const uint32_t DstOff, const uint32_t SrcOff, |
963 | | const uint32_t Len) noexcept; |
964 | | Expect<void> proxyElemDrop(Runtime::StackManager &StackMgr, |
965 | | const uint32_t ElemIdx) noexcept; |
966 | | Expect<void> proxyTableCopy(Runtime::StackManager &StackMgr, |
967 | | const uint32_t TableIdxDst, |
968 | | const uint32_t TableIdxSrc, const uint32_t DstOff, |
969 | | const uint32_t SrcOff, |
970 | | const uint32_t Len) noexcept; |
971 | | Expect<uint32_t> proxyTableGrow(Runtime::StackManager &StackMgr, |
972 | | const uint32_t TableIdx, const RefVariant Val, |
973 | | const uint32_t NewSize) noexcept; |
974 | | Expect<uint32_t> proxyTableSize(Runtime::StackManager &StackMgr, |
975 | | const uint32_t TableIdx) noexcept; |
976 | | Expect<void> proxyTableFill(Runtime::StackManager &StackMgr, |
977 | | const uint32_t TableIdx, const uint32_t Off, |
978 | | const RefVariant Ref, |
979 | | const uint32_t Len) noexcept; |
980 | | Expect<uint32_t> proxyMemGrow(Runtime::StackManager &StackMgr, |
981 | | const uint32_t MemIdx, |
982 | | const uint32_t NewSize) noexcept; |
983 | | Expect<uint32_t> proxyMemSize(Runtime::StackManager &StackMgr, |
984 | | const uint32_t MemIdx) noexcept; |
985 | | Expect<void> proxyMemInit(Runtime::StackManager &StackMgr, |
986 | | const uint32_t MemIdx, const uint32_t DataIdx, |
987 | | const uint32_t DstOff, const uint32_t SrcOff, |
988 | | const uint32_t Len) noexcept; |
989 | | Expect<void> proxyDataDrop(Runtime::StackManager &StackMgr, |
990 | | const uint32_t DataIdx) noexcept; |
991 | | Expect<void> proxyMemCopy(Runtime::StackManager &StackMgr, |
992 | | const uint32_t DstMemIdx, const uint32_t SrcMemIdx, |
993 | | const uint32_t DstOff, const uint32_t SrcOff, |
994 | | const uint32_t Len) noexcept; |
995 | | Expect<void> proxyMemFill(Runtime::StackManager &StackMgr, |
996 | | const uint32_t MemIdx, const uint32_t Off, |
997 | | const uint8_t Val, const uint32_t Len) noexcept; |
998 | | Expect<uint32_t> proxyMemAtomicNotify(Runtime::StackManager &StackMgr, |
999 | | const uint32_t MemIdx, |
1000 | | const uint32_t Offset, |
1001 | | const uint32_t Count) noexcept; |
1002 | | Expect<uint32_t> |
1003 | | proxyMemAtomicWait(Runtime::StackManager &StackMgr, const uint32_t MemIdx, |
1004 | | const uint32_t Offset, const uint64_t Expected, |
1005 | | const int64_t Timeout, const uint32_t BitWidth) noexcept; |
1006 | | Expect<void *> proxyTableGetFuncSymbol(Runtime::StackManager &StackMgr, |
1007 | | const uint32_t TableIdx, |
1008 | | const uint32_t FuncTypeIdx, |
1009 | | const uint32_t FuncIdx) noexcept; |
1010 | | Expect<void *> proxyRefGetFuncSymbol(Runtime::StackManager &StackMgr, |
1011 | | const RefVariant Ref) noexcept; |
1012 | | /// @} |
1013 | | |
1014 | | /// Callbacks for compiled modules |
1015 | | static const Executable::IntrinsicsTable Intrinsics; |
1016 | | /// Proxy helper template struct |
1017 | | template <typename FuncPtr> struct ProxyHelper; |
1018 | | |
1019 | | private: |
1020 | | /// Execution context for compiled functions. |
1021 | | struct ExecutionContextStruct { |
1022 | | #if WASMEDGE_ALLOCATOR_IS_STABLE |
1023 | | uint8_t *const *Memories; |
1024 | | #else |
1025 | | uint8_t **const *Memories; |
1026 | | #endif |
1027 | | ValVariant *const *Globals; |
1028 | | std::atomic_uint64_t *InstrCount; |
1029 | | uint64_t *CostTable; |
1030 | | std::atomic_uint64_t *Gas; |
1031 | | uint64_t GasLimit; |
1032 | | std::atomic_uint32_t *StopToken; |
1033 | | }; |
1034 | | |
1035 | | /// Restores thread local VM reference after overwriting it. |
1036 | | struct SavedThreadLocal { |
1037 | | SavedThreadLocal(Executor &Ex, Runtime::StackManager &StackMgr, |
1038 | | const Runtime::Instance::FunctionInstance &Func) noexcept; |
1039 | | |
1040 | | SavedThreadLocal(const SavedThreadLocal &) = delete; |
1041 | | SavedThreadLocal(SavedThreadLocal &&) = delete; |
1042 | | |
1043 | | ~SavedThreadLocal() noexcept; |
1044 | | |
1045 | | Executor *SavedThis; |
1046 | | Runtime::StackManager *SavedCurrentStack; |
1047 | | ExecutionContextStruct SavedExecutionContext; |
1048 | | }; |
1049 | | |
1050 | | /// Pointer to current object. |
1051 | | static thread_local Executor *This; |
1052 | | /// Stack for passing into compiled functions |
1053 | | static thread_local Runtime::StackManager *CurrentStack; |
1054 | | /// Execution context for compiled functions |
1055 | | static thread_local ExecutionContextStruct ExecutionContext; |
1056 | | /// Record stack track on error |
1057 | | static thread_local std::array<uint32_t, 256> StackTrace; |
1058 | | static thread_local size_t StackTraceSize; |
1059 | | |
1060 | | /// Waiter struct for atomic instructions |
1061 | | struct Waiter { |
1062 | | std::mutex Mutex; |
1063 | | std::condition_variable Cond; |
1064 | | Runtime::Instance::MemoryInstance *MemInst; |
1065 | 0 | Waiter(Runtime::Instance::MemoryInstance *Inst) noexcept : MemInst(Inst) {} |
1066 | | }; |
1067 | | /// Waiter map mutex |
1068 | | std::mutex WaiterMapMutex; |
1069 | | /// Waiter multimap |
1070 | | std::unordered_multimap<uint32_t, Waiter> WaiterMap; |
1071 | | |
1072 | | /// WasmEdge configuration |
1073 | | const Configure Conf; |
1074 | | /// Executor statistics |
1075 | | Statistics::Statistics *Stat; |
1076 | | /// Stop Execution |
1077 | | std::atomic_uint32_t StopToken = 0; |
1078 | | /// Executor Host Function Handler |
1079 | | HostFuncHandler HostFuncHelper = {}; |
1080 | | }; |
1081 | | |
1082 | | } // namespace Executor |
1083 | | } // namespace WasmEdge |
1084 | | |
1085 | | #include "engine/atomic.ipp" |
1086 | | #include "engine/binary_numeric.ipp" |
1087 | | #include "engine/cast_numeric.ipp" |
1088 | | #include "engine/memory.ipp" |
1089 | | #include "engine/relation_numeric.ipp" |
1090 | | #include "engine/unary_numeric.ipp" |