Coverage Report

Created: 2025-07-01 06:18

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