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