Coverage Report

Created: 2026-11-12 06:35

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/WasmEdge/include/common/configure.h
Line
Count
Source
1
// SPDX-License-Identifier: Apache-2.0
2
// SPDX-FileCopyrightText: Copyright The WasmEdge Authors
3
4
//===-- wasmedge/common/configure.h - Configuration class -----------------===//
5
//
6
// Part of the WasmEdge Project.
7
//
8
//===----------------------------------------------------------------------===//
9
///
10
/// \file
11
/// This file contains the configuration class of proposals, pre-registration
12
/// host functions, etc.
13
///
14
//===----------------------------------------------------------------------===//
15
#pragma once
16
17
#include "common/enum_ast.hpp"
18
#include "common/enum_configure.hpp"
19
#include "common/errcode.h"
20
#include "common/hash.h"
21
22
#include <atomic>
23
#include <bitset>
24
#include <cstdint>
25
#include <initializer_list>
26
#include <mutex>
27
#include <optional>
28
#include <shared_mutex>
29
#include <unordered_set>
30
31
namespace WasmEdge {
32
33
class CompilerConfigure {
34
public:
35
34.4k
  CompilerConfigure() noexcept = default;
36
  CompilerConfigure(const CompilerConfigure &RHS) noexcept
37
55.2k
      : OptLevel(RHS.OptLevel.load(std::memory_order_relaxed)),
38
55.2k
        OFormat(RHS.OFormat.load(std::memory_order_relaxed)),
39
55.2k
        DumpIR(RHS.DumpIR.load(std::memory_order_relaxed)),
40
55.2k
        GenericBinary(RHS.GenericBinary.load(std::memory_order_relaxed)),
41
55.2k
        Interruptible(RHS.Interruptible.load(std::memory_order_relaxed)) {}
42
43
  /// AOT compiler optimization level enum class.
44
  enum class OptimizationLevel : uint8_t {
45
    // Disable as many optimizations as possible.
46
    O0,
47
    // Optimize quickly without destroying debuggability.
48
    O1,
49
    // Optimize for fast execution as much as possible without triggering
50
    // significant incremental compile time or code size growth.
51
    O2,
52
    // Optimize for fast execution as much as possible.
53
    O3,
54
    // Optimize for small code size as much as possible without triggering
55
    // significant incremental compile time or execution time slowdowns.
56
    Os,
57
    // Optimize for small code size as much as possible.
58
    Oz
59
  };
60
0
  void setOptimizationLevel(OptimizationLevel Level) noexcept {
61
0
    OptLevel.store(Level, std::memory_order_relaxed);
62
0
  }
63
7.06k
  OptimizationLevel getOptimizationLevel() const noexcept {
64
7.06k
    return OptLevel.load(std::memory_order_relaxed);
65
7.06k
  }
66
67
  /// AOT compiler output binary format.
68
  enum class OutputFormat : uint8_t {
69
    // Native dynamic library format.
70
    Native,
71
    // WebAssembly with AOT compiled codes in custom sections.
72
    Wasm,
73
  };
74
0
  void setOutputFormat(OutputFormat Format) noexcept {
75
0
    OFormat.store(Format, std::memory_order_relaxed);
76
0
  }
77
4.70k
  OutputFormat getOutputFormat() const noexcept {
78
4.70k
    return OFormat.load(std::memory_order_relaxed);
79
4.70k
  }
80
81
0
  void setDumpIR(bool IsDump) noexcept {
82
0
    DumpIR.store(IsDump, std::memory_order_relaxed);
83
0
  }
84
85
4.70k
  bool isDumpIR() const noexcept {
86
4.70k
    return DumpIR.load(std::memory_order_relaxed);
87
4.70k
  }
88
89
0
  void setGenericBinary(bool IsGenericBinary) noexcept {
90
0
    GenericBinary.store(IsGenericBinary, std::memory_order_relaxed);
91
0
  }
92
93
4.70k
  bool isGenericBinary() const noexcept {
94
4.70k
    return GenericBinary.load(std::memory_order_relaxed);
95
4.70k
  }
96
97
0
  void setInterruptible(bool IsInterruptible) noexcept {
98
0
    Interruptible.store(IsInterruptible, std::memory_order_relaxed);
99
0
  }
100
101
10.6k
  bool isInterruptible() const noexcept {
102
10.6k
    return Interruptible.load(std::memory_order_relaxed);
103
10.6k
  }
104
105
private:
106
  std::atomic<OptimizationLevel> OptLevel = OptimizationLevel::O3;
107
  std::atomic<OutputFormat> OFormat = OutputFormat::Wasm;
108
  std::atomic<bool> DumpIR = false;
109
  std::atomic<bool> GenericBinary = false;
110
  std::atomic<bool> Interruptible = false;
111
};
112
113
class RuntimeConfigure {
114
public:
115
  /// Stack budgets used when MaxStackSize is 0: the interpreter's heap stack
116
  /// and the native stack of compiled code.
117
  static constexpr uint64_t DefaultInterpreterStackSize = UINT64_C(8) << 20;
118
  static constexpr uint64_t DefaultCompiledStackSize = UINT64_C(512) << 10;
119
120
34.4k
  RuntimeConfigure() noexcept = default;
121
  RuntimeConfigure(const RuntimeConfigure &RHS) noexcept
122
55.2k
      : MaxMemPage(RHS.MaxMemPage.load(std::memory_order_relaxed)),
123
55.2k
        MaxStackSize(RHS.MaxStackSize.load(std::memory_order_relaxed)),
124
55.2k
        Mode(RHS.Mode.load(std::memory_order_relaxed)),
125
55.2k
        EnableCoredump(RHS.EnableCoredump.load(std::memory_order_relaxed)),
126
55.2k
        CoredumpWasmgdb(RHS.CoredumpWasmgdb.load(std::memory_order_relaxed)),
127
55.2k
        AllowAFUNIX(RHS.AllowAFUNIX.load(std::memory_order_relaxed)) {}
128
129
0
  void setMaxMemoryPage(const uint64_t Page) noexcept {
130
0
    MaxMemPage.store(Page, std::memory_order_relaxed);
131
0
  }
132
133
0
  uint64_t getMaxMemoryPage() const noexcept {
134
0
    return MaxMemPage.load(std::memory_order_relaxed);
135
0
  }
136
137
0
  void setMaxStackSize(const uint64_t Size) noexcept {
138
0
    MaxStackSize.store(Size, std::memory_order_relaxed);
139
0
  }
140
141
0
  uint64_t getMaxStackSize() const noexcept {
142
0
    return MaxStackSize.load(std::memory_order_relaxed);
143
0
  }
144
145
9.37k
  void setRunMode(RunMode M) noexcept {
146
9.37k
    Mode.store(M, std::memory_order_relaxed);
147
9.37k
  }
148
149
74.6k
  RunMode getRunMode() const noexcept {
150
74.6k
    return Mode.load(std::memory_order_relaxed);
151
74.6k
  }
152
153
0
  void setEnableCoredump(bool IsEnableCoredump) noexcept {
154
0
    EnableCoredump.store(IsEnableCoredump, std::memory_order_relaxed);
155
0
  }
156
157
0
  bool isEnableCoredump() const noexcept {
158
0
    return EnableCoredump.load(std::memory_order_relaxed);
159
0
  }
160
161
0
  void setCoredumpWasmgdb(bool IsCoredumpWasmgdb) noexcept {
162
0
    CoredumpWasmgdb.store(IsCoredumpWasmgdb, std::memory_order_relaxed);
163
0
  }
164
165
0
  bool isCoredumpWasmgdb() const noexcept {
166
0
    return CoredumpWasmgdb.load(std::memory_order_relaxed);
167
0
  }
168
169
0
  void setAllowAFUNIX(bool IsAllowAFUNIX) noexcept {
170
0
    AllowAFUNIX.store(IsAllowAFUNIX, std::memory_order_relaxed);
171
0
  }
172
173
0
  bool isAllowAFUNIX() const noexcept {
174
0
    return AllowAFUNIX.load(std::memory_order_relaxed);
175
0
  }
176
177
private:
178
  std::atomic<uint64_t> MaxMemPage = 65536;
179
  // Max stack bytes per execution: heap stack (interpreter) or native stack
180
  // (compiled). 0 selects the engine default.
181
  std::atomic<uint64_t> MaxStackSize = 0;
182
  std::atomic<RunMode> Mode = RunMode::Interpreter;
183
  std::atomic<bool> EnableCoredump = false;
184
  std::atomic<bool> CoredumpWasmgdb = false;
185
  std::atomic<bool> AllowAFUNIX = false;
186
};
187
188
class StatisticsConfigure {
189
public:
190
34.4k
  StatisticsConfigure() noexcept = default;
191
  StatisticsConfigure(const StatisticsConfigure &RHS) noexcept
192
55.2k
      : InstrCounting(RHS.InstrCounting.load(std::memory_order_relaxed)),
193
55.2k
        CostMeasuring(RHS.CostMeasuring.load(std::memory_order_relaxed)),
194
55.2k
        TimeMeasuring(RHS.TimeMeasuring.load(std::memory_order_relaxed)) {}
195
196
0
  void setInstructionCounting(bool IsCount) noexcept {
197
0
    InstrCounting.store(IsCount, std::memory_order_relaxed);
198
0
  }
199
200
10.6k
  bool isInstructionCounting() const noexcept {
201
10.6k
    return InstrCounting.load(std::memory_order_relaxed);
202
10.6k
  }
203
204
0
  void setCostMeasuring(bool IsMeasure) noexcept {
205
0
    CostMeasuring.store(IsMeasure, std::memory_order_relaxed);
206
0
  }
207
208
10.6k
  bool isCostMeasuring() const noexcept {
209
10.6k
    return CostMeasuring.load(std::memory_order_relaxed);
210
10.6k
  }
211
212
0
  void setTimeMeasuring(bool IsTimeMeasure) noexcept {
213
0
    TimeMeasuring.store(IsTimeMeasure, std::memory_order_relaxed);
214
0
  }
215
216
0
  bool isTimeMeasuring() const noexcept {
217
0
    return TimeMeasuring.load(std::memory_order_relaxed);
218
0
  }
219
220
0
  void setCostLimit(uint64_t Cost) noexcept {
221
0
    CostLimit.store(Cost, std::memory_order_relaxed);
222
0
  }
223
224
0
  uint64_t getCostLimit() const noexcept {
225
0
    return CostLimit.load(std::memory_order_relaxed);
226
0
  }
227
228
private:
229
  std::atomic<bool> InstrCounting = false;
230
  std::atomic<bool> CostMeasuring = false;
231
  std::atomic<bool> TimeMeasuring = false;
232
233
  std::atomic<uint64_t> CostLimit = std::numeric_limits<uint64_t>::max();
234
};
235
236
class Configure {
237
public:
238
34.4k
  Configure() noexcept {
239
34.4k
    unsafeAddProposal(Proposal::ImportExportMutGlobals);
240
34.4k
    unsafeAddProposal(Proposal::NonTrapFloatToIntConversions);
241
34.4k
    unsafeAddProposal(Proposal::SignExtensionOperators);
242
34.4k
    unsafeAddProposal(Proposal::MultiValue);
243
34.4k
    unsafeAddProposal(Proposal::BulkMemoryOperations);
244
34.4k
    unsafeAddProposal(Proposal::ReferenceTypes);
245
34.4k
    unsafeAddProposal(Proposal::SIMD);
246
34.4k
    unsafeAddProposal(Proposal::TailCall);
247
34.4k
    unsafeAddProposal(Proposal::ExtendedConst);
248
34.4k
    unsafeAddProposal(Proposal::FunctionReferences);
249
34.4k
    unsafeAddProposal(Proposal::GC);
250
34.4k
    unsafeAddProposal(Proposal::MultiMemories);
251
34.4k
    unsafeAddProposal(Proposal::RelaxSIMD);
252
    // unsafeAddProposal(Proposal::Annotations);    Not implemented
253
34.4k
    unsafeAddProposal(Proposal::ExceptionHandling);
254
34.4k
    unsafeAddProposal(Proposal::Memory64);
255
34.4k
  }
256
  template <typename... ArgsT> Configure(ArgsT... Args) noexcept : Configure() {
257
    (unsafeAddSet(Args), ...);
258
  }
259
  Configure(const Configure &RHS) noexcept
260
55.2k
      : Proposals(RHS.Proposals), Hosts(RHS.Hosts),
261
55.2k
        ForbiddenPlugins(RHS.ForbiddenPlugins), CompilerConf(RHS.CompilerConf),
262
55.2k
        RuntimeConf(RHS.RuntimeConf), StatisticsConf(RHS.StatisticsConf) {}
263
264
25.0k
  void addProposal(const Proposal Type) noexcept {
265
25.0k
    std::unique_lock Lock(Mutex);
266
25.0k
    unsafeAddProposal(Type);
267
25.0k
  }
268
269
0
  void removeProposal(const Proposal Type) noexcept {
270
0
    std::unique_lock Lock(Mutex);
271
0
    if (Type == Proposal::FunctionReferences &&
272
0
        Proposals.test(static_cast<uint8_t>(Proposal::GC))) {
273
0
      // Proposal dependency: GC depends FunctionReferences.
274
0
      return;
275
0
    }
276
0
    if (Type == Proposal::ReferenceTypes &&
277
0
        (Proposals.test(static_cast<uint8_t>(Proposal::GC)) ||
278
0
         Proposals.test(static_cast<uint8_t>(Proposal::FunctionReferences)))) {
279
0
      // Proposal dependency: GC and FunctionReferences depend on
280
0
      // ReferenceTypes.
281
0
      return;
282
0
    }
283
0
    Proposals.reset(static_cast<uint8_t>(Type));
284
0
  }
285
286
0
  void setWASMStandard(const Standard Std) noexcept {
287
0
    std::unique_lock Lock(Mutex);
288
0
    switch (Std) {
289
0
    case Standard::WASM_1:
290
0
      Proposals.reset();
291
0
      unsafeAddProposal(Proposal::ImportExportMutGlobals);
292
0
      break;
293
0
    case Standard::WASM_2:
294
0
      Proposals.reset();
295
0
      unsafeAddProposal(Proposal::ImportExportMutGlobals);
296
0
      unsafeAddProposal(Proposal::NonTrapFloatToIntConversions);
297
0
      unsafeAddProposal(Proposal::SignExtensionOperators);
298
0
      unsafeAddProposal(Proposal::MultiValue);
299
0
      unsafeAddProposal(Proposal::BulkMemoryOperations);
300
0
      unsafeAddProposal(Proposal::ReferenceTypes);
301
0
      unsafeAddProposal(Proposal::SIMD);
302
0
      break;
303
0
    case Standard::WASM_3:
304
0
      Proposals.reset();
305
0
      unsafeAddProposal(Proposal::ImportExportMutGlobals);
306
0
      unsafeAddProposal(Proposal::NonTrapFloatToIntConversions);
307
0
      unsafeAddProposal(Proposal::SignExtensionOperators);
308
0
      unsafeAddProposal(Proposal::MultiValue);
309
0
      unsafeAddProposal(Proposal::BulkMemoryOperations);
310
0
      unsafeAddProposal(Proposal::ReferenceTypes);
311
0
      unsafeAddProposal(Proposal::SIMD);
312
0
      unsafeAddProposal(Proposal::TailCall);
313
0
      unsafeAddProposal(Proposal::ExtendedConst);
314
0
      unsafeAddProposal(Proposal::FunctionReferences);
315
0
      unsafeAddProposal(Proposal::GC);
316
0
      unsafeAddProposal(Proposal::MultiMemories);
317
0
      unsafeAddProposal(Proposal::RelaxSIMD);
318
0
      // unsafeAddProposal(Proposal::Annotations);    Not implemented
319
0
      unsafeAddProposal(Proposal::ExceptionHandling);
320
0
      unsafeAddProposal(Proposal::Memory64);
321
0
      break;
322
0
    default:
323
0
      break;
324
0
    }
325
0
  }
326
327
8.85M
  bool hasProposal(const Proposal Type) const noexcept {
328
8.85M
    std::shared_lock Lock(Mutex);
329
8.85M
    return Proposals.test(static_cast<uint8_t>(Type));
330
8.85M
  }
331
332
0
  void addHostRegistration(const HostRegistration Host) noexcept {
333
0
    std::unique_lock Lock(Mutex);
334
0
    Hosts.set(static_cast<uint8_t>(Host));
335
0
  }
336
337
0
  void removeHostRegistration(const HostRegistration Host) noexcept {
338
0
    std::unique_lock Lock(Mutex);
339
0
    Hosts.reset(static_cast<uint8_t>(Host));
340
0
  }
341
342
0
  void addForbiddenPlugins(std::string PluginName) noexcept {
343
0
    std::unique_lock Lock(Mutex);
344
0
    ForbiddenPlugins.emplace(std::move(PluginName));
345
0
  }
346
347
0
  bool isForbiddenPlugins(const std::string &PluginName) const noexcept {
348
0
    std::shared_lock Lock(Mutex);
349
0
    return ForbiddenPlugins.find(PluginName) != ForbiddenPlugins.end();
350
0
  }
351
352
0
  bool hasHostRegistration(const HostRegistration Host) const noexcept {
353
0
    std::shared_lock Lock(Mutex);
354
0
    return Hosts.test(static_cast<uint8_t>(Host));
355
0
  }
356
357
31.7k
  const CompilerConfigure &getCompilerConfigure() const noexcept {
358
31.7k
    return CompilerConf;
359
31.7k
  }
360
0
  CompilerConfigure &getCompilerConfigure() noexcept { return CompilerConf; }
361
362
74.6k
  const RuntimeConfigure &getRuntimeConfigure() const noexcept {
363
74.6k
    return RuntimeConf;
364
74.6k
  }
365
9.37k
  RuntimeConfigure &getRuntimeConfigure() noexcept { return RuntimeConf; }
366
367
21.2k
  const StatisticsConfigure &getStatisticsConfigure() const noexcept {
368
21.2k
    return StatisticsConf;
369
21.2k
  }
370
0
  StatisticsConfigure &getStatisticsConfigure() noexcept {
371
0
    return StatisticsConf;
372
0
  }
373
374
  /// Helper function for checking instruction proposals.
375
40.9M
  std::optional<Proposal> isInstrNeedProposal(OpCode Code) const noexcept {
376
40.9M
    if (Code >= OpCode::I64__add128 && Code <= OpCode::I64__mul_wide_u &&
377
12
        !hasProposal(Proposal::WideArithmetic)) {
378
12
      return Proposal::WideArithmetic;
379
12
    }
380
40.9M
    if (Code >= OpCode::I32__trunc_sat_f32_s &&
381
2.03M
        Code <= OpCode::I64__trunc_sat_f64_u) {
382
      // These instructions are for NonTrapFloatToIntConversions proposal.
383
34.5k
      if (unlikely(!hasProposal(Proposal::NonTrapFloatToIntConversions))) {
384
0
        return Proposal::NonTrapFloatToIntConversions;
385
0
      }
386
40.8M
    } else if (Code >= OpCode::I32__extend8_s &&
387
2.29M
               Code <= OpCode::I64__extend32_s) {
388
      // These instructions are for SignExtensionOperators proposal.
389
167k
      if (unlikely(!hasProposal(Proposal::SignExtensionOperators))) {
390
0
        return Proposal::SignExtensionOperators;
391
0
      }
392
40.7M
    } else if ((Code >= OpCode::Ref__null && Code <= OpCode::Ref__func) ||
393
40.6M
               (Code >= OpCode::Table__init && Code <= OpCode::Table__copy) ||
394
40.6M
               (Code >= OpCode::Memory__init && Code <= OpCode::Memory__fill)) {
395
      // These instructions are for ReferenceTypes or BulkMemoryOperations
396
      // proposal.
397
55.3k
      if (unlikely(!hasProposal(Proposal::ReferenceTypes)) &&
398
0
          unlikely(!hasProposal(Proposal::BulkMemoryOperations))) {
399
0
        return Proposal::ReferenceTypes;
400
0
      }
401
40.6M
    } else if (Code == OpCode::Select_t ||
402
40.6M
               (Code >= OpCode::Table__get && Code <= OpCode::Table__set) ||
403
40.5M
               (Code >= OpCode::Table__grow && Code <= OpCode::Table__fill)) {
404
      // These instructions are for ReferenceTypes proposal.
405
104k
      if (unlikely(!hasProposal(Proposal::ReferenceTypes))) {
406
0
        return Proposal::ReferenceTypes;
407
0
      }
408
40.5M
    } else if (Code >= OpCode::V128__load &&
409
1.97M
               Code <= OpCode::F64x2__convert_low_i32x4_u) {
410
      // These instructions are for SIMD proposal.
411
1.92M
      if (unlikely(!hasProposal(Proposal::SIMD))) {
412
0
        return Proposal::SIMD;
413
0
      }
414
38.6M
    } else if (Code >= OpCode::I8x16__relaxed_swizzle &&
415
49.3k
               Code <= OpCode::I32x4__relaxed_dot_i8x16_i7x16_add_s) {
416
      // These instructions are for Relaxed SIMD proposal.
417
30.2k
      if (unlikely(!hasProposal(Proposal::RelaxSIMD))) {
418
0
        return Proposal::RelaxSIMD;
419
0
      }
420
38.6M
    } else if (Code == OpCode::Return_call ||
421
38.5M
               Code == OpCode::Return_call_indirect) {
422
      // These instructions are for TailCall proposal.
423
40.1k
      if (unlikely(!hasProposal(Proposal::TailCall))) {
424
0
        return Proposal::TailCall;
425
0
      }
426
38.5M
    } else if (Code >= OpCode::I32__atomic__load &&
427
245
               Code <= OpCode::I64__atomic__rmw32__cmpxchg_u) {
428
      // These instructions are for Thread proposal.
429
245
      if (!hasProposal(Proposal::Threads)) {
430
245
        return Proposal::Threads;
431
245
      }
432
38.5M
    } else if (Code == OpCode::Call_ref || Code == OpCode::Return_call_ref ||
433
38.4M
               Code == OpCode::Ref__as_non_null || Code == OpCode::Br_on_null ||
434
38.4M
               Code == OpCode::Br_on_non_null) {
435
      // These instructions are for TypedFunctionReferences proposal.
436
98.4k
      if (unlikely(!hasProposal(Proposal::FunctionReferences))) {
437
0
        return Proposal::FunctionReferences;
438
0
      }
439
98.4k
      if (Code == OpCode::Return_call_ref && !hasProposal(Proposal::TailCall)) {
440
0
        return Proposal::TailCall;
441
0
      }
442
38.4M
    } else if (Code == OpCode::Ref__eq ||
443
38.4M
               (Code >= OpCode::Struct__new && Code <= OpCode::I31__get_u)) {
444
      // These instructions are for GC proposal.
445
62.0k
      if (unlikely(!hasProposal(Proposal::GC))) {
446
0
        return Proposal::GC;
447
0
      }
448
38.4M
    } else if (Code == OpCode::Throw || Code == OpCode::Throw_ref ||
449
38.3M
               Code == OpCode::Try_table) {
450
      // These instructions are for ExceptionHandling proposal.
451
91.8k
      if (unlikely(!hasProposal(Proposal::ExceptionHandling))) {
452
0
        return Proposal::ExceptionHandling;
453
0
      }
454
91.8k
    }
455
40.9M
    return {};
456
40.9M
  }
457
458
private:
459
0
  void unsafeAddSet(const Proposal P) noexcept { unsafeAddProposal(P); }
460
0
  void unsafeAddSet(const HostRegistration H) noexcept {
461
0
    unsafeAddHostRegistration(H);
462
0
  }
463
464
541k
  void unsafeAddProposal(const Proposal Type) noexcept {
465
541k
    Proposals.set(static_cast<uint8_t>(Type));
466
    // Proposal dependency: FunctionReferences depends on ReferenceTypes.
467
541k
    if (Type == Proposal::FunctionReferences) {
468
34.4k
      Proposals.set(static_cast<uint8_t>(Proposal::ReferenceTypes));
469
34.4k
    }
470
    // Proposal dependency: GC depends on FunctionReferences and ReferenceTypes.
471
541k
    if (Type == Proposal::GC) {
472
34.4k
      Proposals.set(static_cast<uint8_t>(Proposal::FunctionReferences));
473
34.4k
      Proposals.set(static_cast<uint8_t>(Proposal::ReferenceTypes));
474
34.4k
    }
475
541k
  }
476
477
0
  void unsafeAddHostRegistration(const HostRegistration Host) noexcept {
478
0
    Hosts.set(static_cast<uint8_t>(Host));
479
0
  }
480
481
  mutable std::shared_mutex Mutex;
482
  std::bitset<static_cast<uint8_t>(Proposal::Max)> Proposals;
483
  std::bitset<static_cast<uint8_t>(HostRegistration::Max)> Hosts;
484
  std::unordered_set<std::string, Hash::Hash> ForbiddenPlugins;
485
486
  CompilerConfigure CompilerConf;
487
  RuntimeConfigure RuntimeConf;
488
  StatisticsConfigure StatisticsConf;
489
};
490
491
} // namespace WasmEdge