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