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