Coverage Report

Created: 2025-08-29 06:29

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