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/Builder.h" |
20 | #include "mlir/TableGen/Dialect.h" |
21 | #include "mlir/TableGen/Property.h" |
22 | #include "mlir/TableGen/Region.h" |
23 | #include "mlir/TableGen/Successor.h" |
24 | #include "mlir/TableGen/Trait.h" |
25 | #include "mlir/TableGen/Type.h" |
26 | #include "llvm/ADT/PointerUnion.h" |
27 | #include "llvm/ADT/SmallVector.h" |
28 | #include "llvm/ADT/StringMap.h" |
29 | #include "llvm/ADT/StringRef.h" |
30 | #include "llvm/Support/SMLoc.h" |
31 | |
32 | namespace llvm { |
33 | class DefInit; |
34 | class Record; |
35 | class StringInit; |
36 | } // namespace llvm |
37 | |
38 | namespace mlir { |
39 | namespace tblgen { |
40 | |
41 | /// This class represents an inferred result type. The result type can be |
42 | /// inferred from an argument or result type. If it is inferred from another |
43 | /// result type, that type must be buildable or inferred from yet another type. |
44 | class InferredResultType { |
45 | public: |
46 | InferredResultType(int index, std::string transformer) |
47 | : index(index), transformer(std::move(transformer)) {} |
48 | |
49 | /// Returns true if result type is inferred from an argument type. |
50 | bool isArg() const { return isArgIndex(i: index); } |
51 | /// Return the mapped argument or result index. |
52 | int getIndex() const { return index; } |
53 | /// If the type is inferred from a result, return the result index. |
54 | int getResultIndex() const { return unmapResultIndex(i: index); } |
55 | |
56 | // Mapping from result index to combined argument and result index. |
57 | // Arguments are indexed to match getArg index, while the result indexes are |
58 | // mapped to avoid overlap. |
59 | static int mapResultIndex(int i) { return -1 - i; } |
60 | static int unmapResultIndex(int i) { return -i - 1; } |
61 | static bool isResultIndex(int i) { return i < 0; } |
62 | static bool isArgIndex(int i) { return i >= 0; } |
63 | |
64 | StringRef getTransformer() const { return transformer; } |
65 | |
66 | private: |
67 | /// The index of the source argument or result. |
68 | int index; |
69 | |
70 | /// The transfer to apply to the type to obtain the inferred type. |
71 | std::string transformer; |
72 | }; |
73 | |
74 | /// Wrapper class that contains a MLIR op's information (e.g., operands, |
75 | /// attributes) defined in TableGen and provides helper methods for |
76 | /// accessing them. |
77 | class Operator { |
78 | public: |
79 | explicit Operator(const llvm::Record &def); |
80 | explicit Operator(const llvm::Record *def) : Operator(*def) {} |
81 | |
82 | /// Returns this op's dialect name. |
83 | StringRef getDialectName() const; |
84 | |
85 | /// Returns the operation name. The name will follow the "<dialect>.<op-name>" |
86 | /// format if its dialect name is not empty. |
87 | std::string getOperationName() const; |
88 | |
89 | /// Returns this op's C++ class name. |
90 | StringRef getCppClassName() const; |
91 | |
92 | /// Returns this op's C++ class name prefixed with namespaces. |
93 | std::string getQualCppClassName() const; |
94 | |
95 | /// Returns this op's C++ namespace. |
96 | StringRef getCppNamespace() const; |
97 | |
98 | /// Returns the name of op's adaptor C++ class. |
99 | std::string getAdaptorName() const; |
100 | |
101 | /// Returns the name of op's generic adaptor C++ class. |
102 | std::string getGenericAdaptorName() const; |
103 | |
104 | /// Check invariants (like no duplicated or conflicted names) and abort the |
105 | /// process if any invariant is broken. |
106 | void assertInvariants() const; |
107 | |
108 | /// A class used to represent the decorators of an operator variable, i.e. |
109 | /// argument or result. |
110 | struct VariableDecorator { |
111 | public: |
112 | explicit VariableDecorator(const llvm::Record *def) : def(def) {} |
113 | const llvm::Record &getDef() const { return *def; } |
114 | |
115 | protected: |
116 | /// The TableGen definition of this decorator. |
117 | const llvm::Record *def; |
118 | }; |
119 | |
120 | /// A utility iterator over a list of variable decorators. |
121 | struct VariableDecoratorIterator |
122 | : public llvm::mapped_iterator<llvm::Init *const *, |
123 | VariableDecorator (*)(llvm::Init *)> { |
124 | /// Initializes the iterator to the specified iterator. |
125 | VariableDecoratorIterator(llvm::Init *const *it) |
126 | : llvm::mapped_iterator<llvm::Init *const *, |
127 | VariableDecorator (*)(llvm::Init *)>(it, |
128 | &unwrap) {} |
129 | static VariableDecorator unwrap(llvm::Init *init); |
130 | }; |
131 | using var_decorator_iterator = VariableDecoratorIterator; |
132 | using var_decorator_range = llvm::iterator_range<VariableDecoratorIterator>; |
133 | |
134 | using value_iterator = NamedTypeConstraint *; |
135 | using const_value_iterator = const NamedTypeConstraint *; |
136 | using value_range = llvm::iterator_range<value_iterator>; |
137 | using const_value_range = llvm::iterator_range<const_value_iterator>; |
138 | |
139 | /// Returns true if this op has variable length operands or results. |
140 | bool isVariadic() const; |
141 | |
142 | /// Returns true if default builders should not be generated. |
143 | bool skipDefaultBuilders() const; |
144 | |
145 | /// Op result iterators. |
146 | const_value_iterator result_begin() const; |
147 | const_value_iterator result_end() const; |
148 | const_value_range getResults() const; |
149 | |
150 | /// Returns the number of results this op produces. |
151 | int getNumResults() const; |
152 | |
153 | /// Returns the op result at the given `index`. |
154 | NamedTypeConstraint &getResult(int index) { return results[index]; } |
155 | const NamedTypeConstraint &getResult(int index) const { |
156 | return results[index]; |
157 | } |
158 | |
159 | /// Returns the `index`-th result's type constraint. |
160 | TypeConstraint getResultTypeConstraint(int index) const; |
161 | /// Returns the `index`-th result's name. |
162 | StringRef getResultName(int index) const; |
163 | /// Returns the `index`-th result's decorators. |
164 | var_decorator_range getResultDecorators(int index) const; |
165 | |
166 | /// Returns the number of variable length results in this operation. |
167 | unsigned getNumVariableLengthResults() const; |
168 | |
169 | /// Op attribute iterators. |
170 | using const_attribute_iterator = const NamedAttribute *; |
171 | const_attribute_iterator attribute_begin() const; |
172 | const_attribute_iterator attribute_end() const; |
173 | llvm::iterator_range<const_attribute_iterator> getAttributes() const; |
174 | using attribute_iterator = NamedAttribute *; |
175 | attribute_iterator attribute_begin(); |
176 | attribute_iterator attribute_end(); |
177 | llvm::iterator_range<attribute_iterator> getAttributes(); |
178 | |
179 | int getNumAttributes() const { return attributes.size(); } |
180 | int getNumNativeAttributes() const { return numNativeAttributes; } |
181 | |
182 | /// Op attribute accessors. |
183 | NamedAttribute &getAttribute(int index) { return attributes[index]; } |
184 | const NamedAttribute &getAttribute(int index) const { |
185 | return attributes[index]; |
186 | } |
187 | |
188 | /// Op operand iterators. |
189 | const_value_iterator operand_begin() const; |
190 | const_value_iterator operand_end() const; |
191 | const_value_range getOperands() const; |
192 | |
193 | // Op properties iterators. |
194 | using const_property_iterator = const NamedProperty *; |
195 | const_property_iterator properties_begin() const { |
196 | return properties.begin(); |
197 | } |
198 | const_property_iterator properties_end() const { return properties.end(); } |
199 | llvm::iterator_range<const_property_iterator> getProperties() const { |
200 | return properties; |
201 | } |
202 | using property_iterator = NamedProperty *; |
203 | property_iterator properties_begin() { return properties.begin(); } |
204 | property_iterator properties_end() { return properties.end(); } |
205 | llvm::iterator_range<property_iterator> getProperties() { return properties; } |
206 | int getNumCoreAttributes() const { return properties.size(); } |
207 | |
208 | // Op properties accessors. |
209 | NamedProperty &getProperty(int index) { return properties[index]; } |
210 | const NamedProperty &getProperty(int index) const { |
211 | return properties[index]; |
212 | } |
213 | |
214 | int getNumOperands() const { return operands.size(); } |
215 | NamedTypeConstraint &getOperand(int index) { return operands[index]; } |
216 | const NamedTypeConstraint &getOperand(int index) const { |
217 | return operands[index]; |
218 | } |
219 | |
220 | /// Returns the number of variadic operands in this operation. |
221 | unsigned getNumVariableLengthOperands() const; |
222 | |
223 | /// Returns the total number of arguments. |
224 | int getNumArgs() const { return arguments.size(); } |
225 | |
226 | /// Returns true of the operation has a single variadic arg. |
227 | bool hasSingleVariadicArg() const; |
228 | |
229 | /// Returns true if the operation has a single variadic result. |
230 | bool hasSingleVariadicResult() const { |
231 | return getNumResults() == 1 && getResult(index: 0).isVariadic(); |
232 | } |
233 | |
234 | /// Returns true of the operation has no variadic regions. |
235 | bool hasNoVariadicRegions() const { return getNumVariadicRegions() == 0; } |
236 | |
237 | using arg_iterator = const Argument *; |
238 | using arg_range = llvm::iterator_range<arg_iterator>; |
239 | |
240 | /// Op argument (attribute or operand) iterators. |
241 | arg_iterator arg_begin() const; |
242 | arg_iterator arg_end() const; |
243 | arg_range getArgs() const; |
244 | |
245 | /// Op argument (attribute or operand) accessors. |
246 | Argument getArg(int index) const; |
247 | StringRef getArgName(int index) const; |
248 | var_decorator_range getArgDecorators(int index) const; |
249 | |
250 | /// Returns the trait wrapper for the given MLIR C++ `trait`. |
251 | const Trait *getTrait(llvm::StringRef trait) const; |
252 | |
253 | /// Regions. |
254 | using const_region_iterator = const NamedRegion *; |
255 | const_region_iterator region_begin() const; |
256 | const_region_iterator region_end() const; |
257 | llvm::iterator_range<const_region_iterator> getRegions() const; |
258 | |
259 | /// Returns the number of regions. |
260 | unsigned getNumRegions() const; |
261 | /// Returns the `index`-th region. |
262 | const NamedRegion &getRegion(unsigned index) const; |
263 | |
264 | /// Returns the number of variadic regions in this operation. |
265 | unsigned getNumVariadicRegions() const; |
266 | |
267 | /// Successors. |
268 | using const_successor_iterator = const NamedSuccessor *; |
269 | const_successor_iterator successor_begin() const; |
270 | const_successor_iterator successor_end() const; |
271 | llvm::iterator_range<const_successor_iterator> getSuccessors() const; |
272 | |
273 | /// Returns the number of successors. |
274 | unsigned getNumSuccessors() const; |
275 | /// Returns the `index`-th successor. |
276 | const NamedSuccessor &getSuccessor(unsigned index) const; |
277 | |
278 | /// Returns the number of variadic successors in this operation. |
279 | unsigned getNumVariadicSuccessors() const; |
280 | |
281 | /// Trait. |
282 | using const_trait_iterator = const Trait *; |
283 | const_trait_iterator trait_begin() const; |
284 | const_trait_iterator trait_end() const; |
285 | llvm::iterator_range<const_trait_iterator> getTraits() const; |
286 | |
287 | ArrayRef<SMLoc> getLoc() const; |
288 | |
289 | /// Query functions for the documentation of the operator. |
290 | bool hasDescription() const; |
291 | StringRef getDescription() const; |
292 | bool hasSummary() const; |
293 | StringRef getSummary() const; |
294 | |
295 | /// Query functions for the assembly format of the operator. |
296 | bool hasAssemblyFormat() const; |
297 | StringRef getAssemblyFormat() const; |
298 | |
299 | /// Returns this op's extra class declaration code. |
300 | StringRef () const; |
301 | |
302 | /// Returns this op's extra class definition code. |
303 | StringRef () const; |
304 | |
305 | /// Returns the Tablegen definition this operator was constructed from. |
306 | /// TODO: do not expose the TableGen record, this is a temporary solution to |
307 | /// OpEmitter requiring a Record because Operator does not provide enough |
308 | /// methods. |
309 | const llvm::Record &getDef() const; |
310 | |
311 | /// Returns the dialect of the op. |
312 | const Dialect &getDialect() const { return dialect; } |
313 | |
314 | /// Prints the contents in this operator to the given `os`. This is used for |
315 | /// debugging purposes. |
316 | void print(llvm::raw_ostream &os) const; |
317 | |
318 | /// Return whether all the result types are known. |
319 | bool allResultTypesKnown() const { return allResultsHaveKnownTypes; }; |
320 | |
321 | /// Return all arguments or type constraints with same type as result[index]. |
322 | /// Requires: all result types are known. |
323 | const InferredResultType &getInferredResultType(int index) const; |
324 | |
325 | /// Pair consisting kind of argument and index into operands or attributes. |
326 | struct OperandOrAttribute { |
327 | enum class Kind { Operand, Attribute }; |
328 | OperandOrAttribute(Kind kind, int index) { |
329 | packed = (index << 1) | (kind == Kind::Attribute); |
330 | } |
331 | int operandOrAttributeIndex() const { return (packed >> 1); } |
332 | Kind kind() { return (packed & 0x1) ? Kind::Attribute : Kind::Operand; } |
333 | |
334 | private: |
335 | int packed; |
336 | }; |
337 | |
338 | /// Returns the OperandOrAttribute corresponding to the index. |
339 | OperandOrAttribute getArgToOperandOrAttribute(int index) const; |
340 | |
341 | /// Returns the builders of this operation. |
342 | ArrayRef<Builder> getBuilders() const { return builders; } |
343 | |
344 | /// Returns the getter name for the accessor of `name`. |
345 | std::string getGetterName(StringRef name) const; |
346 | |
347 | /// Returns the setter name for the accessor of `name`. |
348 | std::string getSetterName(StringRef name) const; |
349 | |
350 | /// Returns the remove name for the accessor of `name`. |
351 | std::string getRemoverName(StringRef name) const; |
352 | |
353 | bool hasFolder() const; |
354 | |
355 | /// Whether to generate the `readProperty`/`writeProperty` methods for |
356 | /// bytecode emission. |
357 | bool useCustomPropertiesEncoding() const; |
358 | |
359 | private: |
360 | /// Populates the vectors containing operands, attributes, results and traits. |
361 | void populateOpStructure(); |
362 | |
363 | /// Populates type inference info (mostly equality) with input a mapping from |
364 | /// names to indices for arguments and results. |
365 | void populateTypeInferenceInfo( |
366 | const llvm::StringMap<int> &argumentsAndResultsIndex); |
367 | |
368 | /// The dialect of this op. |
369 | Dialect dialect; |
370 | |
371 | /// The unqualified C++ class name of the op. |
372 | StringRef cppClassName; |
373 | |
374 | /// The C++ namespace for this op. |
375 | StringRef cppNamespace; |
376 | |
377 | /// The operands of the op. |
378 | SmallVector<NamedTypeConstraint, 4> operands; |
379 | |
380 | /// The attributes of the op. Contains native attributes (corresponding to |
381 | /// the actual stored attributed of the operation) followed by derived |
382 | /// attributes (corresponding to dynamic properties of the operation that are |
383 | /// computed upon request). |
384 | SmallVector<NamedAttribute, 4> attributes; |
385 | |
386 | /// The properties of the op. |
387 | SmallVector<NamedProperty> properties; |
388 | |
389 | /// The arguments of the op (operands and native attributes). |
390 | SmallVector<Argument, 4> arguments; |
391 | |
392 | /// The results of the op. |
393 | SmallVector<NamedTypeConstraint, 4> results; |
394 | |
395 | /// The successors of this op. |
396 | SmallVector<NamedSuccessor, 0> successors; |
397 | |
398 | /// The traits of the op. |
399 | SmallVector<Trait, 4> traits; |
400 | |
401 | /// The regions of this op. |
402 | SmallVector<NamedRegion, 1> regions; |
403 | |
404 | /// The argument with the same type as the result. |
405 | SmallVector<InferredResultType> resultTypeMapping; |
406 | |
407 | /// Map from argument to attribute or operand number. |
408 | SmallVector<OperandOrAttribute, 4> attrOrOperandMapping; |
409 | |
410 | /// The builders of this operator. |
411 | SmallVector<Builder> builders; |
412 | |
413 | /// The number of native attributes stored in the leading positions of |
414 | /// `attributes`. |
415 | int numNativeAttributes; |
416 | |
417 | /// The TableGen definition of this op. |
418 | const llvm::Record &def; |
419 | |
420 | /// Whether the type of all results are known. |
421 | bool allResultsHaveKnownTypes; |
422 | }; |
423 | |
424 | } // namespace tblgen |
425 | } // namespace mlir |
426 | |
427 | #endif // MLIR_TABLEGEN_OPERATOR_H_ |
428 | |