Coverage Report

Created: 2026-06-30 06:10

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/WasmEdge/include/common/errinfo.h
Line
Count
Source
1
// SPDX-License-Identifier: Apache-2.0
2
// SPDX-FileCopyrightText: Copyright The WasmEdge Authors
3
4
//===-- wasmedge/common/errinfo.h - Error information definition ----------===//
5
//
6
// Part of the WasmEdge Project.
7
//
8
//===----------------------------------------------------------------------===//
9
///
10
/// \file
11
/// This file contains the enumerations of WasmEdge error information.
12
///
13
//===----------------------------------------------------------------------===//
14
#pragma once
15
16
#include "common/enum_ast.hpp"
17
#include "common/enum_configure.hpp"
18
#include "common/enum_errcode.hpp"
19
#include "common/enum_errinfo.hpp"
20
#include "common/enum_types.hpp"
21
#include "common/filesystem.h"
22
#include "common/fmt.h"
23
#include "common/spdlog.h"
24
#include "common/types.h"
25
26
#include <iterator>
27
#if !defined(__has_include) || __has_include(<spdlog/fmt/ranges.h>)
28
#include <spdlog/fmt/ranges.h>
29
#else
30
#include <fmt/ranges.h>
31
#endif
32
33
#include <cstdint>
34
#include <iosfwd>
35
#include <limits>
36
#include <string>
37
#include <string_view>
38
#include <vector>
39
40
namespace WasmEdge {
41
namespace ErrInfo {
42
43
/// Information structures.
44
struct InfoFile {
45
  InfoFile() = delete;
46
0
  InfoFile(const std::filesystem::path &FName) noexcept : FileName(FName) {}
47
48
  std::filesystem::path FileName;
49
};
50
51
struct InfoLoading {
52
  InfoLoading() = delete;
53
5.15k
  InfoLoading(const uint64_t Off) noexcept : Offset(Off) {}
54
55
  uint64_t Offset;
56
};
57
58
struct InfoAST {
59
  InfoAST() = delete;
60
29.1k
  InfoAST(const ASTNodeAttr Attr) noexcept : NodeAttr(Attr) {}
61
62
  ASTNodeAttr NodeAttr;
63
};
64
65
struct InfoInstanceBound {
66
  InfoInstanceBound() = delete;
67
  InfoInstanceBound(const ExternalType Inst, const uint32_t Num,
68
                    const uint32_t Lim) noexcept
69
0
      : Instance(Inst), Number(Num), Limited(Lim) {}
70
71
  ExternalType Instance;
72
  uint32_t Number, Limited;
73
};
74
75
struct InfoForbidIndex {
76
  InfoForbidIndex() = delete;
77
  InfoForbidIndex(const IndexCategory Cate, const uint32_t Idx,
78
                  const uint32_t Bound) noexcept
79
598
      : Category(Cate), Index(Idx), Boundary(Bound) {}
80
81
  IndexCategory Category;
82
  uint32_t Index, Boundary;
83
};
84
85
struct InfoExporting {
86
  InfoExporting() = delete;
87
0
  InfoExporting(std::string_view Ext) noexcept : ExtName(Ext) {}
88
89
  std::string ExtName;
90
};
91
92
struct InfoLimit {
93
  InfoLimit() = delete;
94
  InfoLimit(const bool HasMax, const uint64_t Min,
95
            const uint64_t Max = 0) noexcept
96
53
      : LimHasMax(HasMax), LimMin(Min), LimMax(Max) {}
97
98
  bool LimHasMax;
99
  uint64_t LimMin, LimMax;
100
};
101
102
struct InfoRegistering {
103
  InfoRegistering() = delete;
104
0
  InfoRegistering(std::string_view Mod) noexcept : ModName(Mod) {}
105
106
  std::string ModName;
107
};
108
109
struct InfoLinking {
110
  InfoLinking() = delete;
111
  InfoLinking(std::string_view Mod, std::string_view Ext,
112
              const ExternalType ExtT = ExternalType::Function) noexcept
113
0
      : ModName(Mod), ExtName(Ext), ExtType(ExtT) {}
114
115
  std::string ModName;
116
  std::string ExtName;
117
  ExternalType ExtType;
118
};
119
120
struct InfoExecuting {
121
  InfoExecuting() = delete;
122
  InfoExecuting(std::string_view Mod, std::string_view Func) noexcept
123
0
      : ModName(Mod), FuncName(Func) {}
124
0
  InfoExecuting(std::string_view Func) noexcept : ModName(""), FuncName(Func) {}
125
126
  std::string ModName;
127
  std::string FuncName;
128
};
129
130
struct InfoMismatch {
131
  InfoMismatch() = delete;
132
133
  /// Case 1: unexpected alignment
134
  InfoMismatch(const uint8_t ExpAlign, const uint32_t GotAlign) noexcept
135
43
      : Category(MismatchCategory::Alignment), ExpAlignment(ExpAlign),
136
43
        GotAlignment(GotAlign) {}
137
138
  /// Case 2: unexpected value type
139
  InfoMismatch(const ValType &ExpVT, const ValType &GotVT) noexcept
140
663
      : Category(MismatchCategory::ValueType), ExpValType(ExpVT),
141
663
        GotValType(GotVT) {}
142
143
  /// Case 3: unexpected value type list
144
  InfoMismatch(const std::vector<ValType> &ExpV,
145
               const std::vector<ValType> &GotV) noexcept
146
17
      : Category(MismatchCategory::ValueTypes), ExpParams(ExpV),
147
17
        GotParams(GotV) {}
148
149
  /// Case 4: unexpected mutation settings
150
  InfoMismatch(const ValMut ExpM, const ValMut GotM) noexcept
151
0
      : Category(MismatchCategory::Mutation), ExpValMut(ExpM), GotValMut(GotM) {
152
0
  }
153
154
  /// Case 5: unexpected external types
155
  InfoMismatch(const ExternalType ExpExt, const ExternalType GotExt) noexcept
156
0
      : Category(MismatchCategory::ExternalType), ExpExtType(ExpExt),
157
0
        GotExtType(GotExt) {}
158
159
  /// Case 6: unexpected function types
160
  InfoMismatch(const std::vector<ValType> &ExpP,
161
               const std::vector<ValType> &ExpR,
162
               const std::vector<ValType> &GotP,
163
               const std::vector<ValType> &GotR) noexcept
164
2
      : Category(MismatchCategory::FunctionType), ExpParams(ExpP),
165
2
        GotParams(GotP), ExpReturns(ExpR), GotReturns(GotR) {}
166
167
  /// Case 7: unexpected table types
168
  InfoMismatch(const ValType &ExpRType,
169
               // Expected reference type
170
               const bool ExpHasMax, const uint64_t ExpMin,
171
               const uint64_t ExpMax,
172
               // Expected Limit
173
               const ValType &GotRType,
174
               // Got reference type
175
               const bool GotHasMax, const uint64_t GotMin,
176
               const uint64_t GotMax
177
               // Got limit
178
               ) noexcept
179
0
      : Category(MismatchCategory::Table), ExpValType(ExpRType),
180
0
        GotValType(GotRType), ExpLimHasMax(ExpHasMax), GotLimHasMax(GotHasMax),
181
0
        ExpLimMin(ExpMin), GotLimMin(GotMin), ExpLimMax(ExpMax),
182
0
        GotLimMax(GotMax) {}
183
184
  /// Case 8: unexpected memory limits
185
  InfoMismatch(const bool ExpHasMax, const uint64_t ExpMin,
186
               const uint64_t ExpMax,
187
               // Expect Limit
188
               const bool GotHasMax, const uint64_t GotMin,
189
               const uint64_t GotMax
190
               // Got limit
191
               ) noexcept
192
0
      : Category(MismatchCategory::Memory), ExpLimHasMax(ExpHasMax),
193
0
        GotLimHasMax(GotHasMax), ExpLimMin(ExpMin), GotLimMin(GotMin),
194
0
        ExpLimMax(ExpMax), GotLimMax(GotMax) {}
195
196
  /// Case 9: unexpected global types
197
  InfoMismatch(const ValType &ExpVType, const ValMut ExpVMut,
198
               const ValType &GotVType, const ValMut GotVMut) noexcept
199
0
      : Category(MismatchCategory::Global), ExpValType(ExpVType),
200
0
        GotValType(GotVType), ExpValMut(ExpVMut), GotValMut(GotVMut) {}
201
202
  /// Case 10: unexpected version
203
  InfoMismatch(const uint32_t ExpV, const uint32_t GotV) noexcept
204
0
      : Category(MismatchCategory::Version), ExpVersion(ExpV),
205
0
        GotVersion(GotV) {}
206
207
  /// Mismatched category
208
  MismatchCategory Category;
209
210
  /// Case 1: unexpected alignment
211
  uint8_t ExpAlignment;
212
  uint32_t GotAlignment;
213
214
  /// Case 5: unexpected external type
215
  ExternalType ExpExtType, GotExtType;
216
217
  /// Case 6: unexpected function type
218
  /// Case 3: unexpected value type list
219
  std::vector<ValType> ExpParams, GotParams;
220
  std::vector<ValType> ExpReturns, GotReturns;
221
222
  /// Case 2: unexpected value type
223
  /// Case 7: unexpected table type: reference type
224
  /// Case 9: unexpected global type: value type
225
  ValType ExpValType, GotValType;
226
  /// Case 4: unexpected mutation settings
227
  /// Case 9: unexpected global type: value mutation
228
  ValMut ExpValMut, GotValMut;
229
  /// Case 7 & 8: unexpected table or memory type: limit
230
  bool ExpLimHasMax, GotLimHasMax;
231
  uint64_t ExpLimMin, GotLimMin;
232
  uint64_t ExpLimMax, GotLimMax;
233
234
  /// Case 10: unexpected version
235
  uint32_t ExpVersion, GotVersion;
236
};
237
238
struct InfoInstruction {
239
  InfoInstruction() = delete;
240
  InfoInstruction(const OpCode Op, const uint64_t Off,
241
                  const std::vector<ValVariant> &ArgsVec = {},
242
                  const std::vector<ValType> &ArgsTypesVec = {},
243
                  const bool Signed = false) noexcept
244
1.73k
      : Code(Op), Offset(Off), Args(ArgsVec), ArgsTypes(ArgsTypesVec),
245
1.73k
        IsSigned(Signed) {}
246
247
  OpCode Code;
248
  uint64_t Offset;
249
  std::vector<ValVariant> Args;
250
  std::vector<ValType> ArgsTypes;
251
  bool IsSigned;
252
};
253
254
struct InfoBoundary {
255
  InfoBoundary() = delete;
256
  InfoBoundary(const uint64_t Off, const uint64_t Len = 0,
257
               const uint64_t Lim = std::numeric_limits<uint64_t>::max(),
258
               const bool IsOverflow = false) noexcept
259
0
      : IsOffsetOverflow(IsOverflow), Offset(Off), Size(Len), Limit(Lim) {}
260
261
  bool IsOffsetOverflow;
262
  uint64_t Offset;
263
  uint64_t Size;
264
  uint64_t Limit;
265
};
266
267
struct InfoProposal {
268
  InfoProposal() = delete;
269
119
  InfoProposal(Proposal P) noexcept : P(P) {}
270
271
  Proposal P;
272
};
273
274
} // namespace ErrInfo
275
} // namespace WasmEdge
276
277
template <>
278
struct fmt::formatter<WasmEdge::ErrInfo::InfoFile>
279
    : fmt::formatter<std::string_view> {
280
  template <typename FmtCtx>
281
  auto format(const WasmEdge::ErrInfo::InfoFile &Info,
282
0
              FmtCtx &Ctx) WASMEDGE_FMT_CONST noexcept -> decltype(Ctx.out()) {
283
0
    using namespace std::literals;
284
0
    fmt::memory_buffer Buffer;
285
0
    fmt::format_to(std::back_inserter(Buffer), "    File name: {}"sv,
286
0
                   Info.FileName);
287
0
    return formatter<std::string_view>::format(
288
0
        std::string_view(Buffer.data(), Buffer.size()), Ctx);
289
0
  }
290
};
291
template <>
292
struct fmt::formatter<WasmEdge::ErrInfo::InfoLoading>
293
    : fmt::formatter<std::string_view> {
294
  template <typename FmtCtx>
295
  auto format(const WasmEdge::ErrInfo::InfoLoading &Info,
296
0
              FmtCtx &Ctx) WASMEDGE_FMT_CONST noexcept -> decltype(Ctx.out()) {
297
0
    using namespace std::literals;
298
0
    fmt::memory_buffer Buffer;
299
0
    fmt::format_to(std::back_inserter(Buffer),
300
0
                   "    Bytecode offset: 0x{:08x}"sv, Info.Offset);
301
0
    return formatter<std::string_view>::format(
302
0
        std::string_view(Buffer.data(), Buffer.size()), Ctx);
303
0
  }
304
};
305
template <>
306
struct fmt::formatter<WasmEdge::ErrInfo::InfoAST>
307
    : fmt::formatter<std::string_view> {
308
  template <typename FmtCtx>
309
  auto format(const WasmEdge::ErrInfo::InfoAST &Info,
310
0
              FmtCtx &Ctx) WASMEDGE_FMT_CONST noexcept -> decltype(Ctx.out()) {
311
0
    using namespace std::literals;
312
0
    fmt::memory_buffer Buffer;
313
0
    fmt::format_to(std::back_inserter(Buffer), "    At AST node: {}"sv,
314
0
                   Info.NodeAttr);
315
0
    return formatter<std::string_view>::format(
316
0
        std::string_view(Buffer.data(), Buffer.size()), Ctx);
317
0
  }
318
};
319
template <>
320
struct fmt::formatter<WasmEdge::ErrInfo::InfoInstanceBound>
321
    : fmt::formatter<std::string_view> {
322
  template <typename FmtCtx>
323
  auto format(const WasmEdge::ErrInfo::InfoInstanceBound &Info,
324
              FmtCtx &Ctx) WASMEDGE_FMT_CONST noexcept -> decltype(Ctx.out()) {
325
    using namespace std::literals;
326
    fmt::memory_buffer Buffer;
327
    fmt::format_to(std::back_inserter(Buffer),
328
                   "    Instance {} has limited number {} , Got: {}"sv,
329
                   Info.Instance, Info.Limited, Info.Number);
330
    return formatter<std::string_view>::format(
331
        std::string_view(Buffer.data(), Buffer.size()), Ctx);
332
  }
333
};
334
template <>
335
struct fmt::formatter<WasmEdge::ErrInfo::InfoForbidIndex>
336
    : fmt::formatter<std::string_view> {
337
  template <typename FmtCtx>
338
  auto format(const WasmEdge::ErrInfo::InfoForbidIndex &Info,
339
0
              FmtCtx &Ctx) WASMEDGE_FMT_CONST noexcept -> decltype(Ctx.out()) {
340
0
    using namespace std::literals;
341
0
    fmt::memory_buffer Buffer;
342
0
    auto Iter =
343
0
        fmt::format_to(std::back_inserter(Buffer),
344
0
                       "    When checking {} index: {} , Out of boundary: "sv,
345
0
                       Info.Category, Info.Index);
346
0
    if (Info.Boundary > 0) {
347
0
      fmt::format_to(Iter, "{}"sv, Info.Boundary - 1);
348
0
    } else {
349
0
      fmt::format_to(Iter, "empty"sv);
350
0
    }
351
0
    return formatter<std::string_view>::format(
352
0
        std::string_view(Buffer.data(), Buffer.size()), Ctx);
353
0
  }
354
};
355
template <>
356
struct fmt::formatter<WasmEdge::ErrInfo::InfoExporting>
357
    : fmt::formatter<std::string_view> {
358
  template <typename FmtCtx>
359
  auto format(const WasmEdge::ErrInfo::InfoExporting &Info,
360
              FmtCtx &Ctx) WASMEDGE_FMT_CONST noexcept -> decltype(Ctx.out()) {
361
    using namespace std::literals;
362
    fmt::memory_buffer Buffer;
363
    fmt::format_to(std::back_inserter(Buffer),
364
                   "    Duplicated exporting name: \"{}\""sv, Info.ExtName);
365
    return formatter<std::string_view>::format(
366
        std::string_view(Buffer.data(), Buffer.size()), Ctx);
367
  }
368
};
369
template <>
370
struct fmt::formatter<WasmEdge::ErrInfo::InfoLimit>
371
    : fmt::formatter<std::string_view> {
372
  template <typename FmtCtx>
373
  auto format(const WasmEdge::ErrInfo::InfoLimit &Info,
374
0
              FmtCtx &Ctx) WASMEDGE_FMT_CONST noexcept -> decltype(Ctx.out()) {
375
0
    using namespace std::literals;
376
0
    fmt::memory_buffer Buffer;
377
0
    auto Iter = fmt::format_to(std::back_inserter(Buffer),
378
0
                               "    In Limit type: {{ min: {}"sv, Info.LimMin);
379
0
    if (Info.LimHasMax) {
380
0
      Iter = fmt::format_to(Iter, " , max: {}"sv, Info.LimMax);
381
0
    }
382
0
    fmt::format_to(Iter, " }}"sv);
383
0
    return formatter<std::string_view>::format(
384
0
        std::string_view(Buffer.data(), Buffer.size()), Ctx);
385
0
  }
386
};
387
template <>
388
struct fmt::formatter<WasmEdge::ErrInfo::InfoRegistering>
389
    : fmt::formatter<std::string_view> {
390
  template <typename FmtCtx>
391
  auto format(const WasmEdge::ErrInfo::InfoRegistering &Info,
392
              FmtCtx &Ctx) WASMEDGE_FMT_CONST noexcept -> decltype(Ctx.out()) {
393
    using namespace std::literals;
394
    fmt::memory_buffer Buffer;
395
    fmt::format_to(std::back_inserter(Buffer), "    Module name: \"{}\""sv,
396
                   Info.ModName);
397
    return formatter<std::string_view>::format(
398
        std::string_view(Buffer.data(), Buffer.size()), Ctx);
399
  }
400
};
401
template <>
402
struct fmt::formatter<WasmEdge::ErrInfo::InfoLinking>
403
    : fmt::formatter<std::string_view> {
404
  template <typename FmtCtx>
405
  auto format(const WasmEdge::ErrInfo::InfoLinking &Info,
406
0
              FmtCtx &Ctx) WASMEDGE_FMT_CONST noexcept -> decltype(Ctx.out()) {
407
0
    using namespace std::literals;
408
0
    fmt::memory_buffer Buffer;
409
0
    fmt::format_to(std::back_inserter(Buffer),
410
0
                   "    When linking module: \"{}\" , {} name: \"{}\""sv,
411
0
                   Info.ModName, Info.ExtType, Info.ExtName);
412
0
    return formatter<std::string_view>::format(
413
0
        std::string_view(Buffer.data(), Buffer.size()), Ctx);
414
0
  }
415
};
416
template <>
417
struct fmt::formatter<WasmEdge::ErrInfo::InfoExecuting>
418
    : fmt::formatter<std::string_view> {
419
  template <typename FmtCtx>
420
  auto format(const WasmEdge::ErrInfo::InfoExecuting &Info,
421
0
              FmtCtx &Ctx) WASMEDGE_FMT_CONST noexcept -> decltype(Ctx.out()) {
422
0
    using namespace std::literals;
423
0
    fmt::memory_buffer Buffer;
424
0
    auto Iter =
425
0
        fmt::format_to(std::back_inserter(Buffer), "    When executing "sv);
426
0
    if (!Info.ModName.empty()) {
427
0
      Iter = fmt::format_to(Iter, "module name: \"{}\" , "sv, Info.ModName);
428
0
    }
429
0
    fmt::format_to(Iter, "function name: \"{}\""sv, Info.FuncName);
430
0
    return formatter<std::string_view>::format(
431
0
        std::string_view(Buffer.data(), Buffer.size()), Ctx);
432
0
  }
433
};
434
template <>
435
struct fmt::formatter<WasmEdge::ErrInfo::InfoMismatch>
436
    : fmt::formatter<std::string_view> {
437
  template <typename FmtCtx>
438
  auto format(const WasmEdge::ErrInfo::InfoMismatch &Info,
439
0
              FmtCtx &Ctx) WASMEDGE_FMT_CONST noexcept -> decltype(Ctx.out()) {
440
0
    using namespace std::literals;
441
0
    fmt::memory_buffer Buffer;
442
0
    auto Iter = fmt::format_to(std::back_inserter(Buffer),
443
0
                               "    Mismatched {}. "sv, Info.Category);
444
0
    auto FormatLimit = [](auto Out, bool LimHasMax, uint64_t LimMin,
445
0
                          uint64_t LimMax) {
446
0
      Out = fmt::format_to(Out, "Limit{{{}"sv, LimMin);
447
0
      if (LimHasMax) {
448
0
        Out = fmt::format_to(Out, " , {}"sv, LimMax);
449
0
      }
450
0
      Out = fmt::format_to(Out, "}}"sv);
451
0
      return Out;
452
0
    };
453
0
    switch (Info.Category) {
454
0
    case WasmEdge::ErrInfo::MismatchCategory::Alignment:
455
0
      if (Info.GotAlignment < Info.ExpAlignment) {
456
0
        fmt::format_to(Iter, "Expected: need to == {} , Got: {}"sv,
457
0
                       static_cast<uint32_t>(Info.ExpAlignment),
458
0
                       static_cast<uint32_t>(Info.GotAlignment));
459
0
      } else {
460
0
        fmt::format_to(Iter, "Expected: need to <= {} , Got: {}"sv,
461
0
                       static_cast<uint32_t>(Info.ExpAlignment),
462
0
                       static_cast<uint32_t>(Info.GotAlignment));
463
0
      }
464
0
      break;
465
0
    case WasmEdge::ErrInfo::MismatchCategory::ValueType:
466
0
      fmt::format_to(Iter, "Expected: {} , Got: {}"sv, Info.ExpValType,
467
0
                     Info.GotValType);
468
0
      break;
469
0
    case WasmEdge::ErrInfo::MismatchCategory::ValueTypes:
470
0
      fmt::format_to(Iter, "Expected: types{{{}}} , Got: types{{{}}}"sv,
471
0
                     fmt::join(Info.ExpParams, " , "sv),
472
0
                     fmt::join(Info.GotParams, " , "sv));
473
0
      break;
474
0
    case WasmEdge::ErrInfo::MismatchCategory::Mutation:
475
0
      fmt::format_to(Iter, "Expected: {} , Got: {}"sv, Info.ExpValMut,
476
0
                     Info.GotValMut);
477
0
      break;
478
0
    case WasmEdge::ErrInfo::MismatchCategory::ExternalType:
479
0
      fmt::format_to(Iter, "Expected: {} , Got: {}", Info.ExpExtType,
480
0
                     Info.GotExtType);
481
0
      break;
482
0
    case WasmEdge::ErrInfo::MismatchCategory::FunctionType:
483
0
      fmt::format_to(Iter,
484
0
                     "Expected: FuncType {{params{{{}}} returns{{{}}}}} , "
485
0
                     "Got: FuncType {{params{{{}}} returns{{{}}}}}"sv,
486
0
                     fmt::join(Info.ExpParams, " , "sv),
487
0
                     fmt::join(Info.ExpReturns, " , "sv),
488
0
                     fmt::join(Info.GotParams, " , "sv),
489
0
                     fmt::join(Info.GotReturns, " , "sv));
490
0
      break;
491
0
    case WasmEdge::ErrInfo::MismatchCategory::Table:
492
0
      Iter = fmt::format_to(Iter, "Expected: TableType {{RefType{{{}}} "sv,
493
0
                            static_cast<WasmEdge::ValType>(Info.ExpValType));
494
0
      Iter =
495
0
          FormatLimit(Iter, Info.ExpLimHasMax, Info.ExpLimMin, Info.ExpLimMax);
496
0
      Iter = fmt::format_to(Iter, "}} , Got: TableType {{RefType{{{}}} "sv,
497
0
                            static_cast<WasmEdge::ValType>(Info.GotValType));
498
0
      Iter =
499
0
          FormatLimit(Iter, Info.GotLimHasMax, Info.GotLimMin, Info.GotLimMax);
500
0
      fmt::format_to(Iter, "}}"sv);
501
0
      break;
502
0
    case WasmEdge::ErrInfo::MismatchCategory::Memory:
503
0
      Iter = fmt::format_to(Iter, "Expected: MemoryType {{"sv);
504
0
      Iter =
505
0
          FormatLimit(Iter, Info.ExpLimHasMax, Info.ExpLimMin, Info.ExpLimMax);
506
0
      Iter = fmt::format_to(Iter, "}} , Got: MemoryType {{"sv);
507
0
      Iter =
508
0
          FormatLimit(Iter, Info.GotLimHasMax, Info.GotLimMin, Info.GotLimMax);
509
0
      fmt::format_to(Iter, "}}"sv);
510
0
      break;
511
0
    case WasmEdge::ErrInfo::MismatchCategory::Global:
512
0
      fmt::format_to(Iter,
513
0
                     "Expected: GlobalType {{Mutation{{{}}} ValType{{{}}}}} , "
514
0
                     "Got: GlobalType {{Mutation{{{}}} ValType{{{}}}}}"sv,
515
0
                     Info.ExpValMut, Info.ExpValType, Info.GotValMut,
516
0
                     Info.GotValType);
517
0
      break;
518
0
    case WasmEdge::ErrInfo::MismatchCategory::Version:
519
0
      fmt::format_to(Iter, "Expected: {} , Got: {}"sv, Info.ExpVersion,
520
0
                     Info.GotVersion);
521
0
      break;
522
0
    default:
523
0
      break;
524
0
    }
525
0
    return formatter<std::string_view>::format(
526
0
        std::string_view(Buffer.data(), Buffer.size()), Ctx);
527
0
  }
528
};
529
template <>
530
struct fmt::formatter<WasmEdge::ErrInfo::InfoInstruction>
531
    : fmt::formatter<std::string_view> {
532
  template <typename FmtCtx>
533
  auto format(const WasmEdge::ErrInfo::InfoInstruction &Info,
534
0
              FmtCtx &Ctx) WASMEDGE_FMT_CONST noexcept -> decltype(Ctx.out()) {
535
0
    using namespace std::literals;
536
0
    uint16_t Payload = static_cast<uint16_t>(Info.Code);
537
0
    fmt::memory_buffer Buffer;
538
0
    auto Iter = fmt::format_to(std::back_inserter(Buffer),
539
0
                               "    In instruction: {} ("sv, Info.Code);
540
0
    if ((Payload >> 8) >= static_cast<uint16_t>(0xFCU)) {
541
0
      Iter = fmt::format_to(Iter, "0x{:02x} "sv, Payload >> 8);
542
0
    }
543
0
    Iter = fmt::format_to(Iter, "0x{:02x}) , Bytecode offset: 0x{:08x}"sv,
544
0
                          Payload & 0xFFU, Info.Offset);
545
0
    if (!Info.Args.empty()) {
546
0
      Iter = fmt::format_to(Iter, " , Args: ["sv);
547
0
      for (uint32_t I = 0; I < Info.Args.size(); ++I) {
548
0
        switch (Info.ArgsTypes[I].getCode()) {
549
0
        case WasmEdge::TypeCode::I32:
550
0
          if (Info.IsSigned) {
551
0
            Iter = fmt::format_to(Iter, "{}"sv, Info.Args[I].get<int32_t>());
552
0
          } else {
553
0
            Iter = fmt::format_to(Iter, "{}"sv, Info.Args[I].get<uint32_t>());
554
0
          }
555
0
          break;
556
0
        case WasmEdge::TypeCode::I64:
557
0
          if (Info.IsSigned) {
558
0
            Iter = fmt::format_to(Iter, "{}"sv, Info.Args[I].get<int64_t>());
559
0
          } else {
560
0
            Iter = fmt::format_to(Iter, "{}"sv, Info.Args[I].get<uint64_t>());
561
0
          }
562
0
          break;
563
0
        case WasmEdge::TypeCode::F32:
564
0
          Iter = fmt::format_to(Iter, "{}"sv, Info.Args[I].get<float>());
565
0
          break;
566
0
        case WasmEdge::TypeCode::F64:
567
0
          Iter = fmt::format_to(Iter, "{}"sv, Info.Args[I].get<double>());
568
0
          break;
569
0
        case WasmEdge::TypeCode::V128: {
570
0
          const auto Value = Info.Args[I].get<WasmEdge::uint64x2_t>();
571
0
          Iter = fmt::format_to(Iter, "0x{:08x}{:08x}"sv, Value[1], Value[0]);
572
0
          break;
573
0
        }
574
0
        case WasmEdge::TypeCode::Ref:
575
0
        case WasmEdge::TypeCode::RefNull:
576
0
          Iter = fmt::format_to(Iter, "{}"sv, Info.ArgsTypes[I]);
577
0
          if (Info.Args[I].get<WasmEdge::RefVariant>().isNull()) {
578
0
            Iter = fmt::format_to(Iter, ":null"sv);
579
0
          } else {
580
0
            Iter = fmt::format_to(Iter, ":0x{:08x}"sv,
581
0
                                  Info.Args[I].get<uint64_t>());
582
0
          }
583
0
          break;
584
0
        default:
585
0
          break;
586
0
        }
587
0
        if (I < Info.Args.size() - 1) {
588
0
          Iter = fmt::format_to(Iter, " , "sv);
589
0
        }
590
0
      }
591
0
      Iter = fmt::format_to(Iter, "]"sv);
592
0
    }
593
0
    return formatter<std::string_view>::format(
594
0
        std::string_view(Buffer.data(), Buffer.size()), Ctx);
595
0
  }
596
};
597
template <>
598
struct fmt::formatter<WasmEdge::ErrInfo::InfoBoundary>
599
    : fmt::formatter<std::string_view> {
600
  template <typename FmtCtx>
601
  auto format(const WasmEdge::ErrInfo::InfoBoundary &Info,
602
0
              FmtCtx &Ctx) WASMEDGE_FMT_CONST noexcept -> decltype(Ctx.out()) {
603
0
    using namespace std::literals;
604
0
    fmt::memory_buffer Buffer;
605
0
    WasmEdge::uint128_t OffFrom = Info.Offset;
606
0
    if (Info.IsOffsetOverflow) {
607
0
      OffFrom += (WasmEdge::uint128_t(1ULL) << 64);
608
0
    }
609
0
    WasmEdge::uint128_t OffTo =
610
0
        OffFrom + WasmEdge::uint128_t(Info.Size > 0U ? Info.Size - 1U : 0U);
611
0
    uint64_t Bound = (Info.Limit > 0U ? Info.Limit - 1U : 0U);
612
#if WASMEDGE_OS_WINDOWS
613
    uint64_t OffFromHigh = static_cast<uint64_t>(OffFrom >> 64);
614
    uint64_t OffFromLow = static_cast<uint64_t>(OffFrom);
615
    uint64_t OffToHigh = static_cast<uint64_t>(OffTo >> 64);
616
    uint64_t OffToLow = static_cast<uint64_t>(OffTo);
617
    if (OffFromHigh > 0) {
618
      fmt::format_to(std::back_inserter(Buffer),
619
                     "    Accessing offset from: 0x{:8x}{:016x} to: "
620
                     "0x{:8x}{:016x} , Out of "
621
                     "boundary: 0x{:016x}"sv,
622
                     OffFromHigh, OffFromLow, OffToHigh, OffToLow, Bound);
623
    } else {
624
      fmt::format_to(
625
          std::back_inserter(Buffer),
626
          "    Accessing offset from: 0x{:08x} to: 0x{:08x} , Out of "
627
          "boundary: 0x{:08x}"sv,
628
          OffFromLow, OffToLow, Bound);
629
    }
630
#elif defined(__x86_64__) || defined(__aarch64__) ||                           \
631
    (defined(__riscv) && __riscv_xlen == 64) || defined(__s390x__)
632
    fmt::format_to(std::back_inserter(Buffer),
633
0
                   "    Accessing offset from: 0x{:08x} to: 0x{:08x} , Out of "
634
0
                   "boundary: 0x{:08x}"sv,
635
0
                   OffFrom, OffTo, Bound);
636
#else
637
    if (OffFrom.high() > 0) {
638
      fmt::format_to(std::back_inserter(Buffer),
639
                     "    Accessing offset from: 0x{:8x}{:016x} to: "
640
                     "0x{:8x}{:016x} , Out of "
641
                     "boundary: 0x{:016x}"sv,
642
                     OffFrom.high(), OffFrom.low(), OffTo.high(), OffTo.low(),
643
                     Bound);
644
    } else {
645
      fmt::format_to(
646
          std::back_inserter(Buffer),
647
          "    Accessing offset from: 0x{:08x} to: 0x{:08x} , Out of "
648
          "boundary: 0x{:08x}"sv,
649
          OffFrom.low(), OffTo.low(), Bound);
650
    }
651
#endif
652
0
    return formatter<std::string_view>::format(
653
0
        std::string_view(Buffer.data(), Buffer.size()), Ctx);
654
0
  }
655
};
656
template <>
657
struct fmt::formatter<WasmEdge::ErrInfo::InfoProposal>
658
    : fmt::formatter<std::string_view> {
659
  template <typename FmtCtx>
660
  auto format(const WasmEdge::ErrInfo::InfoProposal &Info,
661
0
              FmtCtx &Ctx) WASMEDGE_FMT_CONST noexcept -> decltype(Ctx.out()) {
662
0
    using namespace std::literals;
663
0
    fmt::memory_buffer Buffer;
664
0
    if (auto Iter = WasmEdge::ProposalStr.find(Info.P);
665
0
        Iter != WasmEdge::ProposalStr.end()) {
666
0
      fmt::format_to(
667
0
          std::back_inserter(Buffer),
668
0
          "    This instruction or syntax requires enabling {} proposal"sv,
669
0
          Iter->second);
670
0
    } else {
671
0
      fmt::format_to(std::back_inserter(Buffer),
672
0
                     "    Unknown proposal, Code 0x{:08x}"sv,
673
0
                     static_cast<uint32_t>(Info.P));
674
0
    }
675
0
    return formatter<std::string_view>::format(
676
0
        std::string_view(Buffer.data(), Buffer.size()), Ctx);
677
0
  }
678
};