brintos

brintos / llvm-project-archived public Read only

0
0
Text · 105.8 KiB · 8ad20b4 Raw
3414 lines · cpp
1//===- Record.cpp - Record implementation ---------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// Implement the tablegen record classes.10//11//===----------------------------------------------------------------------===//12 13#include "llvm/TableGen/Record.h"14#include "llvm/ADT/ArrayRef.h"15#include "llvm/ADT/DenseMap.h"16#include "llvm/ADT/FoldingSet.h"17#include "llvm/ADT/SmallString.h"18#include "llvm/ADT/SmallVector.h"19#include "llvm/ADT/StringExtras.h"20#include "llvm/ADT/StringMap.h"21#include "llvm/ADT/StringRef.h"22#include "llvm/Config/llvm-config.h"23#include "llvm/Support/Allocator.h"24#include "llvm/Support/Casting.h"25#include "llvm/Support/Compiler.h"26#include "llvm/Support/ErrorHandling.h"27#include "llvm/Support/MathExtras.h"28#include "llvm/Support/Regex.h"29#include "llvm/Support/SMLoc.h"30#include "llvm/Support/raw_ostream.h"31#include "llvm/TableGen/Error.h"32#include "llvm/TableGen/TGTimer.h"33#include <cassert>34#include <cstdint>35#include <map>36#include <memory>37#include <string>38#include <utility>39#include <vector>40 41using namespace llvm;42 43#define DEBUG_TYPE "tblgen-records"44 45//===----------------------------------------------------------------------===//46//    Context47//===----------------------------------------------------------------------===//48 49/// This class represents the internal implementation of the RecordKeeper.50/// It contains all of the contextual static state of the Record classes. It is51/// kept out-of-line to simplify dependencies, and also make it easier for52/// internal classes to access the uniquer state of the keeper.53struct detail::RecordKeeperImpl {54  RecordKeeperImpl(RecordKeeper &RK)55      : SharedBitRecTy(RK), SharedIntRecTy(RK), SharedStringRecTy(RK),56        SharedDagRecTy(RK), AnyRecord(RK, {}), TheUnsetInit(RK),57        TrueBitInit(true, &SharedBitRecTy),58        FalseBitInit(false, &SharedBitRecTy), StringInitStringPool(Allocator),59        StringInitCodePool(Allocator), AnonCounter(0), LastRecordID(0) {}60 61  BumpPtrAllocator Allocator;62  std::vector<BitsRecTy *> SharedBitsRecTys;63  BitRecTy SharedBitRecTy;64  IntRecTy SharedIntRecTy;65  StringRecTy SharedStringRecTy;66  DagRecTy SharedDagRecTy;67 68  RecordRecTy AnyRecord;69  UnsetInit TheUnsetInit;70  BitInit TrueBitInit;71  BitInit FalseBitInit;72 73  FoldingSet<ArgumentInit> TheArgumentInitPool;74  FoldingSet<BitsInit> TheBitsInitPool;75  std::map<int64_t, IntInit *> TheIntInitPool;76  StringMap<const StringInit *, BumpPtrAllocator &> StringInitStringPool;77  StringMap<const StringInit *, BumpPtrAllocator &> StringInitCodePool;78  FoldingSet<ListInit> TheListInitPool;79  FoldingSet<UnOpInit> TheUnOpInitPool;80  FoldingSet<BinOpInit> TheBinOpInitPool;81  FoldingSet<TernOpInit> TheTernOpInitPool;82  FoldingSet<FoldOpInit> TheFoldOpInitPool;83  FoldingSet<IsAOpInit> TheIsAOpInitPool;84  FoldingSet<ExistsOpInit> TheExistsOpInitPool;85  FoldingSet<InstancesOpInit> TheInstancesOpInitPool;86  DenseMap<std::pair<const RecTy *, const Init *>, VarInit *> TheVarInitPool;87  DenseMap<std::pair<const TypedInit *, unsigned>, VarBitInit *>88      TheVarBitInitPool;89  FoldingSet<VarDefInit> TheVarDefInitPool;90  DenseMap<std::pair<const Init *, const StringInit *>, FieldInit *>91      TheFieldInitPool;92  FoldingSet<CondOpInit> TheCondOpInitPool;93  FoldingSet<DagInit> TheDagInitPool;94  FoldingSet<RecordRecTy> RecordTypePool;95 96  unsigned AnonCounter;97  unsigned LastRecordID;98 99  void dumpAllocationStats(raw_ostream &OS) const;100};101 102void detail::RecordKeeperImpl::dumpAllocationStats(raw_ostream &OS) const {103  // Dump memory allocation related stats.104  OS << "TheArgumentInitPool size = " << TheArgumentInitPool.size() << '\n';105  OS << "TheBitsInitPool size = " << TheBitsInitPool.size() << '\n';106  OS << "TheIntInitPool size = " << TheIntInitPool.size() << '\n';107  OS << "StringInitStringPool size = " << StringInitStringPool.size() << '\n';108  OS << "StringInitCodePool size = " << StringInitCodePool.size() << '\n';109  OS << "TheListInitPool size = " << TheListInitPool.size() << '\n';110  OS << "TheUnOpInitPool size = " << TheUnOpInitPool.size() << '\n';111  OS << "TheBinOpInitPool size = " << TheBinOpInitPool.size() << '\n';112  OS << "TheTernOpInitPool size = " << TheTernOpInitPool.size() << '\n';113  OS << "TheFoldOpInitPool size = " << TheFoldOpInitPool.size() << '\n';114  OS << "TheIsAOpInitPool size = " << TheIsAOpInitPool.size() << '\n';115  OS << "TheExistsOpInitPool size = " << TheExistsOpInitPool.size() << '\n';116  OS << "TheCondOpInitPool size = " << TheCondOpInitPool.size() << '\n';117  OS << "TheDagInitPool size = " << TheDagInitPool.size() << '\n';118  OS << "RecordTypePool size = " << RecordTypePool.size() << '\n';119  OS << "TheVarInitPool size = " << TheVarInitPool.size() << '\n';120  OS << "TheVarBitInitPool size = " << TheVarBitInitPool.size() << '\n';121  OS << "TheVarDefInitPool size = " << TheVarDefInitPool.size() << '\n';122  OS << "TheFieldInitPool size = " << TheFieldInitPool.size() << '\n';123  OS << "Bytes allocated = " << Allocator.getBytesAllocated() << '\n';124  OS << "Total allocator memory = " << Allocator.getTotalMemory() << "\n\n";125 126  OS << "Number of records instantiated = " << LastRecordID << '\n';127  OS << "Number of anonymous records = " << AnonCounter << '\n';128}129 130//===----------------------------------------------------------------------===//131//    Type implementations132//===----------------------------------------------------------------------===//133 134#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)135LLVM_DUMP_METHOD void RecTy::dump() const { print(errs()); }136#endif137 138const ListRecTy *RecTy::getListTy() const {139  if (!ListTy)140    ListTy = new (RK.getImpl().Allocator) ListRecTy(this);141  return ListTy;142}143 144bool RecTy::typeIsConvertibleTo(const RecTy *RHS) const {145  assert(RHS && "NULL pointer");146  return Kind == RHS->getRecTyKind();147}148 149bool RecTy::typeIsA(const RecTy *RHS) const { return this == RHS; }150 151const BitRecTy *BitRecTy::get(RecordKeeper &RK) {152  return &RK.getImpl().SharedBitRecTy;153}154 155bool BitRecTy::typeIsConvertibleTo(const RecTy *RHS) const{156  if (RecTy::typeIsConvertibleTo(RHS) || RHS->getRecTyKind() == IntRecTyKind)157    return true;158  if (const auto *BitsTy = dyn_cast<BitsRecTy>(RHS))159    return BitsTy->getNumBits() == 1;160  return false;161}162 163const BitsRecTy *BitsRecTy::get(RecordKeeper &RK, unsigned Sz) {164  detail::RecordKeeperImpl &RKImpl = RK.getImpl();165  if (Sz >= RKImpl.SharedBitsRecTys.size())166    RKImpl.SharedBitsRecTys.resize(Sz + 1);167  BitsRecTy *&Ty = RKImpl.SharedBitsRecTys[Sz];168  if (!Ty)169    Ty = new (RKImpl.Allocator) BitsRecTy(RK, Sz);170  return Ty;171}172 173std::string BitsRecTy::getAsString() const {174  return "bits<" + utostr(Size) + ">";175}176 177bool BitsRecTy::typeIsConvertibleTo(const RecTy *RHS) const {178  if (RecTy::typeIsConvertibleTo(RHS)) //argument and the sender are same type179    return cast<BitsRecTy>(RHS)->Size == Size;180  RecTyKind kind = RHS->getRecTyKind();181  return (kind == BitRecTyKind && Size == 1) || (kind == IntRecTyKind);182}183 184const IntRecTy *IntRecTy::get(RecordKeeper &RK) {185  return &RK.getImpl().SharedIntRecTy;186}187 188bool IntRecTy::typeIsConvertibleTo(const RecTy *RHS) const {189  RecTyKind kind = RHS->getRecTyKind();190  return kind==BitRecTyKind || kind==BitsRecTyKind || kind==IntRecTyKind;191}192 193const StringRecTy *StringRecTy::get(RecordKeeper &RK) {194  return &RK.getImpl().SharedStringRecTy;195}196 197std::string StringRecTy::getAsString() const {198  return "string";199}200 201bool StringRecTy::typeIsConvertibleTo(const RecTy *RHS) const {202  RecTyKind Kind = RHS->getRecTyKind();203  return Kind == StringRecTyKind;204}205 206std::string ListRecTy::getAsString() const {207  return "list<" + ElementTy->getAsString() + ">";208}209 210bool ListRecTy::typeIsConvertibleTo(const RecTy *RHS) const {211  if (const auto *ListTy = dyn_cast<ListRecTy>(RHS))212    return ElementTy->typeIsConvertibleTo(ListTy->getElementType());213  return false;214}215 216bool ListRecTy::typeIsA(const RecTy *RHS) const {217  if (const auto *RHSl = dyn_cast<ListRecTy>(RHS))218    return getElementType()->typeIsA(RHSl->getElementType());219  return false;220}221 222const DagRecTy *DagRecTy::get(RecordKeeper &RK) {223  return &RK.getImpl().SharedDagRecTy;224}225 226std::string DagRecTy::getAsString() const {227  return "dag";228}229 230static void ProfileRecordRecTy(FoldingSetNodeID &ID,231                               ArrayRef<const Record *> Classes) {232  ID.AddInteger(Classes.size());233  for (const Record *R : Classes)234    ID.AddPointer(R);235}236 237RecordRecTy::RecordRecTy(RecordKeeper &RK, ArrayRef<const Record *> Classes)238    : RecTy(RecordRecTyKind, RK), NumClasses(Classes.size()) {239  llvm::uninitialized_copy(Classes, getTrailingObjects());240}241 242const RecordRecTy *RecordRecTy::get(RecordKeeper &RK,243                                    ArrayRef<const Record *> UnsortedClasses) {244  detail::RecordKeeperImpl &RKImpl = RK.getImpl();245  if (UnsortedClasses.empty())246    return &RKImpl.AnyRecord;247 248  FoldingSet<RecordRecTy> &ThePool = RKImpl.RecordTypePool;249 250  SmallVector<const Record *, 4> Classes(UnsortedClasses);251  llvm::sort(Classes, [](const Record *LHS, const Record *RHS) {252    return LHS->getNameInitAsString() < RHS->getNameInitAsString();253  });254 255  FoldingSetNodeID ID;256  ProfileRecordRecTy(ID, Classes);257 258  void *IP = nullptr;259  if (RecordRecTy *Ty = ThePool.FindNodeOrInsertPos(ID, IP))260    return Ty;261 262#ifndef NDEBUG263  // Check for redundancy.264  for (unsigned i = 0; i < Classes.size(); ++i) {265    for (unsigned j = 0; j < Classes.size(); ++j) {266      assert(i == j || !Classes[i]->isSubClassOf(Classes[j]));267    }268    assert(&Classes[0]->getRecords() == &Classes[i]->getRecords());269  }270#endif271 272  void *Mem = RKImpl.Allocator.Allocate(273      totalSizeToAlloc<const Record *>(Classes.size()), alignof(RecordRecTy));274  RecordRecTy *Ty = new (Mem) RecordRecTy(RK, Classes);275  ThePool.InsertNode(Ty, IP);276  return Ty;277}278 279const RecordRecTy *RecordRecTy::get(const Record *Class) {280  assert(Class && "unexpected null class");281  return get(Class->getRecords(), {Class});282}283 284void RecordRecTy::Profile(FoldingSetNodeID &ID) const {285  ProfileRecordRecTy(ID, getClasses());286}287 288std::string RecordRecTy::getAsString() const {289  if (NumClasses == 1)290    return getClasses()[0]->getNameInitAsString();291 292  std::string Str = "{";293  ListSeparator LS;294  for (const Record *R : getClasses()) {295    Str += LS;296    Str += R->getNameInitAsString();297  }298  Str += "}";299  return Str;300}301 302bool RecordRecTy::isSubClassOf(const Record *Class) const {303  return llvm::any_of(getClasses(), [Class](const Record *MySuperClass) {304    return MySuperClass == Class || MySuperClass->isSubClassOf(Class);305  });306}307 308bool RecordRecTy::typeIsConvertibleTo(const RecTy *RHS) const {309  if (this == RHS)310    return true;311 312  const auto *RTy = dyn_cast<RecordRecTy>(RHS);313  if (!RTy)314    return false;315 316  return llvm::all_of(RTy->getClasses(), [this](const Record *TargetClass) {317    return isSubClassOf(TargetClass);318  });319}320 321bool RecordRecTy::typeIsA(const RecTy *RHS) const {322  return typeIsConvertibleTo(RHS);323}324 325static const RecordRecTy *resolveRecordTypes(const RecordRecTy *T1,326                                             const RecordRecTy *T2) {327  SmallVector<const Record *, 4> CommonSuperClasses;328  SmallVector<const Record *, 4> Stack(T1->getClasses());329 330  while (!Stack.empty()) {331    const Record *R = Stack.pop_back_val();332 333    if (T2->isSubClassOf(R))334      CommonSuperClasses.push_back(R);335    else336      llvm::append_range(Stack, make_first_range(R->getDirectSuperClasses()));337  }338 339  return RecordRecTy::get(T1->getRecordKeeper(), CommonSuperClasses);340}341 342const RecTy *llvm::resolveTypes(const RecTy *T1, const RecTy *T2) {343  if (T1 == T2)344    return T1;345 346  if (const auto *RecTy1 = dyn_cast<RecordRecTy>(T1)) {347    if (const auto *RecTy2 = dyn_cast<RecordRecTy>(T2))348      return resolveRecordTypes(RecTy1, RecTy2);349  }350 351  assert(T1 != nullptr && "Invalid record type");352  if (T1->typeIsConvertibleTo(T2))353    return T2;354 355  assert(T2 != nullptr && "Invalid record type");356  if (T2->typeIsConvertibleTo(T1))357    return T1;358 359  if (const auto *ListTy1 = dyn_cast<ListRecTy>(T1)) {360    if (const auto *ListTy2 = dyn_cast<ListRecTy>(T2)) {361      const RecTy *NewType =362          resolveTypes(ListTy1->getElementType(), ListTy2->getElementType());363      if (NewType)364        return NewType->getListTy();365    }366  }367 368  return nullptr;369}370 371//===----------------------------------------------------------------------===//372//    Initializer implementations373//===----------------------------------------------------------------------===//374 375void Init::anchor() {}376 377#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)378LLVM_DUMP_METHOD void Init::dump() const { return print(errs()); }379#endif380 381RecordKeeper &Init::getRecordKeeper() const {382  if (auto *TyInit = dyn_cast<TypedInit>(this))383    return TyInit->getType()->getRecordKeeper();384  if (auto *ArgInit = dyn_cast<ArgumentInit>(this))385    return ArgInit->getRecordKeeper();386  return cast<UnsetInit>(this)->getRecordKeeper();387}388 389UnsetInit *UnsetInit::get(RecordKeeper &RK) {390  return &RK.getImpl().TheUnsetInit;391}392 393const Init *UnsetInit::getCastTo(const RecTy *Ty) const { return this; }394 395const Init *UnsetInit::convertInitializerTo(const RecTy *Ty) const {396  return this;397}398 399static void ProfileArgumentInit(FoldingSetNodeID &ID, const Init *Value,400                                ArgAuxType Aux) {401  auto I = Aux.index();402  ID.AddInteger(I);403  if (I == ArgumentInit::Positional)404    ID.AddInteger(std::get<ArgumentInit::Positional>(Aux));405  if (I == ArgumentInit::Named)406    ID.AddPointer(std::get<ArgumentInit::Named>(Aux));407  ID.AddPointer(Value);408}409 410void ArgumentInit::Profile(FoldingSetNodeID &ID) const {411  ProfileArgumentInit(ID, Value, Aux);412}413 414const ArgumentInit *ArgumentInit::get(const Init *Value, ArgAuxType Aux) {415  FoldingSetNodeID ID;416  ProfileArgumentInit(ID, Value, Aux);417 418  RecordKeeper &RK = Value->getRecordKeeper();419  detail::RecordKeeperImpl &RKImpl = RK.getImpl();420  void *IP = nullptr;421  if (const ArgumentInit *I =422          RKImpl.TheArgumentInitPool.FindNodeOrInsertPos(ID, IP))423    return I;424 425  ArgumentInit *I = new (RKImpl.Allocator) ArgumentInit(Value, Aux);426  RKImpl.TheArgumentInitPool.InsertNode(I, IP);427  return I;428}429 430const Init *ArgumentInit::resolveReferences(Resolver &R) const {431  const Init *NewValue = Value->resolveReferences(R);432  if (NewValue != Value)433    return cloneWithValue(NewValue);434 435  return this;436}437 438BitInit *BitInit::get(RecordKeeper &RK, bool V) {439  return V ? &RK.getImpl().TrueBitInit : &RK.getImpl().FalseBitInit;440}441 442const Init *BitInit::convertInitializerTo(const RecTy *Ty) const {443  if (isa<BitRecTy>(Ty))444    return this;445 446  if (isa<IntRecTy>(Ty))447    return IntInit::get(getRecordKeeper(), getValue());448 449  if (auto *BRT = dyn_cast<BitsRecTy>(Ty)) {450    // Can only convert single bit.451    if (BRT->getNumBits() == 1)452      return BitsInit::get(getRecordKeeper(), this);453  }454 455  return nullptr;456}457 458static void ProfileBitsInit(FoldingSetNodeID &ID,459                            ArrayRef<const Init *> Range) {460  ID.AddInteger(Range.size());461 462  for (const Init *I : Range)463    ID.AddPointer(I);464}465 466BitsInit::BitsInit(RecordKeeper &RK, ArrayRef<const Init *> Bits)467    : TypedInit(IK_BitsInit, BitsRecTy::get(RK, Bits.size())),468      NumBits(Bits.size()) {469  llvm::uninitialized_copy(Bits, getTrailingObjects());470}471 472BitsInit *BitsInit::get(RecordKeeper &RK, ArrayRef<const Init *> Bits) {473  FoldingSetNodeID ID;474  ProfileBitsInit(ID, Bits);475 476  detail::RecordKeeperImpl &RKImpl = RK.getImpl();477  void *IP = nullptr;478  if (BitsInit *I = RKImpl.TheBitsInitPool.FindNodeOrInsertPos(ID, IP))479    return I;480 481  void *Mem = RKImpl.Allocator.Allocate(482      totalSizeToAlloc<const Init *>(Bits.size()), alignof(BitsInit));483  BitsInit *I = new (Mem) BitsInit(RK, Bits);484  RKImpl.TheBitsInitPool.InsertNode(I, IP);485  return I;486}487 488void BitsInit::Profile(FoldingSetNodeID &ID) const {489  ProfileBitsInit(ID, getBits());490}491 492const Init *BitsInit::convertInitializerTo(const RecTy *Ty) const {493  if (isa<BitRecTy>(Ty)) {494    if (getNumBits() != 1) return nullptr; // Only accept if just one bit!495    return getBit(0);496  }497 498  if (auto *BRT = dyn_cast<BitsRecTy>(Ty)) {499    // If the number of bits is right, return it. Otherwise we need to expand500    // or truncate.501    if (getNumBits() != BRT->getNumBits()) return nullptr;502    return this;503  }504 505  if (isa<IntRecTy>(Ty)) {506    std::optional<int64_t> Result = convertInitializerToInt();507    if (Result)508      return IntInit::get(getRecordKeeper(), *Result);509  }510 511  return nullptr;512}513 514std::optional<int64_t> BitsInit::convertInitializerToInt() const {515  int64_t Result = 0;516  for (auto [Idx, InitV] : enumerate(getBits()))517    if (auto *Bit = dyn_cast<BitInit>(InitV))518      Result |= static_cast<int64_t>(Bit->getValue()) << Idx;519    else520      return std::nullopt;521  return Result;522}523 524uint64_t BitsInit::convertKnownBitsToInt() const {525  uint64_t Result = 0;526  for (auto [Idx, InitV] : enumerate(getBits()))527    if (auto *Bit = dyn_cast<BitInit>(InitV))528      Result |= static_cast<int64_t>(Bit->getValue()) << Idx;529  return Result;530}531 532const Init *533BitsInit::convertInitializerBitRange(ArrayRef<unsigned> Bits) const {534  SmallVector<const Init *, 16> NewBits(Bits.size());535 536  for (auto [Bit, NewBit] : zip_equal(Bits, NewBits)) {537    if (Bit >= getNumBits())538      return nullptr;539    NewBit = getBit(Bit);540  }541  return BitsInit::get(getRecordKeeper(), NewBits);542}543 544bool BitsInit::isComplete() const {545  return all_of(getBits(), [](const Init *Bit) { return Bit->isComplete(); });546}547bool BitsInit::allInComplete() const {548  return all_of(getBits(), [](const Init *Bit) { return !Bit->isComplete(); });549}550bool BitsInit::isConcrete() const {551  return all_of(getBits(), [](const Init *Bit) { return Bit->isConcrete(); });552}553 554std::string BitsInit::getAsString() const {555  std::string Result = "{ ";556  ListSeparator LS;557  for (const Init *Bit : reverse(getBits())) {558    Result += LS;559    if (Bit)560      Result += Bit->getAsString();561    else562      Result += "*";563  }564  return Result + " }";565}566 567// resolveReferences - If there are any field references that refer to fields568// that have been filled in, we can propagate the values now.569const Init *BitsInit::resolveReferences(Resolver &R) const {570  bool Changed = false;571  SmallVector<const Init *, 16> NewBits(getNumBits());572 573  const Init *CachedBitVarRef = nullptr;574  const Init *CachedBitVarResolved = nullptr;575 576  for (auto [CurBit, NewBit] : zip_equal(getBits(), NewBits)) {577    NewBit = CurBit;578 579    if (const auto *CurBitVar = dyn_cast<VarBitInit>(CurBit)) {580      if (CurBitVar->getBitVar() != CachedBitVarRef) {581        CachedBitVarRef = CurBitVar->getBitVar();582        CachedBitVarResolved = CachedBitVarRef->resolveReferences(R);583      }584      assert(CachedBitVarResolved && "Unresolved bitvar reference");585      NewBit = CachedBitVarResolved->getBit(CurBitVar->getBitNum());586    } else {587      // getBit(0) implicitly converts int and bits<1> values to bit.588      NewBit = CurBit->resolveReferences(R)->getBit(0);589    }590 591    if (isa<UnsetInit>(NewBit) && R.keepUnsetBits())592      NewBit = CurBit;593    Changed |= CurBit != NewBit;594  }595 596  if (Changed)597    return BitsInit::get(getRecordKeeper(), NewBits);598 599  return this;600}601 602IntInit *IntInit::get(RecordKeeper &RK, int64_t V) {603  IntInit *&I = RK.getImpl().TheIntInitPool[V];604  if (!I)605    I = new (RK.getImpl().Allocator) IntInit(RK, V);606  return I;607}608 609std::string IntInit::getAsString() const {610  return itostr(Value);611}612 613static bool canFitInBitfield(int64_t Value, unsigned NumBits) {614  // For example, with NumBits == 4, we permit Values from [-7 .. 15].615  return (NumBits >= sizeof(Value) * 8) ||616         (Value >> NumBits == 0) || (Value >> (NumBits-1) == -1);617}618 619const Init *IntInit::convertInitializerTo(const RecTy *Ty) const {620  if (isa<IntRecTy>(Ty))621    return this;622 623  if (isa<BitRecTy>(Ty)) {624    int64_t Val = getValue();625    if (Val != 0 && Val != 1) return nullptr;  // Only accept 0 or 1 for a bit!626    return BitInit::get(getRecordKeeper(), Val != 0);627  }628 629  if (const auto *BRT = dyn_cast<BitsRecTy>(Ty)) {630    int64_t Value = getValue();631    // Make sure this bitfield is large enough to hold the integer value.632    if (!canFitInBitfield(Value, BRT->getNumBits()))633      return nullptr;634 635    SmallVector<const Init *, 16> NewBits(BRT->getNumBits());636    for (unsigned i = 0; i != BRT->getNumBits(); ++i)637      NewBits[i] =638          BitInit::get(getRecordKeeper(), Value & ((i < 64) ? (1LL << i) : 0));639 640    return BitsInit::get(getRecordKeeper(), NewBits);641  }642 643  return nullptr;644}645 646const Init *IntInit::convertInitializerBitRange(ArrayRef<unsigned> Bits) const {647  SmallVector<const Init *, 16> NewBits(Bits.size());648 649  for (auto [Bit, NewBit] : zip_equal(Bits, NewBits)) {650    if (Bit >= 64)651      return nullptr;652 653    NewBit = BitInit::get(getRecordKeeper(), Value & (INT64_C(1) << Bit));654  }655  return BitsInit::get(getRecordKeeper(), NewBits);656}657 658AnonymousNameInit *AnonymousNameInit::get(RecordKeeper &RK, unsigned V) {659  return new (RK.getImpl().Allocator) AnonymousNameInit(RK, V);660}661 662const StringInit *AnonymousNameInit::getNameInit() const {663  return StringInit::get(getRecordKeeper(), getAsString());664}665 666std::string AnonymousNameInit::getAsString() const {667  return "anonymous_" + utostr(Value);668}669 670const Init *AnonymousNameInit::resolveReferences(Resolver &R) const {671  auto *Old = this;672  auto *New = R.resolve(Old);673  New = New ? New : Old;674  if (R.isFinal())675    if (const auto *Anonymous = dyn_cast<AnonymousNameInit>(New))676      return Anonymous->getNameInit();677  return New;678}679 680const StringInit *StringInit::get(RecordKeeper &RK, StringRef V,681                                  StringFormat Fmt) {682  detail::RecordKeeperImpl &RKImpl = RK.getImpl();683  auto &InitMap = Fmt == SF_String ? RKImpl.StringInitStringPool684                                   : RKImpl.StringInitCodePool;685  auto &Entry = *InitMap.try_emplace(V, nullptr).first;686  if (!Entry.second)687    Entry.second = new (RKImpl.Allocator) StringInit(RK, Entry.getKey(), Fmt);688  return Entry.second;689}690 691const Init *StringInit::convertInitializerTo(const RecTy *Ty) const {692  if (isa<StringRecTy>(Ty))693    return this;694 695  return nullptr;696}697 698static void ProfileListInit(FoldingSetNodeID &ID,699                            ArrayRef<const Init *> Elements,700                            const RecTy *EltTy) {701  ID.AddInteger(Elements.size());702  ID.AddPointer(EltTy);703 704  for (const Init *E : Elements)705    ID.AddPointer(E);706}707 708ListInit::ListInit(ArrayRef<const Init *> Elements, const RecTy *EltTy)709    : TypedInit(IK_ListInit, ListRecTy::get(EltTy)),710      NumElements(Elements.size()) {711  llvm::uninitialized_copy(Elements, getTrailingObjects());712}713 714const ListInit *ListInit::get(ArrayRef<const Init *> Elements,715                              const RecTy *EltTy) {716  FoldingSetNodeID ID;717  ProfileListInit(ID, Elements, EltTy);718 719  detail::RecordKeeperImpl &RK = EltTy->getRecordKeeper().getImpl();720  void *IP = nullptr;721  if (const ListInit *I = RK.TheListInitPool.FindNodeOrInsertPos(ID, IP))722    return I;723 724  assert(Elements.empty() || !isa<TypedInit>(Elements[0]) ||725         cast<TypedInit>(Elements[0])->getType()->typeIsConvertibleTo(EltTy));726 727  void *Mem = RK.Allocator.Allocate(728      totalSizeToAlloc<const Init *>(Elements.size()), alignof(ListInit));729  ListInit *I = new (Mem) ListInit(Elements, EltTy);730  RK.TheListInitPool.InsertNode(I, IP);731  return I;732}733 734void ListInit::Profile(FoldingSetNodeID &ID) const {735  const RecTy *EltTy = cast<ListRecTy>(getType())->getElementType();736  ProfileListInit(ID, getElements(), EltTy);737}738 739const Init *ListInit::convertInitializerTo(const RecTy *Ty) const {740  if (getType() == Ty)741    return this;742 743  if (const auto *LRT = dyn_cast<ListRecTy>(Ty)) {744    SmallVector<const Init *, 8> Elements;745    Elements.reserve(size());746 747    // Verify that all of the elements of the list are subclasses of the748    // appropriate class!749    bool Changed = false;750    const RecTy *ElementType = LRT->getElementType();751    for (const Init *I : getElements())752      if (const Init *CI = I->convertInitializerTo(ElementType)) {753        Elements.push_back(CI);754        if (CI != I)755          Changed = true;756      } else {757        return nullptr;758      }759 760    if (!Changed)761      return this;762    return ListInit::get(Elements, ElementType);763  }764 765  return nullptr;766}767 768const Record *ListInit::getElementAsRecord(unsigned Idx) const {769  const auto *DI = dyn_cast<DefInit>(getElement(Idx));770  if (!DI)771    PrintFatalError("Expected record in list!");772  return DI->getDef();773}774 775const Init *ListInit::resolveReferences(Resolver &R) const {776  SmallVector<const Init *, 8> Resolved;777  Resolved.reserve(size());778  bool Changed = false;779 780  for (const Init *CurElt : getElements()) {781    const Init *E = CurElt->resolveReferences(R);782    Changed |= E != CurElt;783    Resolved.push_back(E);784  }785 786  if (Changed)787    return ListInit::get(Resolved, getElementType());788  return this;789}790 791bool ListInit::isComplete() const {792  return all_of(*this,793                [](const Init *Element) { return Element->isComplete(); });794}795 796bool ListInit::isConcrete() const {797  return all_of(*this,798                [](const Init *Element) { return Element->isConcrete(); });799}800 801std::string ListInit::getAsString() const {802  std::string Result = "[";803  ListSeparator LS;804  for (const Init *Element : *this) {805    Result += LS;806    Result += Element->getAsString();807  }808  return Result + "]";809}810 811const Init *OpInit::getBit(unsigned Bit) const {812  if (getType() == BitRecTy::get(getRecordKeeper()))813    return this;814  return VarBitInit::get(this, Bit);815}816 817static void ProfileUnOpInit(FoldingSetNodeID &ID, unsigned Opcode,818                            const Init *Op, const RecTy *Type) {819  ID.AddInteger(Opcode);820  ID.AddPointer(Op);821  ID.AddPointer(Type);822}823 824const UnOpInit *UnOpInit::get(UnaryOp Opc, const Init *LHS, const RecTy *Type) {825  FoldingSetNodeID ID;826  ProfileUnOpInit(ID, Opc, LHS, Type);827 828  detail::RecordKeeperImpl &RK = Type->getRecordKeeper().getImpl();829  void *IP = nullptr;830  if (const UnOpInit *I = RK.TheUnOpInitPool.FindNodeOrInsertPos(ID, IP))831    return I;832 833  UnOpInit *I = new (RK.Allocator) UnOpInit(Opc, LHS, Type);834  RK.TheUnOpInitPool.InsertNode(I, IP);835  return I;836}837 838void UnOpInit::Profile(FoldingSetNodeID &ID) const {839  ProfileUnOpInit(ID, getOpcode(), getOperand(), getType());840}841 842const Init *UnOpInit::Fold(const Record *CurRec, bool IsFinal) const {843  RecordKeeper &RK = getRecordKeeper();844  switch (getOpcode()) {845  case REPR:846    if (LHS->isConcrete()) {847      // If it is a Record, print the full content.848      if (const auto *Def = dyn_cast<DefInit>(LHS)) {849        std::string S;850        raw_string_ostream OS(S);851        OS << *Def->getDef();852        return StringInit::get(RK, S);853      } else {854        // Otherwise, print the value of the variable.855        //856        // NOTE: we could recursively !repr the elements of a list,857        // but that could produce a lot of output when printing a858        // defset.859        return StringInit::get(RK, LHS->getAsString());860      }861    }862    break;863  case TOLOWER:864    if (const auto *LHSs = dyn_cast<StringInit>(LHS))865      return StringInit::get(RK, LHSs->getValue().lower());866    break;867  case TOUPPER:868    if (const auto *LHSs = dyn_cast<StringInit>(LHS))869      return StringInit::get(RK, LHSs->getValue().upper());870    break;871  case CAST:872    if (isa<StringRecTy>(getType())) {873      if (const auto *LHSs = dyn_cast<StringInit>(LHS))874        return LHSs;875 876      if (const auto *LHSd = dyn_cast<DefInit>(LHS))877        return StringInit::get(RK, LHSd->getAsString());878 879      if (const auto *LHSi = dyn_cast_or_null<IntInit>(880              LHS->convertInitializerTo(IntRecTy::get(RK))))881        return StringInit::get(RK, LHSi->getAsString());882 883    } else if (isa<RecordRecTy>(getType())) {884      if (const auto *Name = dyn_cast<StringInit>(LHS)) {885        const Record *D = RK.getDef(Name->getValue());886        if (!D && CurRec) {887          // Self-references are allowed, but their resolution is delayed until888          // the final resolve to ensure that we get the correct type for them.889          auto *Anonymous = dyn_cast<AnonymousNameInit>(CurRec->getNameInit());890          if (Name == CurRec->getNameInit() ||891              (Anonymous && Name == Anonymous->getNameInit())) {892            if (!IsFinal)893              break;894            D = CurRec;895          }896        }897 898        auto PrintFatalErrorHelper = [CurRec](const Twine &T) {899          if (CurRec)900            PrintFatalError(CurRec->getLoc(), T);901          else902            PrintFatalError(T);903        };904 905        if (!D) {906          if (IsFinal) {907            PrintFatalErrorHelper(Twine("Undefined reference to record: '") +908                                  Name->getValue() + "'\n");909          }910          break;911        }912 913        DefInit *DI = D->getDefInit();914        if (!DI->getType()->typeIsA(getType())) {915          PrintFatalErrorHelper(Twine("Expected type '") +916                                getType()->getAsString() + "', got '" +917                                DI->getType()->getAsString() + "' in: " +918                                getAsString() + "\n");919        }920        return DI;921      }922    }923 924    if (const Init *NewInit = LHS->convertInitializerTo(getType()))925      return NewInit;926    break;927 928  case INITIALIZED:929    if (isa<UnsetInit>(LHS))930      return IntInit::get(RK, 0);931    if (LHS->isConcrete())932      return IntInit::get(RK, 1);933    break;934 935  case NOT:936    if (const auto *LHSi = dyn_cast_or_null<IntInit>(937            LHS->convertInitializerTo(IntRecTy::get(RK))))938      return IntInit::get(RK, LHSi->getValue() ? 0 : 1);939    break;940 941  case HEAD:942    if (const auto *LHSl = dyn_cast<ListInit>(LHS)) {943      assert(!LHSl->empty() && "Empty list in head");944      return LHSl->getElement(0);945    }946    break;947 948  case TAIL:949    if (const auto *LHSl = dyn_cast<ListInit>(LHS)) {950      assert(!LHSl->empty() && "Empty list in tail");951      // Note the slice(1). We can't just pass the result of getElements()952      // directly.953      return ListInit::get(LHSl->getElements().slice(1),954                           LHSl->getElementType());955    }956    break;957 958  case SIZE:959    if (const auto *LHSl = dyn_cast<ListInit>(LHS))960      return IntInit::get(RK, LHSl->size());961    if (const auto *LHSd = dyn_cast<DagInit>(LHS))962      return IntInit::get(RK, LHSd->arg_size());963    if (const auto *LHSs = dyn_cast<StringInit>(LHS))964      return IntInit::get(RK, LHSs->getValue().size());965    break;966 967  case EMPTY:968    if (const auto *LHSl = dyn_cast<ListInit>(LHS))969      return IntInit::get(RK, LHSl->empty());970    if (const auto *LHSd = dyn_cast<DagInit>(LHS))971      return IntInit::get(RK, LHSd->arg_empty());972    if (const auto *LHSs = dyn_cast<StringInit>(LHS))973      return IntInit::get(RK, LHSs->getValue().empty());974    break;975 976  case GETDAGOP:977    if (const auto *Dag = dyn_cast<DagInit>(LHS)) {978      // TI is not necessarily a def due to the late resolution in multiclasses,979      // but has to be a TypedInit.980      auto *TI = cast<TypedInit>(Dag->getOperator());981      if (!TI->getType()->typeIsA(getType())) {982        PrintFatalError(CurRec->getLoc(),983                        Twine("Expected type '") + getType()->getAsString() +984                            "', got '" + TI->getType()->getAsString() +985                            "' in: " + getAsString() + "\n");986      } else {987        return Dag->getOperator();988      }989    }990    break;991 992  case GETDAGOPNAME:993    if (const auto *Dag = dyn_cast<DagInit>(LHS)) {994      return Dag->getName();995    }996    break;997 998  case LOG2:999    if (const auto *LHSi = dyn_cast_or_null<IntInit>(1000            LHS->convertInitializerTo(IntRecTy::get(RK)))) {1001      int64_t LHSv = LHSi->getValue();1002      if (LHSv <= 0) {1003        PrintFatalError(CurRec->getLoc(),1004                        "Illegal operation: logtwo is undefined "1005                        "on arguments less than or equal to 0");1006      } else {1007        uint64_t Log = Log2_64(LHSv);1008        assert(Log <= INT64_MAX &&1009               "Log of an int64_t must be smaller than INT64_MAX");1010        return IntInit::get(RK, static_cast<int64_t>(Log));1011      }1012    }1013    break;1014 1015  case LISTFLATTEN:1016    if (const auto *LHSList = dyn_cast<ListInit>(LHS)) {1017      const auto *InnerListTy = dyn_cast<ListRecTy>(LHSList->getElementType());1018      // list of non-lists, !listflatten() is a NOP.1019      if (!InnerListTy)1020        return LHS;1021 1022      auto Flatten =1023          [](const ListInit *List) -> std::optional<std::vector<const Init *>> {1024        std::vector<const Init *> Flattened;1025        // Concatenate elements of all the inner lists.1026        for (const Init *InnerInit : List->getElements()) {1027          const auto *InnerList = dyn_cast<ListInit>(InnerInit);1028          if (!InnerList)1029            return std::nullopt;1030          llvm::append_range(Flattened, InnerList->getElements());1031        };1032        return Flattened;1033      };1034 1035      auto Flattened = Flatten(LHSList);1036      if (Flattened)1037        return ListInit::get(*Flattened, InnerListTy->getElementType());1038    }1039    break;1040  }1041  return this;1042}1043 1044const Init *UnOpInit::resolveReferences(Resolver &R) const {1045  const Init *lhs = LHS->resolveReferences(R);1046 1047  if (LHS != lhs || (R.isFinal() && getOpcode() == CAST))1048    return (UnOpInit::get(getOpcode(), lhs, getType()))1049        ->Fold(R.getCurrentRecord(), R.isFinal());1050  return this;1051}1052 1053std::string UnOpInit::getAsString() const {1054  std::string Result;1055  switch (getOpcode()) {1056  case CAST: Result = "!cast<" + getType()->getAsString() + ">"; break;1057  case NOT: Result = "!not"; break;1058  case HEAD: Result = "!head"; break;1059  case TAIL: Result = "!tail"; break;1060  case SIZE: Result = "!size"; break;1061  case EMPTY: Result = "!empty"; break;1062  case GETDAGOP: Result = "!getdagop"; break;1063  case GETDAGOPNAME:1064    Result = "!getdagopname";1065    break;1066  case LOG2 : Result = "!logtwo"; break;1067  case LISTFLATTEN:1068    Result = "!listflatten";1069    break;1070  case REPR:1071    Result = "!repr";1072    break;1073  case TOLOWER:1074    Result = "!tolower";1075    break;1076  case TOUPPER:1077    Result = "!toupper";1078    break;1079  case INITIALIZED:1080    Result = "!initialized";1081    break;1082  }1083  return Result + "(" + LHS->getAsString() + ")";1084}1085 1086static void ProfileBinOpInit(FoldingSetNodeID &ID, unsigned Opcode,1087                             const Init *LHS, const Init *RHS,1088                             const RecTy *Type) {1089  ID.AddInteger(Opcode);1090  ID.AddPointer(LHS);1091  ID.AddPointer(RHS);1092  ID.AddPointer(Type);1093}1094 1095const BinOpInit *BinOpInit::get(BinaryOp Opc, const Init *LHS, const Init *RHS,1096                                const RecTy *Type) {1097  FoldingSetNodeID ID;1098  ProfileBinOpInit(ID, Opc, LHS, RHS, Type);1099 1100  detail::RecordKeeperImpl &RK = LHS->getRecordKeeper().getImpl();1101  void *IP = nullptr;1102  if (const BinOpInit *I = RK.TheBinOpInitPool.FindNodeOrInsertPos(ID, IP))1103    return I;1104 1105  BinOpInit *I = new (RK.Allocator) BinOpInit(Opc, LHS, RHS, Type);1106  RK.TheBinOpInitPool.InsertNode(I, IP);1107  return I;1108}1109 1110void BinOpInit::Profile(FoldingSetNodeID &ID) const {1111  ProfileBinOpInit(ID, getOpcode(), getLHS(), getRHS(), getType());1112}1113 1114static const StringInit *ConcatStringInits(const StringInit *I0,1115                                           const StringInit *I1) {1116  SmallString<80> Concat(I0->getValue());1117  Concat.append(I1->getValue());1118  return StringInit::get(1119      I0->getRecordKeeper(), Concat,1120      StringInit::determineFormat(I0->getFormat(), I1->getFormat()));1121}1122 1123static const StringInit *interleaveStringList(const ListInit *List,1124                                              const StringInit *Delim) {1125  if (List->size() == 0)1126    return StringInit::get(List->getRecordKeeper(), "");1127  const auto *Element = dyn_cast<StringInit>(List->getElement(0));1128  if (!Element)1129    return nullptr;1130  SmallString<80> Result(Element->getValue());1131  StringInit::StringFormat Fmt = StringInit::SF_String;1132 1133  for (const Init *Elem : List->getElements().drop_front()) {1134    Result.append(Delim->getValue());1135    const auto *Element = dyn_cast<StringInit>(Elem);1136    if (!Element)1137      return nullptr;1138    Result.append(Element->getValue());1139    Fmt = StringInit::determineFormat(Fmt, Element->getFormat());1140  }1141  return StringInit::get(List->getRecordKeeper(), Result, Fmt);1142}1143 1144static const StringInit *interleaveIntList(const ListInit *List,1145                                           const StringInit *Delim) {1146  RecordKeeper &RK = List->getRecordKeeper();1147  if (List->size() == 0)1148    return StringInit::get(RK, "");1149  const auto *Element = dyn_cast_or_null<IntInit>(1150      List->getElement(0)->convertInitializerTo(IntRecTy::get(RK)));1151  if (!Element)1152    return nullptr;1153  SmallString<80> Result(Element->getAsString());1154 1155  for (const Init *Elem : List->getElements().drop_front()) {1156    Result.append(Delim->getValue());1157    const auto *Element = dyn_cast_or_null<IntInit>(1158        Elem->convertInitializerTo(IntRecTy::get(RK)));1159    if (!Element)1160      return nullptr;1161    Result.append(Element->getAsString());1162  }1163  return StringInit::get(RK, Result);1164}1165 1166const Init *BinOpInit::getStrConcat(const Init *I0, const Init *I1) {1167  // Shortcut for the common case of concatenating two strings.1168  if (const auto *I0s = dyn_cast<StringInit>(I0))1169    if (const auto *I1s = dyn_cast<StringInit>(I1))1170      return ConcatStringInits(I0s, I1s);1171  return BinOpInit::get(BinOpInit::STRCONCAT, I0, I1,1172                        StringRecTy::get(I0->getRecordKeeper()));1173}1174 1175static const ListInit *ConcatListInits(const ListInit *LHS,1176                                       const ListInit *RHS) {1177  SmallVector<const Init *, 8> Args;1178  llvm::append_range(Args, *LHS);1179  llvm::append_range(Args, *RHS);1180  return ListInit::get(Args, LHS->getElementType());1181}1182 1183const Init *BinOpInit::getListConcat(const TypedInit *LHS, const Init *RHS) {1184  assert(isa<ListRecTy>(LHS->getType()) && "First arg must be a list");1185 1186  // Shortcut for the common case of concatenating two lists.1187  if (const auto *LHSList = dyn_cast<ListInit>(LHS))1188    if (const auto *RHSList = dyn_cast<ListInit>(RHS))1189      return ConcatListInits(LHSList, RHSList);1190  return BinOpInit::get(BinOpInit::LISTCONCAT, LHS, RHS, LHS->getType());1191}1192 1193std::optional<bool> BinOpInit::CompareInit(unsigned Opc, const Init *LHS,1194                                           const Init *RHS) const {1195  // First see if we have two bit, bits, or int.1196  const auto *LHSi = dyn_cast_or_null<IntInit>(1197      LHS->convertInitializerTo(IntRecTy::get(getRecordKeeper())));1198  const auto *RHSi = dyn_cast_or_null<IntInit>(1199      RHS->convertInitializerTo(IntRecTy::get(getRecordKeeper())));1200 1201  if (LHSi && RHSi) {1202    bool Result;1203    switch (Opc) {1204    case EQ:1205      Result = LHSi->getValue() == RHSi->getValue();1206      break;1207    case NE:1208      Result = LHSi->getValue() != RHSi->getValue();1209      break;1210    case LE:1211      Result = LHSi->getValue() <= RHSi->getValue();1212      break;1213    case LT:1214      Result = LHSi->getValue() < RHSi->getValue();1215      break;1216    case GE:1217      Result = LHSi->getValue() >= RHSi->getValue();1218      break;1219    case GT:1220      Result = LHSi->getValue() > RHSi->getValue();1221      break;1222    default:1223      llvm_unreachable("unhandled comparison");1224    }1225    return Result;1226  }1227 1228  // Next try strings.1229  const auto *LHSs = dyn_cast<StringInit>(LHS);1230  const auto *RHSs = dyn_cast<StringInit>(RHS);1231 1232  if (LHSs && RHSs) {1233    bool Result;1234    switch (Opc) {1235    case EQ:1236      Result = LHSs->getValue() == RHSs->getValue();1237      break;1238    case NE:1239      Result = LHSs->getValue() != RHSs->getValue();1240      break;1241    case LE:1242      Result = LHSs->getValue() <= RHSs->getValue();1243      break;1244    case LT:1245      Result = LHSs->getValue() < RHSs->getValue();1246      break;1247    case GE:1248      Result = LHSs->getValue() >= RHSs->getValue();1249      break;1250    case GT:1251      Result = LHSs->getValue() > RHSs->getValue();1252      break;1253    default:1254      llvm_unreachable("unhandled comparison");1255    }1256    return Result;1257  }1258 1259  // Finally, !eq and !ne can be used with records.1260  if (Opc == EQ || Opc == NE) {1261    const auto *LHSd = dyn_cast<DefInit>(LHS);1262    const auto *RHSd = dyn_cast<DefInit>(RHS);1263    if (LHSd && RHSd)1264      return (Opc == EQ) ? LHSd == RHSd : LHSd != RHSd;1265  }1266 1267  return std::nullopt;1268}1269 1270static std::optional<unsigned>1271getDagArgNoByKey(const DagInit *Dag, const Init *Key, std::string &Error) {1272  // Accessor by index1273  if (const auto *Idx = dyn_cast<IntInit>(Key)) {1274    int64_t Pos = Idx->getValue();1275    if (Pos < 0) {1276      // The index is negative.1277      Error =1278          (Twine("index ") + std::to_string(Pos) + Twine(" is negative")).str();1279      return std::nullopt;1280    }1281    if (Pos >= Dag->getNumArgs()) {1282      // The index is out-of-range.1283      Error = (Twine("index ") + std::to_string(Pos) +1284               " is out of range (dag has " +1285               std::to_string(Dag->getNumArgs()) + " arguments)")1286                  .str();1287      return std::nullopt;1288    }1289    return Pos;1290  }1291  assert(isa<StringInit>(Key));1292  // Accessor by name1293  const auto *Name = dyn_cast<StringInit>(Key);1294  auto ArgNo = Dag->getArgNo(Name->getValue());1295  if (!ArgNo) {1296    // The key is not found.1297    Error = (Twine("key '") + Name->getValue() + Twine("' is not found")).str();1298    return std::nullopt;1299  }1300  return *ArgNo;1301}1302 1303const Init *BinOpInit::Fold(const Record *CurRec) const {1304  switch (getOpcode()) {1305  case CONCAT: {1306    const auto *LHSs = dyn_cast<DagInit>(LHS);1307    const auto *RHSs = dyn_cast<DagInit>(RHS);1308    if (LHSs && RHSs) {1309      const auto *LOp = dyn_cast<DefInit>(LHSs->getOperator());1310      const auto *ROp = dyn_cast<DefInit>(RHSs->getOperator());1311      if ((!LOp && !isa<UnsetInit>(LHSs->getOperator())) ||1312          (!ROp && !isa<UnsetInit>(RHSs->getOperator())))1313        break;1314      if (LOp && ROp && LOp->getDef() != ROp->getDef()) {1315        PrintFatalError(Twine("Concatenated Dag operators do not match: '") +1316                        LHSs->getAsString() + "' vs. '" + RHSs->getAsString() +1317                        "'");1318      }1319      const Init *Op = LOp ? LOp : ROp;1320      if (!Op)1321        Op = UnsetInit::get(getRecordKeeper());1322 1323      SmallVector<std::pair<const Init *, const StringInit *>, 8> Args;1324      llvm::append_range(Args, LHSs->getArgAndNames());1325      llvm::append_range(Args, RHSs->getArgAndNames());1326      // Use the name of the LHS DAG if it's set, otherwise the name of the RHS.1327      const auto *NameInit = LHSs->getName();1328      if (!NameInit)1329        NameInit = RHSs->getName();1330      return DagInit::get(Op, NameInit, Args);1331    }1332    break;1333  }1334  case MATCH: {1335    const auto *StrInit = dyn_cast<StringInit>(LHS);1336    if (!StrInit)1337      return this;1338 1339    const auto *RegexInit = dyn_cast<StringInit>(RHS);1340    if (!RegexInit)1341      return this;1342 1343    StringRef RegexStr = RegexInit->getValue();1344    llvm::Regex Matcher(RegexStr);1345    if (!Matcher.isValid())1346      PrintFatalError(Twine("invalid regex '") + RegexStr + Twine("'"));1347 1348    return BitInit::get(LHS->getRecordKeeper(),1349                        Matcher.match(StrInit->getValue()));1350  }1351  case LISTCONCAT: {1352    const auto *LHSs = dyn_cast<ListInit>(LHS);1353    const auto *RHSs = dyn_cast<ListInit>(RHS);1354    if (LHSs && RHSs) {1355      SmallVector<const Init *, 8> Args;1356      llvm::append_range(Args, *LHSs);1357      llvm::append_range(Args, *RHSs);1358      return ListInit::get(Args, LHSs->getElementType());1359    }1360    break;1361  }1362  case LISTSPLAT: {1363    const auto *Value = dyn_cast<TypedInit>(LHS);1364    const auto *Count = dyn_cast<IntInit>(RHS);1365    if (Value && Count) {1366      if (Count->getValue() < 0)1367        PrintFatalError(Twine("!listsplat count ") + Count->getAsString() +1368                        " is negative");1369      SmallVector<const Init *, 8> Args(Count->getValue(), Value);1370      return ListInit::get(Args, Value->getType());1371    }1372    break;1373  }1374  case LISTREMOVE: {1375    const auto *LHSs = dyn_cast<ListInit>(LHS);1376    const auto *RHSs = dyn_cast<ListInit>(RHS);1377    if (LHSs && RHSs) {1378      SmallVector<const Init *, 8> Args;1379      for (const Init *EltLHS : *LHSs) {1380        bool Found = false;1381        for (const Init *EltRHS : *RHSs) {1382          if (std::optional<bool> Result = CompareInit(EQ, EltLHS, EltRHS)) {1383            if (*Result) {1384              Found = true;1385              break;1386            }1387          }1388        }1389        if (!Found)1390          Args.push_back(EltLHS);1391      }1392      return ListInit::get(Args, LHSs->getElementType());1393    }1394    break;1395  }1396  case LISTELEM: {1397    const auto *TheList = dyn_cast<ListInit>(LHS);1398    const auto *Idx = dyn_cast<IntInit>(RHS);1399    if (!TheList || !Idx)1400      break;1401    auto i = Idx->getValue();1402    if (i < 0 || i >= (ssize_t)TheList->size())1403      break;1404    return TheList->getElement(i);1405  }1406  case LISTSLICE: {1407    const auto *TheList = dyn_cast<ListInit>(LHS);1408    const auto *SliceIdxs = dyn_cast<ListInit>(RHS);1409    if (!TheList || !SliceIdxs)1410      break;1411    SmallVector<const Init *, 8> Args;1412    Args.reserve(SliceIdxs->size());1413    for (auto *I : *SliceIdxs) {1414      auto *II = dyn_cast<IntInit>(I);1415      if (!II)1416        goto unresolved;1417      auto i = II->getValue();1418      if (i < 0 || i >= (ssize_t)TheList->size())1419        goto unresolved;1420      Args.push_back(TheList->getElement(i));1421    }1422    return ListInit::get(Args, TheList->getElementType());1423  }1424  case RANGEC: {1425    const auto *LHSi = dyn_cast<IntInit>(LHS);1426    const auto *RHSi = dyn_cast<IntInit>(RHS);1427    if (!LHSi || !RHSi)1428      break;1429 1430    int64_t Start = LHSi->getValue();1431    int64_t End = RHSi->getValue();1432    SmallVector<const Init *, 8> Args;1433    if (getOpcode() == RANGEC) {1434      // Closed interval1435      if (Start <= End) {1436        // Ascending order1437        Args.reserve(End - Start + 1);1438        for (auto i = Start; i <= End; ++i)1439          Args.push_back(IntInit::get(getRecordKeeper(), i));1440      } else {1441        // Descending order1442        Args.reserve(Start - End + 1);1443        for (auto i = Start; i >= End; --i)1444          Args.push_back(IntInit::get(getRecordKeeper(), i));1445      }1446    } else if (Start < End) {1447      // Half-open interval (excludes `End`)1448      Args.reserve(End - Start);1449      for (auto i = Start; i < End; ++i)1450        Args.push_back(IntInit::get(getRecordKeeper(), i));1451    } else {1452      // Empty set1453    }1454    return ListInit::get(Args, LHSi->getType());1455  }1456  case STRCONCAT: {1457    const auto *LHSs = dyn_cast<StringInit>(LHS);1458    const auto *RHSs = dyn_cast<StringInit>(RHS);1459    if (LHSs && RHSs)1460      return ConcatStringInits(LHSs, RHSs);1461    break;1462  }1463  case INTERLEAVE: {1464    const auto *List = dyn_cast<ListInit>(LHS);1465    const auto *Delim = dyn_cast<StringInit>(RHS);1466    if (List && Delim) {1467      const StringInit *Result;1468      if (isa<StringRecTy>(List->getElementType()))1469        Result = interleaveStringList(List, Delim);1470      else1471        Result = interleaveIntList(List, Delim);1472      if (Result)1473        return Result;1474    }1475    break;1476  }1477  case EQ:1478  case NE:1479  case LE:1480  case LT:1481  case GE:1482  case GT: {1483    if (std::optional<bool> Result = CompareInit(getOpcode(), LHS, RHS))1484      return BitInit::get(getRecordKeeper(), *Result);1485    break;1486  }1487  case GETDAGARG: {1488    const auto *Dag = dyn_cast<DagInit>(LHS);1489    if (Dag && isa<IntInit, StringInit>(RHS)) {1490      std::string Error;1491      auto ArgNo = getDagArgNoByKey(Dag, RHS, Error);1492      if (!ArgNo)1493        PrintFatalError(CurRec->getLoc(), "!getdagarg " + Error);1494 1495      assert(*ArgNo < Dag->getNumArgs());1496 1497      const Init *Arg = Dag->getArg(*ArgNo);1498      if (const auto *TI = dyn_cast<TypedInit>(Arg))1499        if (!TI->getType()->typeIsConvertibleTo(getType()))1500          return UnsetInit::get(Dag->getRecordKeeper());1501      return Arg;1502    }1503    break;1504  }1505  case GETDAGNAME: {1506    const auto *Dag = dyn_cast<DagInit>(LHS);1507    const auto *Idx = dyn_cast<IntInit>(RHS);1508    if (Dag && Idx) {1509      int64_t Pos = Idx->getValue();1510      if (Pos < 0 || Pos >= Dag->getNumArgs()) {1511        // The index is out-of-range.1512        PrintError(CurRec->getLoc(),1513                   Twine("!getdagname index is out of range 0...") +1514                       std::to_string(Dag->getNumArgs() - 1) + ": " +1515                       std::to_string(Pos));1516      }1517      const Init *ArgName = Dag->getArgName(Pos);1518      if (!ArgName)1519        return UnsetInit::get(getRecordKeeper());1520      return ArgName;1521    }1522    break;1523  }1524  case SETDAGOP: {1525    const auto *Dag = dyn_cast<DagInit>(LHS);1526    const auto *Op = dyn_cast<DefInit>(RHS);1527    if (Dag && Op)1528      return DagInit::get(Op, Dag->getArgs(), Dag->getArgNames());1529    break;1530  }1531  case SETDAGOPNAME: {1532    const auto *Dag = dyn_cast<DagInit>(LHS);1533    const auto *Op = dyn_cast<StringInit>(RHS);1534    if (Dag && Op)1535      return DagInit::get(Dag->getOperator(), Op, Dag->getArgs(),1536                          Dag->getArgNames());1537    break;1538  }1539  case ADD:1540  case SUB:1541  case MUL:1542  case DIV:1543  case AND:1544  case OR:1545  case XOR:1546  case SHL:1547  case SRA:1548  case SRL: {1549    const auto *LHSi = dyn_cast_or_null<IntInit>(1550        LHS->convertInitializerTo(IntRecTy::get(getRecordKeeper())));1551    const auto *RHSi = dyn_cast_or_null<IntInit>(1552        RHS->convertInitializerTo(IntRecTy::get(getRecordKeeper())));1553    if (LHSi && RHSi) {1554      int64_t LHSv = LHSi->getValue(), RHSv = RHSi->getValue();1555      int64_t Result;1556      switch (getOpcode()) {1557      default: llvm_unreachable("Bad opcode!");1558      case ADD: Result = LHSv + RHSv; break;1559      case SUB: Result = LHSv - RHSv; break;1560      case MUL: Result = LHSv * RHSv; break;1561      case DIV:1562        if (RHSv == 0)1563          PrintFatalError(CurRec->getLoc(),1564                          "Illegal operation: division by zero");1565        else if (LHSv == INT64_MIN && RHSv == -1)1566          PrintFatalError(CurRec->getLoc(),1567                          "Illegal operation: INT64_MIN / -1");1568        else1569          Result = LHSv / RHSv;1570        break;1571      case AND: Result = LHSv & RHSv; break;1572      case OR:  Result = LHSv | RHSv; break;1573      case XOR: Result = LHSv ^ RHSv; break;1574      case SHL:1575        if (RHSv < 0 || RHSv >= 64)1576          PrintFatalError(CurRec->getLoc(),1577                          "Illegal operation: out of bounds shift");1578        Result = (uint64_t)LHSv << (uint64_t)RHSv;1579        break;1580      case SRA:1581        if (RHSv < 0 || RHSv >= 64)1582          PrintFatalError(CurRec->getLoc(),1583                          "Illegal operation: out of bounds shift");1584        Result = LHSv >> (uint64_t)RHSv;1585        break;1586      case SRL:1587        if (RHSv < 0 || RHSv >= 64)1588          PrintFatalError(CurRec->getLoc(),1589                          "Illegal operation: out of bounds shift");1590        Result = (uint64_t)LHSv >> (uint64_t)RHSv;1591        break;1592      }1593      return IntInit::get(getRecordKeeper(), Result);1594    }1595    break;1596  }1597  }1598unresolved:1599  return this;1600}1601 1602const Init *BinOpInit::resolveReferences(Resolver &R) const {1603  const Init *NewLHS = LHS->resolveReferences(R);1604 1605  unsigned Opc = getOpcode();1606  if (Opc == AND || Opc == OR) {1607    // Short-circuit. Regardless whether this is a logical or bitwise1608    // AND/OR.1609    // Ideally we could also short-circuit `!or(true, ...)`, but it's1610    // difficult to do it right without knowing if rest of the operands1611    // are all `bit` or not. Therefore, we're only implementing a relatively1612    // limited version of short-circuit against all ones (`true` is casted1613    // to 1 rather than all ones before we evaluate `!or`).1614    if (const auto *LHSi = dyn_cast_or_null<IntInit>(1615            NewLHS->convertInitializerTo(IntRecTy::get(getRecordKeeper())))) {1616      if ((Opc == AND && !LHSi->getValue()) ||1617          (Opc == OR && LHSi->getValue() == -1))1618        return LHSi;1619    }1620  }1621 1622  const Init *NewRHS = RHS->resolveReferences(R);1623 1624  if (LHS != NewLHS || RHS != NewRHS)1625    return (BinOpInit::get(getOpcode(), NewLHS, NewRHS, getType()))1626        ->Fold(R.getCurrentRecord());1627  return this;1628}1629 1630std::string BinOpInit::getAsString() const {1631  std::string Result;1632  switch (getOpcode()) {1633  case LISTELEM:1634  case LISTSLICE:1635    return LHS->getAsString() + "[" + RHS->getAsString() + "]";1636  case RANGEC:1637    return LHS->getAsString() + "..." + RHS->getAsString();1638  case CONCAT: Result = "!con"; break;1639  case MATCH:1640    Result = "!match";1641    break;1642  case ADD: Result = "!add"; break;1643  case SUB: Result = "!sub"; break;1644  case MUL: Result = "!mul"; break;1645  case DIV: Result = "!div"; break;1646  case AND: Result = "!and"; break;1647  case OR: Result = "!or"; break;1648  case XOR: Result = "!xor"; break;1649  case SHL: Result = "!shl"; break;1650  case SRA: Result = "!sra"; break;1651  case SRL: Result = "!srl"; break;1652  case EQ: Result = "!eq"; break;1653  case NE: Result = "!ne"; break;1654  case LE: Result = "!le"; break;1655  case LT: Result = "!lt"; break;1656  case GE: Result = "!ge"; break;1657  case GT: Result = "!gt"; break;1658  case LISTCONCAT: Result = "!listconcat"; break;1659  case LISTSPLAT: Result = "!listsplat"; break;1660  case LISTREMOVE:1661    Result = "!listremove";1662    break;1663  case STRCONCAT: Result = "!strconcat"; break;1664  case INTERLEAVE: Result = "!interleave"; break;1665  case SETDAGOP: Result = "!setdagop"; break;1666  case SETDAGOPNAME:1667    Result = "!setdagopname";1668    break;1669  case GETDAGARG:1670    Result = "!getdagarg<" + getType()->getAsString() + ">";1671    break;1672  case GETDAGNAME:1673    Result = "!getdagname";1674    break;1675  }1676  return Result + "(" + LHS->getAsString() + ", " + RHS->getAsString() + ")";1677}1678 1679static void ProfileTernOpInit(FoldingSetNodeID &ID, unsigned Opcode,1680                              const Init *LHS, const Init *MHS, const Init *RHS,1681                              const RecTy *Type) {1682  ID.AddInteger(Opcode);1683  ID.AddPointer(LHS);1684  ID.AddPointer(MHS);1685  ID.AddPointer(RHS);1686  ID.AddPointer(Type);1687}1688 1689const TernOpInit *TernOpInit::get(TernaryOp Opc, const Init *LHS,1690                                  const Init *MHS, const Init *RHS,1691                                  const RecTy *Type) {1692  FoldingSetNodeID ID;1693  ProfileTernOpInit(ID, Opc, LHS, MHS, RHS, Type);1694 1695  detail::RecordKeeperImpl &RK = LHS->getRecordKeeper().getImpl();1696  void *IP = nullptr;1697  if (TernOpInit *I = RK.TheTernOpInitPool.FindNodeOrInsertPos(ID, IP))1698    return I;1699 1700  TernOpInit *I = new (RK.Allocator) TernOpInit(Opc, LHS, MHS, RHS, Type);1701  RK.TheTernOpInitPool.InsertNode(I, IP);1702  return I;1703}1704 1705void TernOpInit::Profile(FoldingSetNodeID &ID) const {1706  ProfileTernOpInit(ID, getOpcode(), getLHS(), getMHS(), getRHS(), getType());1707}1708 1709static const Init *ItemApply(const Init *LHS, const Init *MHSe, const Init *RHS,1710                             const Record *CurRec) {1711  MapResolver R(CurRec);1712  R.set(LHS, MHSe);1713  return RHS->resolveReferences(R);1714}1715 1716static const Init *ForeachDagApply(const Init *LHS, const DagInit *MHSd,1717                                   const Init *RHS, const Record *CurRec) {1718  bool Change = false;1719  const Init *Val = ItemApply(LHS, MHSd->getOperator(), RHS, CurRec);1720  if (Val != MHSd->getOperator())1721    Change = true;1722 1723  SmallVector<std::pair<const Init *, const StringInit *>, 8> NewArgs;1724  for (auto [Arg, ArgName] : MHSd->getArgAndNames()) {1725    const Init *NewArg;1726 1727    if (const auto *Argd = dyn_cast<DagInit>(Arg))1728      NewArg = ForeachDagApply(LHS, Argd, RHS, CurRec);1729    else1730      NewArg = ItemApply(LHS, Arg, RHS, CurRec);1731 1732    NewArgs.emplace_back(NewArg, ArgName);1733    if (Arg != NewArg)1734      Change = true;1735  }1736 1737  if (Change)1738    return DagInit::get(Val, MHSd->getName(), NewArgs);1739  return MHSd;1740}1741 1742// Applies RHS to all elements of MHS, using LHS as a temp variable.1743static const Init *ForeachHelper(const Init *LHS, const Init *MHS,1744                                 const Init *RHS, const RecTy *Type,1745                                 const Record *CurRec) {1746  if (const auto *MHSd = dyn_cast<DagInit>(MHS))1747    return ForeachDagApply(LHS, MHSd, RHS, CurRec);1748 1749  if (const auto *MHSl = dyn_cast<ListInit>(MHS)) {1750    SmallVector<const Init *, 8> NewList(MHSl->begin(), MHSl->end());1751 1752    for (const Init *&Item : NewList) {1753      const Init *NewItem = ItemApply(LHS, Item, RHS, CurRec);1754      if (NewItem != Item)1755        Item = NewItem;1756    }1757    return ListInit::get(NewList, cast<ListRecTy>(Type)->getElementType());1758  }1759 1760  return nullptr;1761}1762 1763// Evaluates RHS for all elements of MHS, using LHS as a temp variable.1764// Creates a new list with the elements that evaluated to true.1765static const Init *FilterHelper(const Init *LHS, const Init *MHS,1766                                const Init *RHS, const RecTy *Type,1767                                const Record *CurRec) {1768  if (const auto *MHSl = dyn_cast<ListInit>(MHS)) {1769    SmallVector<const Init *, 8> NewList;1770 1771    for (const Init *Item : MHSl->getElements()) {1772      const Init *Include = ItemApply(LHS, Item, RHS, CurRec);1773      if (!Include)1774        return nullptr;1775      if (const auto *IncludeInt =1776              dyn_cast_or_null<IntInit>(Include->convertInitializerTo(1777                  IntRecTy::get(LHS->getRecordKeeper())))) {1778        if (IncludeInt->getValue())1779          NewList.push_back(Item);1780      } else {1781        return nullptr;1782      }1783    }1784    return ListInit::get(NewList, cast<ListRecTy>(Type)->getElementType());1785  }1786 1787  return nullptr;1788}1789 1790const Init *TernOpInit::Fold(const Record *CurRec) const {1791  RecordKeeper &RK = getRecordKeeper();1792  switch (getOpcode()) {1793  case SUBST: {1794    const auto *LHSd = dyn_cast<DefInit>(LHS);1795    const auto *LHSv = dyn_cast<VarInit>(LHS);1796    const auto *LHSs = dyn_cast<StringInit>(LHS);1797 1798    const auto *MHSd = dyn_cast<DefInit>(MHS);1799    const auto *MHSv = dyn_cast<VarInit>(MHS);1800    const auto *MHSs = dyn_cast<StringInit>(MHS);1801 1802    const auto *RHSd = dyn_cast<DefInit>(RHS);1803    const auto *RHSv = dyn_cast<VarInit>(RHS);1804    const auto *RHSs = dyn_cast<StringInit>(RHS);1805 1806    if (LHSd && MHSd && RHSd) {1807      const Record *Val = RHSd->getDef();1808      if (LHSd->getAsString() == RHSd->getAsString())1809        Val = MHSd->getDef();1810      return Val->getDefInit();1811    }1812    if (LHSv && MHSv && RHSv) {1813      std::string Val = RHSv->getName().str();1814      if (LHSv->getAsString() == RHSv->getAsString())1815        Val = MHSv->getName().str();1816      return VarInit::get(Val, getType());1817    }1818    if (LHSs && MHSs && RHSs) {1819      std::string Val = RHSs->getValue().str();1820 1821      std::string::size_type Idx = 0;1822      while (true) {1823        std::string::size_type Found = Val.find(LHSs->getValue(), Idx);1824        if (Found == std::string::npos)1825          break;1826        Val.replace(Found, LHSs->getValue().size(), MHSs->getValue().str());1827        Idx = Found + MHSs->getValue().size();1828      }1829 1830      return StringInit::get(RK, Val);1831    }1832    break;1833  }1834 1835  case FOREACH: {1836    if (const Init *Result = ForeachHelper(LHS, MHS, RHS, getType(), CurRec))1837      return Result;1838    break;1839  }1840 1841  case FILTER: {1842    if (const Init *Result = FilterHelper(LHS, MHS, RHS, getType(), CurRec))1843      return Result;1844    break;1845  }1846 1847  case IF: {1848    if (const auto *LHSi = dyn_cast_or_null<IntInit>(1849            LHS->convertInitializerTo(IntRecTy::get(RK)))) {1850      if (LHSi->getValue())1851        return MHS;1852      return RHS;1853    }1854    break;1855  }1856 1857  case DAG: {1858    const auto *MHSl = dyn_cast<ListInit>(MHS);1859    const auto *RHSl = dyn_cast<ListInit>(RHS);1860    bool MHSok = MHSl || isa<UnsetInit>(MHS);1861    bool RHSok = RHSl || isa<UnsetInit>(RHS);1862 1863    if (isa<UnsetInit>(MHS) && isa<UnsetInit>(RHS))1864      break; // Typically prevented by the parser, but might happen with template args1865 1866    if (MHSok && RHSok && (!MHSl || !RHSl || MHSl->size() == RHSl->size())) {1867      SmallVector<std::pair<const Init *, const StringInit *>, 8> Children;1868      unsigned Size = MHSl ? MHSl->size() : RHSl->size();1869      for (unsigned i = 0; i != Size; ++i) {1870        const Init *Node = MHSl ? MHSl->getElement(i) : UnsetInit::get(RK);1871        const Init *Name = RHSl ? RHSl->getElement(i) : UnsetInit::get(RK);1872        if (!isa<StringInit>(Name) && !isa<UnsetInit>(Name))1873          return this;1874        Children.emplace_back(Node, dyn_cast<StringInit>(Name));1875      }1876      return DagInit::get(LHS, Children);1877    }1878    break;1879  }1880 1881  case RANGE: {1882    const auto *LHSi = dyn_cast<IntInit>(LHS);1883    const auto *MHSi = dyn_cast<IntInit>(MHS);1884    const auto *RHSi = dyn_cast<IntInit>(RHS);1885    if (!LHSi || !MHSi || !RHSi)1886      break;1887 1888    auto Start = LHSi->getValue();1889    auto End = MHSi->getValue();1890    auto Step = RHSi->getValue();1891    if (Step == 0)1892      PrintError(CurRec->getLoc(), "Step of !range can't be 0");1893 1894    SmallVector<const Init *, 8> Args;1895    if (Start < End && Step > 0) {1896      Args.reserve((End - Start) / Step);1897      for (auto I = Start; I < End; I += Step)1898        Args.push_back(IntInit::get(getRecordKeeper(), I));1899    } else if (Start > End && Step < 0) {1900      Args.reserve((Start - End) / -Step);1901      for (auto I = Start; I > End; I += Step)1902        Args.push_back(IntInit::get(getRecordKeeper(), I));1903    } else {1904      // Empty set1905    }1906    return ListInit::get(Args, LHSi->getType());1907  }1908 1909  case SUBSTR: {1910    const auto *LHSs = dyn_cast<StringInit>(LHS);1911    const auto *MHSi = dyn_cast<IntInit>(MHS);1912    const auto *RHSi = dyn_cast<IntInit>(RHS);1913    if (LHSs && MHSi && RHSi) {1914      int64_t StringSize = LHSs->getValue().size();1915      int64_t Start = MHSi->getValue();1916      int64_t Length = RHSi->getValue();1917      if (Start < 0 || Start > StringSize)1918        PrintError(CurRec->getLoc(),1919                   Twine("!substr start position is out of range 0...") +1920                       std::to_string(StringSize) + ": " +1921                       std::to_string(Start));1922      if (Length < 0)1923        PrintError(CurRec->getLoc(), "!substr length must be nonnegative");1924      return StringInit::get(RK, LHSs->getValue().substr(Start, Length),1925                             LHSs->getFormat());1926    }1927    break;1928  }1929 1930  case FIND: {1931    const auto *LHSs = dyn_cast<StringInit>(LHS);1932    const auto *MHSs = dyn_cast<StringInit>(MHS);1933    const auto *RHSi = dyn_cast<IntInit>(RHS);1934    if (LHSs && MHSs && RHSi) {1935      int64_t SourceSize = LHSs->getValue().size();1936      int64_t Start = RHSi->getValue();1937      if (Start < 0 || Start > SourceSize)1938        PrintError(CurRec->getLoc(),1939                   Twine("!find start position is out of range 0...") +1940                       std::to_string(SourceSize) + ": " +1941                       std::to_string(Start));1942      auto I = LHSs->getValue().find(MHSs->getValue(), Start);1943      if (I == std::string::npos)1944        return IntInit::get(RK, -1);1945      return IntInit::get(RK, I);1946    }1947    break;1948  }1949 1950  case SETDAGARG: {1951    const auto *Dag = dyn_cast<DagInit>(LHS);1952    if (Dag && isa<IntInit, StringInit>(MHS)) {1953      std::string Error;1954      auto ArgNo = getDagArgNoByKey(Dag, MHS, Error);1955      if (!ArgNo)1956        PrintFatalError(CurRec->getLoc(), "!setdagarg " + Error);1957 1958      assert(*ArgNo < Dag->getNumArgs());1959 1960      SmallVector<const Init *, 8> Args(Dag->getArgs());1961      Args[*ArgNo] = RHS;1962      return DagInit::get(Dag->getOperator(), Dag->getName(), Args,1963                          Dag->getArgNames());1964    }1965    break;1966  }1967 1968  case SETDAGNAME: {1969    const auto *Dag = dyn_cast<DagInit>(LHS);1970    if (Dag && isa<IntInit, StringInit>(MHS)) {1971      std::string Error;1972      auto ArgNo = getDagArgNoByKey(Dag, MHS, Error);1973      if (!ArgNo)1974        PrintFatalError(CurRec->getLoc(), "!setdagname " + Error);1975 1976      assert(*ArgNo < Dag->getNumArgs());1977 1978      SmallVector<const StringInit *, 8> Names(Dag->getArgNames());1979      Names[*ArgNo] = dyn_cast<StringInit>(RHS);1980      return DagInit::get(Dag->getOperator(), Dag->getName(), Dag->getArgs(),1981                          Names);1982    }1983    break;1984  }1985  }1986 1987  return this;1988}1989 1990const Init *TernOpInit::resolveReferences(Resolver &R) const {1991  const Init *lhs = LHS->resolveReferences(R);1992 1993  if (getOpcode() == IF && lhs != LHS) {1994    if (const auto *Value = dyn_cast_or_null<IntInit>(1995            lhs->convertInitializerTo(IntRecTy::get(getRecordKeeper())))) {1996      // Short-circuit1997      if (Value->getValue())1998        return MHS->resolveReferences(R);1999      return RHS->resolveReferences(R);2000    }2001  }2002 2003  const Init *mhs = MHS->resolveReferences(R);2004  const Init *rhs;2005 2006  if (getOpcode() == FOREACH || getOpcode() == FILTER) {2007    ShadowResolver SR(R);2008    SR.addShadow(lhs);2009    rhs = RHS->resolveReferences(SR);2010  } else {2011    rhs = RHS->resolveReferences(R);2012  }2013 2014  if (LHS != lhs || MHS != mhs || RHS != rhs)2015    return (TernOpInit::get(getOpcode(), lhs, mhs, rhs, getType()))2016        ->Fold(R.getCurrentRecord());2017  return this;2018}2019 2020std::string TernOpInit::getAsString() const {2021  std::string Result;2022  bool UnquotedLHS = false;2023  switch (getOpcode()) {2024  case DAG: Result = "!dag"; break;2025  case FILTER: Result = "!filter"; UnquotedLHS = true; break;2026  case FOREACH: Result = "!foreach"; UnquotedLHS = true; break;2027  case IF: Result = "!if"; break;2028  case RANGE:2029    Result = "!range";2030    break;2031  case SUBST: Result = "!subst"; break;2032  case SUBSTR: Result = "!substr"; break;2033  case FIND: Result = "!find"; break;2034  case SETDAGARG:2035    Result = "!setdagarg";2036    break;2037  case SETDAGNAME:2038    Result = "!setdagname";2039    break;2040  }2041  return (Result + "(" +2042          (UnquotedLHS ? LHS->getAsUnquotedString() : LHS->getAsString()) +2043          ", " + MHS->getAsString() + ", " + RHS->getAsString() + ")");2044}2045 2046static void ProfileFoldOpInit(FoldingSetNodeID &ID, const Init *Start,2047                              const Init *List, const Init *A, const Init *B,2048                              const Init *Expr, const RecTy *Type) {2049  ID.AddPointer(Start);2050  ID.AddPointer(List);2051  ID.AddPointer(A);2052  ID.AddPointer(B);2053  ID.AddPointer(Expr);2054  ID.AddPointer(Type);2055}2056 2057const FoldOpInit *FoldOpInit::get(const Init *Start, const Init *List,2058                                  const Init *A, const Init *B,2059                                  const Init *Expr, const RecTy *Type) {2060  FoldingSetNodeID ID;2061  ProfileFoldOpInit(ID, Start, List, A, B, Expr, Type);2062 2063  detail::RecordKeeperImpl &RK = Start->getRecordKeeper().getImpl();2064  void *IP = nullptr;2065  if (const FoldOpInit *I = RK.TheFoldOpInitPool.FindNodeOrInsertPos(ID, IP))2066    return I;2067 2068  FoldOpInit *I = new (RK.Allocator) FoldOpInit(Start, List, A, B, Expr, Type);2069  RK.TheFoldOpInitPool.InsertNode(I, IP);2070  return I;2071}2072 2073void FoldOpInit::Profile(FoldingSetNodeID &ID) const {2074  ProfileFoldOpInit(ID, Start, List, A, B, Expr, getType());2075}2076 2077const Init *FoldOpInit::Fold(const Record *CurRec) const {2078  if (const auto *LI = dyn_cast<ListInit>(List)) {2079    const Init *Accum = Start;2080    for (const Init *Elt : *LI) {2081      MapResolver R(CurRec);2082      R.set(A, Accum);2083      R.set(B, Elt);2084      Accum = Expr->resolveReferences(R);2085    }2086    return Accum;2087  }2088  return this;2089}2090 2091const Init *FoldOpInit::resolveReferences(Resolver &R) const {2092  const Init *NewStart = Start->resolveReferences(R);2093  const Init *NewList = List->resolveReferences(R);2094  ShadowResolver SR(R);2095  SR.addShadow(A);2096  SR.addShadow(B);2097  const Init *NewExpr = Expr->resolveReferences(SR);2098 2099  if (Start == NewStart && List == NewList && Expr == NewExpr)2100    return this;2101 2102  return get(NewStart, NewList, A, B, NewExpr, getType())2103      ->Fold(R.getCurrentRecord());2104}2105 2106const Init *FoldOpInit::getBit(unsigned Bit) const {2107  return VarBitInit::get(this, Bit);2108}2109 2110std::string FoldOpInit::getAsString() const {2111  return (Twine("!foldl(") + Start->getAsString() + ", " + List->getAsString() +2112          ", " + A->getAsUnquotedString() + ", " + B->getAsUnquotedString() +2113          ", " + Expr->getAsString() + ")")2114      .str();2115}2116 2117static void ProfileIsAOpInit(FoldingSetNodeID &ID, const RecTy *CheckType,2118                             const Init *Expr) {2119  ID.AddPointer(CheckType);2120  ID.AddPointer(Expr);2121}2122 2123const IsAOpInit *IsAOpInit::get(const RecTy *CheckType, const Init *Expr) {2124 2125  FoldingSetNodeID ID;2126  ProfileIsAOpInit(ID, CheckType, Expr);2127 2128  detail::RecordKeeperImpl &RK = Expr->getRecordKeeper().getImpl();2129  void *IP = nullptr;2130  if (const IsAOpInit *I = RK.TheIsAOpInitPool.FindNodeOrInsertPos(ID, IP))2131    return I;2132 2133  IsAOpInit *I = new (RK.Allocator) IsAOpInit(CheckType, Expr);2134  RK.TheIsAOpInitPool.InsertNode(I, IP);2135  return I;2136}2137 2138void IsAOpInit::Profile(FoldingSetNodeID &ID) const {2139  ProfileIsAOpInit(ID, CheckType, Expr);2140}2141 2142const Init *IsAOpInit::Fold() const {2143  if (const auto *TI = dyn_cast<TypedInit>(Expr)) {2144    // Is the expression type known to be (a subclass of) the desired type?2145    if (TI->getType()->typeIsConvertibleTo(CheckType))2146      return IntInit::get(getRecordKeeper(), 1);2147 2148    if (isa<RecordRecTy>(CheckType)) {2149      // If the target type is not a subclass of the expression type once the2150      // expression has been made concrete, or if the expression has fully2151      // resolved to a record, we know that it can't be of the required type.2152      if ((!CheckType->typeIsConvertibleTo(TI->getType()) &&2153           Expr->isConcrete()) ||2154          isa<DefInit>(Expr))2155        return IntInit::get(getRecordKeeper(), 0);2156    } else {2157      // We treat non-record types as not castable.2158      return IntInit::get(getRecordKeeper(), 0);2159    }2160  }2161  return this;2162}2163 2164const Init *IsAOpInit::resolveReferences(Resolver &R) const {2165  const Init *NewExpr = Expr->resolveReferences(R);2166  if (Expr != NewExpr)2167    return get(CheckType, NewExpr)->Fold();2168  return this;2169}2170 2171const Init *IsAOpInit::getBit(unsigned Bit) const {2172  return VarBitInit::get(this, Bit);2173}2174 2175std::string IsAOpInit::getAsString() const {2176  return (Twine("!isa<") + CheckType->getAsString() + ">(" +2177          Expr->getAsString() + ")")2178      .str();2179}2180 2181static void ProfileExistsOpInit(FoldingSetNodeID &ID, const RecTy *CheckType,2182                                const Init *Expr) {2183  ID.AddPointer(CheckType);2184  ID.AddPointer(Expr);2185}2186 2187const ExistsOpInit *ExistsOpInit::get(const RecTy *CheckType,2188                                      const Init *Expr) {2189  FoldingSetNodeID ID;2190  ProfileExistsOpInit(ID, CheckType, Expr);2191 2192  detail::RecordKeeperImpl &RK = Expr->getRecordKeeper().getImpl();2193  void *IP = nullptr;2194  if (const ExistsOpInit *I =2195          RK.TheExistsOpInitPool.FindNodeOrInsertPos(ID, IP))2196    return I;2197 2198  ExistsOpInit *I = new (RK.Allocator) ExistsOpInit(CheckType, Expr);2199  RK.TheExistsOpInitPool.InsertNode(I, IP);2200  return I;2201}2202 2203void ExistsOpInit::Profile(FoldingSetNodeID &ID) const {2204  ProfileExistsOpInit(ID, CheckType, Expr);2205}2206 2207const Init *ExistsOpInit::Fold(const Record *CurRec, bool IsFinal) const {2208  if (const auto *Name = dyn_cast<StringInit>(Expr)) {2209    // Look up all defined records to see if we can find one.2210    const Record *D = CheckType->getRecordKeeper().getDef(Name->getValue());2211    if (D) {2212      // Check if types are compatible.2213      return IntInit::get(getRecordKeeper(),2214                          D->getDefInit()->getType()->typeIsA(CheckType));2215    }2216 2217    if (CurRec) {2218      // Self-references are allowed, but their resolution is delayed until2219      // the final resolve to ensure that we get the correct type for them.2220      auto *Anonymous = dyn_cast<AnonymousNameInit>(CurRec->getNameInit());2221      if (Name == CurRec->getNameInit() ||2222          (Anonymous && Name == Anonymous->getNameInit())) {2223        if (!IsFinal)2224          return this;2225 2226        // No doubt that there exists a record, so we should check if types are2227        // compatible.2228        return IntInit::get(getRecordKeeper(),2229                            CurRec->getType()->typeIsA(CheckType));2230      }2231    }2232 2233    if (IsFinal)2234      return IntInit::get(getRecordKeeper(), 0);2235  }2236  return this;2237}2238 2239const Init *ExistsOpInit::resolveReferences(Resolver &R) const {2240  const Init *NewExpr = Expr->resolveReferences(R);2241  if (Expr != NewExpr || R.isFinal())2242    return get(CheckType, NewExpr)->Fold(R.getCurrentRecord(), R.isFinal());2243  return this;2244}2245 2246const Init *ExistsOpInit::getBit(unsigned Bit) const {2247  return VarBitInit::get(this, Bit);2248}2249 2250std::string ExistsOpInit::getAsString() const {2251  return (Twine("!exists<") + CheckType->getAsString() + ">(" +2252          Expr->getAsString() + ")")2253      .str();2254}2255 2256static void ProfileInstancesOpInit(FoldingSetNodeID &ID, const RecTy *Type,2257                                   const Init *Regex) {2258  ID.AddPointer(Type);2259  ID.AddPointer(Regex);2260}2261 2262const InstancesOpInit *InstancesOpInit::get(const RecTy *Type,2263                                            const Init *Regex) {2264  FoldingSetNodeID ID;2265  ProfileInstancesOpInit(ID, Type, Regex);2266 2267  detail::RecordKeeperImpl &RK = Regex->getRecordKeeper().getImpl();2268  void *IP = nullptr;2269  if (const InstancesOpInit *I =2270          RK.TheInstancesOpInitPool.FindNodeOrInsertPos(ID, IP))2271    return I;2272 2273  InstancesOpInit *I = new (RK.Allocator) InstancesOpInit(Type, Regex);2274  RK.TheInstancesOpInitPool.InsertNode(I, IP);2275  return I;2276}2277 2278void InstancesOpInit::Profile(FoldingSetNodeID &ID) const {2279  ProfileInstancesOpInit(ID, Type, Regex);2280}2281 2282const Init *InstancesOpInit::Fold(const Record *CurRec, bool IsFinal) const {2283  if (CurRec && !IsFinal)2284    return this;2285 2286  const auto *RegexInit = dyn_cast<StringInit>(Regex);2287  if (!RegexInit)2288    return this;2289 2290  StringRef RegexStr = RegexInit->getValue();2291  llvm::Regex Matcher(RegexStr);2292  if (!Matcher.isValid())2293    PrintFatalError(Twine("invalid regex '") + RegexStr + Twine("'"));2294 2295  const RecordKeeper &RK = Type->getRecordKeeper();2296  SmallVector<Init *, 8> Selected;2297  for (auto &Def : RK.getAllDerivedDefinitionsIfDefined(Type->getAsString()))2298    if (Matcher.match(Def->getName()))2299      Selected.push_back(Def->getDefInit());2300 2301  return ListInit::get(Selected, Type);2302}2303 2304const Init *InstancesOpInit::resolveReferences(Resolver &R) const {2305  const Init *NewRegex = Regex->resolveReferences(R);2306  if (Regex != NewRegex || R.isFinal())2307    return get(Type, NewRegex)->Fold(R.getCurrentRecord(), R.isFinal());2308  return this;2309}2310 2311const Init *InstancesOpInit::getBit(unsigned Bit) const {2312  return VarBitInit::get(this, Bit);2313}2314 2315std::string InstancesOpInit::getAsString() const {2316  return "!instances<" + Type->getAsString() + ">(" + Regex->getAsString() +2317         ")";2318}2319 2320const RecTy *TypedInit::getFieldType(const StringInit *FieldName) const {2321  if (const auto *RecordType = dyn_cast<RecordRecTy>(getType())) {2322    for (const Record *Rec : RecordType->getClasses()) {2323      if (const RecordVal *Field = Rec->getValue(FieldName))2324        return Field->getType();2325    }2326  }2327  return nullptr;2328}2329 2330const Init *TypedInit::convertInitializerTo(const RecTy *Ty) const {2331  if (getType() == Ty || getType()->typeIsA(Ty))2332    return this;2333 2334  if (isa<BitRecTy>(getType()) && isa<BitsRecTy>(Ty) &&2335      cast<BitsRecTy>(Ty)->getNumBits() == 1)2336    return BitsInit::get(getRecordKeeper(), {this});2337 2338  return nullptr;2339}2340 2341const Init *2342TypedInit::convertInitializerBitRange(ArrayRef<unsigned> Bits) const {2343  const auto *T = dyn_cast<BitsRecTy>(getType());2344  if (!T) return nullptr;  // Cannot subscript a non-bits variable.2345  unsigned NumBits = T->getNumBits();2346 2347  SmallVector<const Init *, 16> NewBits;2348  NewBits.reserve(Bits.size());2349  for (unsigned Bit : Bits) {2350    if (Bit >= NumBits)2351      return nullptr;2352 2353    NewBits.push_back(VarBitInit::get(this, Bit));2354  }2355  return BitsInit::get(getRecordKeeper(), NewBits);2356}2357 2358const Init *TypedInit::getCastTo(const RecTy *Ty) const {2359  // Handle the common case quickly2360  if (getType() == Ty || getType()->typeIsA(Ty))2361    return this;2362 2363  if (const Init *Converted = convertInitializerTo(Ty)) {2364    assert(!isa<TypedInit>(Converted) ||2365           cast<TypedInit>(Converted)->getType()->typeIsA(Ty));2366    return Converted;2367  }2368 2369  if (!getType()->typeIsConvertibleTo(Ty))2370    return nullptr;2371 2372  return UnOpInit::get(UnOpInit::CAST, this, Ty)->Fold(nullptr);2373}2374 2375const VarInit *VarInit::get(StringRef VN, const RecTy *T) {2376  const Init *Value = StringInit::get(T->getRecordKeeper(), VN);2377  return VarInit::get(Value, T);2378}2379 2380const VarInit *VarInit::get(const Init *VN, const RecTy *T) {2381  detail::RecordKeeperImpl &RK = T->getRecordKeeper().getImpl();2382  VarInit *&I = RK.TheVarInitPool[{T, VN}];2383  if (!I)2384    I = new (RK.Allocator) VarInit(VN, T);2385  return I;2386}2387 2388StringRef VarInit::getName() const {2389  const auto *NameString = cast<StringInit>(getNameInit());2390  return NameString->getValue();2391}2392 2393const Init *VarInit::getBit(unsigned Bit) const {2394  if (getType() == BitRecTy::get(getRecordKeeper()))2395    return this;2396  return VarBitInit::get(this, Bit);2397}2398 2399const Init *VarInit::resolveReferences(Resolver &R) const {2400  if (const Init *Val = R.resolve(VarName))2401    return Val;2402  return this;2403}2404 2405const VarBitInit *VarBitInit::get(const TypedInit *T, unsigned B) {2406  detail::RecordKeeperImpl &RK = T->getRecordKeeper().getImpl();2407  VarBitInit *&I = RK.TheVarBitInitPool[{T, B}];2408  if (!I)2409    I = new (RK.Allocator) VarBitInit(T, B);2410  return I;2411}2412 2413std::string VarBitInit::getAsString() const {2414  return TI->getAsString() + "{" + utostr(Bit) + "}";2415}2416 2417const Init *VarBitInit::resolveReferences(Resolver &R) const {2418  const Init *I = TI->resolveReferences(R);2419  if (TI != I)2420    return I->getBit(getBitNum());2421 2422  return this;2423}2424 2425DefInit::DefInit(const Record *D)2426    : TypedInit(IK_DefInit, D->getType()), Def(D) {}2427 2428const Init *DefInit::convertInitializerTo(const RecTy *Ty) const {2429  if (auto *RRT = dyn_cast<RecordRecTy>(Ty))2430    if (getType()->typeIsConvertibleTo(RRT))2431      return this;2432  return nullptr;2433}2434 2435const RecTy *DefInit::getFieldType(const StringInit *FieldName) const {2436  if (const RecordVal *RV = Def->getValue(FieldName))2437    return RV->getType();2438  return nullptr;2439}2440 2441std::string DefInit::getAsString() const { return Def->getName().str(); }2442 2443static void ProfileVarDefInit(FoldingSetNodeID &ID, const Record *Class,2444                              ArrayRef<const ArgumentInit *> Args) {2445  ID.AddInteger(Args.size());2446  ID.AddPointer(Class);2447 2448  for (const Init *I : Args)2449    ID.AddPointer(I);2450}2451 2452VarDefInit::VarDefInit(SMLoc Loc, const Record *Class,2453                       ArrayRef<const ArgumentInit *> Args)2454    : TypedInit(IK_VarDefInit, RecordRecTy::get(Class)), Loc(Loc), Class(Class),2455      NumArgs(Args.size()) {2456  llvm::uninitialized_copy(Args, getTrailingObjects());2457}2458 2459const VarDefInit *VarDefInit::get(SMLoc Loc, const Record *Class,2460                                  ArrayRef<const ArgumentInit *> Args) {2461  FoldingSetNodeID ID;2462  ProfileVarDefInit(ID, Class, Args);2463 2464  detail::RecordKeeperImpl &RK = Class->getRecords().getImpl();2465  void *IP = nullptr;2466  if (const VarDefInit *I = RK.TheVarDefInitPool.FindNodeOrInsertPos(ID, IP))2467    return I;2468 2469  void *Mem = RK.Allocator.Allocate(2470      totalSizeToAlloc<const ArgumentInit *>(Args.size()), alignof(VarDefInit));2471  VarDefInit *I = new (Mem) VarDefInit(Loc, Class, Args);2472  RK.TheVarDefInitPool.InsertNode(I, IP);2473  return I;2474}2475 2476void VarDefInit::Profile(FoldingSetNodeID &ID) const {2477  ProfileVarDefInit(ID, Class, args());2478}2479 2480const DefInit *VarDefInit::instantiate() {2481  if (Def)2482    return Def;2483 2484  RecordKeeper &Records = Class->getRecords();2485  auto NewRecOwner = std::make_unique<Record>(2486      Records.getNewAnonymousName(), Loc, Records, Record::RK_AnonymousDef);2487  Record *NewRec = NewRecOwner.get();2488 2489  // Copy values from class to instance2490  for (const RecordVal &Val : Class->getValues())2491    NewRec->addValue(Val);2492 2493  // Copy assertions from class to instance.2494  NewRec->appendAssertions(Class);2495 2496  // Copy dumps from class to instance.2497  NewRec->appendDumps(Class);2498 2499  // Substitute and resolve template arguments2500  ArrayRef<const Init *> TArgs = Class->getTemplateArgs();2501  MapResolver R(NewRec);2502 2503  for (const Init *Arg : TArgs) {2504    R.set(Arg, NewRec->getValue(Arg)->getValue());2505    NewRec->removeValue(Arg);2506  }2507 2508  for (auto *Arg : args()) {2509    if (Arg->isPositional())2510      R.set(TArgs[Arg->getIndex()], Arg->getValue());2511    if (Arg->isNamed())2512      R.set(Arg->getName(), Arg->getValue());2513  }2514 2515  NewRec->resolveReferences(R);2516 2517  // Add superclass.2518  NewRec->addDirectSuperClass(2519      Class, SMRange(Class->getLoc().back(), Class->getLoc().back()));2520 2521  // Resolve internal references and store in record keeper2522  NewRec->resolveReferences();2523  Records.addDef(std::move(NewRecOwner));2524 2525  // Check the assertions.2526  NewRec->checkRecordAssertions();2527 2528  // Check the assertions.2529  NewRec->emitRecordDumps();2530 2531  return Def = NewRec->getDefInit();2532}2533 2534const Init *VarDefInit::resolveReferences(Resolver &R) const {2535  TrackUnresolvedResolver UR(&R);2536  bool Changed = false;2537  SmallVector<const ArgumentInit *, 8> NewArgs;2538  NewArgs.reserve(args_size());2539 2540  for (const ArgumentInit *Arg : args()) {2541    const auto *NewArg = cast<ArgumentInit>(Arg->resolveReferences(UR));2542    NewArgs.push_back(NewArg);2543    Changed |= NewArg != Arg;2544  }2545 2546  if (Changed) {2547    auto *New = VarDefInit::get(Loc, Class, NewArgs);2548    if (!UR.foundUnresolved())2549      return const_cast<VarDefInit *>(New)->instantiate();2550    return New;2551  }2552  return this;2553}2554 2555const Init *VarDefInit::Fold() const {2556  if (Def)2557    return Def;2558 2559  TrackUnresolvedResolver R;2560  for (const Init *Arg : args())2561    Arg->resolveReferences(R);2562 2563  if (!R.foundUnresolved())2564    return const_cast<VarDefInit *>(this)->instantiate();2565  return this;2566}2567 2568std::string VarDefInit::getAsString() const {2569  std::string Result = Class->getNameInitAsString() + "<";2570  ListSeparator LS;2571  for (const Init *Arg : args()) {2572    Result += LS;2573    Result += Arg->getAsString();2574  }2575  return Result + ">";2576}2577 2578const FieldInit *FieldInit::get(const Init *R, const StringInit *FN) {2579  detail::RecordKeeperImpl &RK = R->getRecordKeeper().getImpl();2580  FieldInit *&I = RK.TheFieldInitPool[{R, FN}];2581  if (!I)2582    I = new (RK.Allocator) FieldInit(R, FN);2583  return I;2584}2585 2586const Init *FieldInit::getBit(unsigned Bit) const {2587  if (getType() == BitRecTy::get(getRecordKeeper()))2588    return this;2589  return VarBitInit::get(this, Bit);2590}2591 2592const Init *FieldInit::resolveReferences(Resolver &R) const {2593  const Init *NewRec = Rec->resolveReferences(R);2594  if (NewRec != Rec)2595    return FieldInit::get(NewRec, FieldName)->Fold(R.getCurrentRecord());2596  return this;2597}2598 2599const Init *FieldInit::Fold(const Record *CurRec) const {2600  if (const auto *DI = dyn_cast<DefInit>(Rec)) {2601    const Record *Def = DI->getDef();2602    if (Def == CurRec)2603      PrintFatalError(CurRec->getLoc(),2604                      Twine("Attempting to access field '") +2605                      FieldName->getAsUnquotedString() + "' of '" +2606                      Rec->getAsString() + "' is a forbidden self-reference");2607    const Init *FieldVal = Def->getValue(FieldName)->getValue();2608    if (FieldVal->isConcrete())2609      return FieldVal;2610  }2611  return this;2612}2613 2614bool FieldInit::isConcrete() const {2615  if (const auto *DI = dyn_cast<DefInit>(Rec)) {2616    const Init *FieldVal = DI->getDef()->getValue(FieldName)->getValue();2617    return FieldVal->isConcrete();2618  }2619  return false;2620}2621 2622static void ProfileCondOpInit(FoldingSetNodeID &ID,2623                              ArrayRef<const Init *> Conds,2624                              ArrayRef<const Init *> Vals,2625                              const RecTy *ValType) {2626  assert(Conds.size() == Vals.size() &&2627         "Number of conditions and values must match!");2628  ID.AddPointer(ValType);2629 2630  for (const auto &[Cond, Val] : zip(Conds, Vals)) {2631    ID.AddPointer(Cond);2632    ID.AddPointer(Val);2633  }2634}2635 2636CondOpInit::CondOpInit(ArrayRef<const Init *> Conds,2637                       ArrayRef<const Init *> Values, const RecTy *Type)2638    : TypedInit(IK_CondOpInit, Type), NumConds(Conds.size()), ValType(Type) {2639  const Init **TrailingObjects = getTrailingObjects();2640  llvm::uninitialized_copy(Conds, TrailingObjects);2641  llvm::uninitialized_copy(Values, TrailingObjects + NumConds);2642}2643 2644void CondOpInit::Profile(FoldingSetNodeID &ID) const {2645  ProfileCondOpInit(ID, getConds(), getVals(), ValType);2646}2647 2648const CondOpInit *CondOpInit::get(ArrayRef<const Init *> Conds,2649                                  ArrayRef<const Init *> Values,2650                                  const RecTy *Ty) {2651  assert(Conds.size() == Values.size() &&2652         "Number of conditions and values must match!");2653 2654  FoldingSetNodeID ID;2655  ProfileCondOpInit(ID, Conds, Values, Ty);2656 2657  detail::RecordKeeperImpl &RK = Ty->getRecordKeeper().getImpl();2658  void *IP = nullptr;2659  if (const CondOpInit *I = RK.TheCondOpInitPool.FindNodeOrInsertPos(ID, IP))2660    return I;2661 2662  void *Mem = RK.Allocator.Allocate(2663      totalSizeToAlloc<const Init *>(2 * Conds.size()), alignof(CondOpInit));2664  CondOpInit *I = new (Mem) CondOpInit(Conds, Values, Ty);2665  RK.TheCondOpInitPool.InsertNode(I, IP);2666  return I;2667}2668 2669const Init *CondOpInit::resolveReferences(Resolver &R) const {2670  SmallVector<const Init *, 4> NewConds;2671  SmallVector<const Init *, 4> NewVals;2672 2673  bool Changed = false;2674  for (auto [Cond, Val] : getCondAndVals()) {2675    const Init *NewCond = Cond->resolveReferences(R);2676    NewConds.push_back(NewCond);2677    Changed |= NewCond != Cond;2678 2679    const Init *NewVal = Val->resolveReferences(R);2680    NewVals.push_back(NewVal);2681    Changed |= NewVal != Val;2682  }2683 2684  if (Changed)2685    return (CondOpInit::get(NewConds, NewVals,2686            getValType()))->Fold(R.getCurrentRecord());2687 2688  return this;2689}2690 2691const Init *CondOpInit::Fold(const Record *CurRec) const {2692  RecordKeeper &RK = getRecordKeeper();2693  for (auto [Cond, Val] : getCondAndVals()) {2694    if (const auto *CondI = dyn_cast_or_null<IntInit>(2695            Cond->convertInitializerTo(IntRecTy::get(RK)))) {2696      if (CondI->getValue())2697        return Val->convertInitializerTo(getValType());2698    } else {2699      return this;2700    }2701  }2702 2703  PrintFatalError(CurRec->getLoc(),2704                  CurRec->getNameInitAsString() +2705                  " does not have any true condition in:" +2706                  this->getAsString());2707  return nullptr;2708}2709 2710bool CondOpInit::isConcrete() const {2711  return all_of(getCondAndVals(), [](const auto &Pair) {2712    return std::get<0>(Pair)->isConcrete() && std::get<1>(Pair)->isConcrete();2713  });2714}2715 2716bool CondOpInit::isComplete() const {2717  return all_of(getCondAndVals(), [](const auto &Pair) {2718    return std::get<0>(Pair)->isComplete() && std::get<1>(Pair)->isComplete();2719  });2720}2721 2722std::string CondOpInit::getAsString() const {2723  std::string Result = "!cond(";2724  ListSeparator LS;2725  for (auto [Cond, Val] : getCondAndVals()) {2726    Result += LS;2727    Result += Cond->getAsString() + ": ";2728    Result += Val->getAsString();2729  }2730  return Result + ")";2731}2732 2733const Init *CondOpInit::getBit(unsigned Bit) const {2734  return VarBitInit::get(this, Bit);2735}2736 2737static void ProfileDagInit(FoldingSetNodeID &ID, const Init *V,2738                           const StringInit *VN, ArrayRef<const Init *> Args,2739                           ArrayRef<const StringInit *> ArgNames) {2740  ID.AddPointer(V);2741  ID.AddPointer(VN);2742 2743  for (auto [Arg, Name] : zip_equal(Args, ArgNames)) {2744    ID.AddPointer(Arg);2745    ID.AddPointer(Name);2746  }2747}2748 2749DagInit::DagInit(const Init *V, const StringInit *VN,2750                 ArrayRef<const Init *> Args,2751                 ArrayRef<const StringInit *> ArgNames)2752    : TypedInit(IK_DagInit, DagRecTy::get(V->getRecordKeeper())), Val(V),2753      ValName(VN), NumArgs(Args.size()) {2754  llvm::uninitialized_copy(Args, getTrailingObjects<const Init *>());2755  llvm::uninitialized_copy(ArgNames, getTrailingObjects<const StringInit *>());2756}2757 2758const DagInit *DagInit::get(const Init *V, const StringInit *VN,2759                            ArrayRef<const Init *> Args,2760                            ArrayRef<const StringInit *> ArgNames) {2761  assert(Args.size() == ArgNames.size() &&2762         "Number of DAG args and arg names must match!");2763 2764  FoldingSetNodeID ID;2765  ProfileDagInit(ID, V, VN, Args, ArgNames);2766 2767  detail::RecordKeeperImpl &RK = V->getRecordKeeper().getImpl();2768  void *IP = nullptr;2769  if (const DagInit *I = RK.TheDagInitPool.FindNodeOrInsertPos(ID, IP))2770    return I;2771 2772  void *Mem =2773      RK.Allocator.Allocate(totalSizeToAlloc<const Init *, const StringInit *>(2774                                Args.size(), ArgNames.size()),2775                            alignof(DagInit));2776  DagInit *I = new (Mem) DagInit(V, VN, Args, ArgNames);2777  RK.TheDagInitPool.InsertNode(I, IP);2778  return I;2779}2780 2781const DagInit *DagInit::get(2782    const Init *V, const StringInit *VN,2783    ArrayRef<std::pair<const Init *, const StringInit *>> ArgAndNames) {2784  SmallVector<const Init *, 8> Args(make_first_range(ArgAndNames));2785  SmallVector<const StringInit *, 8> Names(make_second_range(ArgAndNames));2786  return DagInit::get(V, VN, Args, Names);2787}2788 2789void DagInit::Profile(FoldingSetNodeID &ID) const {2790  ProfileDagInit(ID, Val, ValName, getArgs(), getArgNames());2791}2792 2793const Record *DagInit::getOperatorAsDef(ArrayRef<SMLoc> Loc) const {2794  if (const auto *DefI = dyn_cast<DefInit>(Val))2795    return DefI->getDef();2796  PrintFatalError(Loc, "Expected record as operator");2797  return nullptr;2798}2799 2800std::optional<unsigned> DagInit::getArgNo(StringRef Name) const {2801  ArrayRef<const StringInit *> ArgNames = getArgNames();2802  auto It = llvm::find_if(ArgNames, [Name](const StringInit *ArgName) {2803    return ArgName && ArgName->getValue() == Name;2804  });2805  if (It == ArgNames.end())2806    return std::nullopt;2807  return std::distance(ArgNames.begin(), It);2808}2809 2810const Init *DagInit::resolveReferences(Resolver &R) const {2811  SmallVector<const Init *, 8> NewArgs;2812  NewArgs.reserve(arg_size());2813  bool ArgsChanged = false;2814  for (const Init *Arg : getArgs()) {2815    const Init *NewArg = Arg->resolveReferences(R);2816    NewArgs.push_back(NewArg);2817    ArgsChanged |= NewArg != Arg;2818  }2819 2820  const Init *Op = Val->resolveReferences(R);2821  if (Op != Val || ArgsChanged)2822    return DagInit::get(Op, ValName, NewArgs, getArgNames());2823 2824  return this;2825}2826 2827bool DagInit::isConcrete() const {2828  if (!Val->isConcrete())2829    return false;2830  return all_of(getArgs(), [](const Init *Elt) { return Elt->isConcrete(); });2831}2832 2833std::string DagInit::getAsString() const {2834  std::string Result = "(" + Val->getAsString();2835  if (ValName)2836    Result += ":$" + ValName->getAsUnquotedString();2837  if (!arg_empty()) {2838    Result += " ";2839    ListSeparator LS;2840    for (auto [Arg, Name] : getArgAndNames()) {2841      Result += LS;2842      Result += Arg->getAsString();2843      if (Name)2844        Result += ":$" + Name->getAsUnquotedString();2845    }2846  }2847  return Result + ")";2848}2849 2850//===----------------------------------------------------------------------===//2851//    Other implementations2852//===----------------------------------------------------------------------===//2853 2854RecordVal::RecordVal(const Init *N, const RecTy *T, FieldKind K)2855    : Name(N), TyAndKind(T, K) {2856  setValue(UnsetInit::get(N->getRecordKeeper()));2857  assert(Value && "Cannot create unset value for current type!");2858}2859 2860// This constructor accepts the same arguments as the above, but also2861// a source location.2862RecordVal::RecordVal(const Init *N, SMLoc Loc, const RecTy *T, FieldKind K)2863    : Name(N), Loc(Loc), TyAndKind(T, K) {2864  setValue(UnsetInit::get(N->getRecordKeeper()));2865  assert(Value && "Cannot create unset value for current type!");2866}2867 2868StringRef RecordVal::getName() const {2869  return cast<StringInit>(getNameInit())->getValue();2870}2871 2872std::string RecordVal::getPrintType() const {2873  if (getType() == StringRecTy::get(getRecordKeeper())) {2874    if (const auto *StrInit = dyn_cast<StringInit>(Value)) {2875      if (StrInit->hasCodeFormat())2876        return "code";2877      else2878        return "string";2879    } else {2880      return "string";2881    }2882  } else {2883    return TyAndKind.getPointer()->getAsString();2884  }2885}2886 2887bool RecordVal::setValue(const Init *V) {2888  if (!V) {2889    Value = nullptr;2890    return false;2891  }2892 2893  Value = V->getCastTo(getType());2894  if (!Value)2895    return true;2896 2897  assert(!isa<TypedInit>(Value) ||2898         cast<TypedInit>(Value)->getType()->typeIsA(getType()));2899  if (const auto *BTy = dyn_cast<BitsRecTy>(getType())) {2900    if (isa<BitsInit>(Value))2901      return false;2902    SmallVector<const Init *, 64> Bits(BTy->getNumBits());2903    for (unsigned I = 0, E = BTy->getNumBits(); I < E; ++I)2904      Bits[I] = Value->getBit(I);2905    Value = BitsInit::get(V->getRecordKeeper(), Bits);2906  }2907 2908  return false;2909}2910 2911// This version of setValue takes a source location and resets the2912// location in the RecordVal.2913bool RecordVal::setValue(const Init *V, SMLoc NewLoc) {2914  Loc = NewLoc;2915  return setValue(V);2916}2917 2918#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)2919LLVM_DUMP_METHOD void RecordVal::dump() const { errs() << *this; }2920#endif2921 2922void RecordVal::print(raw_ostream &OS, bool PrintSem) const {2923  if (isNonconcreteOK()) OS << "field ";2924  OS << getPrintType() << " " << getNameInitAsString();2925 2926  if (getValue())2927    OS << " = " << *getValue();2928 2929  if (PrintSem) OS << ";\n";2930}2931 2932void Record::updateClassLoc(SMLoc Loc) {2933  assert(Locs.size() == 1);2934  ForwardDeclarationLocs.push_back(Locs.front());2935 2936  Locs.clear();2937  Locs.push_back(Loc);2938}2939 2940void Record::checkName() {2941  // Ensure the record name has string type.2942  const auto *TypedName = cast<const TypedInit>(Name);2943  if (!isa<StringRecTy>(TypedName->getType()))2944    PrintFatalError(getLoc(), Twine("Record name '") + Name->getAsString() +2945                                  "' is not a string!");2946}2947 2948const RecordRecTy *Record::getType() const {2949  SmallVector<const Record *> DirectSCs(2950      make_first_range(getDirectSuperClasses()));2951  return RecordRecTy::get(TrackedRecords, DirectSCs);2952}2953 2954DefInit *Record::getDefInit() const {2955  if (!CorrespondingDefInit) {2956    CorrespondingDefInit =2957        new (TrackedRecords.getImpl().Allocator) DefInit(this);2958  }2959  return CorrespondingDefInit;2960}2961 2962unsigned Record::getNewUID(RecordKeeper &RK) {2963  return RK.getImpl().LastRecordID++;2964}2965 2966void Record::setName(const Init *NewName) {2967  Name = NewName;2968  checkName();2969  // DO NOT resolve record values to the name at this point because2970  // there might be default values for arguments of this def. Those2971  // arguments might not have been resolved yet so we don't want to2972  // prematurely assume values for those arguments were not passed to2973  // this def.2974  //2975  // Nonetheless, it may be that some of this Record's values2976  // reference the record name. Indeed, the reason for having the2977  // record name be an Init is to provide this flexibility. The extra2978  // resolve steps after completely instantiating defs takes care of2979  // this. See TGParser::ParseDef and TGParser::ParseDefm.2980}2981 2982void Record::resolveReferences(Resolver &R, const RecordVal *SkipVal) {2983  const Init *OldName = getNameInit();2984  const Init *NewName = Name->resolveReferences(R);2985  if (NewName != OldName) {2986    // Re-register with RecordKeeper.2987    setName(NewName);2988  }2989 2990  // Resolve the field values.2991  for (RecordVal &Value : Values) {2992    if (SkipVal == &Value) // Skip resolve the same field as the given one2993      continue;2994    if (const Init *V = Value.getValue()) {2995      const Init *VR = V->resolveReferences(R);2996      if (Value.setValue(VR)) {2997        std::string Type;2998        if (const auto *VRT = dyn_cast<TypedInit>(VR))2999          Type =3000              (Twine("of type '") + VRT->getType()->getAsString() + "' ").str();3001        PrintFatalError(3002            getLoc(),3003            Twine("Invalid value ") + Type + "found when setting field '" +3004                Value.getNameInitAsString() + "' of type '" +3005                Value.getType()->getAsString() +3006                "' after resolving references: " + VR->getAsUnquotedString() +3007                "\n");3008      }3009    }3010  }3011 3012  // Resolve the assertion expressions.3013  for (AssertionInfo &Assertion : Assertions) {3014    const Init *Value = Assertion.Condition->resolveReferences(R);3015    Assertion.Condition = Value;3016    Value = Assertion.Message->resolveReferences(R);3017    Assertion.Message = Value;3018  }3019  // Resolve the dump expressions.3020  for (DumpInfo &Dump : Dumps) {3021    const Init *Value = Dump.Message->resolveReferences(R);3022    Dump.Message = Value;3023  }3024}3025 3026void Record::resolveReferences(const Init *NewName) {3027  RecordResolver R(*this);3028  R.setName(NewName);3029  R.setFinal(true);3030  resolveReferences(R);3031}3032 3033#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)3034LLVM_DUMP_METHOD void Record::dump() const { errs() << *this; }3035#endif3036 3037raw_ostream &llvm::operator<<(raw_ostream &OS, const Record &R) {3038  OS << R.getNameInitAsString();3039 3040  ArrayRef<const Init *> TArgs = R.getTemplateArgs();3041  if (!TArgs.empty()) {3042    OS << "<";3043    ListSeparator LS;3044    for (const Init *TA : TArgs) {3045      const RecordVal *RV = R.getValue(TA);3046      assert(RV && "Template argument record not found??");3047      OS << LS;3048      RV->print(OS, false);3049    }3050    OS << ">";3051  }3052 3053  OS << " {";3054  std::vector<const Record *> SCs = R.getSuperClasses();3055  if (!SCs.empty()) {3056    OS << "\t//";3057    for (const Record *SC : SCs)3058      OS << " " << SC->getNameInitAsString();3059  }3060  OS << "\n";3061 3062  for (const RecordVal &Val : R.getValues())3063    if (Val.isNonconcreteOK() && !R.isTemplateArg(Val.getNameInit()))3064      OS << Val;3065  for (const RecordVal &Val : R.getValues())3066    if (!Val.isNonconcreteOK() && !R.isTemplateArg(Val.getNameInit()))3067      OS << Val;3068 3069  return OS << "}\n";3070}3071 3072SMLoc Record::getFieldLoc(StringRef FieldName) const {3073  const RecordVal *R = getValue(FieldName);3074  if (!R)3075    PrintFatalError(getLoc(), "Record `" + getName() +3076      "' does not have a field named `" + FieldName + "'!\n");3077  return R->getLoc();3078}3079 3080const Init *Record::getValueInit(StringRef FieldName) const {3081  const RecordVal *R = getValue(FieldName);3082  if (!R || !R->getValue())3083    PrintFatalError(getLoc(), "Record `" + getName() +3084      "' does not have a field named `" + FieldName + "'!\n");3085  return R->getValue();3086}3087 3088StringRef Record::getValueAsString(StringRef FieldName) const {3089  const Init *I = getValueInit(FieldName);3090  if (const auto *SI = dyn_cast<StringInit>(I))3091    return SI->getValue();3092  PrintFatalError(getLoc(), "Record `" + getName() + "', field `" + FieldName +3093                                "' exists but does not have a string value");3094}3095 3096std::optional<StringRef>3097Record::getValueAsOptionalString(StringRef FieldName) const {3098  const RecordVal *R = getValue(FieldName);3099  if (!R || !R->getValue())3100    return std::nullopt;3101  if (isa<UnsetInit>(R->getValue()))3102    return std::nullopt;3103 3104  if (const auto *SI = dyn_cast<StringInit>(R->getValue()))3105    return SI->getValue();3106 3107  PrintFatalError(getLoc(),3108                  "Record `" + getName() + "', ` field `" + FieldName +3109                      "' exists but does not have a string initializer!");3110}3111 3112const BitsInit *Record::getValueAsBitsInit(StringRef FieldName) const {3113  const Init *I = getValueInit(FieldName);3114  if (const auto *BI = dyn_cast<BitsInit>(I))3115    return BI;3116  PrintFatalError(getLoc(), "Record `" + getName() + "', field `" + FieldName +3117                                "' exists but does not have a bits value");3118}3119 3120const ListInit *Record::getValueAsListInit(StringRef FieldName) const {3121  const Init *I = getValueInit(FieldName);3122  if (const auto *LI = dyn_cast<ListInit>(I))3123    return LI;3124  PrintFatalError(getLoc(), "Record `" + getName() + "', field `" + FieldName +3125                                "' exists but does not have a list value");3126}3127 3128std::vector<const Record *>3129Record::getValueAsListOfDefs(StringRef FieldName) const {3130  const ListInit *List = getValueAsListInit(FieldName);3131  std::vector<const Record *> Defs;3132  for (const Init *I : List->getElements()) {3133    if (const auto *DI = dyn_cast<DefInit>(I))3134      Defs.push_back(DI->getDef());3135    else3136      PrintFatalError(getLoc(), "Record `" + getName() + "', field `" +3137                                    FieldName +3138                                    "' list is not entirely DefInit!");3139  }3140  return Defs;3141}3142 3143int64_t Record::getValueAsInt(StringRef FieldName) const {3144  const Init *I = getValueInit(FieldName);3145  if (const auto *II = dyn_cast<IntInit>(I))3146    return II->getValue();3147  PrintFatalError(3148      getLoc(),3149      Twine("Record `") + getName() + "', field `" + FieldName +3150          "' exists but does not have an int value: " + I->getAsString());3151}3152 3153std::vector<int64_t>3154Record::getValueAsListOfInts(StringRef FieldName) const {3155  const ListInit *List = getValueAsListInit(FieldName);3156  std::vector<int64_t> Ints;3157  for (const Init *I : List->getElements()) {3158    if (const auto *II = dyn_cast<IntInit>(I))3159      Ints.push_back(II->getValue());3160    else3161      PrintFatalError(getLoc(),3162                      Twine("Record `") + getName() + "', field `" + FieldName +3163                          "' exists but does not have a list of ints value: " +3164                          I->getAsString());3165  }3166  return Ints;3167}3168 3169std::vector<StringRef>3170Record::getValueAsListOfStrings(StringRef FieldName) const {3171  const ListInit *List = getValueAsListInit(FieldName);3172  std::vector<StringRef> Strings;3173  for (const Init *I : List->getElements()) {3174    if (const auto *SI = dyn_cast<StringInit>(I))3175      Strings.push_back(SI->getValue());3176    else3177      PrintFatalError(getLoc(),3178                      Twine("Record `") + getName() + "', field `" + FieldName +3179                          "' exists but does not have a list of strings value: " +3180                          I->getAsString());3181  }3182  return Strings;3183}3184 3185const Record *Record::getValueAsDef(StringRef FieldName) const {3186  const Init *I = getValueInit(FieldName);3187  if (const auto *DI = dyn_cast<DefInit>(I))3188    return DI->getDef();3189  PrintFatalError(getLoc(), "Record `" + getName() + "', field `" +3190    FieldName + "' does not have a def initializer!");3191}3192 3193const Record *Record::getValueAsOptionalDef(StringRef FieldName) const {3194  const Init *I = getValueInit(FieldName);3195  if (const auto *DI = dyn_cast<DefInit>(I))3196    return DI->getDef();3197  if (isa<UnsetInit>(I))3198    return nullptr;3199  PrintFatalError(getLoc(), "Record `" + getName() + "', field `" +3200    FieldName + "' does not have either a def initializer or '?'!");3201}3202 3203bool Record::getValueAsBit(StringRef FieldName) const {3204  const Init *I = getValueInit(FieldName);3205  if (const auto *BI = dyn_cast<BitInit>(I))3206    return BI->getValue();3207  PrintFatalError(getLoc(), "Record `" + getName() + "', field `" +3208    FieldName + "' does not have a bit initializer!");3209}3210 3211bool Record::getValueAsBitOrUnset(StringRef FieldName, bool &Unset) const {3212  const Init *I = getValueInit(FieldName);3213  if (isa<UnsetInit>(I)) {3214    Unset = true;3215    return false;3216  }3217  Unset = false;3218  if (const auto *BI = dyn_cast<BitInit>(I))3219    return BI->getValue();3220  PrintFatalError(getLoc(), "Record `" + getName() + "', field `" +3221    FieldName + "' does not have a bit initializer!");3222}3223 3224const DagInit *Record::getValueAsDag(StringRef FieldName) const {3225  const Init *I = getValueInit(FieldName);3226  if (const auto *DI = dyn_cast<DagInit>(I))3227    return DI;3228  PrintFatalError(getLoc(), "Record `" + getName() + "', field `" +3229    FieldName + "' does not have a dag initializer!");3230}3231 3232// Check all record assertions: For each one, resolve the condition3233// and message, then call CheckAssert().3234// Note: The condition and message are probably already resolved,3235//       but resolving again allows calls before records are resolved.3236void Record::checkRecordAssertions() {3237  RecordResolver R(*this);3238  R.setFinal(true);3239 3240  bool AnyFailed = false;3241  for (const auto &Assertion : getAssertions()) {3242    const Init *Condition = Assertion.Condition->resolveReferences(R);3243    const Init *Message = Assertion.Message->resolveReferences(R);3244    AnyFailed |= CheckAssert(Assertion.Loc, Condition, Message);3245  }3246 3247  if (!AnyFailed)3248    return;3249 3250  // If any of the record assertions failed, print some context that will3251  // help see where the record that caused these assert failures is defined.3252  PrintError(this, "assertion failed in this record");3253}3254 3255void Record::emitRecordDumps() {3256  RecordResolver R(*this);3257  R.setFinal(true);3258 3259  for (const DumpInfo &Dump : getDumps()) {3260    const Init *Message = Dump.Message->resolveReferences(R);3261    dumpMessage(Dump.Loc, Message);3262  }3263}3264 3265// Report a warning if the record has unused template arguments.3266void Record::checkUnusedTemplateArgs() {3267  for (const Init *TA : getTemplateArgs()) {3268    const RecordVal *Arg = getValue(TA);3269    if (!Arg->isUsed())3270      PrintWarning(Arg->getLoc(),3271                   "unused template argument: " + Twine(Arg->getName()));3272  }3273}3274 3275RecordKeeper::RecordKeeper()3276    : Impl(std::make_unique<detail::RecordKeeperImpl>(*this)),3277      Timer(std::make_unique<TGTimer>()) {}3278 3279RecordKeeper::~RecordKeeper() = default;3280 3281#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)3282LLVM_DUMP_METHOD void RecordKeeper::dump() const { errs() << *this; }3283#endif3284 3285raw_ostream &llvm::operator<<(raw_ostream &OS, const RecordKeeper &RK) {3286  OS << "------------- Classes -----------------\n";3287  for (const auto &[_, C] : RK.getClasses())3288    OS << "class " << *C;3289 3290  OS << "------------- Defs -----------------\n";3291  for (const auto &[_, D] : RK.getDefs())3292    OS << "def " << *D;3293  return OS;3294}3295 3296/// GetNewAnonymousName - Generate a unique anonymous name that can be used as3297/// an identifier.3298const Init *RecordKeeper::getNewAnonymousName() {3299  return AnonymousNameInit::get(*this, getImpl().AnonCounter++);3300}3301 3302ArrayRef<const Record *>3303RecordKeeper::getAllDerivedDefinitions(StringRef ClassName) const {3304  // We cache the record vectors for single classes. Many backends request3305  // the same vectors multiple times.3306  auto [Iter, Inserted] = Cache.try_emplace(ClassName.str());3307  if (Inserted)3308    Iter->second = getAllDerivedDefinitions(ArrayRef(ClassName));3309  return Iter->second;3310}3311 3312std::vector<const Record *>3313RecordKeeper::getAllDerivedDefinitions(ArrayRef<StringRef> ClassNames) const {3314  SmallVector<const Record *, 2> ClassRecs;3315  std::vector<const Record *> Defs;3316 3317  assert(ClassNames.size() > 0 && "At least one class must be passed.");3318  for (StringRef ClassName : ClassNames) {3319    const Record *Class = getClass(ClassName);3320    if (!Class)3321      PrintFatalError("The class '" + ClassName + "' is not defined\n");3322    ClassRecs.push_back(Class);3323  }3324 3325  for (const auto &OneDef : getDefs()) {3326    if (all_of(ClassRecs, [&OneDef](const Record *Class) {3327          return OneDef.second->isSubClassOf(Class);3328        }))3329      Defs.push_back(OneDef.second.get());3330  }3331  llvm::sort(Defs, LessRecord());3332  return Defs;3333}3334 3335ArrayRef<const Record *>3336RecordKeeper::getAllDerivedDefinitionsIfDefined(StringRef ClassName) const {3337  if (getClass(ClassName))3338    return getAllDerivedDefinitions(ClassName);3339  return Cache[""];3340}3341 3342void RecordKeeper::dumpAllocationStats(raw_ostream &OS) const {3343  Impl->dumpAllocationStats(OS);3344}3345 3346const Init *MapResolver::resolve(const Init *VarName) {3347  auto It = Map.find(VarName);3348  if (It == Map.end())3349    return nullptr;3350 3351  const Init *I = It->second.V;3352 3353  if (!It->second.Resolved && Map.size() > 1) {3354    // Resolve mutual references among the mapped variables, but prevent3355    // infinite recursion.3356    Map.erase(It);3357    I = I->resolveReferences(*this);3358    Map[VarName] = {I, true};3359  }3360 3361  return I;3362}3363 3364const Init *RecordResolver::resolve(const Init *VarName) {3365  const Init *Val = Cache.lookup(VarName);3366  if (Val)3367    return Val;3368 3369  if (llvm::is_contained(Stack, VarName))3370    return nullptr; // prevent infinite recursion3371 3372  if (const RecordVal *RV = getCurrentRecord()->getValue(VarName)) {3373    if (!isa<UnsetInit>(RV->getValue())) {3374      Val = RV->getValue();3375      Stack.push_back(VarName);3376      Val = Val->resolveReferences(*this);3377      Stack.pop_back();3378    }3379  } else if (Name && VarName == getCurrentRecord()->getNameInit()) {3380    Stack.push_back(VarName);3381    Val = Name->resolveReferences(*this);3382    Stack.pop_back();3383  }3384 3385  Cache[VarName] = Val;3386  return Val;3387}3388 3389const Init *TrackUnresolvedResolver::resolve(const Init *VarName) {3390  const Init *I = nullptr;3391 3392  if (R) {3393    I = R->resolve(VarName);3394    if (I && !FoundUnresolved) {3395      // Do not recurse into the resolved initializer, as that would change3396      // the behavior of the resolver we're delegating, but do check to see3397      // if there are unresolved variables remaining.3398      TrackUnresolvedResolver Sub;3399      I->resolveReferences(Sub);3400      FoundUnresolved |= Sub.FoundUnresolved;3401    }3402  }3403 3404  if (!I)3405    FoundUnresolved = true;3406  return I;3407}3408 3409const Init *HasReferenceResolver::resolve(const Init *VarName) {3410  if (VarName == VarNameToTrack)3411    Found = true;3412  return nullptr;3413}3414