1 //===- Operator.h - Operator class ------------------------------*- 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 // Operator wrapper to simplify using TableGen Record defining a MLIR Op.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #ifndef MLIR_TABLEGEN_OPERATOR_H_
14 #define MLIR_TABLEGEN_OPERATOR_H_
15 
16 #include "mlir/Support/LLVM.h"
17 #include "mlir/TableGen/Argument.h"
18 #include "mlir/TableGen/Attribute.h"
19 #include "mlir/TableGen/Dialect.h"
20 #include "mlir/TableGen/OpTrait.h"
21 #include "mlir/TableGen/Region.h"
22 #include "mlir/TableGen/Successor.h"
23 #include "mlir/TableGen/Type.h"
24 #include "llvm/ADT/PointerUnion.h"
25 #include "llvm/ADT/SmallVector.h"
26 #include "llvm/ADT/StringMap.h"
27 #include "llvm/ADT/StringRef.h"
28 #include "llvm/Support/SMLoc.h"
29 
30 namespace llvm {
31 class DefInit;
32 class Record;
33 class StringInit;
34 } // end namespace llvm
35 
36 namespace mlir {
37 namespace tblgen {
38 
39 // Wrapper class that contains a MLIR op's information (e.g., operands,
40 // attributes) defined in TableGen and provides helper methods for
41 // accessing them.
42 class Operator {
43 public:
44   explicit Operator(const llvm::Record &def);
Operator(const llvm::Record * def)45   explicit Operator(const llvm::Record *def) : Operator(*def) {}
46 
47   // Returns this op's dialect name.
48   StringRef getDialectName() const;
49 
50   // Returns the operation name. The name will follow the "<dialect>.<op-name>"
51   // format if its dialect name is not empty.
52   std::string getOperationName() const;
53 
54   // Returns this op's C++ class name.
55   StringRef getCppClassName() const;
56 
57   // Returns this op's C++ class name prefixed with namespaces.
58   std::string getQualCppClassName() const;
59 
60   // Returns the name of op's adaptor C++ class.
61   std::string getAdaptorName() const;
62 
63   /// A class used to represent the decorators of an operator variable, i.e.
64   /// argument or result.
65   struct VariableDecorator {
66   public:
VariableDecoratorVariableDecorator67     explicit VariableDecorator(const llvm::Record *def) : def(def) {}
getDefVariableDecorator68     const llvm::Record &getDef() const { return *def; }
69 
70   protected:
71     // The TableGen definition of this decorator.
72     const llvm::Record *def;
73   };
74 
75   // A utility iterator over a list of variable decorators.
76   struct VariableDecoratorIterator
77       : public llvm::mapped_iterator<llvm::Init *const *,
78                                      VariableDecorator (*)(llvm::Init *)> {
79     using reference = VariableDecorator;
80 
81     /// Initializes the iterator to the specified iterator.
VariableDecoratorIteratorVariableDecoratorIterator82     VariableDecoratorIterator(llvm::Init *const *it)
83         : llvm::mapped_iterator<llvm::Init *const *,
84                                 VariableDecorator (*)(llvm::Init *)>(it,
85                                                                      &unwrap) {}
86     static VariableDecorator unwrap(llvm::Init *init);
87   };
88   using var_decorator_iterator = VariableDecoratorIterator;
89   using var_decorator_range = llvm::iterator_range<VariableDecoratorIterator>;
90 
91   using value_iterator = NamedTypeConstraint *;
92   using value_range = llvm::iterator_range<value_iterator>;
93 
94   // Returns true if this op has variable length operands or results.
95   bool isVariadic() const;
96 
97   // Returns true if default builders should not be generated.
98   bool skipDefaultBuilders() const;
99 
100   // Op result iterators.
101   value_iterator result_begin();
102   value_iterator result_end();
103   value_range getResults();
104 
105   // Returns the number of results this op produces.
106   int getNumResults() const;
107 
108   // Returns the op result at the given `index`.
getResult(int index)109   NamedTypeConstraint &getResult(int index) { return results[index]; }
getResult(int index)110   const NamedTypeConstraint &getResult(int index) const {
111     return results[index];
112   }
113 
114   // Returns the `index`-th result's type constraint.
115   TypeConstraint getResultTypeConstraint(int index) const;
116   // Returns the `index`-th result's name.
117   StringRef getResultName(int index) const;
118   // Returns the `index`-th result's decorators.
119   var_decorator_range getResultDecorators(int index) const;
120 
121   // Returns the number of variable length results in this operation.
122   unsigned getNumVariableLengthResults() const;
123 
124   // Op attribute iterators.
125   using attribute_iterator = const NamedAttribute *;
126   attribute_iterator attribute_begin() const;
127   attribute_iterator attribute_end() const;
128   llvm::iterator_range<attribute_iterator> getAttributes() const;
129 
getNumAttributes()130   int getNumAttributes() const { return attributes.size(); }
getNumNativeAttributes()131   int getNumNativeAttributes() const { return numNativeAttributes; }
132 
133   // Op attribute accessors.
getAttribute(int index)134   NamedAttribute &getAttribute(int index) { return attributes[index]; }
135 
136   // Op operand iterators.
137   value_iterator operand_begin();
138   value_iterator operand_end();
139   value_range getOperands();
140 
getNumOperands()141   int getNumOperands() const { return operands.size(); }
getOperand(int index)142   NamedTypeConstraint &getOperand(int index) { return operands[index]; }
getOperand(int index)143   const NamedTypeConstraint &getOperand(int index) const {
144     return operands[index];
145   }
146 
147   // Returns the number of variadic operands in this operation.
148   unsigned getNumVariableLengthOperands() const;
149 
150   // Returns the total number of arguments.
getNumArgs()151   int getNumArgs() const { return arguments.size(); }
152 
153   // Returns true of the operation has a single variadic arg.
154   bool hasSingleVariadicArg() const;
155 
156   // Returns true if the operation has a single variadic result.
hasSingleVariadicResult()157   bool hasSingleVariadicResult() const {
158     return getNumResults() == 1 && getResult(0).isVariadic();
159   }
160 
161   // Returns true of the operation has no variadic regions.
hasNoVariadicRegions()162   bool hasNoVariadicRegions() const { return getNumVariadicRegions() == 0; }
163 
164   using arg_iterator = const Argument *;
165   using arg_range = llvm::iterator_range<arg_iterator>;
166 
167   // Op argument (attribute or operand) iterators.
168   arg_iterator arg_begin() const;
169   arg_iterator arg_end() const;
170   arg_range getArgs() const;
171 
172   // Op argument (attribute or operand) accessors.
173   Argument getArg(int index) const;
174   StringRef getArgName(int index) const;
175   var_decorator_range getArgDecorators(int index) const;
176 
177   // Returns the trait wrapper for the given MLIR C++ `trait`.
178   // TODO: We should add a C++ wrapper class for TableGen OpTrait instead of
179   // requiring the raw MLIR trait here.
180   const OpTrait *getTrait(llvm::StringRef trait) const;
181 
182   // Regions.
183   using const_region_iterator = const NamedRegion *;
184   const_region_iterator region_begin() const;
185   const_region_iterator region_end() const;
186   llvm::iterator_range<const_region_iterator> getRegions() const;
187 
188   // Returns the number of regions.
189   unsigned getNumRegions() const;
190   // Returns the `index`-th region.
191   const NamedRegion &getRegion(unsigned index) const;
192 
193   // Returns the number of variadic regions in this operation.
194   unsigned getNumVariadicRegions() const;
195 
196   // Successors.
197   using const_successor_iterator = const NamedSuccessor *;
198   const_successor_iterator successor_begin() const;
199   const_successor_iterator successor_end() const;
200   llvm::iterator_range<const_successor_iterator> getSuccessors() const;
201 
202   // Returns the number of successors.
203   unsigned getNumSuccessors() const;
204   // Returns the `index`-th successor.
205   const NamedSuccessor &getSuccessor(unsigned index) const;
206 
207   // Returns the number of variadic successors in this operation.
208   unsigned getNumVariadicSuccessors() const;
209 
210   // Trait.
211   using const_trait_iterator = const OpTrait *;
212   const_trait_iterator trait_begin() const;
213   const_trait_iterator trait_end() const;
214   llvm::iterator_range<const_trait_iterator> getTraits() const;
215 
216   ArrayRef<llvm::SMLoc> getLoc() const;
217 
218   // Query functions for the documentation of the operator.
219   bool hasDescription() const;
220   StringRef getDescription() const;
221   bool hasSummary() const;
222   StringRef getSummary() const;
223 
224   // Query functions for the assembly format of the operator.
225   bool hasAssemblyFormat() const;
226   StringRef getAssemblyFormat() const;
227 
228   // Returns this op's extra class declaration code.
229   StringRef getExtraClassDeclaration() const;
230 
231   // Returns the Tablegen definition this operator was constructed from.
232   // TODO: do not expose the TableGen record, this is a temporary solution to
233   // OpEmitter requiring a Record because Operator does not provide enough
234   // methods.
235   const llvm::Record &getDef() const;
236 
237   // Returns the dialect of the op.
getDialect()238   const Dialect &getDialect() const { return dialect; }
239 
240   // Prints the contents in this operator to the given `os`. This is used for
241   // debugging purposes.
242   void print(llvm::raw_ostream &os) const;
243 
244   // Return whether all the result types are known.
allResultTypesKnown()245   bool allResultTypesKnown() const { return allResultsHaveKnownTypes; };
246 
247   // Pair representing either a index to an argument or a type constraint. Only
248   // one of these entries should have the non-default value.
249   struct ArgOrType {
ArgOrTypeArgOrType250     explicit ArgOrType(int index) : index(index), constraint(None) {}
ArgOrTypeArgOrType251     explicit ArgOrType(TypeConstraint constraint)
252         : index(None), constraint(constraint) {}
isArgArgOrType253     bool isArg() const {
254       assert(constraint.hasValue() ^ index.hasValue());
255       return index.hasValue();
256     }
isTypeArgOrType257     bool isType() const {
258       assert(constraint.hasValue() ^ index.hasValue());
259       return constraint.hasValue();
260     }
261 
getArgArgOrType262     int getArg() const { return *index; }
getTypeArgOrType263     TypeConstraint getType() const { return *constraint; }
264 
265   private:
266     Optional<int> index;
267     Optional<TypeConstraint> constraint;
268   };
269 
270   // Return all arguments or type constraints with same type as result[index].
271   // Requires: all result types are known.
272   ArrayRef<ArgOrType> getSameTypeAsResult(int index) const;
273 
274   // Pair consisting kind of argument and index into operands or attributes.
275   struct OperandOrAttribute {
276     enum class Kind { Operand, Attribute };
OperandOrAttributeOperandOrAttribute277     OperandOrAttribute(Kind kind, int index) {
278       packed = (index << 1) & (kind == Kind::Attribute);
279     }
operandOrAttributeIndexOperandOrAttribute280     int operandOrAttributeIndex() const { return (packed >> 1); }
kindOperandOrAttribute281     Kind kind() { return (packed & 0x1) ? Kind::Attribute : Kind::Operand; }
282 
283   private:
284     int packed;
285   };
286 
287   // Returns the OperandOrAttribute corresponding to the index.
288   OperandOrAttribute getArgToOperandOrAttribute(int index) const;
289 
290 private:
291   // Populates the vectors containing operands, attributes, results and traits.
292   void populateOpStructure();
293 
294   // Populates type inference info (mostly equality) with input a mapping from
295   // names to indices for arguments and results.
296   void populateTypeInferenceInfo(
297       const llvm::StringMap<int> &argumentsAndResultsIndex);
298 
299   // The dialect of this op.
300   Dialect dialect;
301 
302   // The unqualified C++ class name of the op.
303   StringRef cppClassName;
304 
305   // The operands of the op.
306   SmallVector<NamedTypeConstraint, 4> operands;
307 
308   // The attributes of the op.  Contains native attributes (corresponding to the
309   // actual stored attributed of the operation) followed by derived attributes
310   // (corresponding to dynamic properties of the operation that are computed
311   // upon request).
312   SmallVector<NamedAttribute, 4> attributes;
313 
314   // The arguments of the op (operands and native attributes).
315   SmallVector<Argument, 4> arguments;
316 
317   // The results of the op.
318   SmallVector<NamedTypeConstraint, 4> results;
319 
320   // The successors of this op.
321   SmallVector<NamedSuccessor, 0> successors;
322 
323   // The traits of the op.
324   SmallVector<OpTrait, 4> traits;
325 
326   // The regions of this op.
327   SmallVector<NamedRegion, 1> regions;
328 
329   // The argument with the same type as the result.
330   SmallVector<SmallVector<ArgOrType, 2>, 4> resultTypeMapping;
331 
332   // Map from argument to attribute or operand number.
333   SmallVector<OperandOrAttribute, 4> attrOrOperandMapping;
334 
335   // The number of native attributes stored in the leading positions of
336   // `attributes`.
337   int numNativeAttributes;
338 
339   // The TableGen definition of this op.
340   const llvm::Record &def;
341 
342   // Whether the type of all results are known.
343   bool allResultsHaveKnownTypes;
344 };
345 
346 } // end namespace tblgen
347 } // end namespace mlir
348 
349 #endif // MLIR_TABLEGEN_OPERATOR_H_
350