/src/WasmEdge/include/common/enum_errcode.hpp
Line | Count | Source |
1 | | // SPDX-License-Identifier: Apache-2.0 |
2 | | // SPDX-FileCopyrightText: Copyright The WasmEdge Authors |
3 | | |
4 | | //===-- wasmedge/common/enum_errcode.h - Error code C++ enumerations ------===// |
5 | | // |
6 | | // Part of the WasmEdge Project. |
7 | | // |
8 | | //===----------------------------------------------------------------------===// |
9 | | /// |
10 | | /// \file |
11 | | /// This file contains the C++ enumerations of WasmEdge error code. |
12 | | /// |
13 | | //===----------------------------------------------------------------------===// |
14 | | |
15 | | #pragma once |
16 | | |
17 | | #include "common/dense_enum_map.h" |
18 | | #include "common/fmt.h" |
19 | | #include "common/spare_enum_map.h" |
20 | | #include "common/spdlog.h" |
21 | | |
22 | | #include <cstdint> |
23 | | #include <string_view> |
24 | | |
25 | | namespace WasmEdge { |
26 | | |
27 | | /// WasmEdge runtime phasing C++ enumeration class. |
28 | | enum class WasmPhase : uint8_t { |
29 | | #define UseWasmPhase |
30 | | #define Line(NAME, VALUE, STRING) NAME = VALUE, |
31 | | #include "enum.inc" |
32 | | #undef Line |
33 | | #undef UseWasmPhase |
34 | | }; |
35 | | |
36 | | static inline constexpr auto WasmPhaseStr = []() constexpr { |
37 | | using namespace std::literals::string_view_literals; |
38 | | std::pair<WasmPhase, std::string_view> Array[] = { |
39 | | #define UseWasmPhase |
40 | | #define Line(NAME, VALUE, STRING) {WasmPhase::NAME, STRING}, |
41 | | #include "enum.inc" |
42 | | #undef Line |
43 | | #undef UseWasmPhase |
44 | | }; |
45 | | return DenseEnumMap(Array); |
46 | | }(); |
47 | | |
48 | | /// Error category C++ enumeration class. |
49 | | enum class ErrCategory : uint8_t { |
50 | | #define UseErrCategory |
51 | | #define Line(NAME, VALUE) NAME = VALUE, |
52 | | #include "enum.inc" |
53 | | #undef Line |
54 | | #undef UseErrCategory |
55 | | }; |
56 | | |
57 | | /// ErrCode wraps a compact uint32_t error code used throughout WasmEdge. |
58 | | /// |
59 | | /// Note: Parameterized error messages (e.g., embedding function names or |
60 | | /// indices into error strings) are intentionally NOT stored in this class. |
61 | | /// Adding a std::string member would prevent ErrCode from being constexpr and |
62 | | /// introduce implicit heap allocations on every copy in Expected<T, ErrCode> |
63 | | /// return paths, causing significant performance regression (~10% release, |
64 | | /// ~16% debug). See PR #4625 for benchmarks and discussion. |
65 | | /// Contextual debug information should be logged separately via spdlog instead. |
66 | | class ErrCode { |
67 | | public: |
68 | | /// Error code C++ enumeration class. |
69 | | enum class Value : uint32_t { |
70 | | #define UseErrCode |
71 | | #define Line(NAME, VALUE, STRING) NAME = VALUE, |
72 | | #include "enum.inc" |
73 | | #undef Line |
74 | | #undef UseErrCode |
75 | | }; |
76 | | |
77 | 0 | constexpr ErrCategory getCategory() const noexcept { |
78 | 0 | return static_cast<ErrCategory>(static_cast<uint8_t>(Inner.Num >> 24)); |
79 | 0 | } |
80 | 0 | constexpr uint32_t getCode() const noexcept { |
81 | 0 | return Inner.Num & 0x00FFFFFFU; |
82 | 0 | } |
83 | 0 | constexpr ErrCode::Value getEnum() const noexcept { |
84 | 0 | return getCategory() != ErrCategory::WASM |
85 | 0 | ? ErrCode::Value::UserDefError |
86 | 0 | : static_cast<ErrCode::Value>(getCode()); |
87 | 0 | } |
88 | 0 | constexpr WasmPhase getErrCodePhase() const noexcept { |
89 | 0 | return getCategory() != ErrCategory::WASM |
90 | 0 | ? WasmPhase::UserDefined |
91 | 0 | : static_cast<WasmPhase>((getCode() >> 8) & 0x0FU); |
92 | 0 | } |
93 | | |
94 | 0 | constexpr ErrCode() noexcept : Inner(0) {} |
95 | 214k | constexpr ErrCode(const ErrCode &E) noexcept : Inner(E.Inner.Num) {} |
96 | 11.5k | constexpr ErrCode(const ErrCode::Value E) noexcept : Inner(E) {} |
97 | | constexpr ErrCode(const uint32_t N) noexcept |
98 | 0 | : Inner((static_cast<uint32_t>(ErrCategory::UserLevelError) << 24) + |
99 | 0 | (N & 0x00FFFFFFU)) {} |
100 | | constexpr ErrCode(const ErrCategory C, const uint32_t N) noexcept |
101 | 0 | : Inner((static_cast<uint32_t>(C) << 24) + (N & 0x00FFFFFFU)) {} |
102 | | |
103 | | friend constexpr bool operator==(const ErrCode &LHS, |
104 | 4.31k | const ErrCode::Value &RHS) noexcept { |
105 | 4.31k | return LHS.Inner.Code == RHS; |
106 | 4.31k | } |
107 | | friend constexpr bool operator==(const ErrCode::Value &LHS, |
108 | 0 | const ErrCode &RHS) noexcept { |
109 | 0 | return RHS.Inner.Code == LHS; |
110 | 0 | } |
111 | | friend constexpr bool operator==(const ErrCode &LHS, |
112 | 0 | const ErrCode &RHS) noexcept { |
113 | 0 | return LHS.Inner.Num == RHS.Inner.Num; |
114 | 0 | } |
115 | | friend constexpr bool operator!=(const ErrCode &LHS, |
116 | 0 | const ErrCode::Value &RHS) noexcept { |
117 | 0 | return !(LHS == RHS); |
118 | 0 | } |
119 | | friend constexpr bool operator!=(const ErrCode::Value &LHS, |
120 | 0 | const ErrCode &RHS) noexcept { |
121 | 0 | return !(LHS == RHS); |
122 | 0 | } |
123 | | friend constexpr bool operator!=(const ErrCode &LHS, |
124 | 0 | const ErrCode &RHS) noexcept { |
125 | 0 | return !(LHS == RHS); |
126 | 0 | } |
127 | | constexpr ErrCode &operator=(const ErrCode &) noexcept = default; |
128 | 7.16k | constexpr operator uint32_t() const noexcept { return Inner.Num; } |
129 | | |
130 | | private: |
131 | | union InnerT { |
132 | 214k | constexpr InnerT(uint32_t Num) : Num(Num) {} |
133 | 11.5k | constexpr InnerT(ErrCode::Value Code) : Code(Code) {} |
134 | | uint32_t Num; |
135 | | ErrCode::Value Code; |
136 | | } Inner; |
137 | | }; |
138 | | |
139 | | static inline constexpr const auto ErrCodeStr = []() constexpr { |
140 | | using namespace std::literals::string_view_literals; |
141 | | std::pair<ErrCode::Value, std::string_view> Array[] = { |
142 | | #define UseErrCode |
143 | | #define Line(NAME, VALUE, STRING) {ErrCode::Value::NAME, STRING}, |
144 | | #include "enum.inc" |
145 | | #undef Line |
146 | | #undef UseErrCode |
147 | | }; |
148 | | return SpareEnumMap(Array); |
149 | | }(); |
150 | | |
151 | | } // namespace WasmEdge |
152 | | |
153 | | template <> |
154 | | struct fmt::formatter<WasmEdge::WasmPhase> : fmt::formatter<std::string_view> { |
155 | | template <typename FmtCtx> |
156 | | auto format(const WasmEdge::WasmPhase &Phase, |
157 | 0 | FmtCtx &Ctx) WASMEDGE_FMT_CONST noexcept -> decltype(Ctx.out()) { |
158 | 0 | return formatter<std::string_view>::format(WasmEdge::WasmPhaseStr[Phase], |
159 | 0 | Ctx); |
160 | 0 | } |
161 | | }; |