/src/WasmEdge/include/ast/component/canonical.h
Line | Count | Source |
1 | | // SPDX-License-Identifier: Apache-2.0 |
2 | | // SPDX-FileCopyrightText: Copyright The WasmEdge Authors |
3 | | |
4 | | //===-- wasmedge/ast/component/canonical.h - Canon class definitions ------===// |
5 | | // |
6 | | // Part of the WasmEdge Project. |
7 | | // |
8 | | //===----------------------------------------------------------------------===// |
9 | | /// |
10 | | /// \file |
11 | | /// This file contains the declaration of the Canon node related classes. |
12 | | /// |
13 | | //===----------------------------------------------------------------------===// |
14 | | #pragma once |
15 | | |
16 | | #include "ast/component/valtype.h" |
17 | | #include "common/component_valtype.h" |
18 | | #include "common/enum_ast.hpp" |
19 | | #include "common/span.h" |
20 | | #include "common/types.h" |
21 | | |
22 | | #include <cstdint> |
23 | | #include <optional> |
24 | | #include <utility> |
25 | | #include <vector> |
26 | | |
27 | | namespace WasmEdge { |
28 | | namespace AST { |
29 | | namespace Component { |
30 | | |
31 | | // canonopt ::= 0x00 => string-encoding=utf8 |
32 | | // | 0x01 => string-encoding=utf16 |
33 | | // | 0x02 => string-encoding=latin1+utf16 |
34 | | // | 0x03 m:<core:memidx> => (memory m) |
35 | | // | 0x04 f:<core:funcidx> => (realloc f) |
36 | | // | 0x05 f:<core:funcidx> => (post-return f) |
37 | | // | 0x06 => async ๐ |
38 | | // | 0x07 f:<core:funcidx> => (callback f) ๐ |
39 | | |
40 | | /// AST Component::CanonOpt definition. |
41 | | class CanonOpt { |
42 | | public: |
43 | 1.56M | CanonOpt() noexcept : Code(ComponentCanonOptCode::Encode_UTF8), Idx(0) {} |
44 | | |
45 | 40.0k | ComponentCanonOptCode getCode() const noexcept { return Code; } |
46 | 11.5k | void setCode(const ComponentCanonOptCode C) noexcept { Code = C; } |
47 | | |
48 | 460 | uint32_t getIndex() const noexcept { return Idx; } |
49 | 1.42k | void setIndex(const uint32_t I) noexcept { Idx = I; } |
50 | | |
51 | | private: |
52 | | ComponentCanonOptCode Code; |
53 | | uint32_t Idx; |
54 | | }; |
55 | | |
56 | | // canon ::= 0x00 0x00 f:<core:funcidx> opts:<opts> ft:<typeidx> |
57 | | // => (canon lift f opts type-index-space[ft]) |
58 | | // | 0x01 0x00 f:<funcidx> opts:<opts> |
59 | | // => (canon lower f opts (core func)) |
60 | | // | 0x02 rt:<typeidx> => (canon resource.new rt (core func)) |
61 | | // | 0x03 rt:<typeidx> => (canon resource.drop rt (core func)) |
62 | | // | 0x04 rt:<typeidx> => (canon resource.rep rt (core func)) |
63 | | // | 0x09 rs:<resultlist> opts:<opts> |
64 | | // => (canon task.return rs opts (core func)) ๐ |
65 | | // | 0x05 => (canon task.cancel (core func)) ๐ |
66 | | // | 0x0a t:<core:valtype> i:<u32> |
67 | | // => (canon context.get t i (core func)) ๐ |
68 | | // | 0x0b t:<core:valtype> i:<u32> |
69 | | // => (canon context.set t i (core func)) ๐ |
70 | | // | 0x0c 0x00 |
71 | | // => (canon thread.yield (core func)) ๐ |
72 | | // | 0x06 async?:<async?> |
73 | | // => (canon subtask.cancel async? (core func)) ๐ |
74 | | // | 0x0d => (canon subtask.drop (core func)) ๐ |
75 | | // | 0x0e t:<typeidx> => (canon stream.new t (core func)) ๐ |
76 | | // | 0x0f t:<typeidx> opts:<opts> |
77 | | // => (canon stream.read t opts (core func)) ๐ |
78 | | // | 0x10 t:<typeidx> opts:<opts> |
79 | | // => (canon stream.write t opts (core func)) ๐ |
80 | | // | 0x11 t:<typeidx> async?:<async?> |
81 | | // => (canon stream.cancel-read t async? (core func)) ๐ |
82 | | // | 0x12 t:<typeidx> async?:<async?> |
83 | | // => (canon stream.cancel-write t async? (core func)) ๐ |
84 | | // | 0x13 t:<typeidx> => (canon stream.drop-readable t (core func)) ๐ |
85 | | // | 0x14 t:<typeidx> => (canon stream.drop-writable t (core func)) ๐ |
86 | | // | 0x2e t:<typeidx> => (canon stream.forward t (core func)) โก๏ธ |
87 | | // | 0x15 t:<typeidx> => (canon future.new t (core func)) ๐ |
88 | | // | 0x16 t:<typeidx> opts:<opts> |
89 | | // => (canon future.read t opts (core func)) ๐ |
90 | | // | 0x17 t:<typeidx> opts:<opts> |
91 | | // => (canon future.write t opts (core func)) ๐ |
92 | | // | 0x18 t:<typeidx> async?:<async?> |
93 | | // => (canon future.cancel-read t async? (core func)) ๐ |
94 | | // | 0x19 t:<typeidx> async?:<async?> |
95 | | // => (canon future.cancel-write t async? (core func)) ๐ |
96 | | // | 0x1a t:<typeidx> => (canon future.drop-readable t (core func)) ๐ |
97 | | // | 0x1b t:<typeidx> => (canon future.drop-writable t (core func)) ๐ |
98 | | // | 0x2f t:<typeidx> => (canon future.forward t (core func)) โก๏ธ |
99 | | // | 0x1c opts:<opts> => (canon error-context.new opts (core func)) ๐ |
100 | | // | 0x1d opts:<opts> |
101 | | // => (canon error-context.debug-message opts (core func)) ๐ |
102 | | // | 0x1e => (canon error-context.drop (core func)) ๐ |
103 | | // | 0x1f => (canon waitable-set.new (core func)) ๐ |
104 | | // | 0x20 0x00 m:<core:memoryidx> |
105 | | // => (canon waitable-set.wait (memory m) (core func)) ๐ |
106 | | // | 0x21 0x00 m:<core:memoryidx> |
107 | | // => (canon waitable-set.poll (memory m) (core func)) ๐ |
108 | | // | 0x22 => (canon waitable-set.drop (core func)) ๐ |
109 | | // | 0x23 => (canon waitable.join (core func)) ๐ |
110 | | // | 0x24 => (canon backpressure.inc (core func)) ๐ |
111 | | // | 0x25 => (canon backpressure.dec (core func)) ๐ |
112 | | // | 0x26 => (canon thread.index (core func)) ๐งต |
113 | | // | 0x27 ft:<core:typeidx> t:<core:tableidx> |
114 | | // => (canon thread.new-indirect ft t (core func)) ๐งต |
115 | | // | 0x28 => (canon thread.resume-later (core func)) ๐งต |
116 | | // | 0x29 0x00 |
117 | | // => (canon thread.suspend (core func)) ๐งต |
118 | | // | 0x2a 0x00 |
119 | | // => (canon thread.suspend-then-resume (core func)) ๐งต |
120 | | // | 0x2b 0x00 |
121 | | // => (canon thread.yield-then-resume (core func)) ๐งต |
122 | | // | 0x2c 0x00 |
123 | | // => (canon thread.suspend-then-promote (core func)) ๐งต |
124 | | // | 0x2d 0x00 |
125 | | // => (canon thread.yield-then-promote (core func)) ๐งต |
126 | | // | 0x40 sh?:<sh?> ft:<core:typeidx> |
127 | | // => (canon thread.spawn-ref sh? ft (core func)) ๐งตโก |
128 | | // | 0x41 sh?:<sh?> ft:<core:typeidx> t:<core:tableidx> |
129 | | // => (canon thread.spawn-indirect sh? ft t (core func)) ๐งตโก |
130 | | // | 0x42 sh?:<sh?> |
131 | | // => (canon thread.available-parallelism sh? (core func)) ๐งตโก |
132 | | // opts ::= opt*:vec(<canonopt>) => opt* |
133 | | // async? ::= 0x00 => ฯต |
134 | | // | 0x01 => async |
135 | | // sh? ::= 0x00 => ฯต |
136 | | // | 0x01 => shared ๐งตโก |
137 | | |
138 | | // Currently implementing: |
139 | | // 0x00 0x00 (canon lift f opts type-index-space[ft]) |
140 | | // 0x01 0x00 (canon lower f opts (core func)) |
141 | | // 0x02 (canon resource.new rt (core func)) |
142 | | // 0x03 (canon resource.drop rt (core func)) |
143 | | // 0x04 (canon resource.rep rt (core func)) |
144 | | |
145 | | class Canonical { |
146 | | public: |
147 | 2.93M | Canonical() noexcept = default; |
148 | | |
149 | 535k | ComponentCanonOpCode getOpCode() const noexcept { return Code; } |
150 | 322k | void setOpCode(const ComponentCanonOpCode C) noexcept { Code = C; } |
151 | | |
152 | | // The `async?` immediate of subtask.cancel and the stream and future cancel |
153 | | // forms. |
154 | 0 | bool getFlagImmediate() const noexcept { return FlagImm; } |
155 | 6.30k | void setFlagImmediate(const bool V) noexcept { FlagImm = V; } |
156 | | |
157 | 213k | uint32_t getIndex() const noexcept { return Idx; } |
158 | 250k | void setIndex(const uint32_t I) noexcept { Idx = I; } |
159 | | |
160 | 8.09k | uint32_t getTargetIndex() const noexcept { return TargetIdx; } |
161 | 9.09k | void setTargetIndex(const uint32_t I) noexcept { TargetIdx = I; } |
162 | | |
163 | 2.58k | uint32_t getConstVal() const noexcept { return I32; } |
164 | 3.24k | void setConstVal(const uint32_t V) noexcept { I32 = V; } |
165 | | |
166 | 2.48k | ValType getContextType() const noexcept { return CtxType; } |
167 | 3.24k | void setContextType(const ValType T) noexcept { CtxType = T; } |
168 | | |
169 | 57.1k | Span<const CanonOpt> getOptions() const noexcept { return Opts; } |
170 | | /// True when the definition carries the option OptCode. |
171 | 28.3k | bool hasOption(ComponentCanonOptCode OptCode) const noexcept { |
172 | 28.3k | for (const auto &Opt : Opts) { |
173 | 15.1k | if (Opt.getCode() == OptCode) { |
174 | 719 | return true; |
175 | 719 | } |
176 | 15.1k | } |
177 | 27.5k | return false; |
178 | 28.3k | } |
179 | 19.3k | void setOptions(std::vector<CanonOpt> &&List) noexcept { |
180 | 19.3k | Opts = std::move(List); |
181 | 19.3k | } |
182 | | |
183 | | /// The result type of task.return; none for no result. |
184 | 8.38k | const std::optional<ComponentValType> &getResult() const noexcept { |
185 | 8.38k | return Result; |
186 | 8.38k | } |
187 | 4.53k | void setResult(std::optional<ComponentValType> R) noexcept { Result = R; } |
188 | | |
189 | | /// The core function type of the canonical built-in Code, as the Explainer's |
190 | | /// synopsis tables give it, with AddrType for the address type of the memory |
191 | | /// the definition names, or of the table for thread.new-indirect. |
192 | | /// context.get and context.set take the context slot type, and task.return |
193 | | /// the lowered results, so their callers form those types themselves. |
194 | | static std::pair<std::vector<ValType>, std::vector<ValType>> |
195 | | getBuiltinCoreFuncType(ComponentCanonOpCode Code, |
196 | 256k | const ValType &AddrType) noexcept { |
197 | 256k | const ValType I32(TypeCode::I32); |
198 | 256k | const ValType I64(TypeCode::I64); |
199 | 256k | switch (Code) { |
200 | 181 | case ComponentCanonOpCode::Backpressure__inc: |
201 | 434 | case ComponentCanonOpCode::Backpressure__dec: |
202 | 595 | case ComponentCanonOpCode::Task__cancel: |
203 | 595 | return {{}, {}}; |
204 | 35 | case ComponentCanonOpCode::Thread__yield: |
205 | 2.52k | case ComponentCanonOpCode::Waitable_set__new: |
206 | 2.97k | case ComponentCanonOpCode::Thread__index: |
207 | 3.17k | case ComponentCanonOpCode::Thread__suspend: |
208 | 3.17k | return {{}, {I32}}; |
209 | 0 | case ComponentCanonOpCode::Waitable_set__wait: |
210 | 0 | case ComponentCanonOpCode::Waitable_set__poll: |
211 | 0 | return {{I32, AddrType}, {I32}}; |
212 | 67 | case ComponentCanonOpCode::Waitable_set__drop: |
213 | 3.66k | case ComponentCanonOpCode::Subtask__drop: |
214 | 3.86k | case ComponentCanonOpCode::Stream__drop_readable: |
215 | 3.92k | case ComponentCanonOpCode::Stream__drop_writable: |
216 | 4.00k | case ComponentCanonOpCode::Future__drop_readable: |
217 | 178k | case ComponentCanonOpCode::Future__drop_writable: |
218 | 179k | case ComponentCanonOpCode::Error_context__drop: |
219 | 179k | case ComponentCanonOpCode::Thread__resume_later: |
220 | 179k | return {{I32}, {}}; |
221 | 387 | case ComponentCanonOpCode::Waitable__join: |
222 | 453 | case ComponentCanonOpCode::Stream__forward: |
223 | 1.82k | case ComponentCanonOpCode::Future__forward: |
224 | 1.82k | return {{I32, I32}, {}}; |
225 | 132 | case ComponentCanonOpCode::Subtask__cancel: |
226 | 841 | case ComponentCanonOpCode::Stream__cancel_read: |
227 | 1.17k | case ComponentCanonOpCode::Stream__cancel_write: |
228 | 1.68k | case ComponentCanonOpCode::Future__cancel_read: |
229 | 5.11k | case ComponentCanonOpCode::Future__cancel_write: |
230 | 5.44k | case ComponentCanonOpCode::Thread__yield_then_resume: |
231 | 6.58k | case ComponentCanonOpCode::Thread__suspend_then_resume: |
232 | 6.64k | case ComponentCanonOpCode::Thread__yield_then_promote: |
233 | 51.5k | case ComponentCanonOpCode::Thread__suspend_then_promote: |
234 | 51.5k | return {{I32}, {I32}}; |
235 | 415 | case ComponentCanonOpCode::Stream__new: |
236 | 18.8k | case ComponentCanonOpCode::Future__new: |
237 | 18.8k | return {{}, {I64}}; |
238 | 67 | case ComponentCanonOpCode::Stream__read: |
239 | 999 | case ComponentCanonOpCode::Stream__write: |
240 | 999 | return {{I32, AddrType, AddrType}, {AddrType}}; |
241 | 208 | case ComponentCanonOpCode::Future__read: |
242 | 274 | case ComponentCanonOpCode::Future__write: |
243 | 274 | return {{I32, AddrType}, {I32}}; |
244 | 0 | case ComponentCanonOpCode::Error_context__new: |
245 | 0 | return {{AddrType, AddrType}, {I32}}; |
246 | 0 | case ComponentCanonOpCode::Error_context__debug_message: |
247 | 0 | return {{I32, AddrType}, {}}; |
248 | 0 | case ComponentCanonOpCode::Thread__new_indirect: |
249 | 0 | return {{AddrType, I32}, {I32}}; |
250 | 0 | default: |
251 | 0 | assumingUnreachable(); |
252 | 256k | } |
253 | 256k | } |
254 | | |
255 | | private: |
256 | | ComponentCanonOpCode Code = ComponentCanonOpCode::Lift; |
257 | | bool FlagImm = false; |
258 | | uint32_t Idx = 0, TargetIdx = 0; |
259 | | uint32_t I32 = 0; |
260 | | ValType CtxType = TypeCode::I32; |
261 | | std::vector<CanonOpt> Opts; |
262 | | std::optional<ComponentValType> Result; |
263 | | }; |
264 | | |
265 | | } // namespace Component |
266 | | } // namespace AST |
267 | | } // namespace WasmEdge |