text: //===- 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/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 {
  
  // 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 "<dialect>.<op-name>"
    // 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;
  
    // 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<llvm::Init *const *,
                                       VariableDecorator (*)(llvm::Init *)> {
      /// Initializes the iterator to the specified iterator.
      VariableDecoratorIterator(llvm::Init *const *it)
          : llvm::mapped_iterator<llvm::Init *const *,
                                  VariableDecorator (*)(llvm::Init *)>(it,
                                                                       &unwrap) {}
      static VariableDecorator unwrap(llvm::Init *init);
    };
    using var_decorator_iterator = VariableDecoratorIterator;
    using var_decorator_range = llvm::iterator_range<VariableDecoratorIterator>;
  
    using value_iterator = NamedTypeConstraint *;
    using value_range = llvm::iterator_range<value_iterator>;
  
    // 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.
    value_iterator result_begin();
    value_iterator result_end();
    value_range getResults();
  
    // 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 attribute_iterator = const NamedAttribute *;
    attribute_iterator attribute_begin() const;
    attribute_iterator attribute_end() const;
    llvm::iterator_range<attribute_iterator> getAttributes() const;
  
    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.
    value_iterator operand_begin();
    value_iterator operand_end();
    value_range getOperands();
  
    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<arg_iterator>;
  
    // 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<const_region_iterator> 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<const_successor_iterator> 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<const_trait_iterator> getTraits() const;
  
    ArrayRef<llvm::SMLoc> 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 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; };
  
    // Pair representing either a index to an argument or a type constraint. Only
    // one of these entries should have the non-default value.
    struct ArgOrType {
      explicit ArgOrType(int index) : index(index), constraint(None) {}
      explicit ArgOrType(TypeConstraint constraint)
          : index(None), constraint(constraint) {}
      bool isArg() const {
        assert(constraint.hasValue() ^ index.hasValue());
        return index.hasValue();
      }
      bool isType() const {
        assert(constraint.hasValue() ^ index.hasValue());
        return constraint.hasValue();
      }
  
      int getArg() const { return *index; }
      TypeConstraint getType() const { return *constraint; }
  
    private:
      Optional<int> index;
      Optional<TypeConstraint> constraint;
    };
  
    // Return all arguments or type constraints with same type as result[index].
    // Requires: all result types are known.
    ArrayRef<ArgOrType> getSameTypeAsResult(int index) const;
  
    // Pair consisting kind of argument and index into operands or attributes.
    struct OperandOrAttribute {
      enum class Kind { Operand, Attribute };
      OperandOrAttribute(Kind kind, int index) {
        packed = (index << 1) | (kind == Kind::Attribute);
      }
      int operandOrAttributeIndex() const { return (packed >> 1); }
      Kind kind() { return (packed & 0x1) ? Kind::Attribute : Kind::Operand; }
  
    private:
      int packed;
    };
  
    // Returns the OperandOrAttribute corresponding to the index.
    OperandOrAttribute getArgToOperandOrAttribute(int index) const;
  
    // Returns the builders of this operation.
    ArrayRef<Builder> getBuilders() const { return builders; }
  
    // Returns the preferred getter name for the accessor.
    std::string getGetterName(StringRef name) const {
      return getGetterNames(name).front();
    }
  
    // Returns the getter names for the accessor.
    SmallVector<std::string, 2> getGetterNames(StringRef name) const;
  
    // Returns the setter names for the accessor.
    SmallVector<std::string, 2> getSetterNames(StringRef name) 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<int> &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<NamedTypeConstraint, 4> 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<NamedAttribute, 4> attributes;
  
    // The arguments of the op (operands and native attributes).
    SmallVector<Argument, 4> arguments;
  
    // The results of the op.
    SmallVector<NamedTypeConstraint, 4> results;
  
    // The successors of this op.
    SmallVector<NamedSuccessor, 0> successors;
  
    // The traits of the op.
    SmallVector<Trait, 4> traits;
  
    // The regions of this op.
    SmallVector<NamedRegion, 1> regions;
  
    // The argument with the same type as the result.
    SmallVector<SmallVector<ArgOrType, 2>, 4> resultTypeMapping;
  
    // Map from argument to attribute or operand number.
    SmallVector<OperandOrAttribute, 4> attrOrOperandMapping;
  
    // The builders of this operator.
    SmallVector<Builder> 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_
  