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