Coverage Report

Created: 2025-12-14 06:36

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