1 //===- Types.h --------------------------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8
9 #ifndef MLIR_TOOLS_PDLL_AST_TYPES_H_
10 #define MLIR_TOOLS_PDLL_AST_TYPES_H_
11
12 #include "mlir/Support/LLVM.h"
13 #include "mlir/Support/StorageUniquer.h"
14
15 namespace mlir {
16 namespace pdll {
17 namespace ods {
18 class Operation;
19 } // namespace ods
20
21 namespace ast {
22 class Context;
23
24 namespace detail {
25 struct AttributeTypeStorage;
26 struct ConstraintTypeStorage;
27 struct OperationTypeStorage;
28 struct RangeTypeStorage;
29 struct RewriteTypeStorage;
30 struct TupleTypeStorage;
31 struct TypeTypeStorage;
32 struct ValueTypeStorage;
33 } // namespace detail
34
35 //===----------------------------------------------------------------------===//
36 // Type
37 //===----------------------------------------------------------------------===//
38
39 class Type {
40 public:
41 /// This class represents the internal storage of the Type class.
42 struct Storage;
43
44 /// This class provides several utilities when defining derived type classes.
45 template <typename ImplT, typename BaseT = Type>
46 class TypeBase : public BaseT {
47 public:
48 using Base = TypeBase<ImplT, BaseT>;
49 using ImplTy = ImplT;
50 using BaseT::BaseT;
51
52 /// Provide type casting support.
classof(Type type)53 static bool classof(Type type) {
54 return type.getTypeID() == TypeID::get<ImplTy>();
55 }
56 };
57
impl(impl)58 Type(Storage *impl = nullptr) : impl(impl) {}
59
60 bool operator==(const Type &other) const { return impl == other.impl; }
61 bool operator!=(const Type &other) const { return !(*this == other); }
62 explicit operator bool() const { return impl; }
63
64 /// Provide type casting support.
65 template <typename U>
isa()66 bool isa() const {
67 assert(impl && "isa<> used on a null type.");
68 return U::classof(*this);
69 }
70 template <typename U, typename V, typename... Others>
isa()71 bool isa() const {
72 return isa<U>() || isa<V, Others...>();
73 }
74 template <typename U>
dyn_cast()75 U dyn_cast() const {
76 return isa<U>() ? U(impl) : U(nullptr);
77 }
78 template <typename U>
dyn_cast_or_null()79 U dyn_cast_or_null() const {
80 return (impl && isa<U>()) ? U(impl) : U(nullptr);
81 }
82 template <typename U>
cast()83 U cast() const {
84 assert(isa<U>());
85 return U(impl);
86 }
87
88 /// Return the internal storage instance of this type.
getImpl()89 Storage *getImpl() const { return impl; }
90
91 /// Return the TypeID instance of this type.
92 TypeID getTypeID() const;
93
94 /// Print this type to the given stream.
95 void print(raw_ostream &os) const;
96
97 /// Try to refine this type with the one provided. Given two compatible types,
98 /// this will return a merged type contains as much detail from the two types.
99 /// For example, if refining two operation types and one contains a name,
100 /// while the other doesn't, the refined type contains the name. If the two
101 /// types are incompatible, null is returned.
102 Type refineWith(Type other) const;
103
104 protected:
105 /// Return the internal storage instance of this type reinterpreted as the
106 /// given derived storage type.
107 template <typename T>
getImplAs()108 const T *getImplAs() const {
109 return static_cast<const T *>(impl);
110 }
111
112 private:
113 Storage *impl;
114 };
115
hash_value(Type type)116 inline llvm::hash_code hash_value(Type type) {
117 return DenseMapInfo<Type::Storage *>::getHashValue(type.getImpl());
118 }
119
120 inline raw_ostream &operator<<(raw_ostream &os, Type type) {
121 type.print(os);
122 return os;
123 }
124
125 //===----------------------------------------------------------------------===//
126 // AttributeType
127 //===----------------------------------------------------------------------===//
128
129 /// This class represents a PDLL type that corresponds to an mlir::Attribute.
130 class AttributeType : public Type::TypeBase<detail::AttributeTypeStorage> {
131 public:
132 using Base::Base;
133
134 /// Return an instance of the Attribute type.
135 static AttributeType get(Context &context);
136 };
137
138 //===----------------------------------------------------------------------===//
139 // ConstraintType
140 //===----------------------------------------------------------------------===//
141
142 /// This class represents a PDLL type that corresponds to a constraint. This
143 /// type has no MLIR C++ API correspondance.
144 class ConstraintType : public Type::TypeBase<detail::ConstraintTypeStorage> {
145 public:
146 using Base::Base;
147
148 /// Return an instance of the Constraint type.
149 static ConstraintType get(Context &context);
150 };
151
152 //===----------------------------------------------------------------------===//
153 // OperationType
154 //===----------------------------------------------------------------------===//
155
156 /// This class represents a PDLL type that corresponds to an mlir::Operation.
157 class OperationType : public Type::TypeBase<detail::OperationTypeStorage> {
158 public:
159 using Base::Base;
160
161 /// Return an instance of the Operation type with an optional operation name.
162 /// If no name is provided, this type may refer to any operation.
163 static OperationType get(Context &context,
164 Optional<StringRef> name = llvm::None,
165 const ods::Operation *odsOp = nullptr);
166
167 /// Return the name of this operation type, or None if it doesn't have on.
168 Optional<StringRef> getName() const;
169
170 /// Return the ODS operation that this type refers to, or nullptr if the ODS
171 /// operation is unknown.
172 const ods::Operation *getODSOperation() const;
173 };
174
175 //===----------------------------------------------------------------------===//
176 // RangeType
177 //===----------------------------------------------------------------------===//
178
179 /// This class represents a PDLL type that corresponds to a range of elements
180 /// with a given element type.
181 class RangeType : public Type::TypeBase<detail::RangeTypeStorage> {
182 public:
183 using Base::Base;
184
185 /// Return an instance of the Range type with the given element type.
186 static RangeType get(Context &context, Type elementType);
187
188 /// Return the element type of this range.
189 Type getElementType() const;
190 };
191
192 //===----------------------------------------------------------------------===//
193 // TypeRangeType
194
195 /// This class represents a PDLL type that corresponds to an mlir::TypeRange.
196 class TypeRangeType : public RangeType {
197 public:
198 using RangeType::RangeType;
199
200 /// Provide type casting support.
201 static bool classof(Type type);
202
203 /// Return an instance of the TypeRange type.
204 static TypeRangeType get(Context &context);
205 };
206
207 //===----------------------------------------------------------------------===//
208 // ValueRangeType
209
210 /// This class represents a PDLL type that corresponds to an mlir::ValueRange.
211 class ValueRangeType : public RangeType {
212 public:
213 using RangeType::RangeType;
214
215 /// Provide type casting support.
216 static bool classof(Type type);
217
218 /// Return an instance of the ValueRange type.
219 static ValueRangeType get(Context &context);
220 };
221
222 //===----------------------------------------------------------------------===//
223 // RewriteType
224 //===----------------------------------------------------------------------===//
225
226 /// This class represents a PDLL type that corresponds to a rewrite reference.
227 /// This type has no MLIR C++ API correspondance.
228 class RewriteType : public Type::TypeBase<detail::RewriteTypeStorage> {
229 public:
230 using Base::Base;
231
232 /// Return an instance of the Rewrite type.
233 static RewriteType get(Context &context);
234 };
235
236 //===----------------------------------------------------------------------===//
237 // TupleType
238 //===----------------------------------------------------------------------===//
239
240 /// This class represents a PDLL tuple type, i.e. an ordered set of element
241 /// types with optional names.
242 class TupleType : public Type::TypeBase<detail::TupleTypeStorage> {
243 public:
244 using Base::Base;
245
246 /// Return an instance of the Tuple type.
247 static TupleType get(Context &context, ArrayRef<Type> elementTypes,
248 ArrayRef<StringRef> elementNames);
249 static TupleType get(Context &context,
250 ArrayRef<Type> elementTypes = llvm::None);
251
252 /// Return the element types of this tuple.
253 ArrayRef<Type> getElementTypes() const;
254
255 /// Return the element names of this tuple.
256 ArrayRef<StringRef> getElementNames() const;
257
258 /// Return the number of elements within this tuple.
size()259 size_t size() const { return getElementTypes().size(); }
260
261 /// Return if the tuple has no elements.
empty()262 bool empty() const { return size() == 0; }
263 };
264
265 //===----------------------------------------------------------------------===//
266 // TypeType
267 //===----------------------------------------------------------------------===//
268
269 /// This class represents a PDLL type that corresponds to an mlir::Type.
270 class TypeType : public Type::TypeBase<detail::TypeTypeStorage> {
271 public:
272 using Base::Base;
273
274 /// Return an instance of the Type type.
275 static TypeType get(Context &context);
276 };
277
278 //===----------------------------------------------------------------------===//
279 // ValueType
280 //===----------------------------------------------------------------------===//
281
282 /// This class represents a PDLL type that corresponds to an mlir::Value.
283 class ValueType : public Type::TypeBase<detail::ValueTypeStorage> {
284 public:
285 using Base::Base;
286
287 /// Return an instance of the Value type.
288 static ValueType get(Context &context);
289 };
290
291 } // namespace ast
292 } // namespace pdll
293 } // namespace mlir
294
295 MLIR_DECLARE_EXPLICIT_TYPE_ID(mlir::pdll::ast::detail::AttributeTypeStorage)
MLIR_DECLARE_EXPLICIT_TYPE_ID(mlir::pdll::ast::detail::ConstraintTypeStorage)296 MLIR_DECLARE_EXPLICIT_TYPE_ID(mlir::pdll::ast::detail::ConstraintTypeStorage)
297 MLIR_DECLARE_EXPLICIT_TYPE_ID(mlir::pdll::ast::detail::OperationTypeStorage)
298 MLIR_DECLARE_EXPLICIT_TYPE_ID(mlir::pdll::ast::detail::RangeTypeStorage)
299 MLIR_DECLARE_EXPLICIT_TYPE_ID(mlir::pdll::ast::detail::RewriteTypeStorage)
300 MLIR_DECLARE_EXPLICIT_TYPE_ID(mlir::pdll::ast::detail::TupleTypeStorage)
301 MLIR_DECLARE_EXPLICIT_TYPE_ID(mlir::pdll::ast::detail::TypeTypeStorage)
302 MLIR_DECLARE_EXPLICIT_TYPE_ID(mlir::pdll::ast::detail::ValueTypeStorage)
303
304 namespace llvm {
305 template <>
306 struct DenseMapInfo<mlir::pdll::ast::Type> {
307 static mlir::pdll::ast::Type getEmptyKey() {
308 void *pointer = llvm::DenseMapInfo<void *>::getEmptyKey();
309 return mlir::pdll::ast::Type(
310 static_cast<mlir::pdll::ast::Type::Storage *>(pointer));
311 }
312 static mlir::pdll::ast::Type getTombstoneKey() {
313 void *pointer = llvm::DenseMapInfo<void *>::getTombstoneKey();
314 return mlir::pdll::ast::Type(
315 static_cast<mlir::pdll::ast::Type::Storage *>(pointer));
316 }
317 static unsigned getHashValue(mlir::pdll::ast::Type val) {
318 return llvm::hash_value(val.getImpl());
319 }
320 static bool isEqual(mlir::pdll::ast::Type lhs, mlir::pdll::ast::Type rhs) {
321 return lhs == rhs;
322 }
323 };
324 } // namespace llvm
325
326 #endif // MLIR_TOOLS_PDLL_AST_TYPES_H_
327