/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/enum_ast.hpp" |
18 | | #include "common/span.h" |
19 | | |
20 | | #include <cstdint> |
21 | | #include <utility> |
22 | | #include <vector> |
23 | | |
24 | | namespace WasmEdge { |
25 | | namespace AST { |
26 | | namespace Component { |
27 | | |
28 | | // canonopt ::= 0x00 => string-encoding=utf8 |
29 | | // | 0x01 => string-encoding=utf16 |
30 | | // | 0x02 => string-encoding=latin1+utf16 |
31 | | // | 0x03 m:<core:memidx> => (memory m) |
32 | | // | 0x04 f:<core:funcidx> => (realloc f) |
33 | | // | 0x05 f:<core:funcidx> => (post-return f) |
34 | | // | 0x06 => async ๐ |
35 | | // | 0x07 f:<core:funcidx> => (callback f) ๐ |
36 | | |
37 | | /// AST Component::CanonOpt definition. |
38 | | class CanonOpt { |
39 | | public: |
40 | 1.14M | CanonOpt() noexcept : Code(ComponentCanonOptCode::Encode_UTF8), Idx(0) {} |
41 | | |
42 | 16.3k | ComponentCanonOptCode getCode() const noexcept { return Code; } |
43 | 7.54k | void setCode(const ComponentCanonOptCode C) noexcept { Code = C; } |
44 | | |
45 | 314 | uint32_t getIndex() const noexcept { return Idx; } |
46 | 1.38k | void setIndex(const uint32_t I) noexcept { Idx = I; } |
47 | | |
48 | | private: |
49 | | ComponentCanonOptCode Code; |
50 | | uint32_t Idx; |
51 | | }; |
52 | | |
53 | | // canon ::= 0x00 0x00 f:<core:funcidx> opts:<opts> ft:<typeidx> |
54 | | // => (canon lift f opts type-index-space[ft]) |
55 | | // | 0x01 0x00 f:<funcidx> opts:<opts> |
56 | | // => (canon lower f opts (core func)) |
57 | | // | 0x02 rt:<typeidx> => (canon resource.new rt (core func)) |
58 | | // | 0x03 rt:<typeidx> => (canon resource.drop rt (core func)) |
59 | | // | 0x04 rt:<typeidx> => (canon resource.rep rt (core func)) |
60 | | // | 0x09 rs:<resultlist> opts:<opts> |
61 | | // => (canon task.return rs opts (core func)) ๐ |
62 | | // | 0x05 => (canon task.cancel (core func)) ๐ |
63 | | // | 0x0a t:<core:valtype> i:<u32> |
64 | | // => (canon context.get t i (core func)) ๐ |
65 | | // | 0x0b t:<core:valtype> i:<u32> |
66 | | // => (canon context.set t i (core func)) ๐ |
67 | | // | 0x0c cancel?:<cancel?> |
68 | | // => (canon thread.yield cancel? (core func)) ๐ |
69 | | // | 0x06 async?:<async?> |
70 | | // => (canon subtask.cancel async? (core func)) ๐ |
71 | | // | 0x0d => (canon subtask.drop (core func)) ๐ |
72 | | // | 0x0e t:<typeidx> => (canon stream.new t (core func)) ๐ |
73 | | // | 0x0f t:<typeidx> opts:<opts> |
74 | | // => (canon stream.read t opts (core func)) ๐ |
75 | | // | 0x10 t:<typeidx> opts:<opts> |
76 | | // => (canon stream.write t opts (core func)) ๐ |
77 | | // | 0x11 t:<typeidx> async?:<async?> |
78 | | // => (canon stream.cancel-read t async? (core func)) ๐ |
79 | | // | 0x12 t:<typeidx> async?:<async?> |
80 | | // => (canon stream.cancel-write t async? (core func)) ๐ |
81 | | // | 0x13 t:<typeidx> => (canon stream.drop-readable t (core func)) ๐ |
82 | | // | 0x14 t:<typeidx> => (canon stream.drop-writable t (core func)) ๐ |
83 | | // | 0x15 t:<typeidx> => (canon future.new t (core func)) ๐ |
84 | | // | 0x16 t:<typeidx> opts:<opts> |
85 | | // => (canon future.read t opts (core func)) ๐ |
86 | | // | 0x17 t:<typeidx> opts:<opts> |
87 | | // => (canon future.write t opts (core func)) ๐ |
88 | | // | 0x18 t:<typeidx> async?:<async?> |
89 | | // => (canon future.cancel-read t async? (core func)) ๐ |
90 | | // | 0x19 t:<typeidx> async?:<async?> |
91 | | // => (canon future.cancel-write t async? (core func)) ๐ |
92 | | // | 0x1a t:<typeidx> => (canon future.drop-readable t (core func)) ๐ |
93 | | // | 0x1b t:<typeidx> => (canon future.drop-writable t (core func)) ๐ |
94 | | // | 0x1c opts:<opts> => (canon error-context.new opts (core func)) ๐ |
95 | | // | 0x1d opts:<opts> |
96 | | // => (canon error-context.debug-message opts (core func)) ๐ |
97 | | // | 0x1e => (canon error-context.drop (core func)) ๐ |
98 | | // | 0x1f => (canon waitable-set.new (core func)) ๐ |
99 | | // | 0x20 cancel?:<cancel?> m:<core:memoryidx> |
100 | | // => (canon waitable-set.wait cancel? (memory m) (core func)) ๐ |
101 | | // | 0x21 cancel?:<cancel?> m:<core:memoryidx> |
102 | | // => (canon waitable-set.poll cancel? (memory m) (core func)) ๐ |
103 | | // | 0x22 => (canon waitable-set.drop (core func)) ๐ |
104 | | // | 0x23 => (canon waitable.join (core func)) ๐ |
105 | | // | 0x24 => (canon backpressure.inc (core func)) ๐ |
106 | | // | 0x25 => (canon backpressure.dec (core func)) ๐ |
107 | | // | 0x26 => (canon thread.index (core func)) ๐งต |
108 | | // | 0x27 ft:<core:typeidx> tbl:<core:tableidx> |
109 | | // => (canon thread.new-indirect ft tbl (core func)) ๐งต |
110 | | // | 0x28 => (canon thread.resume-later (core func)) ๐งต |
111 | | // | 0x29 cancel?:<cancel?> |
112 | | // => (canon thread.suspend cancel? (core func)) ๐งต |
113 | | // | 0x2a cancel?:<cancel?> |
114 | | // => (canon thread.suspend-then-resume cancel? (core func)) ๐งต |
115 | | // | 0x2b cancel?:<cancel?> |
116 | | // => (canon thread.yield-then-resume cancel? (core func)) ๐งต |
117 | | // | 0x2c cancel?:<cancel?> |
118 | | // => (canon thread.suspend-then-promote cancel? (core func)) ๐งต |
119 | | // | 0x2d cancel?:<cancel?> |
120 | | // => (canon thread.yield-then-promote cancel? (core func)) ๐งต |
121 | | // | 0x40 shared?:<sh?> ft:<core:typeidx> |
122 | | // => (canon thread.spawn-ref shared? ft (core func)) ๐งตโก |
123 | | // | 0x41 shared?:<sh?> ft:<core:typeidx> tbl:<core:tableidx> |
124 | | // => (canon thread.spawn-indirect shared? ft tbl (core func)) ๐งตโก |
125 | | // | 0x42 shared?:<sh?> |
126 | | // => (canon thread.available-parallelism shared? (core func)) ๐งตโก |
127 | | // opts ::= opt*:vec(<canonopt>) => opt* |
128 | | // async? ::= 0x00 => ฯต |
129 | | // | 0x01 => async |
130 | | // cancel? ::= 0x00 => ฯต |
131 | | // | 0x01 => cancellable |
132 | | // sh? ::= 0x00 => ฯต |
133 | | // | 0x01 => shared ๐งตโก |
134 | | |
135 | | // Currently implementing: |
136 | | // 0x00 0x00 (canon lift f opts type-index-space[ft]) |
137 | | // 0x01 0x00 (canon lower f opts (core func)) |
138 | | // 0x02 (canon resource.new rt (core func)) |
139 | | // 0x03 (canon resource.drop rt (core func)) |
140 | | // 0x04 (canon resource.rep rt (core func)) |
141 | | |
142 | | class Canonical { |
143 | | public: |
144 | 161k | Canonical() noexcept = default; |
145 | | |
146 | 83.1k | ComponentCanonOpCode getOpCode() const noexcept { return Code; } |
147 | 68.3k | void setOpCode(const ComponentCanonOpCode C) noexcept { Code = C; } |
148 | | |
149 | | // The one-byte flag immediate. It reads as `async?` on subtask.cancel and |
150 | | // the stream and future cancel forms, and as `cancel?` on thread.yield, |
151 | | // waitable-set.wait and poll, and the thread.suspend forms. |
152 | 0 | bool getFlagImmediate() const noexcept { return FlagImm; } |
153 | 4.14k | void setFlagImmediate(const bool V) noexcept { FlagImm = V; } |
154 | | |
155 | 38.8k | uint32_t getIndex() const noexcept { return Idx; } |
156 | 56.1k | void setIndex(const uint32_t I) noexcept { Idx = I; } |
157 | | |
158 | 5.53k | uint32_t getTargetIndex() const noexcept { return TargetIdx; } |
159 | 11.3k | void setTargetIndex(const uint32_t I) noexcept { TargetIdx = I; } |
160 | | |
161 | 1.90k | uint32_t getConstVal() const noexcept { return I32; } |
162 | 3.14k | void setConstVal(const uint32_t V) noexcept { I32 = V; } |
163 | | |
164 | 1.83k | ValType getContextType() const noexcept { return CtxType; } |
165 | 3.14k | void setContextType(const ValType T) noexcept { CtxType = T; } |
166 | | |
167 | 34.7k | Span<const CanonOpt> getOptions() const noexcept { return Opts; } |
168 | | /// True when the definition carries the option OptCode. |
169 | 15.5k | bool hasOption(ComponentCanonOptCode OptCode) const noexcept { |
170 | 15.5k | for (const auto &Opt : Opts) { |
171 | 5.04k | if (Opt.getCode() == OptCode) { |
172 | 26 | return true; |
173 | 26 | } |
174 | 5.04k | } |
175 | 15.5k | return false; |
176 | 15.5k | } |
177 | 16.4k | void setOptions(std::vector<CanonOpt> &&List) noexcept { |
178 | 16.4k | Opts = std::move(List); |
179 | 16.4k | } |
180 | | |
181 | 1.10k | Span<const LabelValType> getResultList() const noexcept { return ResultList; } |
182 | 394 | void setResultList(std::vector<LabelValType> &&R) noexcept { |
183 | 394 | ResultList = std::move(R); |
184 | 394 | } |
185 | 1.30k | void setResultList(const ComponentValType &VT) noexcept { |
186 | 1.30k | ResultList.clear(); |
187 | 1.30k | ResultList.emplace_back(VT); |
188 | 1.30k | } |
189 | | |
190 | | /// The core function type of the canonical built-in Code, as the Explainer's |
191 | | /// synopsis tables give it, with AddrType for the address type of the memory |
192 | | /// the definition names, or of the table for thread.new-indirect. |
193 | | /// context.get and context.set take the context slot type, and task.return |
194 | | /// the lowered results, so their callers form those types themselves. |
195 | | static std::pair<std::vector<ValType>, std::vector<ValType>> |
196 | | getBuiltinCoreFuncType(ComponentCanonOpCode Code, |
197 | 34.5k | const ValType &AddrType) noexcept { |
198 | 34.5k | const ValType I32(TypeCode::I32); |
199 | 34.5k | const ValType I64(TypeCode::I64); |
200 | 34.5k | switch (Code) { |
201 | 64 | case ComponentCanonOpCode::Backpressure__inc: |
202 | 282 | case ComponentCanonOpCode::Backpressure__dec: |
203 | 373 | case ComponentCanonOpCode::Task__cancel: |
204 | 373 | return {{}, {}}; |
205 | 81 | case ComponentCanonOpCode::Yield: |
206 | 350 | case ComponentCanonOpCode::Waitable_set__new: |
207 | 611 | case ComponentCanonOpCode::Thread__index: |
208 | 1.31k | case ComponentCanonOpCode::Thread__suspend: |
209 | 1.31k | return {{}, {I32}}; |
210 | 0 | case ComponentCanonOpCode::Waitable_set__wait: |
211 | 0 | case ComponentCanonOpCode::Waitable_set__poll: |
212 | 0 | return {{I32, AddrType}, {I32}}; |
213 | 116 | case ComponentCanonOpCode::Waitable_set__drop: |
214 | 892 | case ComponentCanonOpCode::Subtask__drop: |
215 | 994 | case ComponentCanonOpCode::Stream__drop_readable: |
216 | 1.60k | case ComponentCanonOpCode::Stream__drop_writable: |
217 | 1.74k | case ComponentCanonOpCode::Future__drop_readable: |
218 | 2.94k | case ComponentCanonOpCode::Future__drop_writable: |
219 | 3.08k | case ComponentCanonOpCode::Error_context__drop: |
220 | 3.11k | case ComponentCanonOpCode::Thread__resume_later: |
221 | 3.11k | return {{I32}, {}}; |
222 | 270 | case ComponentCanonOpCode::Waitable__join: |
223 | 270 | return {{I32, I32}, {}}; |
224 | 88 | case ComponentCanonOpCode::Subtask__cancel: |
225 | 559 | case ComponentCanonOpCode::Stream__cancel_read: |
226 | 627 | case ComponentCanonOpCode::Stream__cancel_write: |
227 | 708 | case ComponentCanonOpCode::Future__cancel_read: |
228 | 941 | case ComponentCanonOpCode::Future__cancel_write: |
229 | 1.42k | case ComponentCanonOpCode::Thread__yield_then_resume: |
230 | 1.51k | case ComponentCanonOpCode::Thread__suspend_then_resume: |
231 | 1.59k | case ComponentCanonOpCode::Thread__yield_then_promote: |
232 | 1.96k | case ComponentCanonOpCode::Thread__suspend_then_promote: |
233 | 1.96k | return {{I32}, {I32}}; |
234 | 66 | case ComponentCanonOpCode::Stream__new: |
235 | 26.7k | case ComponentCanonOpCode::Future__new: |
236 | 26.7k | return {{}, {I64}}; |
237 | 276 | case ComponentCanonOpCode::Stream__read: |
238 | 621 | case ComponentCanonOpCode::Stream__write: |
239 | 621 | return {{I32, AddrType, AddrType}, {AddrType}}; |
240 | 128 | case ComponentCanonOpCode::Future__read: |
241 | 201 | case ComponentCanonOpCode::Future__write: |
242 | 201 | return {{I32, AddrType}, {I32}}; |
243 | 0 | case ComponentCanonOpCode::Error_context__new: |
244 | 0 | return {{AddrType, AddrType}, {I32}}; |
245 | 0 | case ComponentCanonOpCode::Error_context__debug_message: |
246 | 0 | return {{I32, AddrType}, {}}; |
247 | 0 | case ComponentCanonOpCode::Thread__new_indirect: |
248 | 0 | return {{AddrType, I32}, {I32}}; |
249 | 0 | default: |
250 | 0 | assumingUnreachable(); |
251 | 34.5k | } |
252 | 34.5k | } |
253 | | |
254 | | private: |
255 | | ComponentCanonOpCode Code = ComponentCanonOpCode::Lift; |
256 | | bool FlagImm = false; |
257 | | uint32_t Idx = 0, TargetIdx = 0; |
258 | | uint32_t I32 = 0; |
259 | | ValType CtxType = TypeCode::I32; |
260 | | std::vector<CanonOpt> Opts; |
261 | | std::vector<LabelValType> ResultList; |
262 | | }; |
263 | | |
264 | | } // namespace Component |
265 | | } // namespace AST |
266 | | } // namespace WasmEdge |