/src/WasmEdge/include/ast/component/descriptor.h
Line | Count | Source |
1 | | // SPDX-License-Identifier: Apache-2.0 |
2 | | // SPDX-FileCopyrightText: Copyright The WasmEdge Authors |
3 | | |
4 | | //===-- wasmedge/ast/component/descriptor.h - Descriptor class definitions ===// |
5 | | // |
6 | | // Part of the WasmEdge Project. |
7 | | // |
8 | | //===----------------------------------------------------------------------===// |
9 | | /// |
10 | | /// \file |
11 | | /// This file contains the declaration of the Descriptor related class. |
12 | | /// |
13 | | //===----------------------------------------------------------------------===// |
14 | | #pragma once |
15 | | |
16 | | #include "ast/type.h" |
17 | | |
18 | | #include <variant> |
19 | | |
20 | | namespace WasmEdge { |
21 | | namespace AST { |
22 | | namespace Component { |
23 | | |
24 | | /// NOTE: The `ImportDesc` in AST implements the full import with name and |
25 | | /// module name in one class. Therefore, create a `CoreImportDesc` class with |
26 | | /// only the import descriptions for the component model. |
27 | | |
28 | | /// AST Component::CoreImportDesc node. |
29 | | class CoreImportDesc { |
30 | | public: |
31 | 0 | uint32_t getTypeIndex() const noexcept { |
32 | 0 | return *std::get_if<uint32_t>(&Type); |
33 | 0 | } |
34 | 0 | void setTypeIndex(const uint32_t Idx) noexcept { |
35 | 0 | Type.emplace<uint32_t>(Idx); |
36 | 0 | } |
37 | | |
38 | 0 | const TableType &getTableType() const noexcept { |
39 | 0 | return *std::get_if<TableType>(&Type); |
40 | 0 | } |
41 | 0 | void setTableType(TableType &&TT) noexcept { |
42 | 0 | Type.emplace<TableType>(std::move(TT)); |
43 | 0 | } |
44 | | |
45 | 0 | const MemoryType &getMemoryType() const noexcept { |
46 | 0 | return *std::get_if<MemoryType>(&Type); |
47 | 0 | } |
48 | 0 | void setMemoryType(MemoryType &&MT) noexcept { |
49 | 0 | Type.emplace<MemoryType>(std::move(MT)); |
50 | 0 | } |
51 | | |
52 | 0 | const GlobalType &getGlobalType() const noexcept { |
53 | 0 | return *std::get_if<GlobalType>(&Type); |
54 | 0 | } |
55 | 0 | void setGlobalType(GlobalType &>) noexcept { |
56 | 0 | Type.emplace<GlobalType>(std::move(GT)); |
57 | 0 | } |
58 | | |
59 | 0 | const TagType &getTagType() const noexcept { |
60 | 0 | return *std::get_if<TagType>(&Type); |
61 | 0 | } |
62 | 0 | void setTagType(TagType &&TT) noexcept { |
63 | 0 | Type.emplace<TagType>(std::move(TT)); |
64 | 0 | } |
65 | | |
66 | 0 | bool isFunc() const noexcept { |
67 | 0 | return std::holds_alternative<uint32_t>(Type); |
68 | 0 | } |
69 | 0 | bool isTable() const noexcept { |
70 | 0 | return std::holds_alternative<TableType>(Type); |
71 | 0 | } |
72 | 0 | bool isMemory() const noexcept { |
73 | 0 | return std::holds_alternative<MemoryType>(Type); |
74 | 0 | } |
75 | 0 | bool isGlobal() const noexcept { |
76 | 0 | return std::holds_alternative<GlobalType>(Type); |
77 | 0 | } |
78 | 0 | bool isTag() const noexcept { return std::holds_alternative<TagType>(Type); } |
79 | | |
80 | | private: |
81 | | std::variant<uint32_t, TableType, MemoryType, GlobalType, TagType> Type; |
82 | | }; |
83 | | |
84 | | /// FROM: |
85 | | /// https://github.com/WebAssembly/component-model/blob/main/design/mvp/Explainer.md#type-checking |
86 | | /// |
87 | | /// When we next consider type imports and exports, there are two distinct |
88 | | /// subcases of typebound to consider: eq and sub. |
89 | | /// |
90 | | /// The eq bound adds a type equality rule (extending the built-in set of |
91 | | /// subtyping rules) saying that the imported type is structurally equivalent to |
92 | | /// the type referenced in the bound. |
93 | | /// |
94 | | /// In contrast, the sub bound introduces a new abstract type which the rest of |
95 | | /// the component must conservatively assume can be any type that is a subtype |
96 | | /// of the bound. What this means for type-checking is that each subtype-bound |
97 | | /// type import/export introduces a fresh abstract type that is unequal to every |
98 | | /// preceding type definition. |
99 | | /// |
100 | | /// NOTE: |
101 | | /// Think of Java's `? extends T`. |
102 | | /// |
103 | | /// 1. optional `some i` as `(eq i)` |
104 | | /// 2. optional `none` as `sub`, i.e. Subresource |
105 | | |
106 | | // externdesc ::= 0x00 0x11 i:<core:typeidx> => (core module (type i)) |
107 | | // | 0x01 i:<typeidx> => (func (type i)) |
108 | | // | 0x02 b:<valuebound> => (value b) 🪙 |
109 | | // | 0x03 b:<typebound> => (type b) |
110 | | // | 0x04 i:<typeidx> => (component (type i)) |
111 | | // | 0x05 i:<typeidx> => (instance (type i)) |
112 | | // valuebound ::= 0x00 i:<valueidx> => (eq i) 🪙 |
113 | | // | 0x01 t:<valtype> => t 🪙 |
114 | | // typebound ::= 0x00 i:<typeidx> => (eq i) |
115 | | // | 0x01 => (sub resource) |
116 | | |
117 | | class ExternDesc { |
118 | | public: |
119 | | enum class DescType : uint8_t { |
120 | | CoreType = 0x00, |
121 | | FuncType = 0x01, |
122 | | ValueBound = 0x02, |
123 | | TypeBound = 0x03, |
124 | | ComponentType = 0x04, |
125 | | InstanceType = 0x05, |
126 | | }; |
127 | | |
128 | 0 | DescType getDescType() const noexcept { return Type; } |
129 | 0 | uint32_t getTypeIndex() const noexcept { return Idx; } |
130 | 0 | bool isEqType() const noexcept { return Eq; } |
131 | 0 | const ComponentValType &getValType() const noexcept { return VType; } |
132 | | |
133 | 0 | void setCoreTypeIdx(const uint32_t I) noexcept { |
134 | 0 | Type = DescType::CoreType; |
135 | 0 | Idx = I; |
136 | 0 | } |
137 | 0 | void setFuncTypeIdx(const uint32_t I) noexcept { |
138 | 0 | Type = DescType::FuncType; |
139 | 0 | Idx = I; |
140 | 0 | } |
141 | 0 | void setValueBound(const uint32_t I) noexcept { |
142 | 0 | Type = DescType::ValueBound; |
143 | 0 | Eq = true; |
144 | 0 | Idx = I; |
145 | 0 | } |
146 | 0 | void setValueBound(const ComponentValType &T) noexcept { |
147 | 0 | Type = DescType::ValueBound; |
148 | 0 | Eq = false; |
149 | 0 | VType = T; |
150 | 0 | } |
151 | 0 | void setTypeBound(const uint32_t I) noexcept { |
152 | 0 | Type = DescType::TypeBound; |
153 | 0 | Eq = true; |
154 | 0 | Idx = I; |
155 | 0 | } |
156 | 0 | void setTypeBound() noexcept { |
157 | 0 | Type = DescType::TypeBound; |
158 | 0 | Eq = false; |
159 | 0 | } |
160 | 0 | void setComponentTypeIdx(const uint32_t I) noexcept { |
161 | 0 | Type = DescType::ComponentType; |
162 | 0 | Idx = I; |
163 | 0 | } |
164 | 0 | void setInstanceTypeIdx(const uint32_t I) noexcept { |
165 | 0 | Type = DescType::InstanceType; |
166 | 0 | Idx = I; |
167 | 0 | } |
168 | | |
169 | | private: |
170 | | DescType Type; |
171 | | bool Eq; |
172 | | uint32_t Idx; |
173 | | ComponentValType VType; |
174 | | }; |
175 | | |
176 | | } // namespace Component |
177 | | } // namespace AST |
178 | | } // namespace WasmEdge |