/src/WasmEdge/lib/loader/ast/component/component_canonical.cpp
Line | Count | Source |
1 | | // SPDX-License-Identifier: Apache-2.0 |
2 | | // SPDX-FileCopyrightText: Copyright The WasmEdge Authors |
3 | | |
4 | | #include "loader/loader.h" |
5 | | |
6 | | #include "common/component_valtype.h" |
7 | | |
8 | | namespace WasmEdge { |
9 | | namespace Loader { |
10 | | |
11 | 323k | Expect<void> Loader::loadCanonical(AST::Component::Canonical &C) { |
12 | 323k | auto ReportError = [this](auto E) { |
13 | 416 | return logLoadError(E, FMgr.getLastOffset(), ASTNodeAttr::Comp_Canonical); |
14 | 416 | }; component_canonical.cpp:auto WasmEdge::Loader::Loader::loadCanonical(WasmEdge::AST::Component::Canonical&)::$_0::operator()<WasmEdge::ErrCode>(WasmEdge::ErrCode) const Line | Count | Source | 12 | 336 | auto ReportError = [this](auto E) { | 13 | 336 | return logLoadError(E, FMgr.getLastOffset(), ASTNodeAttr::Comp_Canonical); | 14 | 336 | }; |
component_canonical.cpp:auto WasmEdge::Loader::Loader::loadCanonical(WasmEdge::AST::Component::Canonical&)::$_0::operator()<WasmEdge::ErrCode::Value>(WasmEdge::ErrCode::Value) const Line | Count | Source | 12 | 80 | auto ReportError = [this](auto E) { | 13 | 80 | return logLoadError(E, FMgr.getLastOffset(), ASTNodeAttr::Comp_Canonical); | 14 | 80 | }; |
|
15 | | // canon ::= 0x00 0x00 f:<core:funcidx> opts:<opts> ft:<typeidx> |
16 | | // => (canon lift f opts type-index-space[ft]) |
17 | | // | 0x01 0x00 f:<funcidx> opts:<opts> |
18 | | // => (canon lower f opts (core func)) |
19 | | // | 0x02 rt:<typeidx> => (canon resource.new rt (core func)) |
20 | | // | 0x03 rt:<typeidx> => (canon resource.drop rt (core func)) |
21 | | // | 0x04 rt:<typeidx> => (canon resource.rep rt (core func)) |
22 | | // | 0x09 rs:<resultlist> opts:<opts> |
23 | | // => (canon task.return rs opts (core func)) ๐ |
24 | | // | 0x05 => (canon task.cancel (core func)) ๐ |
25 | | // | 0x0a t:<core:valtype> i:<u32> |
26 | | // => (canon context.get t i (core func)) ๐ |
27 | | // | 0x0b t:<core:valtype> i:<u32> |
28 | | // => (canon context.set t i (core func)) ๐ |
29 | | // | 0x0c 0x00 |
30 | | // => (canon thread.yield (core func)) ๐ |
31 | | // | 0x06 async?:<async?> |
32 | | // => (canon subtask.cancel async? (core func)) ๐ |
33 | | // | 0x0d => (canon subtask.drop (core func)) ๐ |
34 | | // | 0x0e t:<typeidx> => (canon stream.new t (core func)) ๐ |
35 | | // | 0x0f t:<typeidx> opts:<opts> |
36 | | // => (canon stream.read t opts (core func)) ๐ |
37 | | // | 0x10 t:<typeidx> opts:<opts> |
38 | | // => (canon stream.write t opts (core func)) ๐ |
39 | | // | 0x11 t:<typeidx> async?:<async?> |
40 | | // => (canon stream.cancel-read t async? (core func)) ๐ |
41 | | // | 0x12 t:<typeidx> async?:<async?> |
42 | | // => (canon stream.cancel-write t async? (core func)) ๐ |
43 | | // | 0x13 t:<typeidx> |
44 | | // => (canon stream.drop-readable t (core func)) ๐ |
45 | | // | 0x14 t:<typeidx> |
46 | | // => (canon stream.drop-writable t (core func)) ๐ |
47 | | // | 0x2e t:<typeidx> => (canon stream.forward t (core func)) โก๏ธ |
48 | | // | 0x15 t:<typeidx> => (canon future.new t (core func)) ๐ |
49 | | // | 0x16 t:<typeidx> opts:<opts> |
50 | | // => (canon future.read t opts (core func)) ๐ |
51 | | // | 0x17 t:<typeidx> opts:<opts> |
52 | | // => (canon future.write t opts (core func)) ๐ |
53 | | // | 0x18 t:<typeidx> async?:<async?> |
54 | | // => (canon future.cancel-read t async? (core func)) ๐ |
55 | | // | 0x19 t:<typeidx> async?:<async?> |
56 | | // => (canon future.cancel-write t async? (core func)) ๐ |
57 | | // | 0x1a t:<typeidx> |
58 | | // => (canon future.drop-readable t (core func)) ๐ |
59 | | // | 0x1b t:<typeidx> |
60 | | // => (canon future.drop-writable t (core func)) ๐ |
61 | | // | 0x2f t:<typeidx> => (canon future.forward t (core func)) โก๏ธ |
62 | | // | 0x1c opts:<opts> => (canon error-context.new opts (core func)) ๐ |
63 | | // | 0x1d opts:<opts> |
64 | | // => (canon error-context.debug-message opts (core func)) ๐ |
65 | | // | 0x1e => (canon error-context.drop (core func)) ๐ |
66 | | // | 0x1f => (canon waitable-set.new (core func)) ๐ |
67 | | // | 0x20 0x00 m:<core:memoryidx> |
68 | | // => (canon waitable-set.wait (memory m) (core func)) ๐ |
69 | | // | 0x21 0x00 m:<core:memoryidx> |
70 | | // => (canon waitable-set.poll (memory m) (core func)) ๐ |
71 | | // | 0x22 => (canon waitable-set.drop (core func)) ๐ |
72 | | // | 0x23 => (canon waitable.join (core func)) ๐ |
73 | | // | 0x24 => (canon backpressure.inc (core func)) ๐ |
74 | | // | 0x25 => (canon backpressure.dec (core func)) ๐ |
75 | | // | 0x26 => (canon thread.index (core func)) ๐งต |
76 | | // | 0x27 ft:<core:typeidx> t:<core:tableidx> |
77 | | // => (canon thread.new-indirect ft t (core func)) ๐งต |
78 | | // | 0x28 => (canon thread.resume-later (core func)) ๐งต |
79 | | // | 0x29 0x00 |
80 | | // => (canon thread.suspend (core func)) ๐งต |
81 | | // | 0x2a 0x00 |
82 | | // => (canon thread.suspend-then-resume (core func)) ๐งต |
83 | | // | 0x2b 0x00 |
84 | | // => (canon thread.yield-then-resume (core func)) ๐งต |
85 | | // | 0x2c 0x00 |
86 | | // => (canon thread.suspend-then-promote (core func)) ๐งต |
87 | | // | 0x2d 0x00 |
88 | | // => (canon thread.yield-then-promote (core func)) ๐งต |
89 | | // | 0x40 sh?:<sh?> ft:<core:typeidx> |
90 | | // => (canon thread.spawn-ref sh? ft (core func)) ๐งตโก |
91 | | // | 0x41 sh?:<sh?> ft:<core:typeidx> t:<core:tableidx> |
92 | | // => (canon thread.spawn-indirect sh? ft t (core func)) ๐งตโก |
93 | | // | 0x42 sh?:<sh?> |
94 | | // => (canon thread.available-parallelism sh? (core func)) ๐งตโก |
95 | | // async? ::= 0x00 => ฯต |
96 | | // | 0x01 => async |
97 | | // sh? ::= 0x00 => ฯต |
98 | | // | 0x01 => shared ๐งตโก |
99 | | |
100 | | // Helper: load the vestigial 0x00 of the thread.* and waitable-set.* |
101 | | // built-ins. |
102 | 323k | auto LoadReservedByte = [this, &ReportError]() -> Expect<void> { |
103 | 53.1k | EXPECTED_TRY(uint8_t B, FMgr.readByte().map_error(ReportError)); |
104 | 53.1k | if (B != 0x00) { |
105 | 7 | return ReportError(ErrCode::Value::NonZeroReservedByte); |
106 | 7 | } |
107 | 53.1k | return {}; |
108 | 53.1k | }; |
109 | | |
110 | | // Helper: load the async? immediate. |
111 | 323k | auto LoadFlagImm = [this, &ReportError, &C]() -> Expect<void> { |
112 | 6.33k | EXPECTED_TRY(uint8_t B, FMgr.readByte().map_error(ReportError)); |
113 | 6.32k | if (B == 0x00) { |
114 | 3.70k | C.setFlagImmediate(false); |
115 | 3.70k | } else if (B == 0x01) { |
116 | 2.60k | C.setFlagImmediate(true); |
117 | 2.60k | } else { |
118 | 13 | return ReportError(ErrCode::Value::MalformedCanonical); |
119 | 13 | } |
120 | 6.30k | return {}; |
121 | 6.32k | }; |
122 | | |
123 | | // Helper: load the ๐งตโก shared? flag. |
124 | 323k | auto LoadShared = [this, &ReportError]() -> Expect<void> { |
125 | 361 | EXPECTED_TRY(uint8_t B, FMgr.readByte().map_error(ReportError)); |
126 | 355 | if (B > 0x01) { |
127 | 6 | return ReportError(ErrCode::Value::MalformedCanonical); |
128 | 6 | } |
129 | 349 | return {}; |
130 | 355 | }; |
131 | | |
132 | | // Helper: load opts (vec of canonopt). |
133 | 323k | auto LoadOpts = [this, &C]() -> Expect<void> { |
134 | 19.4k | std::vector<AST::Component::CanonOpt> Opts; |
135 | 19.4k | EXPECTED_TRY(loadVec<AST::Component::Canonical>( |
136 | 19.3k | Opts, [this](AST::Component::CanonOpt &Opt) { |
137 | 19.3k | return loadCanonicalOption(Opt); |
138 | 19.3k | })); |
139 | 19.3k | C.setOptions(std::move(Opts)); |
140 | 19.3k | return {}; |
141 | 19.4k | }; |
142 | | |
143 | 323k | EXPECTED_TRY(uint8_t Flag, FMgr.readByte().map_error(ReportError)); |
144 | 323k | auto Code = static_cast<ComponentCanonOpCode>(Flag); |
145 | 323k | switch (Code) { |
146 | | |
147 | | // 0x00 0x00 f:<core:funcidx> opts:<opts> ft:<typeidx> |
148 | 8.79k | case ComponentCanonOpCode::Lift: { |
149 | 8.79k | EXPECTED_TRY(uint8_t B, FMgr.readByte().map_error(ReportError)); |
150 | 8.78k | if (unlikely(B != 0x00)) { |
151 | 23 | return ReportError(ErrCode::Value::MalformedCanonical); |
152 | 23 | } |
153 | 17.5k | EXPECTED_TRY(uint32_t Idx, FMgr.readU32().map_error(ReportError)); |
154 | 17.5k | C.setIndex(Idx); |
155 | 17.5k | EXPECTED_TRY(LoadOpts()); |
156 | 8.71k | EXPECTED_TRY(uint32_t TypeIdx, FMgr.readU32().map_error(ReportError)); |
157 | 8.70k | C.setTargetIndex(TypeIdx); |
158 | 8.70k | break; |
159 | 8.71k | } |
160 | | |
161 | | // 0x01 0x00 f:<funcidx> opts:<opts> |
162 | 2.59k | case ComponentCanonOpCode::Lower: { |
163 | 2.59k | EXPECTED_TRY(uint8_t B, FMgr.readByte().map_error(ReportError)); |
164 | 2.59k | if (unlikely(B != 0x00)) { |
165 | 7 | return ReportError(ErrCode::Value::MalformedCanonical); |
166 | 7 | } |
167 | 5.16k | EXPECTED_TRY(uint32_t Idx, FMgr.readU32().map_error(ReportError)); |
168 | 5.16k | C.setIndex(Idx); |
169 | 5.16k | EXPECTED_TRY(LoadOpts()); |
170 | 2.56k | break; |
171 | 5.16k | } |
172 | | |
173 | | // typeidx-only opcodes |
174 | 2.56k | case ComponentCanonOpCode::Resource__new: |
175 | 1.41k | case ComponentCanonOpCode::Resource__drop: |
176 | 2.16k | case ComponentCanonOpCode::Resource__rep: |
177 | 2.79k | case ComponentCanonOpCode::Stream__new: |
178 | 3.19k | case ComponentCanonOpCode::Stream__drop_readable: |
179 | 3.49k | case ComponentCanonOpCode::Stream__drop_writable: |
180 | 3.76k | case ComponentCanonOpCode::Stream__forward: |
181 | 33.7k | case ComponentCanonOpCode::Future__new: |
182 | 34.0k | case ComponentCanonOpCode::Future__drop_readable: |
183 | 227k | case ComponentCanonOpCode::Future__drop_writable: |
184 | 229k | case ComponentCanonOpCode::Future__forward: { |
185 | 229k | EXPECTED_TRY(uint32_t Idx, FMgr.readU32().map_error(ReportError)); |
186 | 229k | C.setIndex(Idx); |
187 | 229k | break; |
188 | 229k | } |
189 | | |
190 | | // no-arg opcodes |
191 | 409 | case ComponentCanonOpCode::Backpressure__inc: |
192 | 871 | case ComponentCanonOpCode::Backpressure__dec: |
193 | 1.55k | case ComponentCanonOpCode::Thread__index: |
194 | 1.85k | case ComponentCanonOpCode::Thread__resume_later: |
195 | 2.21k | case ComponentCanonOpCode::Task__cancel: |
196 | 6.07k | case ComponentCanonOpCode::Subtask__drop: |
197 | 6.91k | case ComponentCanonOpCode::Error_context__drop: |
198 | 9.62k | case ComponentCanonOpCode::Waitable_set__new: |
199 | 10.0k | case ComponentCanonOpCode::Waitable_set__drop: |
200 | 10.6k | case ComponentCanonOpCode::Waitable__join: |
201 | 10.6k | break; |
202 | | |
203 | | // 0x09 rs:<resultlist> opts:<opts> |
204 | 4.55k | case ComponentCanonOpCode::Task__return: { |
205 | | // resultlist ::= 0x00 t:<valtype> => (result t) |
206 | | // | 0x01 0x00 => ฯต |
207 | 4.55k | EXPECTED_TRY(uint8_t RFlag, FMgr.readByte().map_error(ReportError)); |
208 | 4.54k | switch (RFlag) { |
209 | 4.28k | case 0x00: { |
210 | 4.28k | ComponentValType VT; |
211 | 4.28k | EXPECTED_TRY(loadType(VT).map_error([](auto E) { |
212 | 4.27k | spdlog::error(ErrInfo::InfoAST(ASTNodeAttr::Comp_Canonical)); |
213 | 4.27k | return E; |
214 | 4.27k | })); |
215 | 4.27k | C.setResult(VT); |
216 | 4.27k | break; |
217 | 4.28k | } |
218 | 264 | case 0x01: { |
219 | 264 | EXPECTED_TRY(uint8_t B, FMgr.readByte().map_error(ReportError)); |
220 | 263 | if (B != 0x00) { |
221 | 2 | return ReportError(ErrCode::Value::MalformedCanonical); |
222 | 2 | } |
223 | 261 | C.setResult(std::nullopt); |
224 | 261 | break; |
225 | 263 | } |
226 | 1 | default: |
227 | 1 | return ReportError(ErrCode::Value::MalformedCanonical); |
228 | 4.54k | } |
229 | 4.53k | EXPECTED_TRY(LoadOpts()); |
230 | 4.51k | break; |
231 | 4.53k | } |
232 | | |
233 | | // 0x0a t:<core:valtype> i:<u32> and 0x0b t:<core:valtype> i:<u32> |
234 | 4.51k | case ComponentCanonOpCode::Context__get: |
235 | 3.25k | case ComponentCanonOpCode::Context__set: { |
236 | 3.25k | EXPECTED_TRY(ValType T, loadValType(ASTNodeAttr::Comp_Canonical)); |
237 | 3.24k | C.setContextType(T); |
238 | 3.24k | EXPECTED_TRY(uint32_t Val, FMgr.readU32().map_error(ReportError)); |
239 | 3.24k | C.setConstVal(Val); |
240 | 3.24k | break; |
241 | 3.24k | } |
242 | | |
243 | | // 0x06 async?:<async?> |
244 | 279 | case ComponentCanonOpCode::Subtask__cancel: { |
245 | 279 | EXPECTED_TRY(LoadFlagImm()); |
246 | 269 | break; |
247 | 279 | } |
248 | | |
249 | | // 0x00-suffixed opcodes |
250 | 269 | case ComponentCanonOpCode::Thread__yield: |
251 | 411 | case ComponentCanonOpCode::Thread__suspend: |
252 | 1.57k | case ComponentCanonOpCode::Thread__suspend_then_resume: |
253 | 1.91k | case ComponentCanonOpCode::Thread__yield_then_resume: |
254 | 52.6k | case ComponentCanonOpCode::Thread__suspend_then_promote: |
255 | 52.8k | case ComponentCanonOpCode::Thread__yield_then_promote: { |
256 | 52.8k | EXPECTED_TRY(LoadReservedByte()); |
257 | 52.8k | break; |
258 | 52.8k | } |
259 | | |
260 | | // typeidx + opts opcodes |
261 | 52.8k | case ComponentCanonOpCode::Stream__read: |
262 | 2.52k | case ComponentCanonOpCode::Stream__write: |
263 | 2.80k | case ComponentCanonOpCode::Future__read: |
264 | 3.07k | case ComponentCanonOpCode::Future__write: { |
265 | 3.07k | EXPECTED_TRY(uint32_t Idx, FMgr.readU32().map_error(ReportError)); |
266 | 3.06k | C.setIndex(Idx); |
267 | 3.06k | EXPECTED_TRY(LoadOpts()); |
268 | 3.04k | break; |
269 | 3.06k | } |
270 | | |
271 | | // typeidx + async? opcodes |
272 | 3.04k | case ComponentCanonOpCode::Stream__cancel_read: |
273 | 1.61k | case ComponentCanonOpCode::Stream__cancel_write: |
274 | 2.21k | case ComponentCanonOpCode::Future__cancel_read: |
275 | 6.06k | case ComponentCanonOpCode::Future__cancel_write: { |
276 | 6.06k | EXPECTED_TRY(uint32_t Idx, FMgr.readU32().map_error(ReportError)); |
277 | 6.05k | C.setIndex(Idx); |
278 | 6.05k | EXPECTED_TRY(LoadFlagImm()); |
279 | 6.03k | break; |
280 | 6.05k | } |
281 | | |
282 | | // opts-only opcodes |
283 | 6.03k | case ComponentCanonOpCode::Error_context__new: |
284 | 529 | case ComponentCanonOpCode::Error_context__debug_message: { |
285 | 529 | EXPECTED_TRY(LoadOpts()); |
286 | 485 | break; |
287 | 529 | } |
288 | | |
289 | | // 0x00 + memidx opcodes |
290 | 485 | case ComponentCanonOpCode::Waitable_set__wait: |
291 | 294 | case ComponentCanonOpCode::Waitable_set__poll: { |
292 | 294 | EXPECTED_TRY(LoadReservedByte()); |
293 | 284 | EXPECTED_TRY(uint32_t MemIdx, FMgr.readU32().map_error(ReportError)); |
294 | 279 | C.setIndex(MemIdx); |
295 | 279 | break; |
296 | 284 | } |
297 | | |
298 | | // 0x27 ft:<core:typeidx> t:<core:tableidx> |
299 | 323 | case ComponentCanonOpCode::Thread__new_indirect: { |
300 | 323 | EXPECTED_TRY(uint32_t TypeIdx, FMgr.readU32().map_error(ReportError)); |
301 | 322 | C.setIndex(TypeIdx); |
302 | 322 | EXPECTED_TRY(uint32_t TblIdx, FMgr.readU32().map_error(ReportError)); |
303 | 319 | C.setTargetIndex(TblIdx); |
304 | 319 | break; |
305 | 322 | } |
306 | | |
307 | | // ๐งตโก shared?-prefixed opcodes. The flag is parsed but not kept, because |
308 | | // these built-ins belong to shared-everything-threads and are not |
309 | | // instantiated. |
310 | 75 | case ComponentCanonOpCode::Thread__spawn_ref: { |
311 | 75 | EXPECTED_TRY(LoadShared()); |
312 | 71 | EXPECTED_TRY(uint32_t TypeIdx, FMgr.readU32().map_error(ReportError)); |
313 | 70 | C.setIndex(TypeIdx); |
314 | 70 | break; |
315 | 71 | } |
316 | 73 | case ComponentCanonOpCode::Thread__spawn_indirect: { |
317 | 73 | EXPECTED_TRY(LoadShared()); |
318 | 137 | EXPECTED_TRY(uint32_t TypeIdx, FMgr.readU32().map_error(ReportError)); |
319 | 137 | C.setIndex(TypeIdx); |
320 | 137 | EXPECTED_TRY(uint32_t TblIdx, FMgr.readU32().map_error(ReportError)); |
321 | 67 | C.setTargetIndex(TblIdx); |
322 | 67 | break; |
323 | 137 | } |
324 | 213 | case ComponentCanonOpCode::Thread__available_parallelism: |
325 | 213 | EXPECTED_TRY(LoadShared()); |
326 | 209 | break; |
327 | | |
328 | 209 | default: |
329 | 21 | return ReportError(ErrCode::Value::MalformedCanonical); |
330 | 323k | } |
331 | 322k | C.setOpCode(Code); |
332 | 322k | return {}; |
333 | 323k | } |
334 | | |
335 | 11.6k | Expect<void> Loader::loadCanonicalOption(AST::Component::CanonOpt &Opt) { |
336 | 11.6k | auto ReportError = [this](auto E) { |
337 | 114 | return logLoadError(E, FMgr.getLastOffset(), ASTNodeAttr::Comp_CanonOpt); |
338 | 114 | }; component_canonical.cpp:auto WasmEdge::Loader::Loader::loadCanonicalOption(WasmEdge::AST::Component::CanonOpt&)::$_0::operator()<WasmEdge::ErrCode>(WasmEdge::ErrCode) const Line | Count | Source | 336 | 61 | auto ReportError = [this](auto E) { | 337 | 61 | return logLoadError(E, FMgr.getLastOffset(), ASTNodeAttr::Comp_CanonOpt); | 338 | 61 | }; |
component_canonical.cpp:auto WasmEdge::Loader::Loader::loadCanonicalOption(WasmEdge::AST::Component::CanonOpt&)::$_0::operator()<WasmEdge::ErrCode::Value>(WasmEdge::ErrCode::Value) const Line | Count | Source | 336 | 53 | auto ReportError = [this](auto E) { | 337 | 53 | return logLoadError(E, FMgr.getLastOffset(), ASTNodeAttr::Comp_CanonOpt); | 338 | 53 | }; |
|
339 | | // canonopt ::= 0x00 => string-encoding=utf8 |
340 | | // | 0x01 => string-encoding=utf16 |
341 | | // | 0x02 => string-encoding=latin1+utf16 |
342 | | // | 0x03 m:<core:memidx> => (memory m) |
343 | | // | 0x04 f:<core:funcidx> => (realloc f) |
344 | | // | 0x05 f:<core:funcidx> => (post-return f) |
345 | | // | 0x06 => async ๐ |
346 | | // | 0x07 f:<core:funcidx> => (callback f) ๐ |
347 | | |
348 | 11.6k | EXPECTED_TRY(uint8_t Flag, FMgr.readByte().map_error(ReportError)); |
349 | 11.6k | const auto Code = static_cast<ComponentCanonOptCode>(Flag); |
350 | 11.6k | switch (Code) { |
351 | 5.78k | case ComponentCanonOptCode::Encode_UTF8: |
352 | 8.51k | case ComponentCanonOptCode::Encode_UTF16: |
353 | 9.10k | case ComponentCanonOptCode::Encode_Latin1: |
354 | 10.1k | case ComponentCanonOptCode::Async: |
355 | 10.1k | break; |
356 | 264 | case ComponentCanonOptCode::Memory: |
357 | 492 | case ComponentCanonOptCode::Realloc: |
358 | 1.22k | case ComponentCanonOptCode::PostReturn: |
359 | 1.44k | case ComponentCanonOptCode::Callback: { |
360 | 1.44k | EXPECTED_TRY(uint32_t Idx, FMgr.readU32().map_error(ReportError)); |
361 | 1.42k | Opt.setIndex(Idx); |
362 | 1.42k | break; |
363 | 1.44k | } |
364 | 53 | default: |
365 | 53 | return ReportError(ErrCode::Value::UnknownCanonicalOption); |
366 | 11.6k | } |
367 | 11.5k | Opt.setCode(Code); |
368 | 11.5k | return {}; |
369 | 11.6k | } |
370 | | |
371 | | } // namespace Loader |
372 | | } // namespace WasmEdge |