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
32namespace llvm {
33class DefInit;
34class Record;
35class StringInit;
36} // namespace llvm
37
38namespace mlir {
39namespace 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.
44class InferredResultType {
45public:
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
66private:
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.
77class Operator {
78public:
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 getExtraClassDeclaration() const;
301
302 /// Returns this op's extra class definition code.
303 StringRef getExtraClassDefinition() 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
359private:
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

source code of mlir/include/mlir/TableGen/Operator.h