//===- Operator.cpp - Operator class --------------------------------------===//
//
// 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.
//
//===----------------------------------------------------------------------===//

#include "mlir/TableGen/Operator.h"
#include "mlir/TableGen/Argument.h"
#include "mlir/TableGen/Predicate.h"
#include "mlir/TableGen/Trait.h"
#include "mlir/TableGen/Type.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/Sequence.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/TypeSwitch.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FormatVariadic.h"
#include "llvm/TableGen/Error.h"
#include "llvm/TableGen/Record.h"

#define DEBUG_TYPE "mlir-tblgen-operator"

using namespace mlir;
using namespace mlir::tblgen;

using llvm::DagInit;
using llvm::DefInit;
using llvm::Init;
using llvm::ListInit;
using llvm::Record;
using llvm::StringInit;

Operator::Operator(const Record &def)
    : dialect(def.getValueAsDef("opDialect")), def(def) {
  // The first `_` in the op's TableGen def name is treated as separating the
  // dialect prefix and the op class name. The dialect prefix will be ignored if
  // not empty. Otherwise, if def name starts with a `_`, the `_` is considered
  // as part of the class name.
  StringRef prefix;
  std::tie(prefix, cppClassName) = def.getName().split('_');
  if (prefix.empty()) {
    // Class name with a leading underscore and without dialect prefix
    cppClassName = def.getName();
  } else if (cppClassName.empty()) {
    // Class name without dialect prefix
    cppClassName = prefix;
  }

  cppNamespace = def.getValueAsString("cppNamespace");

  populateOpStructure();
  assertInvariants();
}

std::string Operator::getOperationName() const {
  auto prefix = dialect.getName();
  auto opName = def.getValueAsString("opName");
  if (prefix.empty())
    return std::string(opName);
  return std::string(llvm::formatv("{0}.{1}", prefix, opName));
}

std::string Operator::getAdaptorName() const {
  return std::string(llvm::formatv("{0}Adaptor", getCppClassName()));
}

std::string Operator::getGenericAdaptorName() const {
  return std::string(llvm::formatv("{0}GenericAdaptor", getCppClassName()));
}

/// Assert the invariants of accessors generated for the given name.
static void assertAccessorInvariants(const Operator &op, StringRef name) {
  std::string accessorName =
      convertToCamelFromSnakeCase(name, /*capitalizeFirst=*/true);

  // Functor used to detect when an accessor will cause an overlap with an
  // operation API.
  //
  // There are a little bit more invasive checks possible for cases where not
  // all ops have the trait that would cause overlap. For many cases here,
  // renaming would be better (e.g., we can only guard in limited manner
  // against methods from traits and interfaces here, so avoiding these in op
  // definition is safer).
  auto nameOverlapsWithOpAPI = [&](StringRef newName) {
    if (newName == "AttributeNames" || newName == "Attributes" ||
        newName == "Operation")
      return true;
    if (newName == "Operands")
      return op.getNumOperands() != 1 || op.getNumVariableLengthOperands() != 1;
    if (newName == "Regions")
      return op.getNumRegions() != 1 || op.getNumVariadicRegions() != 1;
    if (newName == "Type")
      return op.getNumResults() != 1;
    return false;
  };
  if (nameOverlapsWithOpAPI(accessorName)) {
    // This error could be avoided in situations where the final function is
    // identical, but preferably the op definition should avoid using generic
    // names.
    PrintFatalError(op.getLoc(), "generated accessor for `" + name +
                                     "` overlaps with a default one; please "
                                     "rename to avoid overlap");
  }
}

void Operator::assertInvariants() const {
  // Check that the name of arguments/results/regions/successors don't overlap.
  DenseMap<StringRef, StringRef> existingNames;
  auto checkName = [&](StringRef name, StringRef entity) {
    if (name.empty())
      return;
    auto insertion = existingNames.insert({name, entity});
    if (insertion.second) {
      // Assert invariants for accessors generated for this name.
      assertAccessorInvariants(*this, name);
      return;
    }
    if (entity == insertion.first->second)
      PrintFatalError(getLoc(), "op has a conflict with two " + entity +
                                    " having the same name '" + name + "'");
    PrintFatalError(getLoc(), "op has a conflict with " +
                                  insertion.first->second + " and " + entity +
                                  " both having an entry with the name '" +
                                  name + "'");
  };
  // Check operands amongst themselves.
  for (int i : llvm::seq<int>(0, getNumOperands()))
    checkName(getOperand(i).name, "operands");

  // Check results amongst themselves and against operands.
  for (int i : llvm::seq<int>(0, getNumResults()))
    checkName(getResult(i).name, "results");

  // Check regions amongst themselves and against operands and results.
  for (int i : llvm::seq<int>(0, getNumRegions()))
    checkName(getRegion(i).name, "regions");

  // Check successors amongst themselves and against operands, results, and
  // regions.
  for (int i : llvm::seq<int>(0, getNumSuccessors()))
    checkName(getSuccessor(i).name, "successors");
}

StringRef Operator::getDialectName() const { return dialect.getName(); }

StringRef Operator::getCppClassName() const { return cppClassName; }

std::string Operator::getQualCppClassName() const {
  if (cppNamespace.empty())
    return std::string(cppClassName);
  return std::string(llvm::formatv("{0}::{1}", cppNamespace, cppClassName));
}

StringRef Operator::getCppNamespace() const { return cppNamespace; }

int Operator::getNumResults() const {
  const DagInit *results = def.getValueAsDag("results");
  return results->getNumArgs();
}

StringRef Operator::getExtraClassDeclaration() const {
  constexpr auto attr = "extraClassDeclaration";
  if (def.isValueUnset(attr))
    return {};
  return def.getValueAsString(attr);
}

StringRef Operator::getExtraClassDefinition() const {
  constexpr auto attr = "extraClassDefinition";
  if (def.isValueUnset(attr))
    return {};
  return def.getValueAsString(attr);
}

const Record &Operator::getDef() const { return def; }

bool Operator::skipDefaultBuilders() const {
  return def.getValueAsBit("skipDefaultBuilders");
}

bool Operator::hasCustomPropertiesPrinter() const {
  return def.getValueAsBit("hasCustomPropertiesPrinter");
}

auto Operator::result_begin() const -> const_value_iterator {
  return results.begin();
}

auto Operator::result_end() const -> const_value_iterator {
  return results.end();
}

auto Operator::getResults() const -> const_value_range {
  return {result_begin(), result_end()};
}

TypeConstraint Operator::getResultTypeConstraint(int index) const {
  const DagInit *results = def.getValueAsDag("results");
  return TypeConstraint(cast<DefInit>(results->getArg(index)));
}

StringRef Operator::getResultName(int index) const {
  const DagInit *results = def.getValueAsDag("results");
  return results->getArgNameStr(index);
}

auto Operator::getResultDecorators(int index) const -> var_decorator_range {
  const Record *result =
      cast<DefInit>(def.getValueAsDag("results")->getArg(index))->getDef();
  if (!result->isSubClassOf("OpVariable"))
    return var_decorator_range(nullptr, nullptr);
  return *result->getValueAsListInit("decorators");
}

unsigned Operator::getNumVariableLengthResults() const {
  return llvm::count_if(results, [](const NamedTypeConstraint &c) {
    return c.constraint.isVariableLength();
  });
}

unsigned Operator::getNumVariableLengthOperands() const {
  return llvm::count_if(operands, [](const NamedTypeConstraint &c) {
    return c.constraint.isVariableLength();
  });
}

bool Operator::hasSingleVariadicArg() const {
  return getNumArgs() == 1 && isa<NamedTypeConstraint *>(getArg(0)) &&
         getOperand(0).isVariadic();
}

Operator::arg_iterator Operator::arg_begin() const { return arguments.begin(); }

Operator::arg_iterator Operator::arg_end() const { return arguments.end(); }

Operator::arg_range Operator::getArgs() const {
  return {arg_begin(), arg_end()};
}

StringRef Operator::getArgName(int index) const {
  const DagInit *argumentValues = def.getValueAsDag("arguments");
  return argumentValues->getArgNameStr(index);
}

auto Operator::getArgDecorators(int index) const -> var_decorator_range {
  const Record *arg =
      cast<DefInit>(def.getValueAsDag("arguments")->getArg(index))->getDef();
  if (!arg->isSubClassOf("OpVariable"))
    return var_decorator_range(nullptr, nullptr);
  return *arg->getValueAsListInit("decorators");
}

const Trait *Operator::getTrait(StringRef trait) const {
  for (const auto &t : traits) {
    if (const auto *traitDef = dyn_cast<NativeTrait>(&t)) {
      if (traitDef->getFullyQualifiedTraitName() == trait)
        return traitDef;
    } else if (const auto *traitDef = dyn_cast<InternalTrait>(&t)) {
      if (traitDef->getFullyQualifiedTraitName() == trait)
        return traitDef;
    } else if (const auto *traitDef = dyn_cast<InterfaceTrait>(&t)) {
      if (traitDef->getFullyQualifiedTraitName() == trait)
        return traitDef;
    }
  }
  return nullptr;
}

bool Operator::hasNonEmptyProperties() const {
  if (!properties.empty())
    return true;
  if (getTrait("::mlir::OpTrait::AttrSizedOperandSegments") ||
      getTrait("::mlir::OpTrait::AttrSizedResultSegments"))
    return true;
  return llvm::any_of(attributes, [](const NamedAttribute &attr) {
    return !attr.attr.isDerivedAttr();
  });
}

SmallVector<StringRef> Operator::getInherentAttrNames() const {
  SmallVector<StringRef> names;
  for (const NamedAttribute &attr : attributes)
    if (!attr.attr.isDerivedAttr())
      names.push_back(attr.name);
  for (const NamedProperty &property : properties)
    names.push_back(property.name);
  if (getTrait("::mlir::OpTrait::AttrSizedOperandSegments")) {
    names.push_back(operandSegmentAttrName);
    names.push_back(legacyOperandSegmentAttrName);
  }
  if (getTrait("::mlir::OpTrait::AttrSizedResultSegments")) {
    names.push_back(resultSegmentAttrName);
    names.push_back(legacyResultSegmentAttrName);
  }
  return names;
}

auto Operator::region_begin() const -> const_region_iterator {
  return regions.begin();
}
auto Operator::region_end() const -> const_region_iterator {
  return regions.end();
}
auto Operator::getRegions() const
    -> llvm::iterator_range<const_region_iterator> {
  return {region_begin(), region_end()};
}

unsigned Operator::getNumRegions() const { return regions.size(); }

const NamedRegion &Operator::getRegion(unsigned index) const {
  return regions[index];
}

unsigned Operator::getNumVariadicRegions() const {
  return llvm::count_if(regions,
                        [](const NamedRegion &c) { return c.isVariadic(); });
}

auto Operator::successor_begin() const -> const_successor_iterator {
  return successors.begin();
}
auto Operator::successor_end() const -> const_successor_iterator {
  return successors.end();
}
auto Operator::getSuccessors() const
    -> llvm::iterator_range<const_successor_iterator> {
  return {successor_begin(), successor_end()};
}

unsigned Operator::getNumSuccessors() const { return successors.size(); }

const NamedSuccessor &Operator::getSuccessor(unsigned index) const {
  return successors[index];
}

unsigned Operator::getNumVariadicSuccessors() const {
  return llvm::count_if(successors,
                        [](const NamedSuccessor &c) { return c.isVariadic(); });
}

auto Operator::trait_begin() const -> const_trait_iterator {
  return traits.begin();
}
auto Operator::trait_end() const -> const_trait_iterator {
  return traits.end();
}
auto Operator::getTraits() const -> llvm::iterator_range<const_trait_iterator> {
  return {trait_begin(), trait_end()};
}

auto Operator::attribute_begin() const -> const_attribute_iterator {
  return attributes.begin();
}
auto Operator::attribute_end() const -> const_attribute_iterator {
  return attributes.end();
}
auto Operator::getAttributes() const
    -> llvm::iterator_range<const_attribute_iterator> {
  return {attribute_begin(), attribute_end()};
}
auto Operator::attribute_begin() -> attribute_iterator {
  return attributes.begin();
}
auto Operator::attribute_end() -> attribute_iterator {
  return attributes.end();
}
auto Operator::getAttributes() -> llvm::iterator_range<attribute_iterator> {
  return {attribute_begin(), attribute_end()};
}

auto Operator::operand_begin() const -> const_value_iterator {
  return operands.begin();
}
auto Operator::operand_end() const -> const_value_iterator {
  return operands.end();
}
auto Operator::getOperands() const -> const_value_range {
  return {operand_begin(), operand_end()};
}

auto Operator::getArg(int index) const -> Argument { return arguments[index]; }

bool Operator::isVariadic() const {
  return any_of(llvm::concat<const NamedTypeConstraint>(operands, results),
                [](const NamedTypeConstraint &op) { return op.isVariadic(); });
}

void Operator::populateTypeInferenceInfo(
    const llvm::StringMap<int> &argumentsAndResultsIndex) {
  // If the type inference op interface is not registered, then do not attempt
  // to determine if the result types an be inferred.
  auto &recordKeeper = def.getRecords();
  auto *inferTrait = recordKeeper.getDef(inferTypeOpInterface);
  allResultsHaveKnownTypes = false;
  if (!inferTrait)
    return;

  // If there are no results, the skip this else the build method generated
  // overlaps with another autogenerated builder.
  if (getNumResults() == 0)
    return;

  // Skip ops with variadic or optional results.
  if (getNumVariableLengthResults() > 0)
    return;

  // Skip cases currently being custom generated.
  // TODO: Remove special cases.
  if (getTrait("::mlir::OpTrait::SameOperandsAndResultType")) {
    // Check for a non-variable length operand to use as the type anchor.
    auto *operandI = llvm::find_if(arguments, [](const Argument &arg) {
      NamedTypeConstraint *operand =
          llvm::dyn_cast_if_present<NamedTypeConstraint *>(arg);
      return operand && !operand->isVariableLength();
    });
    if (operandI == arguments.end())
      return;

    // All result types are inferred from the operand type.
    int operandIdx = operandI - arguments.begin();
    for (int i = 0; i < getNumResults(); ++i)
      resultTypeMapping.emplace_back(operandIdx, "$_self");

    allResultsHaveKnownTypes = true;
    traits.push_back(Trait::create(inferTrait->getDefInit()));
    return;
  }

  /// This struct represents a node in this operation's result type inferenece
  /// graph. Each node has a list of incoming type inference edges `sources`.
  /// Each edge represents a "source" from which the result type can be
  /// inferred, either an operand (leaf) or another result (node). When a node
  /// is known to have a fully-inferred type, `inferred` is set to true.
  struct ResultTypeInference {
    /// The list of incoming type inference edges.
    SmallVector<InferredResultType> sources;
    /// This flag is set to true when the result type is known to be inferrable.
    bool inferred = false;
  };

  // This vector represents the type inference graph, with one node for each
  // operation result. The nth element is the node for the nth result.
  SmallVector<ResultTypeInference> inference(getNumResults(), {});

  // For all results whose types are buildable, initialize their type inference
  // nodes with an edge to themselves. Mark those nodes are fully-inferred.
  for (auto [idx, infer] : llvm::enumerate(inference)) {
    if (getResult(idx).constraint.getBuilderCall()) {
      infer.sources.emplace_back(InferredResultType::mapResultIndex(idx),
                                 "$_self");
      infer.inferred = true;
    }
  }

  // Use `AllTypesMatch` and `TypesMatchWith` operation traits to build the
  // result type inference graph.
  for (const Trait &trait : traits) {
    const Record &def = trait.getDef();

    // If the infer type op interface was manually added, then treat it as
    // intention that the op needs special handling.
    // TODO: Reconsider whether to always generate, this is more conservative
    // and keeps existing behavior so starting that way for now.
    if (def.isSubClassOf(
            llvm::formatv("{0}::Trait", inferTypeOpInterface).str()))
      return;
    if (const auto *traitDef = dyn_cast<InterfaceTrait>(&trait))
      if (&traitDef->getDef() == inferTrait)
        return;

    // The `TypesMatchWith` trait represents a 1 -> 1 type inference edge with a
    // type transformer.
    if (def.isSubClassOf("TypesMatchWith")) {
      int target = argumentsAndResultsIndex.lookup(def.getValueAsString("rhs"));
      // Ignore operand type inference.
      if (InferredResultType::isArgIndex(target))
        continue;
      int resultIndex = InferredResultType::unmapResultIndex(target);
      ResultTypeInference &infer = inference[resultIndex];
      // If the type of the result has already been inferred, do nothing.
      if (infer.inferred)
        continue;
      int sourceIndex =
          argumentsAndResultsIndex.lookup(def.getValueAsString("lhs"));
      infer.sources.emplace_back(sourceIndex,
                                 def.getValueAsString("transformer").str());
      // Locally propagate inferredness.
      infer.inferred =
          InferredResultType::isArgIndex(sourceIndex) ||
          inference[InferredResultType::unmapResultIndex(sourceIndex)].inferred;
      continue;
    }

    // The `ShapedTypeMatchesElementCountAndTypes` trait represents a 1 -> 1
    // type inference edge where a shaped type matches element count and types
    // of variadic elements.
    if (def.isSubClassOf("ShapedTypeMatchesElementCountAndTypes")) {
      StringRef shapedArg = def.getValueAsString("shaped");
      StringRef elementsArg = def.getValueAsString("elements");

      int shapedIndex = argumentsAndResultsIndex.lookup(shapedArg);
      int elementsIndex = argumentsAndResultsIndex.lookup(elementsArg);

      // Handle result type inference from shaped type to variadic elements.
      if (InferredResultType::isResultIndex(elementsIndex) &&
          InferredResultType::isArgIndex(shapedIndex)) {
        int resultIndex = InferredResultType::unmapResultIndex(elementsIndex);
        ResultTypeInference &infer = inference[resultIndex];
        if (!infer.inferred) {
          infer.sources.emplace_back(
              shapedIndex,
              "::llvm::SmallVector<::mlir::Type>(::llvm::cast<::mlir::"
              "ShapedType>($_self).getNumElements(), "
              "::llvm::cast<::mlir::ShapedType>($_self).getElementType())");
          infer.inferred = true;
        }
      }

      // Type inference in the opposite direction is not possible as the actual
      // shaped type can't be inferred from the variadic elements.

      continue;
    }

    if (!def.isSubClassOf("AllTypesMatch"))
      continue;

    auto values = def.getValueAsListOfStrings("values");
    // The `AllTypesMatch` trait represents an N <-> N fanin and fanout. That
    // is, every result type has an edge from every other type. However, if any
    // one of the values refers to an operand or a result with a fully-inferred
    // type, we can infer all other types from that value. Try to find a
    // fully-inferred type in the list.
    std::optional<int> fullyInferredIndex;
    SmallVector<int> resultIndices;
    for (StringRef name : values) {
      int index = argumentsAndResultsIndex.lookup(name);
      if (InferredResultType::isResultIndex(index))
        resultIndices.push_back(InferredResultType::unmapResultIndex(index));
      if (InferredResultType::isArgIndex(index) ||
          inference[InferredResultType::unmapResultIndex(index)].inferred)
        fullyInferredIndex = index;
    }
    if (fullyInferredIndex) {
      // Make the fully-inferred type the only source for all results that
      // aren't already inferred -- a 1 -> N fanout.
      for (int resultIndex : resultIndices) {
        ResultTypeInference &infer = inference[resultIndex];
        if (!infer.inferred) {
          infer.sources.assign(1, {*fullyInferredIndex, "$_self"});
          infer.inferred = true;
        }
      }
    } else {
      // Add an edge between every result and every other type; N <-> N.
      for (int resultIndex : resultIndices) {
        for (int otherResultIndex : resultIndices) {
          if (resultIndex == otherResultIndex)
            continue;
          inference[resultIndex].sources.emplace_back(
              InferredResultType::unmapResultIndex(otherResultIndex), "$_self");
        }
      }
    }
  }

  // Propagate inferredness until a fixed point.
  std::vector<ResultTypeInference *> worklist;
  for (ResultTypeInference &infer : inference)
    if (!infer.inferred)
      worklist.push_back(&infer);
  bool changed;
  do {
    changed = false;
    for (auto cur = worklist.begin(); cur != worklist.end();) {
      ResultTypeInference &infer = **cur;

      InferredResultType *iter =
          llvm::find_if(infer.sources, [&](const InferredResultType &source) {
            assert(InferredResultType::isResultIndex(source.getIndex()));
            return inference[InferredResultType::unmapResultIndex(
                                 source.getIndex())]
                .inferred;
          });
      if (iter == infer.sources.end()) {
        ++cur;
        continue;
      }

      changed = true;
      infer.inferred = true;
      // Make this the only source for the result. This breaks any cycles.
      infer.sources.assign(1, *iter);
      cur = worklist.erase(cur);
    }
  } while (changed);

  allResultsHaveKnownTypes = worklist.empty();

  // If the types could be computed, then add type inference trait.
  if (allResultsHaveKnownTypes) {
    traits.push_back(Trait::create(inferTrait->getDefInit()));
    for (const ResultTypeInference &infer : inference)
      resultTypeMapping.push_back(infer.sources.front());
  }
}

void Operator::populateOpStructure() {
  auto &recordKeeper = def.getRecords();
  auto *typeConstraintClass = recordKeeper.getClass("TypeConstraint");
  auto *attrClass = recordKeeper.getClass("Attr");
  auto *propertyClass = recordKeeper.getClass("Property");
  auto *derivedAttrClass = recordKeeper.getClass("DerivedAttr");
  auto *opVarClass = recordKeeper.getClass("OpVariable");
  numNativeAttributes = 0;

  const DagInit *argumentValues = def.getValueAsDag("arguments");
  unsigned numArgs = argumentValues->getNumArgs();

  // Mapping from name of to argument or result index. Arguments are indexed
  // to match getArg index, while the results are negatively indexed.
  llvm::StringMap<int> argumentsAndResultsIndex;

  // Handle operands and native attributes.
  for (unsigned i = 0; i != numArgs; ++i) {
    auto *arg = argumentValues->getArg(i);
    auto givenName = argumentValues->getArgNameStr(i);
    auto *argDefInit = dyn_cast<DefInit>(arg);
    if (!argDefInit)
      PrintFatalError(def.getLoc(),
                      Twine("undefined type for argument #") + Twine(i));
    const Record *argDef = argDefInit->getDef();
    if (argDef->isSubClassOf(opVarClass))
      argDef = argDef->getValueAsDef("constraint");

    if (argDef->isSubClassOf(typeConstraintClass)) {
      operands.push_back(
          NamedTypeConstraint{givenName, TypeConstraint(argDef)});
    } else if (argDef->isSubClassOf(attrClass)) {
      if (givenName.empty())
        PrintFatalError(argDef->getLoc(), "attributes must be named");
      if (argDef->isSubClassOf(derivedAttrClass))
        PrintFatalError(argDef->getLoc(),
                        "derived attributes not allowed in argument list");
      attributes.push_back({givenName, Attribute(argDef)});
      ++numNativeAttributes;
    } else if (argDef->isSubClassOf(propertyClass)) {
      if (givenName.empty())
        PrintFatalError(argDef->getLoc(), "properties must be named");
      properties.push_back({givenName, Property(argDef)});
    } else {
      PrintFatalError(def.getLoc(),
                      "unexpected def type; only defs deriving "
                      "from TypeConstraint or Attr or Property are allowed");
    }
    if (!givenName.empty())
      argumentsAndResultsIndex[givenName] = i;
  }

  // Handle derived attributes.
  for (const auto &val : def.getValues()) {
    if (auto *record = dyn_cast<llvm::RecordRecTy>(val.getType())) {
      if (!record->isSubClassOf(attrClass))
        continue;
      if (!record->isSubClassOf(derivedAttrClass))
        PrintFatalError(def.getLoc(),
                        "unexpected Attr where only DerivedAttr is allowed");

      if (record->getClasses().size() != 1) {
        PrintFatalError(
            def.getLoc(),
            "unsupported attribute modelling, only single class expected");
      }
      attributes.push_back({cast<StringInit>(val.getNameInit())->getValue(),
                            Attribute(cast<DefInit>(val.getValue()))});
    }
  }

  // Populate `arguments`. This must happen after we've finalized `operands` and
  // `attributes` because we will put their elements' pointers in `arguments`.
  // SmallVector may perform re-allocation under the hood when adding new
  // elements.
  int operandIndex = 0, attrIndex = 0, propIndex = 0;
  for (unsigned i = 0; i != numArgs; ++i) {
    const Record *argDef =
        dyn_cast<DefInit>(argumentValues->getArg(i))->getDef();
    if (argDef->isSubClassOf(opVarClass))
      argDef = argDef->getValueAsDef("constraint");

    if (argDef->isSubClassOf(typeConstraintClass)) {
      attrPropOrOperandMapping.push_back(
          {OperandAttrOrProp::Kind::Operand, operandIndex});
      arguments.emplace_back(&operands[operandIndex++]);
    } else if (argDef->isSubClassOf(attrClass)) {
      attrPropOrOperandMapping.push_back(
          {OperandAttrOrProp::Kind::Attribute, attrIndex});
      arguments.emplace_back(&attributes[attrIndex++]);
    } else {
      assert(argDef->isSubClassOf(propertyClass));
      attrPropOrOperandMapping.push_back(
          {OperandAttrOrProp::Kind::Property, propIndex});
      arguments.emplace_back(&properties[propIndex++]);
    }
  }

  auto *resultsDag = def.getValueAsDag("results");
  auto *outsOp = dyn_cast<DefInit>(resultsDag->getOperator());
  if (!outsOp || outsOp->getDef()->getName() != "outs") {
    PrintFatalError(def.getLoc(), "'results' must have 'outs' directive");
  }

  // Handle results.
  for (unsigned i = 0, e = resultsDag->getNumArgs(); i < e; ++i) {
    auto name = resultsDag->getArgNameStr(i);
    auto *resultInit = dyn_cast<DefInit>(resultsDag->getArg(i));
    if (!resultInit) {
      PrintFatalError(def.getLoc(),
                      Twine("undefined type for result #") + Twine(i));
    }
    auto *resultDef = resultInit->getDef();
    if (resultDef->isSubClassOf(opVarClass))
      resultDef = resultDef->getValueAsDef("constraint");
    results.push_back({name, TypeConstraint(resultDef)});
    if (!name.empty())
      argumentsAndResultsIndex[name] = InferredResultType::mapResultIndex(i);

    // We currently only support VariadicOfVariadic operands.
    if (results.back().constraint.isVariadicOfVariadic()) {
      PrintFatalError(
          def.getLoc(),
          "'VariadicOfVariadic' results are currently not supported");
    }
  }

  // Handle successors
  auto *successorsDag = def.getValueAsDag("successors");
  auto *successorsOp = dyn_cast<DefInit>(successorsDag->getOperator());
  if (!successorsOp || successorsOp->getDef()->getName() != "successor") {
    PrintFatalError(def.getLoc(),
                    "'successors' must have 'successor' directive");
  }

  for (unsigned i = 0, e = successorsDag->getNumArgs(); i < e; ++i) {
    auto name = successorsDag->getArgNameStr(i);
    auto *successorInit = dyn_cast<DefInit>(successorsDag->getArg(i));
    if (!successorInit) {
      PrintFatalError(def.getLoc(),
                      Twine("undefined kind for successor #") + Twine(i));
    }
    Successor successor(successorInit->getDef());

    // Only support variadic successors if it is the last one for now.
    if (i != e - 1 && successor.isVariadic())
      PrintFatalError(def.getLoc(), "only the last successor can be variadic");
    successors.push_back({name, successor});
  }

  // Create list of traits, skipping over duplicates: appending to lists in
  // tablegen is easy, making them unique less so, so dedupe here.
  if (auto *traitList = def.getValueAsListInit("traits")) {
    // This is uniquing based on pointers of the trait.
    SmallPtrSet<const Init *, 32> traitSet;
    traits.reserve(traitSet.size());

    // The declaration order of traits imply the verification order of traits.
    // Some traits may require other traits to be verified first then they can
    // do further verification based on those verified facts. If you see this
    // error, fix the traits declaration order by checking the `dependentTraits`
    // field.
    auto verifyTraitValidity = [&](const Record *trait) {
      auto *dependentTraits = trait->getValueAsListInit("dependentTraits");
      for (auto *traitInit : *dependentTraits)
        if (!traitSet.contains(traitInit))
          PrintFatalError(
              def.getLoc(),
              trait->getValueAsString("trait") + " requires " +
                  cast<DefInit>(traitInit)->getDef()->getValueAsString(
                      "trait") +
                  " to precede it in traits list");
    };

    std::function<void(const ListInit *)> insert;
    insert = [&](const ListInit *traitList) {
      for (auto *traitInit : *traitList) {
        auto *def = cast<DefInit>(traitInit)->getDef();
        if (def->isSubClassOf("TraitList")) {
          insert(def->getValueAsListInit("traits"));
          continue;
        }

        // Ignore duplicates.
        if (!traitSet.insert(traitInit).second)
          continue;

        // If this is an interface with base classes, add the bases to the
        // trait list.
        if (def->isSubClassOf("Interface"))
          insert(def->getValueAsListInit("baseInterfaces"));

        // Verify if the trait has all the dependent traits declared before
        // itself.
        verifyTraitValidity(def);
        traits.push_back(Trait::create(traitInit));
      }
    };
    insert(traitList);
  }

  populateTypeInferenceInfo(argumentsAndResultsIndex);

  // Handle regions
  auto *regionsDag = def.getValueAsDag("regions");
  auto *regionsOp = dyn_cast<DefInit>(regionsDag->getOperator());
  if (!regionsOp || regionsOp->getDef()->getName() != "region") {
    PrintFatalError(def.getLoc(), "'regions' must have 'region' directive");
  }

  for (unsigned i = 0, e = regionsDag->getNumArgs(); i < e; ++i) {
    auto name = regionsDag->getArgNameStr(i);
    auto *regionInit = dyn_cast<DefInit>(regionsDag->getArg(i));
    if (!regionInit) {
      PrintFatalError(def.getLoc(),
                      Twine("undefined kind for region #") + Twine(i));
    }
    Region region(regionInit->getDef());
    if (region.isVariadic()) {
      // Only support variadic regions if it is the last one for now.
      if (i != e - 1)
        PrintFatalError(def.getLoc(), "only the last region can be variadic");
      if (name.empty())
        PrintFatalError(def.getLoc(), "variadic regions must be named");
    }

    regions.push_back({name, region});
  }

  // Populate the builders.
  auto *builderList = dyn_cast_or_null<ListInit>(def.getValueInit("builders"));
  if (builderList && !builderList->empty()) {
    for (const Init *init : builderList->getElements())
      builders.emplace_back(cast<DefInit>(init)->getDef(), def.getLoc());
  } else if (skipDefaultBuilders()) {
    PrintFatalError(
        def.getLoc(),
        "default builders are skipped and no custom builders provided");
  }

  LLVM_DEBUG(print(llvm::dbgs()));
}

const InferredResultType &Operator::getInferredResultType(int index) const {
  assert(allResultTypesKnown());
  return resultTypeMapping[index];
}

ArrayRef<SMLoc> Operator::getLoc() const { return def.getLoc(); }

bool Operator::hasDescription() const {
  return !getDescription().trim().empty();
}

StringRef Operator::getDescription() const {
  return def.getValueAsString("description");
}

bool Operator::hasSummary() const { return !getSummary().trim().empty(); }

StringRef Operator::getSummary() const {
  return def.getValueAsString("summary");
}

bool Operator::hasAssemblyFormat() const {
  auto *valueInit = def.getValueInit("assemblyFormat");
  return isa<StringInit>(valueInit);
}

StringRef Operator::getAssemblyFormat() const {
  return TypeSwitch<const Init *, StringRef>(def.getValueInit("assemblyFormat"))
      .Case([&](const StringInit *init) { return init->getValue(); });
}

void Operator::print(llvm::raw_ostream &os) const {
  os << "op '" << getOperationName() << "'\n";
  for (Argument arg : arguments) {
    if (auto *attr = llvm::dyn_cast_if_present<NamedAttribute *>(arg))
      os << "[attribute] " << attr->name << '\n';
    else
      os << "[operand] " << cast<NamedTypeConstraint *>(arg)->name << '\n';
  }
}

auto Operator::VariableDecoratorIterator::unwrap(const Init *init)
    -> VariableDecorator {
  return VariableDecorator(cast<DefInit>(init)->getDef());
}

auto Operator::getArgToOperandAttrOrProp(int index) const -> OperandAttrOrProp {
  return attrPropOrOperandMapping[index];
}

std::string Operator::getGetterName(StringRef name) const {
  return "get" + convertToCamelFromSnakeCase(name, /*capitalizeFirst=*/true);
}

std::string Operator::getSetterName(StringRef name) const {
  return "set" + convertToCamelFromSnakeCase(name, /*capitalizeFirst=*/true);
}

std::string Operator::getRemoverName(StringRef name) const {
  return "remove" + convertToCamelFromSnakeCase(name, /*capitalizeFirst=*/true);
}

bool Operator::hasFolder() const { return def.getValueAsBit("hasFolder"); }

bool Operator::useCustomPropertiesEncoding() const {
  return def.getValueAsBit("useCustomPropertiesEncoding");
}
