//===- llvm/TableGen/Record.h - Classes for Table Records -------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the main TableGen data structures, including the TableGen
// types, values, and high-level data structures.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_TABLEGEN_RECORD_H
#define LLVM_TABLEGEN_RECORD_H

#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/DataTypes.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/raw_ostream.h"
#include <map>

namespace llvm {
class raw_ostream;

// RecTy subclasses.
class BitRecTy;
class BitsRecTy;
class IntRecTy;
class StringRecTy;
class ListRecTy;
class DagRecTy;
class RecordRecTy;

// Init subclasses.
class Init;
class UnsetInit;
class BitInit;
class BitsInit;
class IntInit;
class StringInit;
class ListInit;
class UnOpInit;
class BinOpInit;
class TernOpInit;
class DefInit;
class DagInit;
class TypedInit;
class VarInit;
class FieldInit;
class VarBitInit;
class VarListElementInit;

// Other classes.
class Record;
class RecordVal;
struct MultiClass;
class RecordKeeper;

//===----------------------------------------------------------------------===//
//  Type Classes
//===----------------------------------------------------------------------===//

class RecTy {
public:
  /// \brief Subclass discriminator (for dyn_cast<> et al.)
  enum RecTyKind {
    BitRecTyKind,
    BitsRecTyKind,
    IntRecTyKind,
    StringRecTyKind,
    ListRecTyKind,
    DagRecTyKind,
    RecordRecTyKind
  };

private:
  RecTyKind Kind;
  ListRecTy *ListTy;
  virtual void anchor();

public:
  RecTyKind getRecTyKind() const { return Kind; }

  RecTy(RecTyKind K) : Kind(K), ListTy(nullptr) {}
  virtual ~RecTy() {}

  virtual std::string getAsString() const = 0;
  void print(raw_ostream &OS) const { OS << getAsString(); }
  void dump() const;

  /// typeIsConvertibleTo - Return true if all values of 'this' type can be
  /// converted to the specified type.
  virtual bool typeIsConvertibleTo(const RecTy *RHS) const = 0;

  /// getListTy - Returns the type representing list<this>.
  ListRecTy *getListTy();

public:   // These methods should only be called from subclasses of Init
  virtual Init *convertValue( UnsetInit *UI) { return nullptr; }
  virtual Init *convertValue(   BitInit *BI) { return nullptr; }
  virtual Init *convertValue(  BitsInit *BI) { return nullptr; }
  virtual Init *convertValue(   IntInit *II) { return nullptr; }
  virtual Init *convertValue(StringInit *SI) { return nullptr; }
  virtual Init *convertValue(  ListInit *LI) { return nullptr; }
  virtual Init *convertValue( UnOpInit *UI) {
    return convertValue((TypedInit*)UI);
  }
  virtual Init *convertValue( BinOpInit *UI) {
    return convertValue((TypedInit*)UI);
  }
  virtual Init *convertValue( TernOpInit *UI) {
    return convertValue((TypedInit*)UI);
  }
  virtual Init *convertValue(VarBitInit *VB) { return nullptr; }
  virtual Init *convertValue(   DefInit *DI) { return nullptr; }
  virtual Init *convertValue(   DagInit *DI) { return nullptr; }
  virtual Init *convertValue( TypedInit *TI) { return nullptr; }
  virtual Init *convertValue(   VarInit *VI) {
    return convertValue((TypedInit*)VI);
  }
  virtual Init *convertValue( FieldInit *FI) {
    return convertValue((TypedInit*)FI);
  }

public:
  virtual bool baseClassOf(const RecTy*) const;
};

inline raw_ostream &operator<<(raw_ostream &OS, const RecTy &Ty) {
  Ty.print(OS);
  return OS;
}

/// BitRecTy - 'bit' - Represent a single bit
///
class BitRecTy : public RecTy {
  static BitRecTy Shared;
  BitRecTy() : RecTy(BitRecTyKind) {}

public:
  static bool classof(const RecTy *RT) {
    return RT->getRecTyKind() == BitRecTyKind;
  }

  static BitRecTy *get() { return &Shared; }

  Init *convertValue( UnsetInit *UI) override { return (Init*)UI; }
  Init *convertValue(   BitInit *BI) override { return (Init*)BI; }
  Init *convertValue(  BitsInit *BI) override;
  Init *convertValue(   IntInit *II) override;
  Init *convertValue(StringInit *SI) override { return nullptr; }
  Init *convertValue(  ListInit *LI) override { return nullptr; }
  Init *convertValue(VarBitInit *VB) override { return (Init*)VB; }
  Init *convertValue(   DefInit *DI) override { return nullptr; }
  Init *convertValue(   DagInit *DI) override { return nullptr; }
  Init *convertValue( UnOpInit *UI) override { return RecTy::convertValue(UI);}
  Init *convertValue( BinOpInit *UI) override { return RecTy::convertValue(UI);}
  Init *convertValue( TernOpInit *UI) override {return RecTy::convertValue(UI);}
  Init *convertValue( TypedInit *TI) override;
  Init *convertValue(   VarInit *VI) override { return RecTy::convertValue(VI);}
  Init *convertValue( FieldInit *FI) override { return RecTy::convertValue(FI);}

  std::string getAsString() const override { return "bit"; }

  bool typeIsConvertibleTo(const RecTy *RHS) const override {
    return RHS->baseClassOf(this);
  }
  bool baseClassOf(const RecTy*) const override;
};

/// BitsRecTy - 'bits<n>' - Represent a fixed number of bits
///
class BitsRecTy : public RecTy {
  unsigned Size;
  explicit BitsRecTy(unsigned Sz) : RecTy(BitsRecTyKind), Size(Sz) {}

public:
  static bool classof(const RecTy *RT) {
    return RT->getRecTyKind() == BitsRecTyKind;
  }

  static BitsRecTy *get(unsigned Sz);

  unsigned getNumBits() const { return Size; }

  Init *convertValue( UnsetInit *UI) override;
  Init *convertValue(   BitInit *UI) override;
  Init *convertValue(  BitsInit *BI) override;
  Init *convertValue(   IntInit *II) override;
  Init *convertValue(StringInit *SI) override { return nullptr; }
  Init *convertValue(  ListInit *LI) override { return nullptr; }
  Init *convertValue(VarBitInit *VB) override { return nullptr; }
  Init *convertValue(   DefInit *DI) override { return nullptr; }
  Init *convertValue(   DagInit *DI) override { return nullptr; }
  Init *convertValue(  UnOpInit *UI) override { return RecTy::convertValue(UI);}
  Init *convertValue( BinOpInit *UI) override { return RecTy::convertValue(UI);}
  Init *convertValue(TernOpInit *UI) override { return RecTy::convertValue(UI);}
  Init *convertValue( TypedInit *TI) override;
  Init *convertValue(   VarInit *VI) override { return RecTy::convertValue(VI);}
  Init *convertValue( FieldInit *FI) override { return RecTy::convertValue(FI);}

  std::string getAsString() const override;

  bool typeIsConvertibleTo(const RecTy *RHS) const override {
    return RHS->baseClassOf(this);
  }
  bool baseClassOf(const RecTy*) const override;
};

/// IntRecTy - 'int' - Represent an integer value of no particular size
///
class IntRecTy : public RecTy {
  static IntRecTy Shared;
  IntRecTy() : RecTy(IntRecTyKind) {}

public:
  static bool classof(const RecTy *RT) {
    return RT->getRecTyKind() == IntRecTyKind;
  }

  static IntRecTy *get() { return &Shared; }

  Init *convertValue( UnsetInit *UI) override { return (Init*)UI; }
  Init *convertValue(   BitInit *BI) override;
  Init *convertValue(  BitsInit *BI) override;
  Init *convertValue(   IntInit *II) override { return (Init*)II; }
  Init *convertValue(StringInit *SI) override { return nullptr; }
  Init *convertValue(  ListInit *LI) override { return nullptr; }
  Init *convertValue(VarBitInit *VB) override { return nullptr; }
  Init *convertValue(   DefInit *DI) override { return nullptr; }
  Init *convertValue(   DagInit *DI) override { return nullptr; }
  Init *convertValue( UnOpInit *UI)  override { return RecTy::convertValue(UI);}
  Init *convertValue( BinOpInit *UI) override { return RecTy::convertValue(UI);}
  Init *convertValue( TernOpInit *UI) override {return RecTy::convertValue(UI);}
  Init *convertValue( TypedInit *TI) override;
  Init *convertValue(   VarInit *VI) override { return RecTy::convertValue(VI);}
  Init *convertValue( FieldInit *FI) override { return RecTy::convertValue(FI);}

  std::string getAsString() const override { return "int"; }

  bool typeIsConvertibleTo(const RecTy *RHS) const override {
    return RHS->baseClassOf(this);
  }

  bool baseClassOf(const RecTy*) const override;
};

/// StringRecTy - 'string' - Represent an string value
///
class StringRecTy : public RecTy {
  static StringRecTy Shared;
  StringRecTy() : RecTy(StringRecTyKind) {}

public:
  static bool classof(const RecTy *RT) {
    return RT->getRecTyKind() == StringRecTyKind;
  }

  static StringRecTy *get() { return &Shared; }

  Init *convertValue( UnsetInit *UI) override { return (Init*)UI; }
  Init *convertValue(   BitInit *BI) override { return nullptr; }
  Init *convertValue(  BitsInit *BI) override { return nullptr; }
  Init *convertValue(   IntInit *II) override { return nullptr; }
  Init *convertValue(StringInit *SI) override { return (Init*)SI; }
  Init *convertValue(  ListInit *LI) override { return nullptr; }
  Init *convertValue( UnOpInit *BO) override;
  Init *convertValue( BinOpInit *BO) override;
  Init *convertValue( TernOpInit *BO) override {return RecTy::convertValue(BO);}

  Init *convertValue(VarBitInit *VB) override { return nullptr; }
  Init *convertValue(   DefInit *DI) override { return nullptr; }
  Init *convertValue(   DagInit *DI) override { return nullptr; }
  Init *convertValue( TypedInit *TI) override;
  Init *convertValue(   VarInit *VI) override { return RecTy::convertValue(VI);}
  Init *convertValue( FieldInit *FI) override { return RecTy::convertValue(FI);}

  std::string getAsString() const override { return "string"; }

  bool typeIsConvertibleTo(const RecTy *RHS) const override {
    return RHS->baseClassOf(this);
  }
};

/// ListRecTy - 'list<Ty>' - Represent a list of values, all of which must be of
/// the specified type.
///
class ListRecTy : public RecTy {
  RecTy *Ty;
  explicit ListRecTy(RecTy *T) : RecTy(ListRecTyKind), Ty(T) {}
  friend ListRecTy *RecTy::getListTy();

public:
  static bool classof(const RecTy *RT) {
    return RT->getRecTyKind() == ListRecTyKind;
  }

  static ListRecTy *get(RecTy *T) { return T->getListTy(); }
  RecTy *getElementType() const { return Ty; }

  Init *convertValue( UnsetInit *UI) override { return (Init*)UI; }
  Init *convertValue(   BitInit *BI) override { return nullptr; }
  Init *convertValue(  BitsInit *BI) override { return nullptr; }
  Init *convertValue(   IntInit *II) override { return nullptr; }
  Init *convertValue(StringInit *SI) override { return nullptr; }
  Init *convertValue(  ListInit *LI) override;
  Init *convertValue(VarBitInit *VB) override { return nullptr; }
  Init *convertValue(   DefInit *DI) override { return nullptr; }
  Init *convertValue(   DagInit *DI) override { return nullptr; }
  Init *convertValue(  UnOpInit *UI) override { return RecTy::convertValue(UI);}
  Init *convertValue( BinOpInit *UI) override { return RecTy::convertValue(UI);}
  Init *convertValue(TernOpInit *UI) override { return RecTy::convertValue(UI);}
  Init *convertValue( TypedInit *TI) override;
  Init *convertValue(   VarInit *VI) override { return RecTy::convertValue(VI);}
  Init *convertValue( FieldInit *FI) override { return RecTy::convertValue(FI);}

  std::string getAsString() const override;

  bool typeIsConvertibleTo(const RecTy *RHS) const override {
    return RHS->baseClassOf(this);
  }

  bool baseClassOf(const RecTy*) const override;
};

/// DagRecTy - 'dag' - Represent a dag fragment
///
class DagRecTy : public RecTy {
  static DagRecTy Shared;
  DagRecTy() : RecTy(DagRecTyKind) {}

public:
  static bool classof(const RecTy *RT) {
    return RT->getRecTyKind() == DagRecTyKind;
  }

  static DagRecTy *get() { return &Shared; }

  Init *convertValue( UnsetInit *UI) override { return (Init*)UI; }
  Init *convertValue(   BitInit *BI) override { return nullptr; }
  Init *convertValue(  BitsInit *BI) override { return nullptr; }
  Init *convertValue(   IntInit *II) override { return nullptr; }
  Init *convertValue(StringInit *SI) override { return nullptr; }
  Init *convertValue(  ListInit *LI) override { return nullptr; }
  Init *convertValue(VarBitInit *VB) override { return nullptr; }
  Init *convertValue(   DefInit *DI) override { return nullptr; }
  Init *convertValue( UnOpInit *BO) override;
  Init *convertValue( BinOpInit *BO) override;
  Init *convertValue( TernOpInit *BO) override {return RecTy::convertValue(BO);}
  Init *convertValue(   DagInit *CI) override { return (Init*)CI; }
  Init *convertValue( TypedInit *TI) override;
  Init *convertValue(   VarInit *VI) override { return RecTy::convertValue(VI);}
  Init *convertValue( FieldInit *FI) override { return RecTy::convertValue(FI);}

  std::string getAsString() const override { return "dag"; }

  bool typeIsConvertibleTo(const RecTy *RHS) const override {
    return RHS->baseClassOf(this);
  }
};

/// RecordRecTy - '[classname]' - Represent an instance of a class, such as:
/// (R32 X = EAX).
///
class RecordRecTy : public RecTy {
  Record *Rec;
  explicit RecordRecTy(Record *R) : RecTy(RecordRecTyKind), Rec(R) {}
  friend class Record;

public:
  static bool classof(const RecTy *RT) {
    return RT->getRecTyKind() == RecordRecTyKind;
  }

  static RecordRecTy *get(Record *R);

  Record *getRecord() const { return Rec; }

  Init *convertValue( UnsetInit *UI) override { return (Init*)UI; }
  Init *convertValue(   BitInit *BI) override { return nullptr; }
  Init *convertValue(  BitsInit *BI) override { return nullptr; }
  Init *convertValue(   IntInit *II) override { return nullptr; }
  Init *convertValue(StringInit *SI) override { return nullptr; }
  Init *convertValue(  ListInit *LI) override { return nullptr; }
  Init *convertValue(VarBitInit *VB) override { return nullptr; }
  Init *convertValue( UnOpInit *UI) override { return RecTy::convertValue(UI);}
  Init *convertValue( BinOpInit *UI) override { return RecTy::convertValue(UI);}
  Init *convertValue( TernOpInit *UI) override {return RecTy::convertValue(UI);}
  Init *convertValue(   DefInit *DI) override;
  Init *convertValue(   DagInit *DI) override { return nullptr; }
  Init *convertValue( TypedInit *VI) override;
  Init *convertValue(   VarInit *VI) override { return RecTy::convertValue(VI);}
  Init *convertValue( FieldInit *FI) override { return RecTy::convertValue(FI);}

  std::string getAsString() const override;

  bool typeIsConvertibleTo(const RecTy *RHS) const override {
    return RHS->baseClassOf(this);
  }
  bool baseClassOf(const RecTy*) const override;
};

/// resolveTypes - Find a common type that T1 and T2 convert to.
/// Return 0 if no such type exists.
///
RecTy *resolveTypes(RecTy *T1, RecTy *T2);

//===----------------------------------------------------------------------===//
//  Initializer Classes
//===----------------------------------------------------------------------===//

class Init {
protected:
  /// \brief Discriminator enum (for isa<>, dyn_cast<>, et al.)
  ///
  /// This enum is laid out by a preorder traversal of the inheritance
  /// hierarchy, and does not contain an entry for abstract classes, as per
  /// the recommendation in docs/HowToSetUpLLVMStyleRTTI.rst.
  ///
  /// We also explicitly include "first" and "last" values for each
  /// interior node of the inheritance tree, to make it easier to read the
  /// corresponding classof().
  ///
  /// We could pack these a bit tighter by not having the IK_FirstXXXInit
  /// and IK_LastXXXInit be their own values, but that would degrade
  /// readability for really no benefit.
  enum InitKind {
    IK_BitInit,
    IK_BitsInit,
    IK_FirstTypedInit,
    IK_DagInit,
    IK_DefInit,
    IK_FieldInit,
    IK_IntInit,
    IK_ListInit,
    IK_FirstOpInit,
    IK_BinOpInit,
    IK_TernOpInit,
    IK_UnOpInit,
    IK_LastOpInit,
    IK_StringInit,
    IK_VarInit,
    IK_VarListElementInit,
    IK_LastTypedInit,
    IK_UnsetInit,
    IK_VarBitInit
  };

private:
  const InitKind Kind;
  Init(const Init &) LLVM_DELETED_FUNCTION;
  Init &operator=(const Init &) LLVM_DELETED_FUNCTION;
  virtual void anchor();

public:
  InitKind getKind() const { return Kind; }

protected:
  explicit Init(InitKind K) : Kind(K) {}

public:
  virtual ~Init() {}

  /// isComplete - This virtual method should be overridden by values that may
  /// not be completely specified yet.
  virtual bool isComplete() const { return true; }

  /// print - Print out this value.
  void print(raw_ostream &OS) const { OS << getAsString(); }

  /// getAsString - Convert this value to a string form.
  virtual std::string getAsString() const = 0;
  /// getAsUnquotedString - Convert this value to a string form,
  /// without adding quote markers.  This primaruly affects
  /// StringInits where we will not surround the string value with
  /// quotes.
  virtual std::string getAsUnquotedString() const { return getAsString(); }

  /// dump - Debugging method that may be called through a debugger, just
  /// invokes print on stderr.
  void dump() const;

  /// convertInitializerTo - This virtual function is a simple call-back
  /// function that should be overridden to call the appropriate
  /// RecTy::convertValue method.
  ///
  virtual Init *convertInitializerTo(RecTy *Ty) const = 0;

  /// convertInitializerBitRange - This method is used to implement the bitrange
  /// selection operator.  Given an initializer, it selects the specified bits
  /// out, returning them as a new init of bits type.  If it is not legal to use
  /// the bit subscript operator on this initializer, return null.
  ///
  virtual Init *
  convertInitializerBitRange(const std::vector<unsigned> &Bits) const {
    return nullptr;
  }

  /// convertInitListSlice - This method is used to implement the list slice
  /// selection operator.  Given an initializer, it selects the specified list
  /// elements, returning them as a new init of list type.  If it is not legal
  /// to take a slice of this, return null.
  ///
  virtual Init *
  convertInitListSlice(const std::vector<unsigned> &Elements) const {
    return nullptr;
  }

  /// getFieldType - This method is used to implement the FieldInit class.
  /// Implementors of this method should return the type of the named field if
  /// they are of record type.
  ///
  virtual RecTy *getFieldType(const std::string &FieldName) const {
    return nullptr;
  }

  /// getFieldInit - This method complements getFieldType to return the
  /// initializer for the specified field.  If getFieldType returns non-null
  /// this method should return non-null, otherwise it returns null.
  ///
  virtual Init *getFieldInit(Record &R, const RecordVal *RV,
                             const std::string &FieldName) const {
    return nullptr;
  }

  /// resolveReferences - This method is used by classes that refer to other
  /// variables which may not be defined at the time the expression is formed.
  /// If a value is set for the variable later, this method will be called on
  /// users of the value to allow the value to propagate out.
  ///
  virtual Init *resolveReferences(Record &R, const RecordVal *RV) const {
    return const_cast<Init *>(this);
  }

  /// getBit - This method is used to return the initializer for the specified
  /// bit.
  virtual Init *getBit(unsigned Bit) const = 0;

  /// getBitVar - This method is used to retrieve the initializer for bit
  /// reference. For non-VarBitInit, it simply returns itself.
  virtual Init *getBitVar() const { return const_cast<Init*>(this); }

  /// getBitNum - This method is used to retrieve the bit number of a bit
  /// reference. For non-VarBitInit, it simply returns 0.
  virtual unsigned getBitNum() const { return 0; }
};

inline raw_ostream &operator<<(raw_ostream &OS, const Init &I) {
  I.print(OS); return OS;
}

/// TypedInit - This is the common super-class of types that have a specific,
/// explicit, type.
///
class TypedInit : public Init {
  RecTy *Ty;

  TypedInit(const TypedInit &Other) LLVM_DELETED_FUNCTION;
  TypedInit &operator=(const TypedInit &Other) LLVM_DELETED_FUNCTION;

protected:
  explicit TypedInit(InitKind K, RecTy *T) : Init(K), Ty(T) {}

public:
  static bool classof(const Init *I) {
    return I->getKind() >= IK_FirstTypedInit &&
           I->getKind() <= IK_LastTypedInit;
  }
  RecTy *getType() const { return Ty; }

  Init *
  convertInitializerBitRange(const std::vector<unsigned> &Bits) const override;
  Init *
  convertInitListSlice(const std::vector<unsigned> &Elements) const override;

  /// getFieldType - This method is used to implement the FieldInit class.
  /// Implementors of this method should return the type of the named field if
  /// they are of record type.
  ///
  RecTy *getFieldType(const std::string &FieldName) const override;

  /// resolveListElementReference - This method is used to implement
  /// VarListElementInit::resolveReferences.  If the list element is resolvable
  /// now, we return the resolved value, otherwise we return null.
  virtual Init *resolveListElementReference(Record &R, const RecordVal *RV,
                                            unsigned Elt) const = 0;
};

/// UnsetInit - ? - Represents an uninitialized value
///
class UnsetInit : public Init {
  UnsetInit() : Init(IK_UnsetInit) {}
  UnsetInit(const UnsetInit &) LLVM_DELETED_FUNCTION;
  UnsetInit &operator=(const UnsetInit &Other) LLVM_DELETED_FUNCTION;
  void anchor() override;

public:
  static bool classof(const Init *I) {
    return I->getKind() == IK_UnsetInit;
  }
  static UnsetInit *get();

  Init *convertInitializerTo(RecTy *Ty) const override {
    return Ty->convertValue(const_cast<UnsetInit *>(this));
  }

  Init *getBit(unsigned Bit) const override {
    return const_cast<UnsetInit*>(this);
  }

  bool isComplete() const override { return false; }
  std::string getAsString() const override { return "?"; }
};

/// BitInit - true/false - Represent a concrete initializer for a bit.
///
class BitInit : public Init {
  bool Value;

  explicit BitInit(bool V) : Init(IK_BitInit), Value(V) {}
  BitInit(const BitInit &Other) LLVM_DELETED_FUNCTION;
  BitInit &operator=(BitInit &Other) LLVM_DELETED_FUNCTION;
  void anchor() override;

public:
  static bool classof(const Init *I) {
    return I->getKind() == IK_BitInit;
  }
  static BitInit *get(bool V);

  bool getValue() const { return Value; }

  Init *convertInitializerTo(RecTy *Ty) const override {
    return Ty->convertValue(const_cast<BitInit *>(this));
  }

  Init *getBit(unsigned Bit) const override {
    assert(Bit < 1 && "Bit index out of range!");
    return const_cast<BitInit*>(this);
  }

  std::string getAsString() const override { return Value ? "1" : "0"; }
};

/// BitsInit - { a, b, c } - Represents an initializer for a BitsRecTy value.
/// It contains a vector of bits, whose size is determined by the type.
///
class BitsInit : public Init, public FoldingSetNode {
  std::vector<Init*> Bits;

  BitsInit(ArrayRef<Init *> Range)
    : Init(IK_BitsInit), Bits(Range.begin(), Range.end()) {}

  BitsInit(const BitsInit &Other) LLVM_DELETED_FUNCTION;
  BitsInit &operator=(const BitsInit &Other) LLVM_DELETED_FUNCTION;

public:
  static bool classof(const Init *I) {
    return I->getKind() == IK_BitsInit;
  }
  static BitsInit *get(ArrayRef<Init *> Range);

  void Profile(FoldingSetNodeID &ID) const;

  unsigned getNumBits() const { return Bits.size(); }

  Init *convertInitializerTo(RecTy *Ty) const override {
    return Ty->convertValue(const_cast<BitsInit *>(this));
  }
  Init *
  convertInitializerBitRange(const std::vector<unsigned> &Bits) const override;

  bool isComplete() const override {
    for (unsigned i = 0; i != getNumBits(); ++i)
      if (!getBit(i)->isComplete()) return false;
    return true;
  }
  bool allInComplete() const {
    for (unsigned i = 0; i != getNumBits(); ++i)
      if (getBit(i)->isComplete()) return false;
    return true;
  }
  std::string getAsString() const override;

  Init *resolveReferences(Record &R, const RecordVal *RV) const override;

  Init *getBit(unsigned Bit) const override {
    assert(Bit < Bits.size() && "Bit index out of range!");
    return Bits[Bit];
  }
};

/// IntInit - 7 - Represent an initialization by a literal integer value.
///
class IntInit : public TypedInit {
  int64_t Value;

  explicit IntInit(int64_t V)
    : TypedInit(IK_IntInit, IntRecTy::get()), Value(V) {}

  IntInit(const IntInit &Other) LLVM_DELETED_FUNCTION;
  IntInit &operator=(const IntInit &Other) LLVM_DELETED_FUNCTION;

public:
  static bool classof(const Init *I) {
    return I->getKind() == IK_IntInit;
  }
  static IntInit *get(int64_t V);

  int64_t getValue() const { return Value; }

  Init *convertInitializerTo(RecTy *Ty) const override {
    return Ty->convertValue(const_cast<IntInit *>(this));
  }
  Init *
  convertInitializerBitRange(const std::vector<unsigned> &Bits) const override;

  std::string getAsString() const override;

  /// resolveListElementReference - This method is used to implement
  /// VarListElementInit::resolveReferences.  If the list element is resolvable
  /// now, we return the resolved value, otherwise we return null.
  Init *resolveListElementReference(Record &R, const RecordVal *RV,
                                    unsigned Elt) const override {
    llvm_unreachable("Illegal element reference off int");
  }

  Init *getBit(unsigned Bit) const override {
    return BitInit::get((Value & (1ULL << Bit)) != 0);
  }
};

/// StringInit - "foo" - Represent an initialization by a string value.
///
class StringInit : public TypedInit {
  std::string Value;

  explicit StringInit(const std::string &V)
    : TypedInit(IK_StringInit, StringRecTy::get()), Value(V) {}

  StringInit(const StringInit &Other) LLVM_DELETED_FUNCTION;
  StringInit &operator=(const StringInit &Other) LLVM_DELETED_FUNCTION;
  void anchor() override;

public:
  static bool classof(const Init *I) {
    return I->getKind() == IK_StringInit;
  }
  static StringInit *get(StringRef);

  const std::string &getValue() const { return Value; }

  Init *convertInitializerTo(RecTy *Ty) const override {
    return Ty->convertValue(const_cast<StringInit *>(this));
  }

  std::string getAsString() const override { return "\"" + Value + "\""; }
  std::string getAsUnquotedString() const override { return Value; }

  /// resolveListElementReference - This method is used to implement
  /// VarListElementInit::resolveReferences.  If the list element is resolvable
  /// now, we return the resolved value, otherwise we return null.
  Init *resolveListElementReference(Record &R, const RecordVal *RV,
                                    unsigned Elt) const override {
    llvm_unreachable("Illegal element reference off string");
  }

  Init *getBit(unsigned Bit) const override {
    llvm_unreachable("Illegal bit reference off string");
  }
};

/// ListInit - [AL, AH, CL] - Represent a list of defs
///
class ListInit : public TypedInit, public FoldingSetNode {
  std::vector<Init*> Values;

public:
  typedef std::vector<Init*>::const_iterator const_iterator;

private:
  explicit ListInit(ArrayRef<Init *> Range, RecTy *EltTy)
    : TypedInit(IK_ListInit, ListRecTy::get(EltTy)),
      Values(Range.begin(), Range.end()) {}

  ListInit(const ListInit &Other) LLVM_DELETED_FUNCTION;
  ListInit &operator=(const ListInit &Other) LLVM_DELETED_FUNCTION;

public:
  static bool classof(const Init *I) {
    return I->getKind() == IK_ListInit;
  }
  static ListInit *get(ArrayRef<Init *> Range, RecTy *EltTy);

  void Profile(FoldingSetNodeID &ID) const;

  unsigned getSize() const { return Values.size(); }
  Init *getElement(unsigned i) const {
    assert(i < Values.size() && "List element index out of range!");
    return Values[i];
  }

  Record *getElementAsRecord(unsigned i) const;

  Init *
    convertInitListSlice(const std::vector<unsigned> &Elements) const override;

  Init *convertInitializerTo(RecTy *Ty) const override {
    return Ty->convertValue(const_cast<ListInit *>(this));
  }

  /// resolveReferences - This method is used by classes that refer to other
  /// variables which may not be defined at the time they expression is formed.
  /// If a value is set for the variable later, this method will be called on
  /// users of the value to allow the value to propagate out.
  ///
  Init *resolveReferences(Record &R, const RecordVal *RV) const override;

  std::string getAsString() const override;

  ArrayRef<Init*> getValues() const { return Values; }

  inline const_iterator begin() const { return Values.begin(); }
  inline const_iterator end  () const { return Values.end();   }

  inline size_t         size () const { return Values.size();  }
  inline bool           empty() const { return Values.empty(); }

  /// resolveListElementReference - This method is used to implement
  /// VarListElementInit::resolveReferences.  If the list element is resolvable
  /// now, we return the resolved value, otherwise we return null.
  Init *resolveListElementReference(Record &R, const RecordVal *RV,
                                    unsigned Elt) const override;

  Init *getBit(unsigned Bit) const override {
    llvm_unreachable("Illegal bit reference off list");
  }
};

/// OpInit - Base class for operators
///
class OpInit : public TypedInit {
  OpInit(const OpInit &Other) LLVM_DELETED_FUNCTION;
  OpInit &operator=(OpInit &Other) LLVM_DELETED_FUNCTION;

protected:
  explicit OpInit(InitKind K, RecTy *Type) : TypedInit(K, Type) {}

public:
  static bool classof(const Init *I) {
    return I->getKind() >= IK_FirstOpInit &&
           I->getKind() <= IK_LastOpInit;
  }
  // Clone - Clone this operator, replacing arguments with the new list
  virtual OpInit *clone(std::vector<Init *> &Operands) const = 0;

  virtual int getNumOperands() const = 0;
  virtual Init *getOperand(int i) const = 0;

  // Fold - If possible, fold this to a simpler init.  Return this if not
  // possible to fold.
  virtual Init *Fold(Record *CurRec, MultiClass *CurMultiClass) const = 0;

  Init *convertInitializerTo(RecTy *Ty) const override {
    return Ty->convertValue(const_cast<OpInit *>(this));
  }

  Init *resolveListElementReference(Record &R, const RecordVal *RV,
                                    unsigned Elt) const override;

  Init *getBit(unsigned Bit) const override;
};

/// UnOpInit - !op (X) - Transform an init.
///
class UnOpInit : public OpInit {
public:
  enum UnaryOp { CAST, HEAD, TAIL, EMPTY };

private:
  UnaryOp Opc;
  Init *LHS;

  UnOpInit(UnaryOp opc, Init *lhs, RecTy *Type)
    : OpInit(IK_UnOpInit, Type), Opc(opc), LHS(lhs) {}

  UnOpInit(const UnOpInit &Other) LLVM_DELETED_FUNCTION;
  UnOpInit &operator=(const UnOpInit &Other) LLVM_DELETED_FUNCTION;

public:
  static bool classof(const Init *I) {
    return I->getKind() == IK_UnOpInit;
  }
  static UnOpInit *get(UnaryOp opc, Init *lhs, RecTy *Type);

  // Clone - Clone this operator, replacing arguments with the new list
  OpInit *clone(std::vector<Init *> &Operands) const override {
    assert(Operands.size() == 1 &&
           "Wrong number of operands for unary operation");
    return UnOpInit::get(getOpcode(), *Operands.begin(), getType());
  }

  int getNumOperands() const override { return 1; }
  Init *getOperand(int i) const override {
    assert(i == 0 && "Invalid operand id for unary operator");
    return getOperand();
  }

  UnaryOp getOpcode() const { return Opc; }
  Init *getOperand() const { return LHS; }

  // Fold - If possible, fold this to a simpler init.  Return this if not
  // possible to fold.
  Init *Fold(Record *CurRec, MultiClass *CurMultiClass) const override;

  Init *resolveReferences(Record &R, const RecordVal *RV) const override;

  std::string getAsString() const override;
};

/// BinOpInit - !op (X, Y) - Combine two inits.
///
class BinOpInit : public OpInit {
public:
  enum BinaryOp { ADD, SHL, SRA, SRL, LISTCONCAT, STRCONCAT, CONCAT, EQ };

private:
  BinaryOp Opc;
  Init *LHS, *RHS;

  BinOpInit(BinaryOp opc, Init *lhs, Init *rhs, RecTy *Type) :
      OpInit(IK_BinOpInit, Type), Opc(opc), LHS(lhs), RHS(rhs) {}

  BinOpInit(const BinOpInit &Other) LLVM_DELETED_FUNCTION;
  BinOpInit &operator=(const BinOpInit &Other) LLVM_DELETED_FUNCTION;

public:
  static bool classof(const Init *I) {
    return I->getKind() == IK_BinOpInit;
  }
  static BinOpInit *get(BinaryOp opc, Init *lhs, Init *rhs,
                        RecTy *Type);

  // Clone - Clone this operator, replacing arguments with the new list
  OpInit *clone(std::vector<Init *> &Operands) const override {
    assert(Operands.size() == 2 &&
           "Wrong number of operands for binary operation");
    return BinOpInit::get(getOpcode(), Operands[0], Operands[1], getType());
  }

  int getNumOperands() const override { return 2; }
  Init *getOperand(int i) const override {
    assert((i == 0 || i == 1) && "Invalid operand id for binary operator");
    if (i == 0) {
      return getLHS();
    } else {
      return getRHS();
    }
  }

  BinaryOp getOpcode() const { return Opc; }
  Init *getLHS() const { return LHS; }
  Init *getRHS() const { return RHS; }

  // Fold - If possible, fold this to a simpler init.  Return this if not
  // possible to fold.
  Init *Fold(Record *CurRec, MultiClass *CurMultiClass) const override;

  Init *resolveReferences(Record &R, const RecordVal *RV) const override;

  std::string getAsString() const override;
};

/// TernOpInit - !op (X, Y, Z) - Combine two inits.
///
class TernOpInit : public OpInit {
public:
  enum TernaryOp { SUBST, FOREACH, IF };

private:
  TernaryOp Opc;
  Init *LHS, *MHS, *RHS;

  TernOpInit(TernaryOp opc, Init *lhs, Init *mhs, Init *rhs,
             RecTy *Type) :
      OpInit(IK_TernOpInit, Type), Opc(opc), LHS(lhs), MHS(mhs), RHS(rhs) {}

  TernOpInit(const TernOpInit &Other) LLVM_DELETED_FUNCTION;
  TernOpInit &operator=(const TernOpInit &Other) LLVM_DELETED_FUNCTION;

public:
  static bool classof(const Init *I) {
    return I->getKind() == IK_TernOpInit;
  }
  static TernOpInit *get(TernaryOp opc, Init *lhs,
                         Init *mhs, Init *rhs,
                         RecTy *Type);

  // Clone - Clone this operator, replacing arguments with the new list
  OpInit *clone(std::vector<Init *> &Operands) const override {
    assert(Operands.size() == 3 &&
           "Wrong number of operands for ternary operation");
    return TernOpInit::get(getOpcode(), Operands[0], Operands[1], Operands[2],
                           getType());
  }

  int getNumOperands() const override { return 3; }
  Init *getOperand(int i) const override {
    assert((i == 0 || i == 1 || i == 2) &&
           "Invalid operand id for ternary operator");
    if (i == 0) {
      return getLHS();
    } else if (i == 1) {
      return getMHS();
    } else {
      return getRHS();
    }
  }

  TernaryOp getOpcode() const { return Opc; }
  Init *getLHS() const { return LHS; }
  Init *getMHS() const { return MHS; }
  Init *getRHS() const { return RHS; }

  // Fold - If possible, fold this to a simpler init.  Return this if not
  // possible to fold.
  Init *Fold(Record *CurRec, MultiClass *CurMultiClass) const override;

  bool isComplete() const override { return false; }

  Init *resolveReferences(Record &R, const RecordVal *RV) const override;

  std::string getAsString() const override;
};

/// VarInit - 'Opcode' - Represent a reference to an entire variable object.
///
class VarInit : public TypedInit {
  Init *VarName;

  explicit VarInit(const std::string &VN, RecTy *T)
      : TypedInit(IK_VarInit, T), VarName(StringInit::get(VN)) {}
  explicit VarInit(Init *VN, RecTy *T)
      : TypedInit(IK_VarInit, T), VarName(VN) {}

  VarInit(const VarInit &Other) LLVM_DELETED_FUNCTION;
  VarInit &operator=(const VarInit &Other) LLVM_DELETED_FUNCTION;

public:
  static bool classof(const Init *I) {
    return I->getKind() == IK_VarInit;
  }
  static VarInit *get(const std::string &VN, RecTy *T);
  static VarInit *get(Init *VN, RecTy *T);

  Init *convertInitializerTo(RecTy *Ty) const override {
    return Ty->convertValue(const_cast<VarInit *>(this));
  }

  const std::string &getName() const;
  Init *getNameInit() const { return VarName; }
  std::string getNameInitAsString() const {
    return getNameInit()->getAsUnquotedString();
  }

  Init *resolveListElementReference(Record &R, const RecordVal *RV,
                                    unsigned Elt) const override;

  RecTy *getFieldType(const std::string &FieldName) const override;
  Init *getFieldInit(Record &R, const RecordVal *RV,
                     const std::string &FieldName) const override;

  /// resolveReferences - This method is used by classes that refer to other
  /// variables which may not be defined at the time they expression is formed.
  /// If a value is set for the variable later, this method will be called on
  /// users of the value to allow the value to propagate out.
  ///
  Init *resolveReferences(Record &R, const RecordVal *RV) const override;

  Init *getBit(unsigned Bit) const override;

  std::string getAsString() const override { return getName(); }
};

/// VarBitInit - Opcode{0} - Represent access to one bit of a variable or field.
///
class VarBitInit : public Init {
  TypedInit *TI;
  unsigned Bit;

  VarBitInit(TypedInit *T, unsigned B) : Init(IK_VarBitInit), TI(T), Bit(B) {
    assert(T->getType() &&
           (isa<IntRecTy>(T->getType()) ||
            (isa<BitsRecTy>(T->getType()) &&
             cast<BitsRecTy>(T->getType())->getNumBits() > B)) &&
           "Illegal VarBitInit expression!");
  }

  VarBitInit(const VarBitInit &Other) LLVM_DELETED_FUNCTION;
  VarBitInit &operator=(const VarBitInit &Other) LLVM_DELETED_FUNCTION;

public:
  static bool classof(const Init *I) {
    return I->getKind() == IK_VarBitInit;
  }
  static VarBitInit *get(TypedInit *T, unsigned B);

  Init *convertInitializerTo(RecTy *Ty) const override {
    return Ty->convertValue(const_cast<VarBitInit *>(this));
  }

  Init *getBitVar() const override { return TI; }
  unsigned getBitNum() const override { return Bit; }

  std::string getAsString() const override;
  Init *resolveReferences(Record &R, const RecordVal *RV) const override;

  Init *getBit(unsigned B) const override {
    assert(B < 1 && "Bit index out of range!");
    return const_cast<VarBitInit*>(this);
  }
};

/// VarListElementInit - List[4] - Represent access to one element of a var or
/// field.
class VarListElementInit : public TypedInit {
  TypedInit *TI;
  unsigned Element;

  VarListElementInit(TypedInit *T, unsigned E)
      : TypedInit(IK_VarListElementInit,
                  cast<ListRecTy>(T->getType())->getElementType()),
        TI(T), Element(E) {
    assert(T->getType() && isa<ListRecTy>(T->getType()) &&
           "Illegal VarBitInit expression!");
  }

  VarListElementInit(const VarListElementInit &Other) LLVM_DELETED_FUNCTION;
  void operator=(const VarListElementInit &Other) LLVM_DELETED_FUNCTION;

public:
  static bool classof(const Init *I) {
    return I->getKind() == IK_VarListElementInit;
  }
  static VarListElementInit *get(TypedInit *T, unsigned E);

  Init *convertInitializerTo(RecTy *Ty) const override {
    return Ty->convertValue(const_cast<VarListElementInit *>(this));
  }

  TypedInit *getVariable() const { return TI; }
  unsigned getElementNum() const { return Element; }

  /// resolveListElementReference - This method is used to implement
  /// VarListElementInit::resolveReferences.  If the list element is resolvable
  /// now, we return the resolved value, otherwise we return null.
  Init *resolveListElementReference(Record &R, const RecordVal *RV,
                                    unsigned Elt) const override;

  std::string getAsString() const override;
  Init *resolveReferences(Record &R, const RecordVal *RV) const override;

  Init *getBit(unsigned Bit) const override;
};

/// DefInit - AL - Represent a reference to a 'def' in the description
///
class DefInit : public TypedInit {
  Record *Def;

  DefInit(Record *D, RecordRecTy *T) : TypedInit(IK_DefInit, T), Def(D) {}
  friend class Record;

  DefInit(const DefInit &Other) LLVM_DELETED_FUNCTION;
  DefInit &operator=(const DefInit &Other) LLVM_DELETED_FUNCTION;

public:
  static bool classof(const Init *I) {
    return I->getKind() == IK_DefInit;
  }
  static DefInit *get(Record*);

  Init *convertInitializerTo(RecTy *Ty) const override {
    return Ty->convertValue(const_cast<DefInit *>(this));
  }

  Record *getDef() const { return Def; }

  //virtual Init *convertInitializerBitRange(const std::vector<unsigned> &Bits);

  RecTy *getFieldType(const std::string &FieldName) const override;
  Init *getFieldInit(Record &R, const RecordVal *RV,
                     const std::string &FieldName) const override;

  std::string getAsString() const override;

  Init *getBit(unsigned Bit) const override {
    llvm_unreachable("Illegal bit reference off def");
  }

  /// resolveListElementReference - This method is used to implement
  /// VarListElementInit::resolveReferences.  If the list element is resolvable
  /// now, we return the resolved value, otherwise we return null.
  Init *resolveListElementReference(Record &R, const RecordVal *RV,
                                    unsigned Elt) const override {
    llvm_unreachable("Illegal element reference off def");
  }
};

/// FieldInit - X.Y - Represent a reference to a subfield of a variable
///
class FieldInit : public TypedInit {
  Init *Rec;                // Record we are referring to
  std::string FieldName;    // Field we are accessing

  FieldInit(Init *R, const std::string &FN)
      : TypedInit(IK_FieldInit, R->getFieldType(FN)), Rec(R), FieldName(FN) {
    assert(getType() && "FieldInit with non-record type!");
  }

  FieldInit(const FieldInit &Other) LLVM_DELETED_FUNCTION;
  FieldInit &operator=(const FieldInit &Other) LLVM_DELETED_FUNCTION;

public:
  static bool classof(const Init *I) {
    return I->getKind() == IK_FieldInit;
  }
  static FieldInit *get(Init *R, const std::string &FN);
  static FieldInit *get(Init *R, const Init *FN);

  Init *convertInitializerTo(RecTy *Ty) const override {
    return Ty->convertValue(const_cast<FieldInit *>(this));
  }

  Init *getBit(unsigned Bit) const override;

  Init *resolveListElementReference(Record &R, const RecordVal *RV,
                                    unsigned Elt) const override;

  Init *resolveReferences(Record &R, const RecordVal *RV) const override;

  std::string getAsString() const override {
    return Rec->getAsString() + "." + FieldName;
  }
};

/// DagInit - (v a, b) - Represent a DAG tree value.  DAG inits are required
/// to have at least one value then a (possibly empty) list of arguments.  Each
/// argument can have a name associated with it.
///
class DagInit : public TypedInit, public FoldingSetNode {
  Init *Val;
  std::string ValName;
  std::vector<Init*> Args;
  std::vector<std::string> ArgNames;

  DagInit(Init *V, const std::string &VN,
          ArrayRef<Init *> ArgRange,
          ArrayRef<std::string> NameRange)
      : TypedInit(IK_DagInit, DagRecTy::get()), Val(V), ValName(VN),
          Args(ArgRange.begin(), ArgRange.end()),
          ArgNames(NameRange.begin(), NameRange.end()) {}

  DagInit(const DagInit &Other) LLVM_DELETED_FUNCTION;
  DagInit &operator=(const DagInit &Other) LLVM_DELETED_FUNCTION;

public:
  static bool classof(const Init *I) {
    return I->getKind() == IK_DagInit;
  }
  static DagInit *get(Init *V, const std::string &VN,
                      ArrayRef<Init *> ArgRange,
                      ArrayRef<std::string> NameRange);
  static DagInit *get(Init *V, const std::string &VN,
                      const std::vector<
                        std::pair<Init*, std::string> > &args);

  void Profile(FoldingSetNodeID &ID) const;

  Init *convertInitializerTo(RecTy *Ty) const override {
    return Ty->convertValue(const_cast<DagInit *>(this));
  }

  Init *getOperator() const { return Val; }

  const std::string &getName() const { return ValName; }

  unsigned getNumArgs() const { return Args.size(); }
  Init *getArg(unsigned Num) const {
    assert(Num < Args.size() && "Arg number out of range!");
    return Args[Num];
  }
  const std::string &getArgName(unsigned Num) const {
    assert(Num < ArgNames.size() && "Arg number out of range!");
    return ArgNames[Num];
  }

  Init *resolveReferences(Record &R, const RecordVal *RV) const override;

  std::string getAsString() const override;

  typedef std::vector<Init*>::const_iterator       const_arg_iterator;
  typedef std::vector<std::string>::const_iterator const_name_iterator;

  inline const_arg_iterator  arg_begin() const { return Args.begin(); }
  inline const_arg_iterator  arg_end  () const { return Args.end();   }

  inline size_t              arg_size () const { return Args.size();  }
  inline bool                arg_empty() const { return Args.empty(); }

  inline const_name_iterator name_begin() const { return ArgNames.begin(); }
  inline const_name_iterator name_end  () const { return ArgNames.end();   }

  inline size_t              name_size () const { return ArgNames.size();  }
  inline bool                name_empty() const { return ArgNames.empty(); }

  Init *getBit(unsigned Bit) const override {
    llvm_unreachable("Illegal bit reference off dag");
  }

  Init *resolveListElementReference(Record &R, const RecordVal *RV,
                                    unsigned Elt) const override {
    llvm_unreachable("Illegal element reference off dag");
  }
};

//===----------------------------------------------------------------------===//
//  High-Level Classes
//===----------------------------------------------------------------------===//

class RecordVal {
  Init *Name;
  RecTy *Ty;
  unsigned Prefix;
  Init *Value;

public:
  RecordVal(Init *N, RecTy *T, unsigned P);
  RecordVal(const std::string &N, RecTy *T, unsigned P);

  const std::string &getName() const;
  const Init *getNameInit() const { return Name; }
  std::string getNameInitAsString() const {
    return getNameInit()->getAsUnquotedString();
  }

  unsigned getPrefix() const { return Prefix; }
  RecTy *getType() const { return Ty; }
  Init *getValue() const { return Value; }

  bool setValue(Init *V) {
    if (V) {
      Value = V->convertInitializerTo(Ty);
      return Value == nullptr;
    }
    Value = nullptr;
    return false;
  }

  void dump() const;
  void print(raw_ostream &OS, bool PrintSem = true) const;
};

inline raw_ostream &operator<<(raw_ostream &OS, const RecordVal &RV) {
  RV.print(OS << "  ");
  return OS;
}

class Record {
  static unsigned LastID;

  // Unique record ID.
  unsigned ID;
  Init *Name;
  // Location where record was instantiated, followed by the location of
  // multiclass prototypes used.
  SmallVector<SMLoc, 4> Locs;
  std::vector<Init *> TemplateArgs;
  std::vector<RecordVal> Values;
  std::vector<Record *> SuperClasses;
  std::vector<SMRange> SuperClassRanges;

  // Tracks Record instances. Not owned by Record.
  RecordKeeper &TrackedRecords;

  DefInit *TheInit;
  bool IsAnonymous;

  void init();
  void checkName();

public:
  // Constructs a record.
  explicit Record(const std::string &N, ArrayRef<SMLoc> locs,
                  RecordKeeper &records, bool Anonymous = false) :
    ID(LastID++), Name(StringInit::get(N)), Locs(locs.begin(), locs.end()),
    TrackedRecords(records), TheInit(nullptr), IsAnonymous(Anonymous) {
    init();
  }
  explicit Record(Init *N, ArrayRef<SMLoc> locs, RecordKeeper &records,
                  bool Anonymous = false) :
    ID(LastID++), Name(N), Locs(locs.begin(), locs.end()),
    TrackedRecords(records), TheInit(nullptr), IsAnonymous(Anonymous) {
    init();
  }

  // When copy-constructing a Record, we must still guarantee a globally unique
  // ID number.  All other fields can be copied normally.
  Record(const Record &O) :
    ID(LastID++), Name(O.Name), Locs(O.Locs), TemplateArgs(O.TemplateArgs),
    Values(O.Values), SuperClasses(O.SuperClasses),
    SuperClassRanges(O.SuperClassRanges), TrackedRecords(O.TrackedRecords),
    TheInit(O.TheInit), IsAnonymous(O.IsAnonymous) { }

  ~Record() {}

  static unsigned getNewUID() { return LastID++; }

  unsigned getID() const { return ID; }

  const std::string &getName() const;
  Init *getNameInit() const {
    return Name;
  }
  const std::string getNameInitAsString() const {
    return getNameInit()->getAsUnquotedString();
  }

  void setName(Init *Name);               // Also updates RecordKeeper.
  void setName(const std::string &Name);  // Also updates RecordKeeper.

  ArrayRef<SMLoc> getLoc() const { return Locs; }

  /// get the corresponding DefInit.
  DefInit *getDefInit();

  const std::vector<Init *> &getTemplateArgs() const {
    return TemplateArgs;
  }
  const std::vector<RecordVal> &getValues() const { return Values; }
  const std::vector<Record*>   &getSuperClasses() const { return SuperClasses; }
  ArrayRef<SMRange> getSuperClassRanges() const { return SuperClassRanges; }

  bool isTemplateArg(Init *Name) const {
    for (unsigned i = 0, e = TemplateArgs.size(); i != e; ++i)
      if (TemplateArgs[i] == Name) return true;
    return false;
  }
  bool isTemplateArg(StringRef Name) const {
    return isTemplateArg(StringInit::get(Name.str()));
  }

  const RecordVal *getValue(const Init *Name) const {
    for (unsigned i = 0, e = Values.size(); i != e; ++i)
      if (Values[i].getNameInit() == Name) return &Values[i];
    return nullptr;
  }
  const RecordVal *getValue(StringRef Name) const {
    return getValue(StringInit::get(Name));
  }
  RecordVal *getValue(const Init *Name) {
    for (unsigned i = 0, e = Values.size(); i != e; ++i)
      if (Values[i].getNameInit() == Name) return &Values[i];
    return nullptr;
  }
  RecordVal *getValue(StringRef Name) {
    return getValue(StringInit::get(Name));
  }

  void addTemplateArg(Init *Name) {
    assert(!isTemplateArg(Name) && "Template arg already defined!");
    TemplateArgs.push_back(Name);
  }
  void addTemplateArg(StringRef Name) {
    addTemplateArg(StringInit::get(Name.str()));
  }

  void addValue(const RecordVal &RV) {
    assert(getValue(RV.getNameInit()) == nullptr && "Value already added!");
    Values.push_back(RV);
    if (Values.size() > 1)
      // Keep NAME at the end of the list.  It makes record dumps a
      // bit prettier and allows TableGen tests to be written more
      // naturally.  Tests can use CHECK-NEXT to look for Record
      // fields they expect to see after a def.  They can't do that if
      // NAME is the first Record field.
      std::swap(Values[Values.size() - 2], Values[Values.size() - 1]);
  }

  void removeValue(Init *Name) {
    for (unsigned i = 0, e = Values.size(); i != e; ++i)
      if (Values[i].getNameInit() == Name) {
        Values.erase(Values.begin()+i);
        return;
      }
    llvm_unreachable("Cannot remove an entry that does not exist!");
  }

  void removeValue(StringRef Name) {
    removeValue(StringInit::get(Name.str()));
  }

  bool isSubClassOf(const Record *R) const {
    for (unsigned i = 0, e = SuperClasses.size(); i != e; ++i)
      if (SuperClasses[i] == R)
        return true;
    return false;
  }

  bool isSubClassOf(StringRef Name) const {
    for (unsigned i = 0, e = SuperClasses.size(); i != e; ++i)
      if (SuperClasses[i]->getNameInitAsString() == Name)
        return true;
    return false;
  }

  void addSuperClass(Record *R, SMRange Range) {
    assert(!isSubClassOf(R) && "Already subclassing record!");
    SuperClasses.push_back(R);
    SuperClassRanges.push_back(Range);
  }

  /// resolveReferences - If there are any field references that refer to fields
  /// that have been filled in, we can propagate the values now.
  ///
  void resolveReferences() { resolveReferencesTo(nullptr); }

  /// resolveReferencesTo - If anything in this record refers to RV, replace the
  /// reference to RV with the RHS of RV.  If RV is null, we resolve all
  /// possible references.
  void resolveReferencesTo(const RecordVal *RV);

  RecordKeeper &getRecords() const {
    return TrackedRecords;
  }

  bool isAnonymous() const {
    return IsAnonymous;
  }

  void dump() const;

  //===--------------------------------------------------------------------===//
  // High-level methods useful to tablegen back-ends
  //

  /// getValueInit - Return the initializer for a value with the specified name,
  /// or throw an exception if the field does not exist.
  ///
  Init *getValueInit(StringRef FieldName) const;

  /// Return true if the named field is unset.
  bool isValueUnset(StringRef FieldName) const {
    return getValueInit(FieldName) == UnsetInit::get();
  }

  /// getValueAsString - This method looks up the specified field and returns
  /// its value as a string, throwing an exception if the field does not exist
  /// or if the value is not a string.
  ///
  std::string getValueAsString(StringRef FieldName) const;

  /// getValueAsBitsInit - This method looks up the specified field and returns
  /// its value as a BitsInit, throwing an exception if the field does not exist
  /// or if the value is not the right type.
  ///
  BitsInit *getValueAsBitsInit(StringRef FieldName) const;

  /// getValueAsListInit - This method looks up the specified field and returns
  /// its value as a ListInit, throwing an exception if the field does not exist
  /// or if the value is not the right type.
  ///
  ListInit *getValueAsListInit(StringRef FieldName) const;

  /// getValueAsListOfDefs - This method looks up the specified field and
  /// returns its value as a vector of records, throwing an exception if the
  /// field does not exist or if the value is not the right type.
  ///
  std::vector<Record*> getValueAsListOfDefs(StringRef FieldName) const;

  /// getValueAsListOfInts - This method looks up the specified field and
  /// returns its value as a vector of integers, throwing an exception if the
  /// field does not exist or if the value is not the right type.
  ///
  std::vector<int64_t> getValueAsListOfInts(StringRef FieldName) const;

  /// getValueAsListOfStrings - This method looks up the specified field and
  /// returns its value as a vector of strings, throwing an exception if the
  /// field does not exist or if the value is not the right type.
  ///
  std::vector<std::string> getValueAsListOfStrings(StringRef FieldName) const;

  /// getValueAsDef - This method looks up the specified field and returns its
  /// value as a Record, throwing an exception if the field does not exist or if
  /// the value is not the right type.
  ///
  Record *getValueAsDef(StringRef FieldName) const;

  /// getValueAsBit - This method looks up the specified field and returns its
  /// value as a bit, throwing an exception if the field does not exist or if
  /// the value is not the right type.
  ///
  bool getValueAsBit(StringRef FieldName) const;

  /// getValueAsBitOrUnset - This method looks up the specified field and
  /// returns its value as a bit. If the field is unset, sets Unset to true and
  /// returns false.
  ///
  bool getValueAsBitOrUnset(StringRef FieldName, bool &Unset) const;

  /// getValueAsInt - This method looks up the specified field and returns its
  /// value as an int64_t, throwing an exception if the field does not exist or
  /// if the value is not the right type.
  ///
  int64_t getValueAsInt(StringRef FieldName) const;

  /// getValueAsDag - This method looks up the specified field and returns its
  /// value as an Dag, throwing an exception if the field does not exist or if
  /// the value is not the right type.
  ///
  DagInit *getValueAsDag(StringRef FieldName) const;
};

raw_ostream &operator<<(raw_ostream &OS, const Record &R);

struct MultiClass {
  Record Rec;  // Placeholder for template args and Name.
  typedef std::vector<Record*> RecordVector;
  RecordVector DefPrototypes;

  void dump() const;

  MultiClass(const std::string &Name, SMLoc Loc, RecordKeeper &Records) :
    Rec(Name, Loc, Records) {}
};

class RecordKeeper {
  std::map<std::string, Record*> Classes, Defs;

public:
  ~RecordKeeper() {
    for (std::map<std::string, Record*>::iterator I = Classes.begin(),
           E = Classes.end(); I != E; ++I)
      delete I->second;
    for (std::map<std::string, Record*>::iterator I = Defs.begin(),
           E = Defs.end(); I != E; ++I)
      delete I->second;
  }

  const std::map<std::string, Record*> &getClasses() const { return Classes; }
  const std::map<std::string, Record*> &getDefs() const { return Defs; }

  Record *getClass(const std::string &Name) const {
    std::map<std::string, Record*>::const_iterator I = Classes.find(Name);
    return I == Classes.end() ? nullptr : I->second;
  }
  Record *getDef(const std::string &Name) const {
    std::map<std::string, Record*>::const_iterator I = Defs.find(Name);
    return I == Defs.end() ? nullptr : I->second;
  }
  void addClass(Record *R) {
    bool Ins = Classes.insert(std::make_pair(R->getName(), R)).second;
    (void)Ins;
    assert(Ins && "Class already exists");
  }
  void addDef(Record *R) {
    bool Ins = Defs.insert(std::make_pair(R->getName(), R)).second;
    (void)Ins;
    assert(Ins && "Record already exists");
  }

  /// removeClass - Remove, but do not delete, the specified record.
  ///
  void removeClass(const std::string &Name) {
    assert(Classes.count(Name) && "Class does not exist!");
    Classes.erase(Name);
  }
  /// removeDef - Remove, but do not delete, the specified record.
  ///
  void removeDef(const std::string &Name) {
    assert(Defs.count(Name) && "Def does not exist!");
    Defs.erase(Name);
  }

  //===--------------------------------------------------------------------===//
  // High-level helper methods, useful for tablegen backends...

  /// getAllDerivedDefinitions - This method returns all concrete definitions
  /// that derive from the specified class name.  If a class with the specified
  /// name does not exist, an exception is thrown.
  std::vector<Record*>
  getAllDerivedDefinitions(const std::string &ClassName) const;

  void dump() const;
};

/// LessRecord - Sorting predicate to sort record pointers by name.
///
struct LessRecord {
  bool operator()(const Record *Rec1, const Record *Rec2) const {
    return StringRef(Rec1->getName()).compare_numeric(Rec2->getName()) < 0;
  }
};

/// LessRecordByID - Sorting predicate to sort record pointers by their
/// unique ID. If you just need a deterministic order, use this, since it
/// just compares two `unsigned`; the other sorting predicates require
/// string manipulation.
struct LessRecordByID {
  bool operator()(const Record *LHS, const Record *RHS) const {
    return LHS->getID() < RHS->getID();
  }
};

/// LessRecordFieldName - Sorting predicate to sort record pointers by their
/// name field.
///
struct LessRecordFieldName {
  bool operator()(const Record *Rec1, const Record *Rec2) const {
    return Rec1->getValueAsString("Name") < Rec2->getValueAsString("Name");
  }
};

struct LessRecordRegister {
  static size_t min(size_t a, size_t b) { return a < b ? a : b; }
  static bool ascii_isdigit(char x) { return x >= '0' && x <= '9'; }

  struct RecordParts {
    SmallVector<std::pair< bool, StringRef>, 4> Parts;

    RecordParts(StringRef Rec) {
      if (Rec.empty())
        return;

      size_t Len = 0;
      const char *Start = Rec.data();
      const char *Curr = Start;
      bool isDigitPart = ascii_isdigit(Curr[0]);
      for (size_t I = 0, E = Rec.size(); I != E; ++I, ++Len) {
        bool isDigit = ascii_isdigit(Curr[I]);
        if (isDigit != isDigitPart) {
          Parts.push_back(std::make_pair(isDigitPart, StringRef(Start, Len)));
          Len = 0;
          Start = &Curr[I];
          isDigitPart = ascii_isdigit(Curr[I]);
        }
      }
      // Push the last part.
      Parts.push_back(std::make_pair(isDigitPart, StringRef(Start, Len)));
    }

    size_t size() { return Parts.size(); }

    std::pair<bool, StringRef> getPart(size_t i) {
      assert (i < Parts.size() && "Invalid idx!");
      return Parts[i];
    }
  };

  bool operator()(const Record *Rec1, const Record *Rec2) const {
    RecordParts LHSParts(StringRef(Rec1->getName()));
    RecordParts RHSParts(StringRef(Rec2->getName()));

    size_t LHSNumParts = LHSParts.size();
    size_t RHSNumParts = RHSParts.size();
    assert (LHSNumParts && RHSNumParts && "Expected at least one part!");

    if (LHSNumParts != RHSNumParts)
      return LHSNumParts < RHSNumParts;

    // We expect the registers to be of the form [_a-zA-z]+([0-9]*[_a-zA-Z]*)*.
    for (size_t I = 0, E = LHSNumParts; I < E; I+=2) {
      std::pair<bool, StringRef> LHSPart = LHSParts.getPart(I);
      std::pair<bool, StringRef> RHSPart = RHSParts.getPart(I);
      // Expect even part to always be alpha.
      assert (LHSPart.first == false && RHSPart.first == false &&
              "Expected both parts to be alpha.");
      if (int Res = LHSPart.second.compare(RHSPart.second))
        return Res < 0;
    }
    for (size_t I = 1, E = LHSNumParts; I < E; I+=2) {
      std::pair<bool, StringRef> LHSPart = LHSParts.getPart(I);
      std::pair<bool, StringRef> RHSPart = RHSParts.getPart(I);
      // Expect odd part to always be numeric.
      assert (LHSPart.first == true && RHSPart.first == true &&
              "Expected both parts to be numeric.");
      if (LHSPart.second.size() != RHSPart.second.size())
        return LHSPart.second.size() < RHSPart.second.size();

      unsigned LHSVal, RHSVal;

      bool LHSFailed = LHSPart.second.getAsInteger(10, LHSVal); (void)LHSFailed;
      assert(!LHSFailed && "Unable to convert LHS to integer.");
      bool RHSFailed = RHSPart.second.getAsInteger(10, RHSVal); (void)RHSFailed;
      assert(!RHSFailed && "Unable to convert RHS to integer.");

      if (LHSVal != RHSVal)
        return LHSVal < RHSVal;
    }
    return LHSNumParts < RHSNumParts;
  }
};

raw_ostream &operator<<(raw_ostream &OS, const RecordKeeper &RK);

/// QualifyName - Return an Init with a qualifier prefix referring
/// to CurRec's name.
Init *QualifyName(Record &CurRec, MultiClass *CurMultiClass,
                  Init *Name, const std::string &Scoper);

/// QualifyName - Return an Init with a qualifier prefix referring
/// to CurRec's name.
Init *QualifyName(Record &CurRec, MultiClass *CurMultiClass,
                  const std::string &Name, const std::string &Scoper);

} // End llvm namespace

#endif
