//===- Operator.h - Operator class ------------------------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // Operator wrapper to simplify using TableGen Record defining a MLIR Op. // //===----------------------------------------------------------------------===// #ifndef MLIR_TABLEGEN_OPERATOR_H_ #define MLIR_TABLEGEN_OPERATOR_H_ #include "mlir/Support/LLVM.h" #include "mlir/TableGen/Argument.h" #include "mlir/TableGen/Attribute.h" #include "mlir/TableGen/Builder.h" #include "mlir/TableGen/Dialect.h" #include "mlir/TableGen/Property.h" #include "mlir/TableGen/Region.h" #include "mlir/TableGen/Successor.h" #include "mlir/TableGen/Trait.h" #include "mlir/TableGen/Type.h" #include "llvm/ADT/PointerUnion.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/SMLoc.h" namespace llvm { class DefInit; class Record; class StringInit; } // namespace llvm namespace mlir { namespace tblgen { /// This class represents an inferred result type. The result type can be /// inferred from an argument or result type. If it is inferred from another /// result type, that type must be buildable or inferred from yet another type. class InferredResultType { public: InferredResultType(int index, std::string transformer) : index(index), transformer(std::move(transformer)) {} /// Returns true if result type is inferred from an argument type. bool isArg() const { return isArgIndex(index); } /// Return the mapped argument or result index. int getIndex() const { return index; } /// If the type is inferred from a result, return the result index. int getResultIndex() const { return unmapResultIndex(index); } // Mapping from result index to combined argument and result index. // Arguments are indexed to match getArg index, while the result indexes are // mapped to avoid overlap. static int mapResultIndex(int i) { return -1 - i; } static int unmapResultIndex(int i) { return -i - 1; } static bool isResultIndex(int i) { return i < 0; } static bool isArgIndex(int i) { return i >= 0; } StringRef getTransformer() const { return transformer; } private: /// The index of the source argument or result. int index; /// The transfer to apply to the type to obtain the inferred type. std::string transformer; }; /// Wrapper class that contains a MLIR op's information (e.g., operands, /// attributes) defined in TableGen and provides helper methods for /// accessing them. class Operator { public: explicit Operator(const llvm::Record &def); explicit Operator(const llvm::Record *def) : Operator(*def) {} /// Returns this op's dialect name. StringRef getDialectName() const; /// Returns the operation name. The name will follow the "." /// format if its dialect name is not empty. std::string getOperationName() const; /// Returns this op's C++ class name. StringRef getCppClassName() const; /// Returns this op's C++ class name prefixed with namespaces. std::string getQualCppClassName() const; /// Returns this op's C++ namespace. StringRef getCppNamespace() const; /// Returns the name of op's adaptor C++ class. std::string getAdaptorName() const; /// Returns the name of op's generic adaptor C++ class. std::string getGenericAdaptorName() const; /// Check invariants (like no duplicated or conflicted names) and abort the /// process if any invariant is broken. void assertInvariants() const; /// A class used to represent the decorators of an operator variable, i.e. /// argument or result. struct VariableDecorator { public: explicit VariableDecorator(const llvm::Record *def) : def(def) {} const llvm::Record &getDef() const { return *def; } protected: /// The TableGen definition of this decorator. const llvm::Record *def; }; /// A utility iterator over a list of variable decorators. struct VariableDecoratorIterator : public llvm::mapped_iterator { /// Initializes the iterator to the specified iterator. VariableDecoratorIterator(const llvm::Init *const *it) : llvm::mapped_iterator( it, &unwrap) {} static VariableDecorator unwrap(const llvm::Init *init); }; using var_decorator_iterator = VariableDecoratorIterator; using var_decorator_range = llvm::iterator_range; using value_iterator = NamedTypeConstraint *; using const_value_iterator = const NamedTypeConstraint *; using value_range = llvm::iterator_range; using const_value_range = llvm::iterator_range; /// Returns true if this op has variable length operands or results. bool isVariadic() const; /// Returns true if default builders should not be generated. bool skipDefaultBuilders() const; /// Op result iterators. const_value_iterator result_begin() const; const_value_iterator result_end() const; const_value_range getResults() const; /// Returns the number of results this op produces. int getNumResults() const; /// Returns the op result at the given `index`. NamedTypeConstraint &getResult(int index) { return results[index]; } const NamedTypeConstraint &getResult(int index) const { return results[index]; } /// Returns the `index`-th result's type constraint. TypeConstraint getResultTypeConstraint(int index) const; /// Returns the `index`-th result's name. StringRef getResultName(int index) const; /// Returns the `index`-th result's decorators. var_decorator_range getResultDecorators(int index) const; /// Returns the number of variable length results in this operation. unsigned getNumVariableLengthResults() const; /// Op attribute iterators. using const_attribute_iterator = const NamedAttribute *; const_attribute_iterator attribute_begin() const; const_attribute_iterator attribute_end() const; llvm::iterator_range getAttributes() const; using attribute_iterator = NamedAttribute *; attribute_iterator attribute_begin(); attribute_iterator attribute_end(); llvm::iterator_range getAttributes(); int getNumAttributes() const { return attributes.size(); } int getNumNativeAttributes() const { return numNativeAttributes; } /// Op attribute accessors. NamedAttribute &getAttribute(int index) { return attributes[index]; } const NamedAttribute &getAttribute(int index) const { return attributes[index]; } /// Op operand iterators. const_value_iterator operand_begin() const; const_value_iterator operand_end() const; const_value_range getOperands() const; // Op properties iterators. using const_property_iterator = const NamedProperty *; const_property_iterator properties_begin() const { return properties.begin(); } const_property_iterator properties_end() const { return properties.end(); } llvm::iterator_range getProperties() const { return properties; } using property_iterator = NamedProperty *; property_iterator properties_begin() { return properties.begin(); } property_iterator properties_end() { return properties.end(); } llvm::iterator_range getProperties() { return properties; } int getNumCoreAttributes() const { return properties.size(); } // Op properties accessors. NamedProperty &getProperty(int index) { return properties[index]; } const NamedProperty &getProperty(int index) const { return properties[index]; } int getNumOperands() const { return operands.size(); } NamedTypeConstraint &getOperand(int index) { return operands[index]; } const NamedTypeConstraint &getOperand(int index) const { return operands[index]; } /// Returns the number of variadic operands in this operation. unsigned getNumVariableLengthOperands() const; /// Returns the total number of arguments. int getNumArgs() const { return arguments.size(); } /// Returns true of the operation has a single variadic arg. bool hasSingleVariadicArg() const; /// Returns true if the operation has a single variadic result. bool hasSingleVariadicResult() const { return getNumResults() == 1 && getResult(0).isVariadic(); } /// Returns true of the operation has no variadic regions. bool hasNoVariadicRegions() const { return getNumVariadicRegions() == 0; } using arg_iterator = const Argument *; using arg_range = llvm::iterator_range; /// Op argument (attribute or operand) iterators. arg_iterator arg_begin() const; arg_iterator arg_end() const; arg_range getArgs() const; /// Op argument (attribute or operand) accessors. Argument getArg(int index) const; StringRef getArgName(int index) const; var_decorator_range getArgDecorators(int index) const; /// Returns the trait wrapper for the given MLIR C++ `trait`. const Trait *getTrait(llvm::StringRef trait) const; /// Regions. using const_region_iterator = const NamedRegion *; const_region_iterator region_begin() const; const_region_iterator region_end() const; llvm::iterator_range getRegions() const; /// Returns the number of regions. unsigned getNumRegions() const; /// Returns the `index`-th region. const NamedRegion &getRegion(unsigned index) const; /// Returns the number of variadic regions in this operation. unsigned getNumVariadicRegions() const; /// Successors. using const_successor_iterator = const NamedSuccessor *; const_successor_iterator successor_begin() const; const_successor_iterator successor_end() const; llvm::iterator_range getSuccessors() const; /// Returns the number of successors. unsigned getNumSuccessors() const; /// Returns the `index`-th successor. const NamedSuccessor &getSuccessor(unsigned index) const; /// Returns the number of variadic successors in this operation. unsigned getNumVariadicSuccessors() const; /// Trait. using const_trait_iterator = const Trait *; const_trait_iterator trait_begin() const; const_trait_iterator trait_end() const; llvm::iterator_range getTraits() const; ArrayRef getLoc() const; /// Query functions for the documentation of the operator. bool hasDescription() const; StringRef getDescription() const; bool hasSummary() const; StringRef getSummary() const; /// Query functions for the assembly format of the operator. bool hasAssemblyFormat() const; StringRef getAssemblyFormat() const; /// Returns this op's extra class declaration code. StringRef getExtraClassDeclaration() const; /// Returns this op's extra class definition code. StringRef getExtraClassDefinition() const; /// Returns the Tablegen definition this operator was constructed from. /// TODO: do not expose the TableGen record, this is a temporary solution to /// OpEmitter requiring a Record because Operator does not provide enough /// methods. const llvm::Record &getDef() const; /// Returns the dialect of the op. const Dialect &getDialect() const { return dialect; } /// Prints the contents in this operator to the given `os`. This is used for /// debugging purposes. void print(llvm::raw_ostream &os) const; /// Return whether all the result types are known. bool allResultTypesKnown() const { return allResultsHaveKnownTypes; }; /// Return all arguments or type constraints with same type as result[index]. /// Requires: all result types are known. const InferredResultType &getInferredResultType(int index) const; /// Pair consisting kind of argument and index into operands, attributes, or /// properties. struct OperandAttrOrProp { enum class Kind { Operand = 0x0, Attribute = 0x1, Property = 0x2 }; OperandAttrOrProp(Kind kind, int index) { packed = (index << 2) | static_cast(kind); } int operandOrAttributeIndex() const { return (packed >> 2); } Kind kind() const { return static_cast(packed & 0x3); } private: int packed; }; /// Returns the OperandAttrOrProp corresponding to the index. OperandAttrOrProp getArgToOperandAttrOrProp(int index) const; /// Returns the builders of this operation. ArrayRef getBuilders() const { return builders; } /// Returns the getter name for the accessor of `name`. std::string getGetterName(StringRef name) const; /// Returns the setter name for the accessor of `name`. std::string getSetterName(StringRef name) const; /// Returns the remove name for the accessor of `name`. std::string getRemoverName(StringRef name) const; bool hasFolder() const; /// Whether to generate the `readProperty`/`writeProperty` methods for /// bytecode emission. bool useCustomPropertiesEncoding() const; private: /// Populates the vectors containing operands, attributes, results and traits. void populateOpStructure(); /// Populates type inference info (mostly equality) with input a mapping from /// names to indices for arguments and results. void populateTypeInferenceInfo( const llvm::StringMap &argumentsAndResultsIndex); /// The dialect of this op. Dialect dialect; /// The unqualified C++ class name of the op. StringRef cppClassName; /// The C++ namespace for this op. StringRef cppNamespace; /// The operands of the op. SmallVector operands; /// The attributes of the op. Contains native attributes (corresponding to /// the actual stored attributed of the operation) followed by derived /// attributes (corresponding to dynamic properties of the operation that are /// computed upon request). SmallVector attributes; /// The properties of the op. SmallVector properties; /// The arguments of the op (operands and native attributes). SmallVector arguments; /// The results of the op. SmallVector results; /// The successors of this op. SmallVector successors; /// The traits of the op. SmallVector traits; /// The regions of this op. SmallVector regions; /// The argument with the same type as the result. SmallVector resultTypeMapping; /// Map from argument to attribute, property, or operand number. SmallVector attrPropOrOperandMapping; /// The builders of this operator. SmallVector builders; /// The number of native attributes stored in the leading positions of /// `attributes`. int numNativeAttributes; /// The TableGen definition of this op. const llvm::Record &def; /// Whether the type of all results are known. bool allResultsHaveKnownTypes; }; } // namespace tblgen } // namespace mlir #endif // MLIR_TABLEGEN_OPERATOR_H_