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