Coverage Report

Created: 2025-08-25 06:58

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