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