10b57cec5SDimitry Andric //===- Record.cpp - Record implementation ---------------------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // Implement the tablegen record classes. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 131fd87a68SDimitry Andric #include "llvm/TableGen/Record.h" 140b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h" 150b57cec5SDimitry Andric #include "llvm/ADT/DenseMap.h" 160b57cec5SDimitry Andric #include "llvm/ADT/FoldingSet.h" 170b57cec5SDimitry Andric #include "llvm/ADT/SmallString.h" 180b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h" 190b57cec5SDimitry Andric #include "llvm/ADT/StringExtras.h" 200b57cec5SDimitry Andric #include "llvm/ADT/StringMap.h" 210b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h" 220b57cec5SDimitry Andric #include "llvm/Config/llvm-config.h" 230b57cec5SDimitry Andric #include "llvm/Support/Allocator.h" 240b57cec5SDimitry Andric #include "llvm/Support/Casting.h" 250b57cec5SDimitry Andric #include "llvm/Support/Compiler.h" 260b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h" 27bdd1243dSDimitry Andric #include "llvm/Support/MathExtras.h" 280b57cec5SDimitry Andric #include "llvm/Support/SMLoc.h" 290b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 300b57cec5SDimitry Andric #include "llvm/TableGen/Error.h" 310b57cec5SDimitry Andric #include <cassert> 320b57cec5SDimitry Andric #include <cstdint> 330b57cec5SDimitry Andric #include <map> 341fd87a68SDimitry Andric #include <memory> 350b57cec5SDimitry Andric #include <string> 360b57cec5SDimitry Andric #include <utility> 370b57cec5SDimitry Andric #include <vector> 380b57cec5SDimitry Andric 390b57cec5SDimitry Andric using namespace llvm; 400b57cec5SDimitry Andric 410b57cec5SDimitry Andric #define DEBUG_TYPE "tblgen-records" 420b57cec5SDimitry Andric 43349cc55cSDimitry Andric //===----------------------------------------------------------------------===// 44349cc55cSDimitry Andric // Context 45349cc55cSDimitry Andric //===----------------------------------------------------------------------===// 46349cc55cSDimitry Andric 47349cc55cSDimitry Andric namespace llvm { 48349cc55cSDimitry Andric namespace detail { 4981ad6265SDimitry Andric /// This class represents the internal implementation of the RecordKeeper. 5081ad6265SDimitry Andric /// It contains all of the contextual static state of the Record classes. It is 5181ad6265SDimitry Andric /// kept out-of-line to simplify dependencies, and also make it easier for 5281ad6265SDimitry Andric /// internal classes to access the uniquer state of the keeper. 5381ad6265SDimitry Andric struct RecordKeeperImpl { 5481ad6265SDimitry Andric RecordKeeperImpl(RecordKeeper &RK) 5581ad6265SDimitry Andric : SharedBitRecTy(RK), SharedIntRecTy(RK), SharedStringRecTy(RK), 5681ad6265SDimitry Andric SharedDagRecTy(RK), AnyRecord(RK, 0), TheUnsetInit(RK), 5781ad6265SDimitry Andric TrueBitInit(true, &SharedBitRecTy), 58349cc55cSDimitry Andric FalseBitInit(false, &SharedBitRecTy), StringInitStringPool(Allocator), 5981ad6265SDimitry Andric StringInitCodePool(Allocator), AnonCounter(0), LastRecordID(0) {} 60349cc55cSDimitry Andric 61349cc55cSDimitry Andric BumpPtrAllocator Allocator; 62349cc55cSDimitry Andric std::vector<BitsRecTy *> SharedBitsRecTys; 63349cc55cSDimitry Andric BitRecTy SharedBitRecTy; 64349cc55cSDimitry Andric IntRecTy SharedIntRecTy; 65349cc55cSDimitry Andric StringRecTy SharedStringRecTy; 66349cc55cSDimitry Andric DagRecTy SharedDagRecTy; 67349cc55cSDimitry Andric 68349cc55cSDimitry Andric RecordRecTy AnyRecord; 69349cc55cSDimitry Andric UnsetInit TheUnsetInit; 70349cc55cSDimitry Andric BitInit TrueBitInit; 71349cc55cSDimitry Andric BitInit FalseBitInit; 72349cc55cSDimitry Andric 7306c3fb27SDimitry Andric FoldingSet<ArgumentInit> TheArgumentInitPool; 74349cc55cSDimitry Andric FoldingSet<BitsInit> TheBitsInitPool; 75349cc55cSDimitry Andric std::map<int64_t, IntInit *> TheIntInitPool; 76349cc55cSDimitry Andric StringMap<StringInit *, BumpPtrAllocator &> StringInitStringPool; 77349cc55cSDimitry Andric StringMap<StringInit *, BumpPtrAllocator &> StringInitCodePool; 78349cc55cSDimitry Andric FoldingSet<ListInit> TheListInitPool; 79349cc55cSDimitry Andric FoldingSet<UnOpInit> TheUnOpInitPool; 80349cc55cSDimitry Andric FoldingSet<BinOpInit> TheBinOpInitPool; 81349cc55cSDimitry Andric FoldingSet<TernOpInit> TheTernOpInitPool; 82349cc55cSDimitry Andric FoldingSet<FoldOpInit> TheFoldOpInitPool; 83349cc55cSDimitry Andric FoldingSet<IsAOpInit> TheIsAOpInitPool; 8481ad6265SDimitry Andric FoldingSet<ExistsOpInit> TheExistsOpInitPool; 85349cc55cSDimitry Andric DenseMap<std::pair<RecTy *, Init *>, VarInit *> TheVarInitPool; 86349cc55cSDimitry Andric DenseMap<std::pair<TypedInit *, unsigned>, VarBitInit *> TheVarBitInitPool; 87349cc55cSDimitry Andric FoldingSet<VarDefInit> TheVarDefInitPool; 88349cc55cSDimitry Andric DenseMap<std::pair<Init *, StringInit *>, FieldInit *> TheFieldInitPool; 89349cc55cSDimitry Andric FoldingSet<CondOpInit> TheCondOpInitPool; 90349cc55cSDimitry Andric FoldingSet<DagInit> TheDagInitPool; 9181ad6265SDimitry Andric FoldingSet<RecordRecTy> RecordTypePool; 92349cc55cSDimitry Andric 9381ad6265SDimitry Andric unsigned AnonCounter; 94349cc55cSDimitry Andric unsigned LastRecordID; 95349cc55cSDimitry Andric }; 96349cc55cSDimitry Andric } // namespace detail 97349cc55cSDimitry Andric } // namespace llvm 98349cc55cSDimitry Andric 990b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 1000b57cec5SDimitry Andric // Type implementations 1010b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 1020b57cec5SDimitry Andric 1030b57cec5SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 1040b57cec5SDimitry Andric LLVM_DUMP_METHOD void RecTy::dump() const { print(errs()); } 1050b57cec5SDimitry Andric #endif 1060b57cec5SDimitry Andric 1070b57cec5SDimitry Andric ListRecTy *RecTy::getListTy() { 1080b57cec5SDimitry Andric if (!ListTy) 10981ad6265SDimitry Andric ListTy = new (RK.getImpl().Allocator) ListRecTy(this); 1100b57cec5SDimitry Andric return ListTy; 1110b57cec5SDimitry Andric } 1120b57cec5SDimitry Andric 1130b57cec5SDimitry Andric bool RecTy::typeIsConvertibleTo(const RecTy *RHS) const { 1140b57cec5SDimitry Andric assert(RHS && "NULL pointer"); 1150b57cec5SDimitry Andric return Kind == RHS->getRecTyKind(); 1160b57cec5SDimitry Andric } 1170b57cec5SDimitry Andric 1180b57cec5SDimitry Andric bool RecTy::typeIsA(const RecTy *RHS) const { return this == RHS; } 1190b57cec5SDimitry Andric 12081ad6265SDimitry Andric BitRecTy *BitRecTy::get(RecordKeeper &RK) { 12181ad6265SDimitry Andric return &RK.getImpl().SharedBitRecTy; 12281ad6265SDimitry Andric } 123349cc55cSDimitry Andric 1240b57cec5SDimitry Andric bool BitRecTy::typeIsConvertibleTo(const RecTy *RHS) const{ 1250b57cec5SDimitry Andric if (RecTy::typeIsConvertibleTo(RHS) || RHS->getRecTyKind() == IntRecTyKind) 1260b57cec5SDimitry Andric return true; 1270b57cec5SDimitry Andric if (const BitsRecTy *BitsTy = dyn_cast<BitsRecTy>(RHS)) 1280b57cec5SDimitry Andric return BitsTy->getNumBits() == 1; 1290b57cec5SDimitry Andric return false; 1300b57cec5SDimitry Andric } 1310b57cec5SDimitry Andric 13281ad6265SDimitry Andric BitsRecTy *BitsRecTy::get(RecordKeeper &RK, unsigned Sz) { 13381ad6265SDimitry Andric detail::RecordKeeperImpl &RKImpl = RK.getImpl(); 13481ad6265SDimitry Andric if (Sz >= RKImpl.SharedBitsRecTys.size()) 13581ad6265SDimitry Andric RKImpl.SharedBitsRecTys.resize(Sz + 1); 13681ad6265SDimitry Andric BitsRecTy *&Ty = RKImpl.SharedBitsRecTys[Sz]; 1370b57cec5SDimitry Andric if (!Ty) 13881ad6265SDimitry Andric Ty = new (RKImpl.Allocator) BitsRecTy(RK, Sz); 1390b57cec5SDimitry Andric return Ty; 1400b57cec5SDimitry Andric } 1410b57cec5SDimitry Andric 1420b57cec5SDimitry Andric std::string BitsRecTy::getAsString() const { 1430b57cec5SDimitry Andric return "bits<" + utostr(Size) + ">"; 1440b57cec5SDimitry Andric } 1450b57cec5SDimitry Andric 1460b57cec5SDimitry Andric bool BitsRecTy::typeIsConvertibleTo(const RecTy *RHS) const { 1470b57cec5SDimitry Andric if (RecTy::typeIsConvertibleTo(RHS)) //argument and the sender are same type 1480b57cec5SDimitry Andric return cast<BitsRecTy>(RHS)->Size == Size; 1490b57cec5SDimitry Andric RecTyKind kind = RHS->getRecTyKind(); 1500b57cec5SDimitry Andric return (kind == BitRecTyKind && Size == 1) || (kind == IntRecTyKind); 1510b57cec5SDimitry Andric } 1520b57cec5SDimitry Andric 15381ad6265SDimitry Andric IntRecTy *IntRecTy::get(RecordKeeper &RK) { 15481ad6265SDimitry Andric return &RK.getImpl().SharedIntRecTy; 15581ad6265SDimitry Andric } 156349cc55cSDimitry Andric 1570b57cec5SDimitry Andric bool IntRecTy::typeIsConvertibleTo(const RecTy *RHS) const { 1580b57cec5SDimitry Andric RecTyKind kind = RHS->getRecTyKind(); 1590b57cec5SDimitry Andric return kind==BitRecTyKind || kind==BitsRecTyKind || kind==IntRecTyKind; 1600b57cec5SDimitry Andric } 1610b57cec5SDimitry Andric 16281ad6265SDimitry Andric StringRecTy *StringRecTy::get(RecordKeeper &RK) { 16381ad6265SDimitry Andric return &RK.getImpl().SharedStringRecTy; 16481ad6265SDimitry Andric } 165349cc55cSDimitry Andric 1660b57cec5SDimitry Andric std::string StringRecTy::getAsString() const { 1670b57cec5SDimitry Andric return "string"; 1680b57cec5SDimitry Andric } 1690b57cec5SDimitry Andric 1700b57cec5SDimitry Andric bool StringRecTy::typeIsConvertibleTo(const RecTy *RHS) const { 1710b57cec5SDimitry Andric RecTyKind Kind = RHS->getRecTyKind(); 172e8d8bef9SDimitry Andric return Kind == StringRecTyKind; 1730b57cec5SDimitry Andric } 1740b57cec5SDimitry Andric 1750b57cec5SDimitry Andric std::string ListRecTy::getAsString() const { 176e8d8bef9SDimitry Andric return "list<" + ElementTy->getAsString() + ">"; 1770b57cec5SDimitry Andric } 1780b57cec5SDimitry Andric 1790b57cec5SDimitry Andric bool ListRecTy::typeIsConvertibleTo(const RecTy *RHS) const { 1800b57cec5SDimitry Andric if (const auto *ListTy = dyn_cast<ListRecTy>(RHS)) 181e8d8bef9SDimitry Andric return ElementTy->typeIsConvertibleTo(ListTy->getElementType()); 1820b57cec5SDimitry Andric return false; 1830b57cec5SDimitry Andric } 1840b57cec5SDimitry Andric 1850b57cec5SDimitry Andric bool ListRecTy::typeIsA(const RecTy *RHS) const { 1860b57cec5SDimitry Andric if (const ListRecTy *RHSl = dyn_cast<ListRecTy>(RHS)) 1870b57cec5SDimitry Andric return getElementType()->typeIsA(RHSl->getElementType()); 1880b57cec5SDimitry Andric return false; 1890b57cec5SDimitry Andric } 1900b57cec5SDimitry Andric 19181ad6265SDimitry Andric DagRecTy *DagRecTy::get(RecordKeeper &RK) { 19281ad6265SDimitry Andric return &RK.getImpl().SharedDagRecTy; 19381ad6265SDimitry Andric } 194349cc55cSDimitry Andric 1950b57cec5SDimitry Andric std::string DagRecTy::getAsString() const { 1960b57cec5SDimitry Andric return "dag"; 1970b57cec5SDimitry Andric } 1980b57cec5SDimitry Andric 1990b57cec5SDimitry Andric static void ProfileRecordRecTy(FoldingSetNodeID &ID, 2000b57cec5SDimitry Andric ArrayRef<Record *> Classes) { 2010b57cec5SDimitry Andric ID.AddInteger(Classes.size()); 2020b57cec5SDimitry Andric for (Record *R : Classes) 2030b57cec5SDimitry Andric ID.AddPointer(R); 2040b57cec5SDimitry Andric } 2050b57cec5SDimitry Andric 20681ad6265SDimitry Andric RecordRecTy *RecordRecTy::get(RecordKeeper &RK, 20781ad6265SDimitry Andric ArrayRef<Record *> UnsortedClasses) { 20881ad6265SDimitry Andric detail::RecordKeeperImpl &RKImpl = RK.getImpl(); 209349cc55cSDimitry Andric if (UnsortedClasses.empty()) 21081ad6265SDimitry Andric return &RKImpl.AnyRecord; 2110b57cec5SDimitry Andric 21281ad6265SDimitry Andric FoldingSet<RecordRecTy> &ThePool = RKImpl.RecordTypePool; 2130b57cec5SDimitry Andric 2140b57cec5SDimitry Andric SmallVector<Record *, 4> Classes(UnsortedClasses.begin(), 2150b57cec5SDimitry Andric UnsortedClasses.end()); 2160b57cec5SDimitry Andric llvm::sort(Classes, [](Record *LHS, Record *RHS) { 2170b57cec5SDimitry Andric return LHS->getNameInitAsString() < RHS->getNameInitAsString(); 2180b57cec5SDimitry Andric }); 2190b57cec5SDimitry Andric 2200b57cec5SDimitry Andric FoldingSetNodeID ID; 2210b57cec5SDimitry Andric ProfileRecordRecTy(ID, Classes); 2220b57cec5SDimitry Andric 2230b57cec5SDimitry Andric void *IP = nullptr; 2240b57cec5SDimitry Andric if (RecordRecTy *Ty = ThePool.FindNodeOrInsertPos(ID, IP)) 2250b57cec5SDimitry Andric return Ty; 2260b57cec5SDimitry Andric 2270b57cec5SDimitry Andric #ifndef NDEBUG 2280b57cec5SDimitry Andric // Check for redundancy. 2290b57cec5SDimitry Andric for (unsigned i = 0; i < Classes.size(); ++i) { 2300b57cec5SDimitry Andric for (unsigned j = 0; j < Classes.size(); ++j) { 2310b57cec5SDimitry Andric assert(i == j || !Classes[i]->isSubClassOf(Classes[j])); 2320b57cec5SDimitry Andric } 2330b57cec5SDimitry Andric assert(&Classes[0]->getRecords() == &Classes[i]->getRecords()); 2340b57cec5SDimitry Andric } 2350b57cec5SDimitry Andric #endif 2360b57cec5SDimitry Andric 23781ad6265SDimitry Andric void *Mem = RKImpl.Allocator.Allocate( 238349cc55cSDimitry Andric totalSizeToAlloc<Record *>(Classes.size()), alignof(RecordRecTy)); 23981ad6265SDimitry Andric RecordRecTy *Ty = new (Mem) RecordRecTy(RK, Classes.size()); 2400b57cec5SDimitry Andric std::uninitialized_copy(Classes.begin(), Classes.end(), 2410b57cec5SDimitry Andric Ty->getTrailingObjects<Record *>()); 2420b57cec5SDimitry Andric ThePool.InsertNode(Ty, IP); 2430b57cec5SDimitry Andric return Ty; 2440b57cec5SDimitry Andric } 24581ad6265SDimitry Andric RecordRecTy *RecordRecTy::get(Record *Class) { 24681ad6265SDimitry Andric assert(Class && "unexpected null class"); 24781ad6265SDimitry Andric return get(Class->getRecords(), Class); 24881ad6265SDimitry Andric } 2490b57cec5SDimitry Andric 2500b57cec5SDimitry Andric void RecordRecTy::Profile(FoldingSetNodeID &ID) const { 2510b57cec5SDimitry Andric ProfileRecordRecTy(ID, getClasses()); 2520b57cec5SDimitry Andric } 2530b57cec5SDimitry Andric 2540b57cec5SDimitry Andric std::string RecordRecTy::getAsString() const { 2550b57cec5SDimitry Andric if (NumClasses == 1) 2560b57cec5SDimitry Andric return getClasses()[0]->getNameInitAsString(); 2570b57cec5SDimitry Andric 2580b57cec5SDimitry Andric std::string Str = "{"; 2590b57cec5SDimitry Andric bool First = true; 2600b57cec5SDimitry Andric for (Record *R : getClasses()) { 2610b57cec5SDimitry Andric if (!First) 2620b57cec5SDimitry Andric Str += ", "; 2630b57cec5SDimitry Andric First = false; 2640b57cec5SDimitry Andric Str += R->getNameInitAsString(); 2650b57cec5SDimitry Andric } 2660b57cec5SDimitry Andric Str += "}"; 2670b57cec5SDimitry Andric return Str; 2680b57cec5SDimitry Andric } 2690b57cec5SDimitry Andric 2700b57cec5SDimitry Andric bool RecordRecTy::isSubClassOf(Record *Class) const { 2710b57cec5SDimitry Andric return llvm::any_of(getClasses(), [Class](Record *MySuperClass) { 2720b57cec5SDimitry Andric return MySuperClass == Class || 2730b57cec5SDimitry Andric MySuperClass->isSubClassOf(Class); 2740b57cec5SDimitry Andric }); 2750b57cec5SDimitry Andric } 2760b57cec5SDimitry Andric 2770b57cec5SDimitry Andric bool RecordRecTy::typeIsConvertibleTo(const RecTy *RHS) const { 2780b57cec5SDimitry Andric if (this == RHS) 2790b57cec5SDimitry Andric return true; 2800b57cec5SDimitry Andric 2810b57cec5SDimitry Andric const RecordRecTy *RTy = dyn_cast<RecordRecTy>(RHS); 2820b57cec5SDimitry Andric if (!RTy) 2830b57cec5SDimitry Andric return false; 2840b57cec5SDimitry Andric 2850b57cec5SDimitry Andric return llvm::all_of(RTy->getClasses(), [this](Record *TargetClass) { 2860b57cec5SDimitry Andric return isSubClassOf(TargetClass); 2870b57cec5SDimitry Andric }); 2880b57cec5SDimitry Andric } 2890b57cec5SDimitry Andric 2900b57cec5SDimitry Andric bool RecordRecTy::typeIsA(const RecTy *RHS) const { 2910b57cec5SDimitry Andric return typeIsConvertibleTo(RHS); 2920b57cec5SDimitry Andric } 2930b57cec5SDimitry Andric 2940b57cec5SDimitry Andric static RecordRecTy *resolveRecordTypes(RecordRecTy *T1, RecordRecTy *T2) { 2950b57cec5SDimitry Andric SmallVector<Record *, 4> CommonSuperClasses; 296e8d8bef9SDimitry Andric SmallVector<Record *, 4> Stack(T1->classes_begin(), T1->classes_end()); 2970b57cec5SDimitry Andric 2980b57cec5SDimitry Andric while (!Stack.empty()) { 299e8d8bef9SDimitry Andric Record *R = Stack.pop_back_val(); 3000b57cec5SDimitry Andric 3010b57cec5SDimitry Andric if (T2->isSubClassOf(R)) { 3020b57cec5SDimitry Andric CommonSuperClasses.push_back(R); 3030b57cec5SDimitry Andric } else { 3040b57cec5SDimitry Andric R->getDirectSuperClasses(Stack); 3050b57cec5SDimitry Andric } 3060b57cec5SDimitry Andric } 3070b57cec5SDimitry Andric 30881ad6265SDimitry Andric return RecordRecTy::get(T1->getRecordKeeper(), CommonSuperClasses); 3090b57cec5SDimitry Andric } 3100b57cec5SDimitry Andric 3110b57cec5SDimitry Andric RecTy *llvm::resolveTypes(RecTy *T1, RecTy *T2) { 3120b57cec5SDimitry Andric if (T1 == T2) 3130b57cec5SDimitry Andric return T1; 3140b57cec5SDimitry Andric 3150b57cec5SDimitry Andric if (RecordRecTy *RecTy1 = dyn_cast<RecordRecTy>(T1)) { 3160b57cec5SDimitry Andric if (RecordRecTy *RecTy2 = dyn_cast<RecordRecTy>(T2)) 3170b57cec5SDimitry Andric return resolveRecordTypes(RecTy1, RecTy2); 3180b57cec5SDimitry Andric } 3190b57cec5SDimitry Andric 32006c3fb27SDimitry Andric assert(T1 != nullptr && "Invalid record type"); 3210b57cec5SDimitry Andric if (T1->typeIsConvertibleTo(T2)) 3220b57cec5SDimitry Andric return T2; 32306c3fb27SDimitry Andric 32406c3fb27SDimitry Andric assert(T2 != nullptr && "Invalid record type"); 3250b57cec5SDimitry Andric if (T2->typeIsConvertibleTo(T1)) 3260b57cec5SDimitry Andric return T1; 3270b57cec5SDimitry Andric 3280b57cec5SDimitry Andric if (ListRecTy *ListTy1 = dyn_cast<ListRecTy>(T1)) { 3290b57cec5SDimitry Andric if (ListRecTy *ListTy2 = dyn_cast<ListRecTy>(T2)) { 3300b57cec5SDimitry Andric RecTy* NewType = resolveTypes(ListTy1->getElementType(), 3310b57cec5SDimitry Andric ListTy2->getElementType()); 3320b57cec5SDimitry Andric if (NewType) 3330b57cec5SDimitry Andric return NewType->getListTy(); 3340b57cec5SDimitry Andric } 3350b57cec5SDimitry Andric } 3360b57cec5SDimitry Andric 3370b57cec5SDimitry Andric return nullptr; 3380b57cec5SDimitry Andric } 3390b57cec5SDimitry Andric 3400b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 3410b57cec5SDimitry Andric // Initializer implementations 3420b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 3430b57cec5SDimitry Andric 3440b57cec5SDimitry Andric void Init::anchor() {} 3450b57cec5SDimitry Andric 3460b57cec5SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 3470b57cec5SDimitry Andric LLVM_DUMP_METHOD void Init::dump() const { return print(errs()); } 3480b57cec5SDimitry Andric #endif 3490b57cec5SDimitry Andric 35081ad6265SDimitry Andric RecordKeeper &Init::getRecordKeeper() const { 35181ad6265SDimitry Andric if (auto *TyInit = dyn_cast<TypedInit>(this)) 35281ad6265SDimitry Andric return TyInit->getType()->getRecordKeeper(); 35306c3fb27SDimitry Andric if (auto *ArgInit = dyn_cast<ArgumentInit>(this)) 35406c3fb27SDimitry Andric return ArgInit->getRecordKeeper(); 35581ad6265SDimitry Andric return cast<UnsetInit>(this)->getRecordKeeper(); 35681ad6265SDimitry Andric } 35781ad6265SDimitry Andric 35881ad6265SDimitry Andric UnsetInit *UnsetInit::get(RecordKeeper &RK) { 35981ad6265SDimitry Andric return &RK.getImpl().TheUnsetInit; 36081ad6265SDimitry Andric } 3610b57cec5SDimitry Andric 3620b57cec5SDimitry Andric Init *UnsetInit::getCastTo(RecTy *Ty) const { 3630b57cec5SDimitry Andric return const_cast<UnsetInit *>(this); 3640b57cec5SDimitry Andric } 3650b57cec5SDimitry Andric 3660b57cec5SDimitry Andric Init *UnsetInit::convertInitializerTo(RecTy *Ty) const { 3670b57cec5SDimitry Andric return const_cast<UnsetInit *>(this); 3680b57cec5SDimitry Andric } 3690b57cec5SDimitry Andric 37006c3fb27SDimitry Andric static void ProfileArgumentInit(FoldingSetNodeID &ID, Init *Value, 37106c3fb27SDimitry Andric ArgAuxType Aux) { 37206c3fb27SDimitry Andric auto I = Aux.index(); 37306c3fb27SDimitry Andric ID.AddInteger(I); 37406c3fb27SDimitry Andric if (I == ArgumentInit::Positional) 37506c3fb27SDimitry Andric ID.AddInteger(std::get<ArgumentInit::Positional>(Aux)); 37606c3fb27SDimitry Andric if (I == ArgumentInit::Named) 37706c3fb27SDimitry Andric ID.AddPointer(std::get<ArgumentInit::Named>(Aux)); 37806c3fb27SDimitry Andric ID.AddPointer(Value); 37906c3fb27SDimitry Andric } 38006c3fb27SDimitry Andric 38106c3fb27SDimitry Andric void ArgumentInit::Profile(FoldingSetNodeID &ID) const { 38206c3fb27SDimitry Andric ProfileArgumentInit(ID, Value, Aux); 38306c3fb27SDimitry Andric } 38406c3fb27SDimitry Andric 38506c3fb27SDimitry Andric ArgumentInit *ArgumentInit::get(Init *Value, ArgAuxType Aux) { 38606c3fb27SDimitry Andric FoldingSetNodeID ID; 38706c3fb27SDimitry Andric ProfileArgumentInit(ID, Value, Aux); 38806c3fb27SDimitry Andric 38906c3fb27SDimitry Andric RecordKeeper &RK = Value->getRecordKeeper(); 39006c3fb27SDimitry Andric detail::RecordKeeperImpl &RKImpl = RK.getImpl(); 39106c3fb27SDimitry Andric void *IP = nullptr; 39206c3fb27SDimitry Andric if (ArgumentInit *I = RKImpl.TheArgumentInitPool.FindNodeOrInsertPos(ID, IP)) 39306c3fb27SDimitry Andric return I; 39406c3fb27SDimitry Andric 39506c3fb27SDimitry Andric ArgumentInit *I = new (RKImpl.Allocator) ArgumentInit(Value, Aux); 39606c3fb27SDimitry Andric RKImpl.TheArgumentInitPool.InsertNode(I, IP); 39706c3fb27SDimitry Andric return I; 39806c3fb27SDimitry Andric } 39906c3fb27SDimitry Andric 40006c3fb27SDimitry Andric Init *ArgumentInit::resolveReferences(Resolver &R) const { 40106c3fb27SDimitry Andric Init *NewValue = Value->resolveReferences(R); 40206c3fb27SDimitry Andric if (NewValue != Value) 40306c3fb27SDimitry Andric return cloneWithValue(NewValue); 40406c3fb27SDimitry Andric 40506c3fb27SDimitry Andric return const_cast<ArgumentInit *>(this); 40606c3fb27SDimitry Andric } 40706c3fb27SDimitry Andric 40881ad6265SDimitry Andric BitInit *BitInit::get(RecordKeeper &RK, bool V) { 40981ad6265SDimitry Andric return V ? &RK.getImpl().TrueBitInit : &RK.getImpl().FalseBitInit; 4100b57cec5SDimitry Andric } 4110b57cec5SDimitry Andric 4120b57cec5SDimitry Andric Init *BitInit::convertInitializerTo(RecTy *Ty) const { 4130b57cec5SDimitry Andric if (isa<BitRecTy>(Ty)) 4140b57cec5SDimitry Andric return const_cast<BitInit *>(this); 4150b57cec5SDimitry Andric 4160b57cec5SDimitry Andric if (isa<IntRecTy>(Ty)) 41781ad6265SDimitry Andric return IntInit::get(getRecordKeeper(), getValue()); 4180b57cec5SDimitry Andric 4190b57cec5SDimitry Andric if (auto *BRT = dyn_cast<BitsRecTy>(Ty)) { 4200b57cec5SDimitry Andric // Can only convert single bit. 4210b57cec5SDimitry Andric if (BRT->getNumBits() == 1) 42281ad6265SDimitry Andric return BitsInit::get(getRecordKeeper(), const_cast<BitInit *>(this)); 4230b57cec5SDimitry Andric } 4240b57cec5SDimitry Andric 4250b57cec5SDimitry Andric return nullptr; 4260b57cec5SDimitry Andric } 4270b57cec5SDimitry Andric 4280b57cec5SDimitry Andric static void 4290b57cec5SDimitry Andric ProfileBitsInit(FoldingSetNodeID &ID, ArrayRef<Init *> Range) { 4300b57cec5SDimitry Andric ID.AddInteger(Range.size()); 4310b57cec5SDimitry Andric 4320b57cec5SDimitry Andric for (Init *I : Range) 4330b57cec5SDimitry Andric ID.AddPointer(I); 4340b57cec5SDimitry Andric } 4350b57cec5SDimitry Andric 43681ad6265SDimitry Andric BitsInit *BitsInit::get(RecordKeeper &RK, ArrayRef<Init *> Range) { 4370b57cec5SDimitry Andric FoldingSetNodeID ID; 4380b57cec5SDimitry Andric ProfileBitsInit(ID, Range); 4390b57cec5SDimitry Andric 44081ad6265SDimitry Andric detail::RecordKeeperImpl &RKImpl = RK.getImpl(); 4410b57cec5SDimitry Andric void *IP = nullptr; 44281ad6265SDimitry Andric if (BitsInit *I = RKImpl.TheBitsInitPool.FindNodeOrInsertPos(ID, IP)) 4430b57cec5SDimitry Andric return I; 4440b57cec5SDimitry Andric 44581ad6265SDimitry Andric void *Mem = RKImpl.Allocator.Allocate(totalSizeToAlloc<Init *>(Range.size()), 44681ad6265SDimitry Andric alignof(BitsInit)); 44781ad6265SDimitry Andric BitsInit *I = new (Mem) BitsInit(RK, Range.size()); 4480b57cec5SDimitry Andric std::uninitialized_copy(Range.begin(), Range.end(), 4490b57cec5SDimitry Andric I->getTrailingObjects<Init *>()); 45081ad6265SDimitry Andric RKImpl.TheBitsInitPool.InsertNode(I, IP); 4510b57cec5SDimitry Andric return I; 4520b57cec5SDimitry Andric } 4530b57cec5SDimitry Andric 4540b57cec5SDimitry Andric void BitsInit::Profile(FoldingSetNodeID &ID) const { 455bdd1243dSDimitry Andric ProfileBitsInit(ID, ArrayRef(getTrailingObjects<Init *>(), NumBits)); 4560b57cec5SDimitry Andric } 4570b57cec5SDimitry Andric 4580b57cec5SDimitry Andric Init *BitsInit::convertInitializerTo(RecTy *Ty) const { 4590b57cec5SDimitry Andric if (isa<BitRecTy>(Ty)) { 4600b57cec5SDimitry Andric if (getNumBits() != 1) return nullptr; // Only accept if just one bit! 4610b57cec5SDimitry Andric return getBit(0); 4620b57cec5SDimitry Andric } 4630b57cec5SDimitry Andric 4640b57cec5SDimitry Andric if (auto *BRT = dyn_cast<BitsRecTy>(Ty)) { 4650b57cec5SDimitry Andric // If the number of bits is right, return it. Otherwise we need to expand 4660b57cec5SDimitry Andric // or truncate. 4670b57cec5SDimitry Andric if (getNumBits() != BRT->getNumBits()) return nullptr; 4680b57cec5SDimitry Andric return const_cast<BitsInit *>(this); 4690b57cec5SDimitry Andric } 4700b57cec5SDimitry Andric 4710b57cec5SDimitry Andric if (isa<IntRecTy>(Ty)) { 4720b57cec5SDimitry Andric int64_t Result = 0; 4730b57cec5SDimitry Andric for (unsigned i = 0, e = getNumBits(); i != e; ++i) 4740b57cec5SDimitry Andric if (auto *Bit = dyn_cast<BitInit>(getBit(i))) 4750b57cec5SDimitry Andric Result |= static_cast<int64_t>(Bit->getValue()) << i; 4760b57cec5SDimitry Andric else 4770b57cec5SDimitry Andric return nullptr; 47881ad6265SDimitry Andric return IntInit::get(getRecordKeeper(), Result); 4790b57cec5SDimitry Andric } 4800b57cec5SDimitry Andric 4810b57cec5SDimitry Andric return nullptr; 4820b57cec5SDimitry Andric } 4830b57cec5SDimitry Andric 4840b57cec5SDimitry Andric Init * 4850b57cec5SDimitry Andric BitsInit::convertInitializerBitRange(ArrayRef<unsigned> Bits) const { 4860b57cec5SDimitry Andric SmallVector<Init *, 16> NewBits(Bits.size()); 4870b57cec5SDimitry Andric 4880b57cec5SDimitry Andric for (unsigned i = 0, e = Bits.size(); i != e; ++i) { 4890b57cec5SDimitry Andric if (Bits[i] >= getNumBits()) 4900b57cec5SDimitry Andric return nullptr; 4910b57cec5SDimitry Andric NewBits[i] = getBit(Bits[i]); 4920b57cec5SDimitry Andric } 49381ad6265SDimitry Andric return BitsInit::get(getRecordKeeper(), NewBits); 4940b57cec5SDimitry Andric } 4950b57cec5SDimitry Andric 4960b57cec5SDimitry Andric bool BitsInit::isConcrete() const { 4970b57cec5SDimitry Andric for (unsigned i = 0, e = getNumBits(); i != e; ++i) { 4980b57cec5SDimitry Andric if (!getBit(i)->isConcrete()) 4990b57cec5SDimitry Andric return false; 5000b57cec5SDimitry Andric } 5010b57cec5SDimitry Andric return true; 5020b57cec5SDimitry Andric } 5030b57cec5SDimitry Andric 5040b57cec5SDimitry Andric std::string BitsInit::getAsString() const { 5050b57cec5SDimitry Andric std::string Result = "{ "; 5060b57cec5SDimitry Andric for (unsigned i = 0, e = getNumBits(); i != e; ++i) { 5070b57cec5SDimitry Andric if (i) Result += ", "; 5080b57cec5SDimitry Andric if (Init *Bit = getBit(e-i-1)) 5090b57cec5SDimitry Andric Result += Bit->getAsString(); 5100b57cec5SDimitry Andric else 5110b57cec5SDimitry Andric Result += "*"; 5120b57cec5SDimitry Andric } 5130b57cec5SDimitry Andric return Result + " }"; 5140b57cec5SDimitry Andric } 5150b57cec5SDimitry Andric 5160b57cec5SDimitry Andric // resolveReferences - If there are any field references that refer to fields 5170b57cec5SDimitry Andric // that have been filled in, we can propagate the values now. 5180b57cec5SDimitry Andric Init *BitsInit::resolveReferences(Resolver &R) const { 5190b57cec5SDimitry Andric bool Changed = false; 5200b57cec5SDimitry Andric SmallVector<Init *, 16> NewBits(getNumBits()); 5210b57cec5SDimitry Andric 5220b57cec5SDimitry Andric Init *CachedBitVarRef = nullptr; 5230b57cec5SDimitry Andric Init *CachedBitVarResolved = nullptr; 5240b57cec5SDimitry Andric 5250b57cec5SDimitry Andric for (unsigned i = 0, e = getNumBits(); i != e; ++i) { 5260b57cec5SDimitry Andric Init *CurBit = getBit(i); 5270b57cec5SDimitry Andric Init *NewBit = CurBit; 5280b57cec5SDimitry Andric 5290b57cec5SDimitry Andric if (VarBitInit *CurBitVar = dyn_cast<VarBitInit>(CurBit)) { 5300b57cec5SDimitry Andric if (CurBitVar->getBitVar() != CachedBitVarRef) { 5310b57cec5SDimitry Andric CachedBitVarRef = CurBitVar->getBitVar(); 5320b57cec5SDimitry Andric CachedBitVarResolved = CachedBitVarRef->resolveReferences(R); 5330b57cec5SDimitry Andric } 5348bcb0991SDimitry Andric assert(CachedBitVarResolved && "Unresolved bitvar reference"); 5350b57cec5SDimitry Andric NewBit = CachedBitVarResolved->getBit(CurBitVar->getBitNum()); 5360b57cec5SDimitry Andric } else { 5370b57cec5SDimitry Andric // getBit(0) implicitly converts int and bits<1> values to bit. 5380b57cec5SDimitry Andric NewBit = CurBit->resolveReferences(R)->getBit(0); 5390b57cec5SDimitry Andric } 5400b57cec5SDimitry Andric 5410b57cec5SDimitry Andric if (isa<UnsetInit>(NewBit) && R.keepUnsetBits()) 5420b57cec5SDimitry Andric NewBit = CurBit; 5430b57cec5SDimitry Andric NewBits[i] = NewBit; 5440b57cec5SDimitry Andric Changed |= CurBit != NewBit; 5450b57cec5SDimitry Andric } 5460b57cec5SDimitry Andric 5470b57cec5SDimitry Andric if (Changed) 54881ad6265SDimitry Andric return BitsInit::get(getRecordKeeper(), NewBits); 5490b57cec5SDimitry Andric 5500b57cec5SDimitry Andric return const_cast<BitsInit *>(this); 5510b57cec5SDimitry Andric } 5520b57cec5SDimitry Andric 55381ad6265SDimitry Andric IntInit *IntInit::get(RecordKeeper &RK, int64_t V) { 55481ad6265SDimitry Andric IntInit *&I = RK.getImpl().TheIntInitPool[V]; 555349cc55cSDimitry Andric if (!I) 55681ad6265SDimitry Andric I = new (RK.getImpl().Allocator) IntInit(RK, V); 5570b57cec5SDimitry Andric return I; 5580b57cec5SDimitry Andric } 5590b57cec5SDimitry Andric 5600b57cec5SDimitry Andric std::string IntInit::getAsString() const { 5610b57cec5SDimitry Andric return itostr(Value); 5620b57cec5SDimitry Andric } 5630b57cec5SDimitry Andric 5640b57cec5SDimitry Andric static bool canFitInBitfield(int64_t Value, unsigned NumBits) { 5650b57cec5SDimitry Andric // For example, with NumBits == 4, we permit Values from [-7 .. 15]. 5660b57cec5SDimitry Andric return (NumBits >= sizeof(Value) * 8) || 5670b57cec5SDimitry Andric (Value >> NumBits == 0) || (Value >> (NumBits-1) == -1); 5680b57cec5SDimitry Andric } 5690b57cec5SDimitry Andric 5700b57cec5SDimitry Andric Init *IntInit::convertInitializerTo(RecTy *Ty) const { 5710b57cec5SDimitry Andric if (isa<IntRecTy>(Ty)) 5720b57cec5SDimitry Andric return const_cast<IntInit *>(this); 5730b57cec5SDimitry Andric 5740b57cec5SDimitry Andric if (isa<BitRecTy>(Ty)) { 5750b57cec5SDimitry Andric int64_t Val = getValue(); 5760b57cec5SDimitry Andric if (Val != 0 && Val != 1) return nullptr; // Only accept 0 or 1 for a bit! 57781ad6265SDimitry Andric return BitInit::get(getRecordKeeper(), Val != 0); 5780b57cec5SDimitry Andric } 5790b57cec5SDimitry Andric 5800b57cec5SDimitry Andric if (auto *BRT = dyn_cast<BitsRecTy>(Ty)) { 5810b57cec5SDimitry Andric int64_t Value = getValue(); 5820b57cec5SDimitry Andric // Make sure this bitfield is large enough to hold the integer value. 5830b57cec5SDimitry Andric if (!canFitInBitfield(Value, BRT->getNumBits())) 5840b57cec5SDimitry Andric return nullptr; 5850b57cec5SDimitry Andric 5860b57cec5SDimitry Andric SmallVector<Init *, 16> NewBits(BRT->getNumBits()); 5870b57cec5SDimitry Andric for (unsigned i = 0; i != BRT->getNumBits(); ++i) 58881ad6265SDimitry Andric NewBits[i] = 58981ad6265SDimitry Andric BitInit::get(getRecordKeeper(), Value & ((i < 64) ? (1LL << i) : 0)); 5900b57cec5SDimitry Andric 59181ad6265SDimitry Andric return BitsInit::get(getRecordKeeper(), NewBits); 5920b57cec5SDimitry Andric } 5930b57cec5SDimitry Andric 5940b57cec5SDimitry Andric return nullptr; 5950b57cec5SDimitry Andric } 5960b57cec5SDimitry Andric 5970b57cec5SDimitry Andric Init * 5980b57cec5SDimitry Andric IntInit::convertInitializerBitRange(ArrayRef<unsigned> Bits) const { 5990b57cec5SDimitry Andric SmallVector<Init *, 16> NewBits(Bits.size()); 6000b57cec5SDimitry Andric 6010b57cec5SDimitry Andric for (unsigned i = 0, e = Bits.size(); i != e; ++i) { 6020b57cec5SDimitry Andric if (Bits[i] >= 64) 6030b57cec5SDimitry Andric return nullptr; 6040b57cec5SDimitry Andric 60581ad6265SDimitry Andric NewBits[i] = 60681ad6265SDimitry Andric BitInit::get(getRecordKeeper(), Value & (INT64_C(1) << Bits[i])); 6070b57cec5SDimitry Andric } 60881ad6265SDimitry Andric return BitsInit::get(getRecordKeeper(), NewBits); 6090b57cec5SDimitry Andric } 6100b57cec5SDimitry Andric 61181ad6265SDimitry Andric AnonymousNameInit *AnonymousNameInit::get(RecordKeeper &RK, unsigned V) { 61281ad6265SDimitry Andric return new (RK.getImpl().Allocator) AnonymousNameInit(RK, V); 613fe6060f1SDimitry Andric } 614fe6060f1SDimitry Andric 615fe6060f1SDimitry Andric StringInit *AnonymousNameInit::getNameInit() const { 61681ad6265SDimitry Andric return StringInit::get(getRecordKeeper(), getAsString()); 617fe6060f1SDimitry Andric } 618fe6060f1SDimitry Andric 619fe6060f1SDimitry Andric std::string AnonymousNameInit::getAsString() const { 620fe6060f1SDimitry Andric return "anonymous_" + utostr(Value); 621fe6060f1SDimitry Andric } 622fe6060f1SDimitry Andric 623fe6060f1SDimitry Andric Init *AnonymousNameInit::resolveReferences(Resolver &R) const { 624fe6060f1SDimitry Andric auto *Old = const_cast<Init *>(static_cast<const Init *>(this)); 625fe6060f1SDimitry Andric auto *New = R.resolve(Old); 626fe6060f1SDimitry Andric New = New ? New : Old; 627fe6060f1SDimitry Andric if (R.isFinal()) 628fe6060f1SDimitry Andric if (auto *Anonymous = dyn_cast<AnonymousNameInit>(New)) 629fe6060f1SDimitry Andric return Anonymous->getNameInit(); 630fe6060f1SDimitry Andric return New; 631fe6060f1SDimitry Andric } 632fe6060f1SDimitry Andric 63381ad6265SDimitry Andric StringInit *StringInit::get(RecordKeeper &RK, StringRef V, StringFormat Fmt) { 63481ad6265SDimitry Andric detail::RecordKeeperImpl &RKImpl = RK.getImpl(); 63581ad6265SDimitry Andric auto &InitMap = Fmt == SF_String ? RKImpl.StringInitStringPool 63681ad6265SDimitry Andric : RKImpl.StringInitCodePool; 637349cc55cSDimitry Andric auto &Entry = *InitMap.insert(std::make_pair(V, nullptr)).first; 6380b57cec5SDimitry Andric if (!Entry.second) 63981ad6265SDimitry Andric Entry.second = new (RKImpl.Allocator) StringInit(RK, Entry.getKey(), Fmt); 6400b57cec5SDimitry Andric return Entry.second; 6410b57cec5SDimitry Andric } 6420b57cec5SDimitry Andric 6430b57cec5SDimitry Andric Init *StringInit::convertInitializerTo(RecTy *Ty) const { 6440b57cec5SDimitry Andric if (isa<StringRecTy>(Ty)) 6450b57cec5SDimitry Andric return const_cast<StringInit *>(this); 6460b57cec5SDimitry Andric 6470b57cec5SDimitry Andric return nullptr; 6480b57cec5SDimitry Andric } 6490b57cec5SDimitry Andric 6500b57cec5SDimitry Andric static void ProfileListInit(FoldingSetNodeID &ID, 6510b57cec5SDimitry Andric ArrayRef<Init *> Range, 6520b57cec5SDimitry Andric RecTy *EltTy) { 6530b57cec5SDimitry Andric ID.AddInteger(Range.size()); 6540b57cec5SDimitry Andric ID.AddPointer(EltTy); 6550b57cec5SDimitry Andric 6560b57cec5SDimitry Andric for (Init *I : Range) 6570b57cec5SDimitry Andric ID.AddPointer(I); 6580b57cec5SDimitry Andric } 6590b57cec5SDimitry Andric 6600b57cec5SDimitry Andric ListInit *ListInit::get(ArrayRef<Init *> Range, RecTy *EltTy) { 6610b57cec5SDimitry Andric FoldingSetNodeID ID; 6620b57cec5SDimitry Andric ProfileListInit(ID, Range, EltTy); 6630b57cec5SDimitry Andric 66481ad6265SDimitry Andric detail::RecordKeeperImpl &RK = EltTy->getRecordKeeper().getImpl(); 6650b57cec5SDimitry Andric void *IP = nullptr; 66681ad6265SDimitry Andric if (ListInit *I = RK.TheListInitPool.FindNodeOrInsertPos(ID, IP)) 6670b57cec5SDimitry Andric return I; 6680b57cec5SDimitry Andric 6690b57cec5SDimitry Andric assert(Range.empty() || !isa<TypedInit>(Range[0]) || 6700b57cec5SDimitry Andric cast<TypedInit>(Range[0])->getType()->typeIsConvertibleTo(EltTy)); 6710b57cec5SDimitry Andric 67281ad6265SDimitry Andric void *Mem = RK.Allocator.Allocate(totalSizeToAlloc<Init *>(Range.size()), 67381ad6265SDimitry Andric alignof(ListInit)); 6740b57cec5SDimitry Andric ListInit *I = new (Mem) ListInit(Range.size(), EltTy); 6750b57cec5SDimitry Andric std::uninitialized_copy(Range.begin(), Range.end(), 6760b57cec5SDimitry Andric I->getTrailingObjects<Init *>()); 67781ad6265SDimitry Andric RK.TheListInitPool.InsertNode(I, IP); 6780b57cec5SDimitry Andric return I; 6790b57cec5SDimitry Andric } 6800b57cec5SDimitry Andric 6810b57cec5SDimitry Andric void ListInit::Profile(FoldingSetNodeID &ID) const { 6820b57cec5SDimitry Andric RecTy *EltTy = cast<ListRecTy>(getType())->getElementType(); 6830b57cec5SDimitry Andric 6840b57cec5SDimitry Andric ProfileListInit(ID, getValues(), EltTy); 6850b57cec5SDimitry Andric } 6860b57cec5SDimitry Andric 6870b57cec5SDimitry Andric Init *ListInit::convertInitializerTo(RecTy *Ty) const { 6880b57cec5SDimitry Andric if (getType() == Ty) 6890b57cec5SDimitry Andric return const_cast<ListInit*>(this); 6900b57cec5SDimitry Andric 6910b57cec5SDimitry Andric if (auto *LRT = dyn_cast<ListRecTy>(Ty)) { 6920b57cec5SDimitry Andric SmallVector<Init*, 8> Elements; 6930b57cec5SDimitry Andric Elements.reserve(getValues().size()); 6940b57cec5SDimitry Andric 6950b57cec5SDimitry Andric // Verify that all of the elements of the list are subclasses of the 6960b57cec5SDimitry Andric // appropriate class! 6970b57cec5SDimitry Andric bool Changed = false; 6980b57cec5SDimitry Andric RecTy *ElementType = LRT->getElementType(); 6990b57cec5SDimitry Andric for (Init *I : getValues()) 7000b57cec5SDimitry Andric if (Init *CI = I->convertInitializerTo(ElementType)) { 7010b57cec5SDimitry Andric Elements.push_back(CI); 7020b57cec5SDimitry Andric if (CI != I) 7030b57cec5SDimitry Andric Changed = true; 7040b57cec5SDimitry Andric } else 7050b57cec5SDimitry Andric return nullptr; 7060b57cec5SDimitry Andric 7070b57cec5SDimitry Andric if (!Changed) 7080b57cec5SDimitry Andric return const_cast<ListInit*>(this); 7090b57cec5SDimitry Andric return ListInit::get(Elements, ElementType); 7100b57cec5SDimitry Andric } 7110b57cec5SDimitry Andric 7120b57cec5SDimitry Andric return nullptr; 7130b57cec5SDimitry Andric } 7140b57cec5SDimitry Andric 7150b57cec5SDimitry Andric Record *ListInit::getElementAsRecord(unsigned i) const { 7160b57cec5SDimitry Andric assert(i < NumValues && "List element index out of range!"); 7170b57cec5SDimitry Andric DefInit *DI = dyn_cast<DefInit>(getElement(i)); 7180b57cec5SDimitry Andric if (!DI) 7190b57cec5SDimitry Andric PrintFatalError("Expected record in list!"); 7200b57cec5SDimitry Andric return DI->getDef(); 7210b57cec5SDimitry Andric } 7220b57cec5SDimitry Andric 7230b57cec5SDimitry Andric Init *ListInit::resolveReferences(Resolver &R) const { 7240b57cec5SDimitry Andric SmallVector<Init*, 8> Resolved; 7250b57cec5SDimitry Andric Resolved.reserve(size()); 7260b57cec5SDimitry Andric bool Changed = false; 7270b57cec5SDimitry Andric 7280b57cec5SDimitry Andric for (Init *CurElt : getValues()) { 7290b57cec5SDimitry Andric Init *E = CurElt->resolveReferences(R); 7300b57cec5SDimitry Andric Changed |= E != CurElt; 7310b57cec5SDimitry Andric Resolved.push_back(E); 7320b57cec5SDimitry Andric } 7330b57cec5SDimitry Andric 7340b57cec5SDimitry Andric if (Changed) 7350b57cec5SDimitry Andric return ListInit::get(Resolved, getElementType()); 7360b57cec5SDimitry Andric return const_cast<ListInit *>(this); 7370b57cec5SDimitry Andric } 7380b57cec5SDimitry Andric 739fe6060f1SDimitry Andric bool ListInit::isComplete() const { 740fe6060f1SDimitry Andric for (Init *Element : *this) { 741fe6060f1SDimitry Andric if (!Element->isComplete()) 742fe6060f1SDimitry Andric return false; 743fe6060f1SDimitry Andric } 744fe6060f1SDimitry Andric return true; 745fe6060f1SDimitry Andric } 746fe6060f1SDimitry Andric 7470b57cec5SDimitry Andric bool ListInit::isConcrete() const { 7480b57cec5SDimitry Andric for (Init *Element : *this) { 7490b57cec5SDimitry Andric if (!Element->isConcrete()) 7500b57cec5SDimitry Andric return false; 7510b57cec5SDimitry Andric } 7520b57cec5SDimitry Andric return true; 7530b57cec5SDimitry Andric } 7540b57cec5SDimitry Andric 7550b57cec5SDimitry Andric std::string ListInit::getAsString() const { 7560b57cec5SDimitry Andric std::string Result = "["; 7570b57cec5SDimitry Andric const char *sep = ""; 7580b57cec5SDimitry Andric for (Init *Element : *this) { 7590b57cec5SDimitry Andric Result += sep; 7600b57cec5SDimitry Andric sep = ", "; 7610b57cec5SDimitry Andric Result += Element->getAsString(); 7620b57cec5SDimitry Andric } 7630b57cec5SDimitry Andric return Result + "]"; 7640b57cec5SDimitry Andric } 7650b57cec5SDimitry Andric 7660b57cec5SDimitry Andric Init *OpInit::getBit(unsigned Bit) const { 76781ad6265SDimitry Andric if (getType() == BitRecTy::get(getRecordKeeper())) 7680b57cec5SDimitry Andric return const_cast<OpInit*>(this); 7690b57cec5SDimitry Andric return VarBitInit::get(const_cast<OpInit*>(this), Bit); 7700b57cec5SDimitry Andric } 7710b57cec5SDimitry Andric 7720b57cec5SDimitry Andric static void 7730b57cec5SDimitry Andric ProfileUnOpInit(FoldingSetNodeID &ID, unsigned Opcode, Init *Op, RecTy *Type) { 7740b57cec5SDimitry Andric ID.AddInteger(Opcode); 7750b57cec5SDimitry Andric ID.AddPointer(Op); 7760b57cec5SDimitry Andric ID.AddPointer(Type); 7770b57cec5SDimitry Andric } 7780b57cec5SDimitry Andric 7790b57cec5SDimitry Andric UnOpInit *UnOpInit::get(UnaryOp Opc, Init *LHS, RecTy *Type) { 7800b57cec5SDimitry Andric FoldingSetNodeID ID; 7810b57cec5SDimitry Andric ProfileUnOpInit(ID, Opc, LHS, Type); 7820b57cec5SDimitry Andric 78381ad6265SDimitry Andric detail::RecordKeeperImpl &RK = Type->getRecordKeeper().getImpl(); 7840b57cec5SDimitry Andric void *IP = nullptr; 78581ad6265SDimitry Andric if (UnOpInit *I = RK.TheUnOpInitPool.FindNodeOrInsertPos(ID, IP)) 7860b57cec5SDimitry Andric return I; 7870b57cec5SDimitry Andric 78881ad6265SDimitry Andric UnOpInit *I = new (RK.Allocator) UnOpInit(Opc, LHS, Type); 78981ad6265SDimitry Andric RK.TheUnOpInitPool.InsertNode(I, IP); 7900b57cec5SDimitry Andric return I; 7910b57cec5SDimitry Andric } 7920b57cec5SDimitry Andric 7930b57cec5SDimitry Andric void UnOpInit::Profile(FoldingSetNodeID &ID) const { 7940b57cec5SDimitry Andric ProfileUnOpInit(ID, getOpcode(), getOperand(), getType()); 7950b57cec5SDimitry Andric } 7960b57cec5SDimitry Andric 7970b57cec5SDimitry Andric Init *UnOpInit::Fold(Record *CurRec, bool IsFinal) const { 79881ad6265SDimitry Andric RecordKeeper &RK = getRecordKeeper(); 7990b57cec5SDimitry Andric switch (getOpcode()) { 8005f757f3fSDimitry Andric case REPR: 8015f757f3fSDimitry Andric if (LHS->isConcrete()) { 8025f757f3fSDimitry Andric // If it is a Record, print the full content. 8035f757f3fSDimitry Andric if (const auto *Def = dyn_cast<DefInit>(LHS)) { 8045f757f3fSDimitry Andric std::string S; 8055f757f3fSDimitry Andric raw_string_ostream OS(S); 8065f757f3fSDimitry Andric OS << *Def->getDef(); 8075f757f3fSDimitry Andric OS.flush(); 8085f757f3fSDimitry Andric return StringInit::get(RK, S); 8095f757f3fSDimitry Andric } else { 8105f757f3fSDimitry Andric // Otherwise, print the value of the variable. 8115f757f3fSDimitry Andric // 8125f757f3fSDimitry Andric // NOTE: we could recursively !repr the elements of a list, 8135f757f3fSDimitry Andric // but that could produce a lot of output when printing a 8145f757f3fSDimitry Andric // defset. 8155f757f3fSDimitry Andric return StringInit::get(RK, LHS->getAsString()); 8165f757f3fSDimitry Andric } 8175f757f3fSDimitry Andric } 8185f757f3fSDimitry Andric break; 81906c3fb27SDimitry Andric case TOLOWER: 82006c3fb27SDimitry Andric if (StringInit *LHSs = dyn_cast<StringInit>(LHS)) 82106c3fb27SDimitry Andric return StringInit::get(RK, LHSs->getValue().lower()); 82206c3fb27SDimitry Andric break; 82306c3fb27SDimitry Andric case TOUPPER: 82406c3fb27SDimitry Andric if (StringInit *LHSs = dyn_cast<StringInit>(LHS)) 82506c3fb27SDimitry Andric return StringInit::get(RK, LHSs->getValue().upper()); 82606c3fb27SDimitry Andric break; 8270b57cec5SDimitry Andric case CAST: 8280b57cec5SDimitry Andric if (isa<StringRecTy>(getType())) { 8290b57cec5SDimitry Andric if (StringInit *LHSs = dyn_cast<StringInit>(LHS)) 8300b57cec5SDimitry Andric return LHSs; 8310b57cec5SDimitry Andric 8320b57cec5SDimitry Andric if (DefInit *LHSd = dyn_cast<DefInit>(LHS)) 83381ad6265SDimitry Andric return StringInit::get(RK, LHSd->getAsString()); 8340b57cec5SDimitry Andric 83581ad6265SDimitry Andric if (IntInit *LHSi = dyn_cast_or_null<IntInit>( 83681ad6265SDimitry Andric LHS->convertInitializerTo(IntRecTy::get(RK)))) 83781ad6265SDimitry Andric return StringInit::get(RK, LHSi->getAsString()); 838e8d8bef9SDimitry Andric 8390b57cec5SDimitry Andric } else if (isa<RecordRecTy>(getType())) { 8400b57cec5SDimitry Andric if (StringInit *Name = dyn_cast<StringInit>(LHS)) { 84106c3fb27SDimitry Andric Record *D = RK.getDef(Name->getValue()); 84206c3fb27SDimitry Andric if (!D && CurRec) { 8430b57cec5SDimitry Andric // Self-references are allowed, but their resolution is delayed until 8440b57cec5SDimitry Andric // the final resolve to ensure that we get the correct type for them. 845fe6060f1SDimitry Andric auto *Anonymous = dyn_cast<AnonymousNameInit>(CurRec->getNameInit()); 846fe6060f1SDimitry Andric if (Name == CurRec->getNameInit() || 847fe6060f1SDimitry Andric (Anonymous && Name == Anonymous->getNameInit())) { 8480b57cec5SDimitry Andric if (!IsFinal) 8490b57cec5SDimitry Andric break; 8500b57cec5SDimitry Andric D = CurRec; 8510b57cec5SDimitry Andric } 8520b57cec5SDimitry Andric } 8530b57cec5SDimitry Andric 85406c3fb27SDimitry Andric auto PrintFatalErrorHelper = [CurRec](const Twine &T) { 85506c3fb27SDimitry Andric if (CurRec) 85606c3fb27SDimitry Andric PrintFatalError(CurRec->getLoc(), T); 85706c3fb27SDimitry Andric else 85806c3fb27SDimitry Andric PrintFatalError(T); 85906c3fb27SDimitry Andric }; 86006c3fb27SDimitry Andric 86106c3fb27SDimitry Andric if (!D) { 86206c3fb27SDimitry Andric if (IsFinal) { 86306c3fb27SDimitry Andric PrintFatalErrorHelper(Twine("Undefined reference to record: '") + 86406c3fb27SDimitry Andric Name->getValue() + "'\n"); 86506c3fb27SDimitry Andric } 86606c3fb27SDimitry Andric break; 86706c3fb27SDimitry Andric } 86806c3fb27SDimitry Andric 8690b57cec5SDimitry Andric DefInit *DI = DefInit::get(D); 8700b57cec5SDimitry Andric if (!DI->getType()->typeIsA(getType())) { 87106c3fb27SDimitry Andric PrintFatalErrorHelper(Twine("Expected type '") + 8720b57cec5SDimitry Andric getType()->getAsString() + "', got '" + 8730b57cec5SDimitry Andric DI->getType()->getAsString() + "' in: " + 8740b57cec5SDimitry Andric getAsString() + "\n"); 8750b57cec5SDimitry Andric } 8760b57cec5SDimitry Andric return DI; 8770b57cec5SDimitry Andric } 8780b57cec5SDimitry Andric } 8790b57cec5SDimitry Andric 8800b57cec5SDimitry Andric if (Init *NewInit = LHS->convertInitializerTo(getType())) 8810b57cec5SDimitry Andric return NewInit; 8820b57cec5SDimitry Andric break; 8830b57cec5SDimitry Andric 884e8d8bef9SDimitry Andric case NOT: 88581ad6265SDimitry Andric if (IntInit *LHSi = dyn_cast_or_null<IntInit>( 88681ad6265SDimitry Andric LHS->convertInitializerTo(IntRecTy::get(RK)))) 88781ad6265SDimitry Andric return IntInit::get(RK, LHSi->getValue() ? 0 : 1); 888e8d8bef9SDimitry Andric break; 889e8d8bef9SDimitry Andric 8900b57cec5SDimitry Andric case HEAD: 8910b57cec5SDimitry Andric if (ListInit *LHSl = dyn_cast<ListInit>(LHS)) { 8920b57cec5SDimitry Andric assert(!LHSl->empty() && "Empty list in head"); 8930b57cec5SDimitry Andric return LHSl->getElement(0); 8940b57cec5SDimitry Andric } 8950b57cec5SDimitry Andric break; 8960b57cec5SDimitry Andric 8970b57cec5SDimitry Andric case TAIL: 8980b57cec5SDimitry Andric if (ListInit *LHSl = dyn_cast<ListInit>(LHS)) { 8990b57cec5SDimitry Andric assert(!LHSl->empty() && "Empty list in tail"); 9000b57cec5SDimitry Andric // Note the +1. We can't just pass the result of getValues() 9010b57cec5SDimitry Andric // directly. 9020b57cec5SDimitry Andric return ListInit::get(LHSl->getValues().slice(1), LHSl->getElementType()); 9030b57cec5SDimitry Andric } 9040b57cec5SDimitry Andric break; 9050b57cec5SDimitry Andric 9060b57cec5SDimitry Andric case SIZE: 9070b57cec5SDimitry Andric if (ListInit *LHSl = dyn_cast<ListInit>(LHS)) 90881ad6265SDimitry Andric return IntInit::get(RK, LHSl->size()); 909e8d8bef9SDimitry Andric if (DagInit *LHSd = dyn_cast<DagInit>(LHS)) 91081ad6265SDimitry Andric return IntInit::get(RK, LHSd->arg_size()); 911e8d8bef9SDimitry Andric if (StringInit *LHSs = dyn_cast<StringInit>(LHS)) 91281ad6265SDimitry Andric return IntInit::get(RK, LHSs->getValue().size()); 9130b57cec5SDimitry Andric break; 9140b57cec5SDimitry Andric 9150b57cec5SDimitry Andric case EMPTY: 9160b57cec5SDimitry Andric if (ListInit *LHSl = dyn_cast<ListInit>(LHS)) 91781ad6265SDimitry Andric return IntInit::get(RK, LHSl->empty()); 918e8d8bef9SDimitry Andric if (DagInit *LHSd = dyn_cast<DagInit>(LHS)) 91981ad6265SDimitry Andric return IntInit::get(RK, LHSd->arg_empty()); 9200b57cec5SDimitry Andric if (StringInit *LHSs = dyn_cast<StringInit>(LHS)) 92181ad6265SDimitry Andric return IntInit::get(RK, LHSs->getValue().empty()); 9220b57cec5SDimitry Andric break; 923480093f4SDimitry Andric 924e8d8bef9SDimitry Andric case GETDAGOP: 925480093f4SDimitry Andric if (DagInit *Dag = dyn_cast<DagInit>(LHS)) { 926297eecfbSDimitry Andric // TI is not necessarily a def due to the late resolution in multiclasses, 927297eecfbSDimitry Andric // but has to be a TypedInit. 928297eecfbSDimitry Andric auto *TI = cast<TypedInit>(Dag->getOperator()); 929297eecfbSDimitry Andric if (!TI->getType()->typeIsA(getType())) { 930480093f4SDimitry Andric PrintFatalError(CurRec->getLoc(), 931297eecfbSDimitry Andric Twine("Expected type '") + getType()->getAsString() + 932297eecfbSDimitry Andric "', got '" + TI->getType()->getAsString() + 933297eecfbSDimitry Andric "' in: " + getAsString() + "\n"); 934480093f4SDimitry Andric } else { 935297eecfbSDimitry Andric return Dag->getOperator(); 936480093f4SDimitry Andric } 937480093f4SDimitry Andric } 938480093f4SDimitry Andric break; 939bdd1243dSDimitry Andric 940bdd1243dSDimitry Andric case LOG2: 941bdd1243dSDimitry Andric if (IntInit *LHSi = dyn_cast_or_null<IntInit>( 942bdd1243dSDimitry Andric LHS->convertInitializerTo(IntRecTy::get(RK)))) { 943bdd1243dSDimitry Andric int64_t LHSv = LHSi->getValue(); 944bdd1243dSDimitry Andric if (LHSv <= 0) { 945bdd1243dSDimitry Andric PrintFatalError(CurRec->getLoc(), 946bdd1243dSDimitry Andric "Illegal operation: logtwo is undefined " 947bdd1243dSDimitry Andric "on arguments less than or equal to 0"); 948bdd1243dSDimitry Andric } else { 949bdd1243dSDimitry Andric uint64_t Log = Log2_64(LHSv); 950bdd1243dSDimitry Andric assert(Log <= INT64_MAX && 951bdd1243dSDimitry Andric "Log of an int64_t must be smaller than INT64_MAX"); 952bdd1243dSDimitry Andric return IntInit::get(RK, static_cast<int64_t>(Log)); 953bdd1243dSDimitry Andric } 954bdd1243dSDimitry Andric } 955bdd1243dSDimitry Andric break; 9560b57cec5SDimitry Andric } 9570b57cec5SDimitry Andric return const_cast<UnOpInit *>(this); 9580b57cec5SDimitry Andric } 9590b57cec5SDimitry Andric 9600b57cec5SDimitry Andric Init *UnOpInit::resolveReferences(Resolver &R) const { 9610b57cec5SDimitry Andric Init *lhs = LHS->resolveReferences(R); 9620b57cec5SDimitry Andric 9630b57cec5SDimitry Andric if (LHS != lhs || (R.isFinal() && getOpcode() == CAST)) 9640b57cec5SDimitry Andric return (UnOpInit::get(getOpcode(), lhs, getType())) 9650b57cec5SDimitry Andric ->Fold(R.getCurrentRecord(), R.isFinal()); 9660b57cec5SDimitry Andric return const_cast<UnOpInit *>(this); 9670b57cec5SDimitry Andric } 9680b57cec5SDimitry Andric 9690b57cec5SDimitry Andric std::string UnOpInit::getAsString() const { 9700b57cec5SDimitry Andric std::string Result; 9710b57cec5SDimitry Andric switch (getOpcode()) { 9720b57cec5SDimitry Andric case CAST: Result = "!cast<" + getType()->getAsString() + ">"; break; 973e8d8bef9SDimitry Andric case NOT: Result = "!not"; break; 9740b57cec5SDimitry Andric case HEAD: Result = "!head"; break; 9750b57cec5SDimitry Andric case TAIL: Result = "!tail"; break; 9760b57cec5SDimitry Andric case SIZE: Result = "!size"; break; 9770b57cec5SDimitry Andric case EMPTY: Result = "!empty"; break; 978e8d8bef9SDimitry Andric case GETDAGOP: Result = "!getdagop"; break; 979bdd1243dSDimitry Andric case LOG2 : Result = "!logtwo"; break; 9805f757f3fSDimitry Andric case REPR: 9815f757f3fSDimitry Andric Result = "!repr"; 9825f757f3fSDimitry Andric break; 98306c3fb27SDimitry Andric case TOLOWER: 98406c3fb27SDimitry Andric Result = "!tolower"; 98506c3fb27SDimitry Andric break; 98606c3fb27SDimitry Andric case TOUPPER: 98706c3fb27SDimitry Andric Result = "!toupper"; 98806c3fb27SDimitry Andric break; 9890b57cec5SDimitry Andric } 9900b57cec5SDimitry Andric return Result + "(" + LHS->getAsString() + ")"; 9910b57cec5SDimitry Andric } 9920b57cec5SDimitry Andric 9930b57cec5SDimitry Andric static void 9940b57cec5SDimitry Andric ProfileBinOpInit(FoldingSetNodeID &ID, unsigned Opcode, Init *LHS, Init *RHS, 9950b57cec5SDimitry Andric RecTy *Type) { 9960b57cec5SDimitry Andric ID.AddInteger(Opcode); 9970b57cec5SDimitry Andric ID.AddPointer(LHS); 9980b57cec5SDimitry Andric ID.AddPointer(RHS); 9990b57cec5SDimitry Andric ID.AddPointer(Type); 10000b57cec5SDimitry Andric } 10010b57cec5SDimitry Andric 1002349cc55cSDimitry Andric BinOpInit *BinOpInit::get(BinaryOp Opc, Init *LHS, Init *RHS, RecTy *Type) { 10030b57cec5SDimitry Andric FoldingSetNodeID ID; 10040b57cec5SDimitry Andric ProfileBinOpInit(ID, Opc, LHS, RHS, Type); 10050b57cec5SDimitry Andric 100681ad6265SDimitry Andric detail::RecordKeeperImpl &RK = LHS->getRecordKeeper().getImpl(); 10070b57cec5SDimitry Andric void *IP = nullptr; 100881ad6265SDimitry Andric if (BinOpInit *I = RK.TheBinOpInitPool.FindNodeOrInsertPos(ID, IP)) 10090b57cec5SDimitry Andric return I; 10100b57cec5SDimitry Andric 101181ad6265SDimitry Andric BinOpInit *I = new (RK.Allocator) BinOpInit(Opc, LHS, RHS, Type); 101281ad6265SDimitry Andric RK.TheBinOpInitPool.InsertNode(I, IP); 10130b57cec5SDimitry Andric return I; 10140b57cec5SDimitry Andric } 10150b57cec5SDimitry Andric 10160b57cec5SDimitry Andric void BinOpInit::Profile(FoldingSetNodeID &ID) const { 10170b57cec5SDimitry Andric ProfileBinOpInit(ID, getOpcode(), getLHS(), getRHS(), getType()); 10180b57cec5SDimitry Andric } 10190b57cec5SDimitry Andric 10200b57cec5SDimitry Andric static StringInit *ConcatStringInits(const StringInit *I0, 10210b57cec5SDimitry Andric const StringInit *I1) { 10220b57cec5SDimitry Andric SmallString<80> Concat(I0->getValue()); 10230b57cec5SDimitry Andric Concat.append(I1->getValue()); 102481ad6265SDimitry Andric return StringInit::get( 102581ad6265SDimitry Andric I0->getRecordKeeper(), Concat, 102681ad6265SDimitry Andric StringInit::determineFormat(I0->getFormat(), I1->getFormat())); 1027e8d8bef9SDimitry Andric } 1028e8d8bef9SDimitry Andric 1029e8d8bef9SDimitry Andric static StringInit *interleaveStringList(const ListInit *List, 1030e8d8bef9SDimitry Andric const StringInit *Delim) { 1031e8d8bef9SDimitry Andric if (List->size() == 0) 103281ad6265SDimitry Andric return StringInit::get(List->getRecordKeeper(), ""); 1033e8d8bef9SDimitry Andric StringInit *Element = dyn_cast<StringInit>(List->getElement(0)); 1034e8d8bef9SDimitry Andric if (!Element) 1035e8d8bef9SDimitry Andric return nullptr; 1036e8d8bef9SDimitry Andric SmallString<80> Result(Element->getValue()); 1037e8d8bef9SDimitry Andric StringInit::StringFormat Fmt = StringInit::SF_String; 1038e8d8bef9SDimitry Andric 1039e8d8bef9SDimitry Andric for (unsigned I = 1, E = List->size(); I < E; ++I) { 1040e8d8bef9SDimitry Andric Result.append(Delim->getValue()); 1041e8d8bef9SDimitry Andric StringInit *Element = dyn_cast<StringInit>(List->getElement(I)); 1042e8d8bef9SDimitry Andric if (!Element) 1043e8d8bef9SDimitry Andric return nullptr; 1044e8d8bef9SDimitry Andric Result.append(Element->getValue()); 1045e8d8bef9SDimitry Andric Fmt = StringInit::determineFormat(Fmt, Element->getFormat()); 1046e8d8bef9SDimitry Andric } 104781ad6265SDimitry Andric return StringInit::get(List->getRecordKeeper(), Result, Fmt); 1048e8d8bef9SDimitry Andric } 1049e8d8bef9SDimitry Andric 1050e8d8bef9SDimitry Andric static StringInit *interleaveIntList(const ListInit *List, 1051e8d8bef9SDimitry Andric const StringInit *Delim) { 105281ad6265SDimitry Andric RecordKeeper &RK = List->getRecordKeeper(); 1053e8d8bef9SDimitry Andric if (List->size() == 0) 105481ad6265SDimitry Andric return StringInit::get(RK, ""); 105581ad6265SDimitry Andric IntInit *Element = dyn_cast_or_null<IntInit>( 105681ad6265SDimitry Andric List->getElement(0)->convertInitializerTo(IntRecTy::get(RK))); 1057e8d8bef9SDimitry Andric if (!Element) 1058e8d8bef9SDimitry Andric return nullptr; 1059e8d8bef9SDimitry Andric SmallString<80> Result(Element->getAsString()); 1060e8d8bef9SDimitry Andric 1061e8d8bef9SDimitry Andric for (unsigned I = 1, E = List->size(); I < E; ++I) { 1062e8d8bef9SDimitry Andric Result.append(Delim->getValue()); 106381ad6265SDimitry Andric IntInit *Element = dyn_cast_or_null<IntInit>( 106481ad6265SDimitry Andric List->getElement(I)->convertInitializerTo(IntRecTy::get(RK))); 1065e8d8bef9SDimitry Andric if (!Element) 1066e8d8bef9SDimitry Andric return nullptr; 1067e8d8bef9SDimitry Andric Result.append(Element->getAsString()); 1068e8d8bef9SDimitry Andric } 106981ad6265SDimitry Andric return StringInit::get(RK, Result); 10700b57cec5SDimitry Andric } 10710b57cec5SDimitry Andric 10720b57cec5SDimitry Andric Init *BinOpInit::getStrConcat(Init *I0, Init *I1) { 10730b57cec5SDimitry Andric // Shortcut for the common case of concatenating two strings. 10740b57cec5SDimitry Andric if (const StringInit *I0s = dyn_cast<StringInit>(I0)) 10750b57cec5SDimitry Andric if (const StringInit *I1s = dyn_cast<StringInit>(I1)) 10760b57cec5SDimitry Andric return ConcatStringInits(I0s, I1s); 107781ad6265SDimitry Andric return BinOpInit::get(BinOpInit::STRCONCAT, I0, I1, 107881ad6265SDimitry Andric StringRecTy::get(I0->getRecordKeeper())); 10790b57cec5SDimitry Andric } 10800b57cec5SDimitry Andric 10810b57cec5SDimitry Andric static ListInit *ConcatListInits(const ListInit *LHS, 10820b57cec5SDimitry Andric const ListInit *RHS) { 10830b57cec5SDimitry Andric SmallVector<Init *, 8> Args; 1084e8d8bef9SDimitry Andric llvm::append_range(Args, *LHS); 1085e8d8bef9SDimitry Andric llvm::append_range(Args, *RHS); 10860b57cec5SDimitry Andric return ListInit::get(Args, LHS->getElementType()); 10870b57cec5SDimitry Andric } 10880b57cec5SDimitry Andric 10890b57cec5SDimitry Andric Init *BinOpInit::getListConcat(TypedInit *LHS, Init *RHS) { 10900b57cec5SDimitry Andric assert(isa<ListRecTy>(LHS->getType()) && "First arg must be a list"); 10910b57cec5SDimitry Andric 10920b57cec5SDimitry Andric // Shortcut for the common case of concatenating two lists. 10930b57cec5SDimitry Andric if (const ListInit *LHSList = dyn_cast<ListInit>(LHS)) 10940b57cec5SDimitry Andric if (const ListInit *RHSList = dyn_cast<ListInit>(RHS)) 10950b57cec5SDimitry Andric return ConcatListInits(LHSList, RHSList); 10960b57cec5SDimitry Andric return BinOpInit::get(BinOpInit::LISTCONCAT, LHS, RHS, LHS->getType()); 10970b57cec5SDimitry Andric } 10980b57cec5SDimitry Andric 109906c3fb27SDimitry Andric std::optional<bool> BinOpInit::CompareInit(unsigned Opc, Init *LHS, 110006c3fb27SDimitry Andric Init *RHS) const { 1101bdd1243dSDimitry Andric // First see if we have two bit, bits, or int. 1102bdd1243dSDimitry Andric IntInit *LHSi = dyn_cast_or_null<IntInit>( 1103bdd1243dSDimitry Andric LHS->convertInitializerTo(IntRecTy::get(getRecordKeeper()))); 1104bdd1243dSDimitry Andric IntInit *RHSi = dyn_cast_or_null<IntInit>( 1105bdd1243dSDimitry Andric RHS->convertInitializerTo(IntRecTy::get(getRecordKeeper()))); 1106bdd1243dSDimitry Andric 1107bdd1243dSDimitry Andric if (LHSi && RHSi) { 1108bdd1243dSDimitry Andric bool Result; 1109bdd1243dSDimitry Andric switch (Opc) { 1110bdd1243dSDimitry Andric case EQ: 1111bdd1243dSDimitry Andric Result = LHSi->getValue() == RHSi->getValue(); 1112bdd1243dSDimitry Andric break; 1113bdd1243dSDimitry Andric case NE: 1114bdd1243dSDimitry Andric Result = LHSi->getValue() != RHSi->getValue(); 1115bdd1243dSDimitry Andric break; 1116bdd1243dSDimitry Andric case LE: 1117bdd1243dSDimitry Andric Result = LHSi->getValue() <= RHSi->getValue(); 1118bdd1243dSDimitry Andric break; 1119bdd1243dSDimitry Andric case LT: 1120bdd1243dSDimitry Andric Result = LHSi->getValue() < RHSi->getValue(); 1121bdd1243dSDimitry Andric break; 1122bdd1243dSDimitry Andric case GE: 1123bdd1243dSDimitry Andric Result = LHSi->getValue() >= RHSi->getValue(); 1124bdd1243dSDimitry Andric break; 1125bdd1243dSDimitry Andric case GT: 1126bdd1243dSDimitry Andric Result = LHSi->getValue() > RHSi->getValue(); 1127bdd1243dSDimitry Andric break; 1128bdd1243dSDimitry Andric default: 1129bdd1243dSDimitry Andric llvm_unreachable("unhandled comparison"); 1130bdd1243dSDimitry Andric } 1131bdd1243dSDimitry Andric return Result; 1132bdd1243dSDimitry Andric } 1133bdd1243dSDimitry Andric 1134bdd1243dSDimitry Andric // Next try strings. 1135bdd1243dSDimitry Andric StringInit *LHSs = dyn_cast<StringInit>(LHS); 1136bdd1243dSDimitry Andric StringInit *RHSs = dyn_cast<StringInit>(RHS); 1137bdd1243dSDimitry Andric 1138bdd1243dSDimitry Andric if (LHSs && RHSs) { 1139bdd1243dSDimitry Andric bool Result; 1140bdd1243dSDimitry Andric switch (Opc) { 1141bdd1243dSDimitry Andric case EQ: 1142bdd1243dSDimitry Andric Result = LHSs->getValue() == RHSs->getValue(); 1143bdd1243dSDimitry Andric break; 1144bdd1243dSDimitry Andric case NE: 1145bdd1243dSDimitry Andric Result = LHSs->getValue() != RHSs->getValue(); 1146bdd1243dSDimitry Andric break; 1147bdd1243dSDimitry Andric case LE: 1148bdd1243dSDimitry Andric Result = LHSs->getValue() <= RHSs->getValue(); 1149bdd1243dSDimitry Andric break; 1150bdd1243dSDimitry Andric case LT: 1151bdd1243dSDimitry Andric Result = LHSs->getValue() < RHSs->getValue(); 1152bdd1243dSDimitry Andric break; 1153bdd1243dSDimitry Andric case GE: 1154bdd1243dSDimitry Andric Result = LHSs->getValue() >= RHSs->getValue(); 1155bdd1243dSDimitry Andric break; 1156bdd1243dSDimitry Andric case GT: 1157bdd1243dSDimitry Andric Result = LHSs->getValue() > RHSs->getValue(); 1158bdd1243dSDimitry Andric break; 1159bdd1243dSDimitry Andric default: 1160bdd1243dSDimitry Andric llvm_unreachable("unhandled comparison"); 1161bdd1243dSDimitry Andric } 1162bdd1243dSDimitry Andric return Result; 1163bdd1243dSDimitry Andric } 1164bdd1243dSDimitry Andric 1165bdd1243dSDimitry Andric // Finally, !eq and !ne can be used with records. 1166bdd1243dSDimitry Andric if (Opc == EQ || Opc == NE) { 1167bdd1243dSDimitry Andric DefInit *LHSd = dyn_cast<DefInit>(LHS); 1168bdd1243dSDimitry Andric DefInit *RHSd = dyn_cast<DefInit>(RHS); 1169bdd1243dSDimitry Andric if (LHSd && RHSd) 1170bdd1243dSDimitry Andric return (Opc == EQ) ? LHSd == RHSd : LHSd != RHSd; 1171bdd1243dSDimitry Andric } 1172bdd1243dSDimitry Andric 1173bdd1243dSDimitry Andric return std::nullopt; 1174bdd1243dSDimitry Andric } 1175bdd1243dSDimitry Andric 117606c3fb27SDimitry Andric static std::optional<unsigned> getDagArgNoByKey(DagInit *Dag, Init *Key, 117706c3fb27SDimitry Andric std::string &Error) { 117806c3fb27SDimitry Andric // Accessor by index 117906c3fb27SDimitry Andric if (IntInit *Idx = dyn_cast<IntInit>(Key)) { 118006c3fb27SDimitry Andric int64_t Pos = Idx->getValue(); 118106c3fb27SDimitry Andric if (Pos < 0) { 118206c3fb27SDimitry Andric // The index is negative. 118306c3fb27SDimitry Andric Error = 118406c3fb27SDimitry Andric (Twine("index ") + std::to_string(Pos) + Twine(" is negative")).str(); 118506c3fb27SDimitry Andric return std::nullopt; 118606c3fb27SDimitry Andric } 118706c3fb27SDimitry Andric if (Pos >= Dag->getNumArgs()) { 118806c3fb27SDimitry Andric // The index is out-of-range. 118906c3fb27SDimitry Andric Error = (Twine("index ") + std::to_string(Pos) + 119006c3fb27SDimitry Andric " is out of range (dag has " + 119106c3fb27SDimitry Andric std::to_string(Dag->getNumArgs()) + " arguments)") 119206c3fb27SDimitry Andric .str(); 119306c3fb27SDimitry Andric return std::nullopt; 119406c3fb27SDimitry Andric } 119506c3fb27SDimitry Andric return Pos; 119606c3fb27SDimitry Andric } 119706c3fb27SDimitry Andric assert(isa<StringInit>(Key)); 119806c3fb27SDimitry Andric // Accessor by name 119906c3fb27SDimitry Andric StringInit *Name = dyn_cast<StringInit>(Key); 120006c3fb27SDimitry Andric auto ArgNo = Dag->getArgNo(Name->getValue()); 120106c3fb27SDimitry Andric if (!ArgNo) { 120206c3fb27SDimitry Andric // The key is not found. 120306c3fb27SDimitry Andric Error = (Twine("key '") + Name->getValue() + Twine("' is not found")).str(); 120406c3fb27SDimitry Andric return std::nullopt; 120506c3fb27SDimitry Andric } 120606c3fb27SDimitry Andric return *ArgNo; 120706c3fb27SDimitry Andric } 120806c3fb27SDimitry Andric 12090b57cec5SDimitry Andric Init *BinOpInit::Fold(Record *CurRec) const { 12100b57cec5SDimitry Andric switch (getOpcode()) { 12110b57cec5SDimitry Andric case CONCAT: { 12120b57cec5SDimitry Andric DagInit *LHSs = dyn_cast<DagInit>(LHS); 12130b57cec5SDimitry Andric DagInit *RHSs = dyn_cast<DagInit>(RHS); 12140b57cec5SDimitry Andric if (LHSs && RHSs) { 12150b57cec5SDimitry Andric DefInit *LOp = dyn_cast<DefInit>(LHSs->getOperator()); 12160b57cec5SDimitry Andric DefInit *ROp = dyn_cast<DefInit>(RHSs->getOperator()); 1217480093f4SDimitry Andric if ((!LOp && !isa<UnsetInit>(LHSs->getOperator())) || 1218480093f4SDimitry Andric (!ROp && !isa<UnsetInit>(RHSs->getOperator()))) 12190b57cec5SDimitry Andric break; 1220480093f4SDimitry Andric if (LOp && ROp && LOp->getDef() != ROp->getDef()) { 12210b57cec5SDimitry Andric PrintFatalError(Twine("Concatenated Dag operators do not match: '") + 12220b57cec5SDimitry Andric LHSs->getAsString() + "' vs. '" + RHSs->getAsString() + 12230b57cec5SDimitry Andric "'"); 12240b57cec5SDimitry Andric } 1225480093f4SDimitry Andric Init *Op = LOp ? LOp : ROp; 1226480093f4SDimitry Andric if (!Op) 122781ad6265SDimitry Andric Op = UnsetInit::get(getRecordKeeper()); 1228480093f4SDimitry Andric 12290b57cec5SDimitry Andric SmallVector<Init*, 8> Args; 12300b57cec5SDimitry Andric SmallVector<StringInit*, 8> ArgNames; 12310b57cec5SDimitry Andric for (unsigned i = 0, e = LHSs->getNumArgs(); i != e; ++i) { 12320b57cec5SDimitry Andric Args.push_back(LHSs->getArg(i)); 12330b57cec5SDimitry Andric ArgNames.push_back(LHSs->getArgName(i)); 12340b57cec5SDimitry Andric } 12350b57cec5SDimitry Andric for (unsigned i = 0, e = RHSs->getNumArgs(); i != e; ++i) { 12360b57cec5SDimitry Andric Args.push_back(RHSs->getArg(i)); 12370b57cec5SDimitry Andric ArgNames.push_back(RHSs->getArgName(i)); 12380b57cec5SDimitry Andric } 1239480093f4SDimitry Andric return DagInit::get(Op, nullptr, Args, ArgNames); 12400b57cec5SDimitry Andric } 12410b57cec5SDimitry Andric break; 12420b57cec5SDimitry Andric } 12430b57cec5SDimitry Andric case LISTCONCAT: { 12440b57cec5SDimitry Andric ListInit *LHSs = dyn_cast<ListInit>(LHS); 12450b57cec5SDimitry Andric ListInit *RHSs = dyn_cast<ListInit>(RHS); 12460b57cec5SDimitry Andric if (LHSs && RHSs) { 12470b57cec5SDimitry Andric SmallVector<Init *, 8> Args; 1248e8d8bef9SDimitry Andric llvm::append_range(Args, *LHSs); 1249e8d8bef9SDimitry Andric llvm::append_range(Args, *RHSs); 12500b57cec5SDimitry Andric return ListInit::get(Args, LHSs->getElementType()); 12510b57cec5SDimitry Andric } 12520b57cec5SDimitry Andric break; 12530b57cec5SDimitry Andric } 12540b57cec5SDimitry Andric case LISTSPLAT: { 12550b57cec5SDimitry Andric TypedInit *Value = dyn_cast<TypedInit>(LHS); 12560b57cec5SDimitry Andric IntInit *Size = dyn_cast<IntInit>(RHS); 12570b57cec5SDimitry Andric if (Value && Size) { 12580b57cec5SDimitry Andric SmallVector<Init *, 8> Args(Size->getValue(), Value); 12590b57cec5SDimitry Andric return ListInit::get(Args, Value->getType()); 12600b57cec5SDimitry Andric } 12610b57cec5SDimitry Andric break; 12620b57cec5SDimitry Andric } 1263bdd1243dSDimitry Andric case LISTREMOVE: { 1264bdd1243dSDimitry Andric ListInit *LHSs = dyn_cast<ListInit>(LHS); 1265bdd1243dSDimitry Andric ListInit *RHSs = dyn_cast<ListInit>(RHS); 1266bdd1243dSDimitry Andric if (LHSs && RHSs) { 1267bdd1243dSDimitry Andric SmallVector<Init *, 8> Args; 1268bdd1243dSDimitry Andric for (Init *EltLHS : *LHSs) { 1269bdd1243dSDimitry Andric bool Found = false; 1270bdd1243dSDimitry Andric for (Init *EltRHS : *RHSs) { 1271bdd1243dSDimitry Andric if (std::optional<bool> Result = CompareInit(EQ, EltLHS, EltRHS)) { 1272bdd1243dSDimitry Andric if (*Result) { 1273bdd1243dSDimitry Andric Found = true; 1274bdd1243dSDimitry Andric break; 1275bdd1243dSDimitry Andric } 1276bdd1243dSDimitry Andric } 1277bdd1243dSDimitry Andric } 1278bdd1243dSDimitry Andric if (!Found) 1279bdd1243dSDimitry Andric Args.push_back(EltLHS); 1280bdd1243dSDimitry Andric } 1281bdd1243dSDimitry Andric return ListInit::get(Args, LHSs->getElementType()); 1282bdd1243dSDimitry Andric } 1283bdd1243dSDimitry Andric break; 1284bdd1243dSDimitry Andric } 128506c3fb27SDimitry Andric case LISTELEM: { 128606c3fb27SDimitry Andric auto *TheList = dyn_cast<ListInit>(LHS); 128706c3fb27SDimitry Andric auto *Idx = dyn_cast<IntInit>(RHS); 128806c3fb27SDimitry Andric if (!TheList || !Idx) 128906c3fb27SDimitry Andric break; 129006c3fb27SDimitry Andric auto i = Idx->getValue(); 129106c3fb27SDimitry Andric if (i < 0 || i >= (ssize_t)TheList->size()) 129206c3fb27SDimitry Andric break; 129306c3fb27SDimitry Andric return TheList->getElement(i); 129406c3fb27SDimitry Andric } 129506c3fb27SDimitry Andric case LISTSLICE: { 129606c3fb27SDimitry Andric auto *TheList = dyn_cast<ListInit>(LHS); 129706c3fb27SDimitry Andric auto *SliceIdxs = dyn_cast<ListInit>(RHS); 129806c3fb27SDimitry Andric if (!TheList || !SliceIdxs) 129906c3fb27SDimitry Andric break; 130006c3fb27SDimitry Andric SmallVector<Init *, 8> Args; 130106c3fb27SDimitry Andric Args.reserve(SliceIdxs->size()); 130206c3fb27SDimitry Andric for (auto *I : *SliceIdxs) { 130306c3fb27SDimitry Andric auto *II = dyn_cast<IntInit>(I); 130406c3fb27SDimitry Andric if (!II) 130506c3fb27SDimitry Andric goto unresolved; 130606c3fb27SDimitry Andric auto i = II->getValue(); 130706c3fb27SDimitry Andric if (i < 0 || i >= (ssize_t)TheList->size()) 130806c3fb27SDimitry Andric goto unresolved; 130906c3fb27SDimitry Andric Args.push_back(TheList->getElement(i)); 131006c3fb27SDimitry Andric } 131106c3fb27SDimitry Andric return ListInit::get(Args, TheList->getElementType()); 131206c3fb27SDimitry Andric } 131306c3fb27SDimitry Andric case RANGEC: { 131406c3fb27SDimitry Andric auto *LHSi = dyn_cast<IntInit>(LHS); 131506c3fb27SDimitry Andric auto *RHSi = dyn_cast<IntInit>(RHS); 131606c3fb27SDimitry Andric if (!LHSi || !RHSi) 131706c3fb27SDimitry Andric break; 131806c3fb27SDimitry Andric 131906c3fb27SDimitry Andric auto Start = LHSi->getValue(); 132006c3fb27SDimitry Andric auto End = RHSi->getValue(); 132106c3fb27SDimitry Andric SmallVector<Init *, 8> Args; 132206c3fb27SDimitry Andric if (getOpcode() == RANGEC) { 132306c3fb27SDimitry Andric // Closed interval 132406c3fb27SDimitry Andric if (Start <= End) { 132506c3fb27SDimitry Andric // Ascending order 132606c3fb27SDimitry Andric Args.reserve(End - Start + 1); 132706c3fb27SDimitry Andric for (auto i = Start; i <= End; ++i) 132806c3fb27SDimitry Andric Args.push_back(IntInit::get(getRecordKeeper(), i)); 132906c3fb27SDimitry Andric } else { 133006c3fb27SDimitry Andric // Descending order 133106c3fb27SDimitry Andric Args.reserve(Start - End + 1); 133206c3fb27SDimitry Andric for (auto i = Start; i >= End; --i) 133306c3fb27SDimitry Andric Args.push_back(IntInit::get(getRecordKeeper(), i)); 133406c3fb27SDimitry Andric } 133506c3fb27SDimitry Andric } else if (Start < End) { 133606c3fb27SDimitry Andric // Half-open interval (excludes `End`) 133706c3fb27SDimitry Andric Args.reserve(End - Start); 133806c3fb27SDimitry Andric for (auto i = Start; i < End; ++i) 133906c3fb27SDimitry Andric Args.push_back(IntInit::get(getRecordKeeper(), i)); 134006c3fb27SDimitry Andric } else { 134106c3fb27SDimitry Andric // Empty set 134206c3fb27SDimitry Andric } 134306c3fb27SDimitry Andric return ListInit::get(Args, LHSi->getType()); 134406c3fb27SDimitry Andric } 13450b57cec5SDimitry Andric case STRCONCAT: { 13460b57cec5SDimitry Andric StringInit *LHSs = dyn_cast<StringInit>(LHS); 13470b57cec5SDimitry Andric StringInit *RHSs = dyn_cast<StringInit>(RHS); 13480b57cec5SDimitry Andric if (LHSs && RHSs) 13490b57cec5SDimitry Andric return ConcatStringInits(LHSs, RHSs); 13500b57cec5SDimitry Andric break; 13510b57cec5SDimitry Andric } 1352e8d8bef9SDimitry Andric case INTERLEAVE: { 1353e8d8bef9SDimitry Andric ListInit *List = dyn_cast<ListInit>(LHS); 1354e8d8bef9SDimitry Andric StringInit *Delim = dyn_cast<StringInit>(RHS); 1355e8d8bef9SDimitry Andric if (List && Delim) { 1356e8d8bef9SDimitry Andric StringInit *Result; 1357e8d8bef9SDimitry Andric if (isa<StringRecTy>(List->getElementType())) 1358e8d8bef9SDimitry Andric Result = interleaveStringList(List, Delim); 1359e8d8bef9SDimitry Andric else 1360e8d8bef9SDimitry Andric Result = interleaveIntList(List, Delim); 1361e8d8bef9SDimitry Andric if (Result) 1362e8d8bef9SDimitry Andric return Result; 1363e8d8bef9SDimitry Andric } 1364e8d8bef9SDimitry Andric break; 1365e8d8bef9SDimitry Andric } 13660b57cec5SDimitry Andric case EQ: 13670b57cec5SDimitry Andric case NE: 13680b57cec5SDimitry Andric case LE: 13690b57cec5SDimitry Andric case LT: 13700b57cec5SDimitry Andric case GE: 13710b57cec5SDimitry Andric case GT: { 1372bdd1243dSDimitry Andric if (std::optional<bool> Result = CompareInit(getOpcode(), LHS, RHS)) 1373bdd1243dSDimitry Andric return BitInit::get(getRecordKeeper(), *Result); 13740b57cec5SDimitry Andric break; 13750b57cec5SDimitry Andric } 137606c3fb27SDimitry Andric case GETDAGARG: { 137706c3fb27SDimitry Andric DagInit *Dag = dyn_cast<DagInit>(LHS); 137806c3fb27SDimitry Andric if (Dag && isa<IntInit, StringInit>(RHS)) { 137906c3fb27SDimitry Andric std::string Error; 138006c3fb27SDimitry Andric auto ArgNo = getDagArgNoByKey(Dag, RHS, Error); 138106c3fb27SDimitry Andric if (!ArgNo) 138206c3fb27SDimitry Andric PrintFatalError(CurRec->getLoc(), "!getdagarg " + Error); 138306c3fb27SDimitry Andric 138406c3fb27SDimitry Andric assert(*ArgNo < Dag->getNumArgs()); 138506c3fb27SDimitry Andric 138606c3fb27SDimitry Andric Init *Arg = Dag->getArg(*ArgNo); 138706c3fb27SDimitry Andric if (auto *TI = dyn_cast<TypedInit>(Arg)) 138806c3fb27SDimitry Andric if (!TI->getType()->typeIsConvertibleTo(getType())) 138906c3fb27SDimitry Andric return UnsetInit::get(Dag->getRecordKeeper()); 139006c3fb27SDimitry Andric return Arg; 139106c3fb27SDimitry Andric } 139206c3fb27SDimitry Andric break; 139306c3fb27SDimitry Andric } 139406c3fb27SDimitry Andric case GETDAGNAME: { 139506c3fb27SDimitry Andric DagInit *Dag = dyn_cast<DagInit>(LHS); 139606c3fb27SDimitry Andric IntInit *Idx = dyn_cast<IntInit>(RHS); 139706c3fb27SDimitry Andric if (Dag && Idx) { 139806c3fb27SDimitry Andric int64_t Pos = Idx->getValue(); 139906c3fb27SDimitry Andric if (Pos < 0 || Pos >= Dag->getNumArgs()) { 140006c3fb27SDimitry Andric // The index is out-of-range. 140106c3fb27SDimitry Andric PrintError(CurRec->getLoc(), 140206c3fb27SDimitry Andric Twine("!getdagname index is out of range 0...") + 140306c3fb27SDimitry Andric std::to_string(Dag->getNumArgs() - 1) + ": " + 140406c3fb27SDimitry Andric std::to_string(Pos)); 140506c3fb27SDimitry Andric } 140606c3fb27SDimitry Andric Init *ArgName = Dag->getArgName(Pos); 140706c3fb27SDimitry Andric if (!ArgName) 140806c3fb27SDimitry Andric return UnsetInit::get(getRecordKeeper()); 140906c3fb27SDimitry Andric return ArgName; 141006c3fb27SDimitry Andric } 141106c3fb27SDimitry Andric break; 141206c3fb27SDimitry Andric } 1413e8d8bef9SDimitry Andric case SETDAGOP: { 1414480093f4SDimitry Andric DagInit *Dag = dyn_cast<DagInit>(LHS); 1415480093f4SDimitry Andric DefInit *Op = dyn_cast<DefInit>(RHS); 1416480093f4SDimitry Andric if (Dag && Op) { 1417480093f4SDimitry Andric SmallVector<Init*, 8> Args; 1418480093f4SDimitry Andric SmallVector<StringInit*, 8> ArgNames; 1419480093f4SDimitry Andric for (unsigned i = 0, e = Dag->getNumArgs(); i != e; ++i) { 1420480093f4SDimitry Andric Args.push_back(Dag->getArg(i)); 1421480093f4SDimitry Andric ArgNames.push_back(Dag->getArgName(i)); 1422480093f4SDimitry Andric } 1423480093f4SDimitry Andric return DagInit::get(Op, nullptr, Args, ArgNames); 1424480093f4SDimitry Andric } 1425480093f4SDimitry Andric break; 1426480093f4SDimitry Andric } 14270b57cec5SDimitry Andric case ADD: 1428e8d8bef9SDimitry Andric case SUB: 14290b57cec5SDimitry Andric case MUL: 1430bdd1243dSDimitry Andric case DIV: 14310b57cec5SDimitry Andric case AND: 14320b57cec5SDimitry Andric case OR: 1433e8d8bef9SDimitry Andric case XOR: 14340b57cec5SDimitry Andric case SHL: 14350b57cec5SDimitry Andric case SRA: 14360b57cec5SDimitry Andric case SRL: { 143781ad6265SDimitry Andric IntInit *LHSi = dyn_cast_or_null<IntInit>( 143881ad6265SDimitry Andric LHS->convertInitializerTo(IntRecTy::get(getRecordKeeper()))); 143981ad6265SDimitry Andric IntInit *RHSi = dyn_cast_or_null<IntInit>( 144081ad6265SDimitry Andric RHS->convertInitializerTo(IntRecTy::get(getRecordKeeper()))); 14410b57cec5SDimitry Andric if (LHSi && RHSi) { 14420b57cec5SDimitry Andric int64_t LHSv = LHSi->getValue(), RHSv = RHSi->getValue(); 14430b57cec5SDimitry Andric int64_t Result; 14440b57cec5SDimitry Andric switch (getOpcode()) { 14450b57cec5SDimitry Andric default: llvm_unreachable("Bad opcode!"); 14460b57cec5SDimitry Andric case ADD: Result = LHSv + RHSv; break; 1447e8d8bef9SDimitry Andric case SUB: Result = LHSv - RHSv; break; 14480b57cec5SDimitry Andric case MUL: Result = LHSv * RHSv; break; 1449bdd1243dSDimitry Andric case DIV: 1450bdd1243dSDimitry Andric if (RHSv == 0) 1451bdd1243dSDimitry Andric PrintFatalError(CurRec->getLoc(), 1452bdd1243dSDimitry Andric "Illegal operation: division by zero"); 1453bdd1243dSDimitry Andric else if (LHSv == INT64_MIN && RHSv == -1) 1454bdd1243dSDimitry Andric PrintFatalError(CurRec->getLoc(), 1455bdd1243dSDimitry Andric "Illegal operation: INT64_MIN / -1"); 1456bdd1243dSDimitry Andric else 1457bdd1243dSDimitry Andric Result = LHSv / RHSv; 1458bdd1243dSDimitry Andric break; 14590b57cec5SDimitry Andric case AND: Result = LHSv & RHSv; break; 14600b57cec5SDimitry Andric case OR: Result = LHSv | RHSv; break; 1461e8d8bef9SDimitry Andric case XOR: Result = LHSv ^ RHSv; break; 14625ffd83dbSDimitry Andric case SHL: Result = (uint64_t)LHSv << (uint64_t)RHSv; break; 14630b57cec5SDimitry Andric case SRA: Result = LHSv >> RHSv; break; 14640b57cec5SDimitry Andric case SRL: Result = (uint64_t)LHSv >> (uint64_t)RHSv; break; 14650b57cec5SDimitry Andric } 146681ad6265SDimitry Andric return IntInit::get(getRecordKeeper(), Result); 14670b57cec5SDimitry Andric } 14680b57cec5SDimitry Andric break; 14690b57cec5SDimitry Andric } 14700b57cec5SDimitry Andric } 147106c3fb27SDimitry Andric unresolved: 14720b57cec5SDimitry Andric return const_cast<BinOpInit *>(this); 14730b57cec5SDimitry Andric } 14740b57cec5SDimitry Andric 14750b57cec5SDimitry Andric Init *BinOpInit::resolveReferences(Resolver &R) const { 14760b57cec5SDimitry Andric Init *lhs = LHS->resolveReferences(R); 14770b57cec5SDimitry Andric Init *rhs = RHS->resolveReferences(R); 14780b57cec5SDimitry Andric 14790b57cec5SDimitry Andric if (LHS != lhs || RHS != rhs) 14800b57cec5SDimitry Andric return (BinOpInit::get(getOpcode(), lhs, rhs, getType())) 14810b57cec5SDimitry Andric ->Fold(R.getCurrentRecord()); 14820b57cec5SDimitry Andric return const_cast<BinOpInit *>(this); 14830b57cec5SDimitry Andric } 14840b57cec5SDimitry Andric 14850b57cec5SDimitry Andric std::string BinOpInit::getAsString() const { 14860b57cec5SDimitry Andric std::string Result; 14870b57cec5SDimitry Andric switch (getOpcode()) { 148806c3fb27SDimitry Andric case LISTELEM: 148906c3fb27SDimitry Andric case LISTSLICE: 149006c3fb27SDimitry Andric return LHS->getAsString() + "[" + RHS->getAsString() + "]"; 149106c3fb27SDimitry Andric case RANGEC: 149206c3fb27SDimitry Andric return LHS->getAsString() + "..." + RHS->getAsString(); 14930b57cec5SDimitry Andric case CONCAT: Result = "!con"; break; 14940b57cec5SDimitry Andric case ADD: Result = "!add"; break; 1495e8d8bef9SDimitry Andric case SUB: Result = "!sub"; break; 14960b57cec5SDimitry Andric case MUL: Result = "!mul"; break; 1497bdd1243dSDimitry Andric case DIV: Result = "!div"; break; 14980b57cec5SDimitry Andric case AND: Result = "!and"; break; 14990b57cec5SDimitry Andric case OR: Result = "!or"; break; 1500e8d8bef9SDimitry Andric case XOR: Result = "!xor"; break; 15010b57cec5SDimitry Andric case SHL: Result = "!shl"; break; 15020b57cec5SDimitry Andric case SRA: Result = "!sra"; break; 15030b57cec5SDimitry Andric case SRL: Result = "!srl"; break; 15040b57cec5SDimitry Andric case EQ: Result = "!eq"; break; 15050b57cec5SDimitry Andric case NE: Result = "!ne"; break; 15060b57cec5SDimitry Andric case LE: Result = "!le"; break; 15070b57cec5SDimitry Andric case LT: Result = "!lt"; break; 15080b57cec5SDimitry Andric case GE: Result = "!ge"; break; 15090b57cec5SDimitry Andric case GT: Result = "!gt"; break; 15100b57cec5SDimitry Andric case LISTCONCAT: Result = "!listconcat"; break; 15110b57cec5SDimitry Andric case LISTSPLAT: Result = "!listsplat"; break; 15125f757f3fSDimitry Andric case LISTREMOVE: 15135f757f3fSDimitry Andric Result = "!listremove"; 15145f757f3fSDimitry Andric break; 15150b57cec5SDimitry Andric case STRCONCAT: Result = "!strconcat"; break; 1516e8d8bef9SDimitry Andric case INTERLEAVE: Result = "!interleave"; break; 1517e8d8bef9SDimitry Andric case SETDAGOP: Result = "!setdagop"; break; 151806c3fb27SDimitry Andric case GETDAGARG: 151906c3fb27SDimitry Andric Result = "!getdagarg<" + getType()->getAsString() + ">"; 152006c3fb27SDimitry Andric break; 152106c3fb27SDimitry Andric case GETDAGNAME: 152206c3fb27SDimitry Andric Result = "!getdagname"; 152306c3fb27SDimitry Andric break; 15240b57cec5SDimitry Andric } 15250b57cec5SDimitry Andric return Result + "(" + LHS->getAsString() + ", " + RHS->getAsString() + ")"; 15260b57cec5SDimitry Andric } 15270b57cec5SDimitry Andric 15280b57cec5SDimitry Andric static void 15290b57cec5SDimitry Andric ProfileTernOpInit(FoldingSetNodeID &ID, unsigned Opcode, Init *LHS, Init *MHS, 15300b57cec5SDimitry Andric Init *RHS, RecTy *Type) { 15310b57cec5SDimitry Andric ID.AddInteger(Opcode); 15320b57cec5SDimitry Andric ID.AddPointer(LHS); 15330b57cec5SDimitry Andric ID.AddPointer(MHS); 15340b57cec5SDimitry Andric ID.AddPointer(RHS); 15350b57cec5SDimitry Andric ID.AddPointer(Type); 15360b57cec5SDimitry Andric } 15370b57cec5SDimitry Andric 15380b57cec5SDimitry Andric TernOpInit *TernOpInit::get(TernaryOp Opc, Init *LHS, Init *MHS, Init *RHS, 15390b57cec5SDimitry Andric RecTy *Type) { 15400b57cec5SDimitry Andric FoldingSetNodeID ID; 15410b57cec5SDimitry Andric ProfileTernOpInit(ID, Opc, LHS, MHS, RHS, Type); 15420b57cec5SDimitry Andric 154381ad6265SDimitry Andric detail::RecordKeeperImpl &RK = LHS->getRecordKeeper().getImpl(); 15440b57cec5SDimitry Andric void *IP = nullptr; 154581ad6265SDimitry Andric if (TernOpInit *I = RK.TheTernOpInitPool.FindNodeOrInsertPos(ID, IP)) 15460b57cec5SDimitry Andric return I; 15470b57cec5SDimitry Andric 154881ad6265SDimitry Andric TernOpInit *I = new (RK.Allocator) TernOpInit(Opc, LHS, MHS, RHS, Type); 154981ad6265SDimitry Andric RK.TheTernOpInitPool.InsertNode(I, IP); 15500b57cec5SDimitry Andric return I; 15510b57cec5SDimitry Andric } 15520b57cec5SDimitry Andric 15530b57cec5SDimitry Andric void TernOpInit::Profile(FoldingSetNodeID &ID) const { 15540b57cec5SDimitry Andric ProfileTernOpInit(ID, getOpcode(), getLHS(), getMHS(), getRHS(), getType()); 15550b57cec5SDimitry Andric } 15560b57cec5SDimitry Andric 1557e8d8bef9SDimitry Andric static Init *ItemApply(Init *LHS, Init *MHSe, Init *RHS, Record *CurRec) { 15580b57cec5SDimitry Andric MapResolver R(CurRec); 15590b57cec5SDimitry Andric R.set(LHS, MHSe); 15600b57cec5SDimitry Andric return RHS->resolveReferences(R); 15610b57cec5SDimitry Andric } 15620b57cec5SDimitry Andric 15630b57cec5SDimitry Andric static Init *ForeachDagApply(Init *LHS, DagInit *MHSd, Init *RHS, 15640b57cec5SDimitry Andric Record *CurRec) { 15650b57cec5SDimitry Andric bool Change = false; 1566e8d8bef9SDimitry Andric Init *Val = ItemApply(LHS, MHSd->getOperator(), RHS, CurRec); 15670b57cec5SDimitry Andric if (Val != MHSd->getOperator()) 15680b57cec5SDimitry Andric Change = true; 15690b57cec5SDimitry Andric 15700b57cec5SDimitry Andric SmallVector<std::pair<Init *, StringInit *>, 8> NewArgs; 15710b57cec5SDimitry Andric for (unsigned int i = 0; i < MHSd->getNumArgs(); ++i) { 15720b57cec5SDimitry Andric Init *Arg = MHSd->getArg(i); 15730b57cec5SDimitry Andric Init *NewArg; 15740b57cec5SDimitry Andric StringInit *ArgName = MHSd->getArgName(i); 15750b57cec5SDimitry Andric 15760b57cec5SDimitry Andric if (DagInit *Argd = dyn_cast<DagInit>(Arg)) 15770b57cec5SDimitry Andric NewArg = ForeachDagApply(LHS, Argd, RHS, CurRec); 15780b57cec5SDimitry Andric else 1579e8d8bef9SDimitry Andric NewArg = ItemApply(LHS, Arg, RHS, CurRec); 15800b57cec5SDimitry Andric 15810b57cec5SDimitry Andric NewArgs.push_back(std::make_pair(NewArg, ArgName)); 15820b57cec5SDimitry Andric if (Arg != NewArg) 15830b57cec5SDimitry Andric Change = true; 15840b57cec5SDimitry Andric } 15850b57cec5SDimitry Andric 15860b57cec5SDimitry Andric if (Change) 15870b57cec5SDimitry Andric return DagInit::get(Val, nullptr, NewArgs); 15880b57cec5SDimitry Andric return MHSd; 15890b57cec5SDimitry Andric } 15900b57cec5SDimitry Andric 15910b57cec5SDimitry Andric // Applies RHS to all elements of MHS, using LHS as a temp variable. 15920b57cec5SDimitry Andric static Init *ForeachHelper(Init *LHS, Init *MHS, Init *RHS, RecTy *Type, 15930b57cec5SDimitry Andric Record *CurRec) { 15940b57cec5SDimitry Andric if (DagInit *MHSd = dyn_cast<DagInit>(MHS)) 15950b57cec5SDimitry Andric return ForeachDagApply(LHS, MHSd, RHS, CurRec); 15960b57cec5SDimitry Andric 15970b57cec5SDimitry Andric if (ListInit *MHSl = dyn_cast<ListInit>(MHS)) { 15980b57cec5SDimitry Andric SmallVector<Init *, 8> NewList(MHSl->begin(), MHSl->end()); 15990b57cec5SDimitry Andric 16000b57cec5SDimitry Andric for (Init *&Item : NewList) { 1601e8d8bef9SDimitry Andric Init *NewItem = ItemApply(LHS, Item, RHS, CurRec); 16020b57cec5SDimitry Andric if (NewItem != Item) 16030b57cec5SDimitry Andric Item = NewItem; 16040b57cec5SDimitry Andric } 16050b57cec5SDimitry Andric return ListInit::get(NewList, cast<ListRecTy>(Type)->getElementType()); 16060b57cec5SDimitry Andric } 16070b57cec5SDimitry Andric 16080b57cec5SDimitry Andric return nullptr; 16090b57cec5SDimitry Andric } 16100b57cec5SDimitry Andric 1611e8d8bef9SDimitry Andric // Evaluates RHS for all elements of MHS, using LHS as a temp variable. 1612e8d8bef9SDimitry Andric // Creates a new list with the elements that evaluated to true. 1613e8d8bef9SDimitry Andric static Init *FilterHelper(Init *LHS, Init *MHS, Init *RHS, RecTy *Type, 1614e8d8bef9SDimitry Andric Record *CurRec) { 1615e8d8bef9SDimitry Andric if (ListInit *MHSl = dyn_cast<ListInit>(MHS)) { 1616e8d8bef9SDimitry Andric SmallVector<Init *, 8> NewList; 1617e8d8bef9SDimitry Andric 1618e8d8bef9SDimitry Andric for (Init *Item : MHSl->getValues()) { 1619e8d8bef9SDimitry Andric Init *Include = ItemApply(LHS, Item, RHS, CurRec); 1620e8d8bef9SDimitry Andric if (!Include) 1621e8d8bef9SDimitry Andric return nullptr; 162281ad6265SDimitry Andric if (IntInit *IncludeInt = 162381ad6265SDimitry Andric dyn_cast_or_null<IntInit>(Include->convertInitializerTo( 162481ad6265SDimitry Andric IntRecTy::get(LHS->getRecordKeeper())))) { 1625e8d8bef9SDimitry Andric if (IncludeInt->getValue()) 1626e8d8bef9SDimitry Andric NewList.push_back(Item); 1627e8d8bef9SDimitry Andric } else { 1628e8d8bef9SDimitry Andric return nullptr; 1629e8d8bef9SDimitry Andric } 1630e8d8bef9SDimitry Andric } 1631e8d8bef9SDimitry Andric return ListInit::get(NewList, cast<ListRecTy>(Type)->getElementType()); 1632e8d8bef9SDimitry Andric } 1633e8d8bef9SDimitry Andric 1634e8d8bef9SDimitry Andric return nullptr; 1635e8d8bef9SDimitry Andric } 1636e8d8bef9SDimitry Andric 16370b57cec5SDimitry Andric Init *TernOpInit::Fold(Record *CurRec) const { 163881ad6265SDimitry Andric RecordKeeper &RK = getRecordKeeper(); 16390b57cec5SDimitry Andric switch (getOpcode()) { 16400b57cec5SDimitry Andric case SUBST: { 16410b57cec5SDimitry Andric DefInit *LHSd = dyn_cast<DefInit>(LHS); 16420b57cec5SDimitry Andric VarInit *LHSv = dyn_cast<VarInit>(LHS); 16430b57cec5SDimitry Andric StringInit *LHSs = dyn_cast<StringInit>(LHS); 16440b57cec5SDimitry Andric 16450b57cec5SDimitry Andric DefInit *MHSd = dyn_cast<DefInit>(MHS); 16460b57cec5SDimitry Andric VarInit *MHSv = dyn_cast<VarInit>(MHS); 16470b57cec5SDimitry Andric StringInit *MHSs = dyn_cast<StringInit>(MHS); 16480b57cec5SDimitry Andric 16490b57cec5SDimitry Andric DefInit *RHSd = dyn_cast<DefInit>(RHS); 16500b57cec5SDimitry Andric VarInit *RHSv = dyn_cast<VarInit>(RHS); 16510b57cec5SDimitry Andric StringInit *RHSs = dyn_cast<StringInit>(RHS); 16520b57cec5SDimitry Andric 16530b57cec5SDimitry Andric if (LHSd && MHSd && RHSd) { 16540b57cec5SDimitry Andric Record *Val = RHSd->getDef(); 16550b57cec5SDimitry Andric if (LHSd->getAsString() == RHSd->getAsString()) 16560b57cec5SDimitry Andric Val = MHSd->getDef(); 16570b57cec5SDimitry Andric return DefInit::get(Val); 16580b57cec5SDimitry Andric } 16590b57cec5SDimitry Andric if (LHSv && MHSv && RHSv) { 16605ffd83dbSDimitry Andric std::string Val = std::string(RHSv->getName()); 16610b57cec5SDimitry Andric if (LHSv->getAsString() == RHSv->getAsString()) 16625ffd83dbSDimitry Andric Val = std::string(MHSv->getName()); 16630b57cec5SDimitry Andric return VarInit::get(Val, getType()); 16640b57cec5SDimitry Andric } 16650b57cec5SDimitry Andric if (LHSs && MHSs && RHSs) { 16665ffd83dbSDimitry Andric std::string Val = std::string(RHSs->getValue()); 16670b57cec5SDimitry Andric 16680b57cec5SDimitry Andric std::string::size_type found; 16690b57cec5SDimitry Andric std::string::size_type idx = 0; 16700b57cec5SDimitry Andric while (true) { 16715ffd83dbSDimitry Andric found = Val.find(std::string(LHSs->getValue()), idx); 16720b57cec5SDimitry Andric if (found == std::string::npos) 16730b57cec5SDimitry Andric break; 16745ffd83dbSDimitry Andric Val.replace(found, LHSs->getValue().size(), 16755ffd83dbSDimitry Andric std::string(MHSs->getValue())); 16760b57cec5SDimitry Andric idx = found + MHSs->getValue().size(); 16770b57cec5SDimitry Andric } 16780b57cec5SDimitry Andric 167981ad6265SDimitry Andric return StringInit::get(RK, Val); 16800b57cec5SDimitry Andric } 16810b57cec5SDimitry Andric break; 16820b57cec5SDimitry Andric } 16830b57cec5SDimitry Andric 16840b57cec5SDimitry Andric case FOREACH: { 16850b57cec5SDimitry Andric if (Init *Result = ForeachHelper(LHS, MHS, RHS, getType(), CurRec)) 16860b57cec5SDimitry Andric return Result; 16870b57cec5SDimitry Andric break; 16880b57cec5SDimitry Andric } 16890b57cec5SDimitry Andric 1690e8d8bef9SDimitry Andric case FILTER: { 1691e8d8bef9SDimitry Andric if (Init *Result = FilterHelper(LHS, MHS, RHS, getType(), CurRec)) 1692e8d8bef9SDimitry Andric return Result; 1693e8d8bef9SDimitry Andric break; 1694e8d8bef9SDimitry Andric } 1695e8d8bef9SDimitry Andric 16960b57cec5SDimitry Andric case IF: { 16970b57cec5SDimitry Andric if (IntInit *LHSi = dyn_cast_or_null<IntInit>( 169881ad6265SDimitry Andric LHS->convertInitializerTo(IntRecTy::get(RK)))) { 16990b57cec5SDimitry Andric if (LHSi->getValue()) 17000b57cec5SDimitry Andric return MHS; 17010b57cec5SDimitry Andric return RHS; 17020b57cec5SDimitry Andric } 17030b57cec5SDimitry Andric break; 17040b57cec5SDimitry Andric } 17050b57cec5SDimitry Andric 17060b57cec5SDimitry Andric case DAG: { 17070b57cec5SDimitry Andric ListInit *MHSl = dyn_cast<ListInit>(MHS); 17080b57cec5SDimitry Andric ListInit *RHSl = dyn_cast<ListInit>(RHS); 17090b57cec5SDimitry Andric bool MHSok = MHSl || isa<UnsetInit>(MHS); 17100b57cec5SDimitry Andric bool RHSok = RHSl || isa<UnsetInit>(RHS); 17110b57cec5SDimitry Andric 17120b57cec5SDimitry Andric if (isa<UnsetInit>(MHS) && isa<UnsetInit>(RHS)) 17130b57cec5SDimitry Andric break; // Typically prevented by the parser, but might happen with template args 17140b57cec5SDimitry Andric 17150b57cec5SDimitry Andric if (MHSok && RHSok && (!MHSl || !RHSl || MHSl->size() == RHSl->size())) { 17160b57cec5SDimitry Andric SmallVector<std::pair<Init *, StringInit *>, 8> Children; 17170b57cec5SDimitry Andric unsigned Size = MHSl ? MHSl->size() : RHSl->size(); 17180b57cec5SDimitry Andric for (unsigned i = 0; i != Size; ++i) { 171981ad6265SDimitry Andric Init *Node = MHSl ? MHSl->getElement(i) : UnsetInit::get(RK); 172081ad6265SDimitry Andric Init *Name = RHSl ? RHSl->getElement(i) : UnsetInit::get(RK); 17210b57cec5SDimitry Andric if (!isa<StringInit>(Name) && !isa<UnsetInit>(Name)) 17220b57cec5SDimitry Andric return const_cast<TernOpInit *>(this); 17230b57cec5SDimitry Andric Children.emplace_back(Node, dyn_cast<StringInit>(Name)); 17240b57cec5SDimitry Andric } 17250b57cec5SDimitry Andric return DagInit::get(LHS, nullptr, Children); 17260b57cec5SDimitry Andric } 17270b57cec5SDimitry Andric break; 17280b57cec5SDimitry Andric } 1729e8d8bef9SDimitry Andric 17305f757f3fSDimitry Andric case RANGE: { 17315f757f3fSDimitry Andric auto *LHSi = dyn_cast<IntInit>(LHS); 17325f757f3fSDimitry Andric auto *MHSi = dyn_cast<IntInit>(MHS); 17335f757f3fSDimitry Andric auto *RHSi = dyn_cast<IntInit>(RHS); 17345f757f3fSDimitry Andric if (!LHSi || !MHSi || !RHSi) 17355f757f3fSDimitry Andric break; 17365f757f3fSDimitry Andric 17375f757f3fSDimitry Andric auto Start = LHSi->getValue(); 17385f757f3fSDimitry Andric auto End = MHSi->getValue(); 17395f757f3fSDimitry Andric auto Step = RHSi->getValue(); 17405f757f3fSDimitry Andric if (Step == 0) 17415f757f3fSDimitry Andric PrintError(CurRec->getLoc(), "Step of !range can't be 0"); 17425f757f3fSDimitry Andric 17435f757f3fSDimitry Andric SmallVector<Init *, 8> Args; 17445f757f3fSDimitry Andric if (Start < End && Step > 0) { 17455f757f3fSDimitry Andric Args.reserve((End - Start) / Step); 17465f757f3fSDimitry Andric for (auto I = Start; I < End; I += Step) 17475f757f3fSDimitry Andric Args.push_back(IntInit::get(getRecordKeeper(), I)); 17485f757f3fSDimitry Andric } else if (Start > End && Step < 0) { 17495f757f3fSDimitry Andric Args.reserve((Start - End) / -Step); 17505f757f3fSDimitry Andric for (auto I = Start; I > End; I += Step) 17515f757f3fSDimitry Andric Args.push_back(IntInit::get(getRecordKeeper(), I)); 17525f757f3fSDimitry Andric } else { 17535f757f3fSDimitry Andric // Empty set 17545f757f3fSDimitry Andric } 17555f757f3fSDimitry Andric return ListInit::get(Args, LHSi->getType()); 17565f757f3fSDimitry Andric } 17575f757f3fSDimitry Andric 1758e8d8bef9SDimitry Andric case SUBSTR: { 1759e8d8bef9SDimitry Andric StringInit *LHSs = dyn_cast<StringInit>(LHS); 1760e8d8bef9SDimitry Andric IntInit *MHSi = dyn_cast<IntInit>(MHS); 1761e8d8bef9SDimitry Andric IntInit *RHSi = dyn_cast<IntInit>(RHS); 1762e8d8bef9SDimitry Andric if (LHSs && MHSi && RHSi) { 1763e8d8bef9SDimitry Andric int64_t StringSize = LHSs->getValue().size(); 1764e8d8bef9SDimitry Andric int64_t Start = MHSi->getValue(); 1765e8d8bef9SDimitry Andric int64_t Length = RHSi->getValue(); 1766e8d8bef9SDimitry Andric if (Start < 0 || Start > StringSize) 1767e8d8bef9SDimitry Andric PrintError(CurRec->getLoc(), 1768e8d8bef9SDimitry Andric Twine("!substr start position is out of range 0...") + 1769e8d8bef9SDimitry Andric std::to_string(StringSize) + ": " + 1770e8d8bef9SDimitry Andric std::to_string(Start)); 1771e8d8bef9SDimitry Andric if (Length < 0) 1772e8d8bef9SDimitry Andric PrintError(CurRec->getLoc(), "!substr length must be nonnegative"); 177381ad6265SDimitry Andric return StringInit::get(RK, LHSs->getValue().substr(Start, Length), 1774e8d8bef9SDimitry Andric LHSs->getFormat()); 1775e8d8bef9SDimitry Andric } 1776e8d8bef9SDimitry Andric break; 1777e8d8bef9SDimitry Andric } 1778fe6060f1SDimitry Andric 1779fe6060f1SDimitry Andric case FIND: { 1780fe6060f1SDimitry Andric StringInit *LHSs = dyn_cast<StringInit>(LHS); 1781fe6060f1SDimitry Andric StringInit *MHSs = dyn_cast<StringInit>(MHS); 1782fe6060f1SDimitry Andric IntInit *RHSi = dyn_cast<IntInit>(RHS); 1783fe6060f1SDimitry Andric if (LHSs && MHSs && RHSi) { 1784fe6060f1SDimitry Andric int64_t SourceSize = LHSs->getValue().size(); 1785fe6060f1SDimitry Andric int64_t Start = RHSi->getValue(); 1786fe6060f1SDimitry Andric if (Start < 0 || Start > SourceSize) 1787fe6060f1SDimitry Andric PrintError(CurRec->getLoc(), 1788fe6060f1SDimitry Andric Twine("!find start position is out of range 0...") + 1789fe6060f1SDimitry Andric std::to_string(SourceSize) + ": " + 1790fe6060f1SDimitry Andric std::to_string(Start)); 1791fe6060f1SDimitry Andric auto I = LHSs->getValue().find(MHSs->getValue(), Start); 1792fe6060f1SDimitry Andric if (I == std::string::npos) 179381ad6265SDimitry Andric return IntInit::get(RK, -1); 179481ad6265SDimitry Andric return IntInit::get(RK, I); 1795fe6060f1SDimitry Andric } 1796fe6060f1SDimitry Andric break; 1797fe6060f1SDimitry Andric } 179806c3fb27SDimitry Andric 179906c3fb27SDimitry Andric case SETDAGARG: { 180006c3fb27SDimitry Andric DagInit *Dag = dyn_cast<DagInit>(LHS); 180106c3fb27SDimitry Andric if (Dag && isa<IntInit, StringInit>(MHS)) { 180206c3fb27SDimitry Andric std::string Error; 180306c3fb27SDimitry Andric auto ArgNo = getDagArgNoByKey(Dag, MHS, Error); 180406c3fb27SDimitry Andric if (!ArgNo) 180506c3fb27SDimitry Andric PrintFatalError(CurRec->getLoc(), "!setdagarg " + Error); 180606c3fb27SDimitry Andric 180706c3fb27SDimitry Andric assert(*ArgNo < Dag->getNumArgs()); 180806c3fb27SDimitry Andric 180906c3fb27SDimitry Andric SmallVector<Init *, 8> Args(Dag->getArgs()); 181006c3fb27SDimitry Andric SmallVector<StringInit *, 8> Names(Dag->getArgNames()); 181106c3fb27SDimitry Andric Args[*ArgNo] = RHS; 181206c3fb27SDimitry Andric return DagInit::get(Dag->getOperator(), Dag->getName(), Args, Names); 181306c3fb27SDimitry Andric } 181406c3fb27SDimitry Andric break; 181506c3fb27SDimitry Andric } 181606c3fb27SDimitry Andric 181706c3fb27SDimitry Andric case SETDAGNAME: { 181806c3fb27SDimitry Andric DagInit *Dag = dyn_cast<DagInit>(LHS); 181906c3fb27SDimitry Andric if (Dag && isa<IntInit, StringInit>(MHS)) { 182006c3fb27SDimitry Andric std::string Error; 182106c3fb27SDimitry Andric auto ArgNo = getDagArgNoByKey(Dag, MHS, Error); 182206c3fb27SDimitry Andric if (!ArgNo) 182306c3fb27SDimitry Andric PrintFatalError(CurRec->getLoc(), "!setdagname " + Error); 182406c3fb27SDimitry Andric 182506c3fb27SDimitry Andric assert(*ArgNo < Dag->getNumArgs()); 182606c3fb27SDimitry Andric 182706c3fb27SDimitry Andric SmallVector<Init *, 8> Args(Dag->getArgs()); 182806c3fb27SDimitry Andric SmallVector<StringInit *, 8> Names(Dag->getArgNames()); 182906c3fb27SDimitry Andric Names[*ArgNo] = dyn_cast<StringInit>(RHS); 183006c3fb27SDimitry Andric return DagInit::get(Dag->getOperator(), Dag->getName(), Args, Names); 183106c3fb27SDimitry Andric } 183206c3fb27SDimitry Andric break; 183306c3fb27SDimitry Andric } 18340b57cec5SDimitry Andric } 18350b57cec5SDimitry Andric 18360b57cec5SDimitry Andric return const_cast<TernOpInit *>(this); 18370b57cec5SDimitry Andric } 18380b57cec5SDimitry Andric 18390b57cec5SDimitry Andric Init *TernOpInit::resolveReferences(Resolver &R) const { 18400b57cec5SDimitry Andric Init *lhs = LHS->resolveReferences(R); 18410b57cec5SDimitry Andric 18420b57cec5SDimitry Andric if (getOpcode() == IF && lhs != LHS) { 18430b57cec5SDimitry Andric if (IntInit *Value = dyn_cast_or_null<IntInit>( 184481ad6265SDimitry Andric lhs->convertInitializerTo(IntRecTy::get(getRecordKeeper())))) { 18450b57cec5SDimitry Andric // Short-circuit 18460b57cec5SDimitry Andric if (Value->getValue()) 18470b57cec5SDimitry Andric return MHS->resolveReferences(R); 18480b57cec5SDimitry Andric return RHS->resolveReferences(R); 18490b57cec5SDimitry Andric } 18500b57cec5SDimitry Andric } 18510b57cec5SDimitry Andric 18520b57cec5SDimitry Andric Init *mhs = MHS->resolveReferences(R); 18530b57cec5SDimitry Andric Init *rhs; 18540b57cec5SDimitry Andric 1855e8d8bef9SDimitry Andric if (getOpcode() == FOREACH || getOpcode() == FILTER) { 18560b57cec5SDimitry Andric ShadowResolver SR(R); 18570b57cec5SDimitry Andric SR.addShadow(lhs); 18580b57cec5SDimitry Andric rhs = RHS->resolveReferences(SR); 18590b57cec5SDimitry Andric } else { 18600b57cec5SDimitry Andric rhs = RHS->resolveReferences(R); 18610b57cec5SDimitry Andric } 18620b57cec5SDimitry Andric 18630b57cec5SDimitry Andric if (LHS != lhs || MHS != mhs || RHS != rhs) 18640b57cec5SDimitry Andric return (TernOpInit::get(getOpcode(), lhs, mhs, rhs, getType())) 18650b57cec5SDimitry Andric ->Fold(R.getCurrentRecord()); 18660b57cec5SDimitry Andric return const_cast<TernOpInit *>(this); 18670b57cec5SDimitry Andric } 18680b57cec5SDimitry Andric 18690b57cec5SDimitry Andric std::string TernOpInit::getAsString() const { 18700b57cec5SDimitry Andric std::string Result; 18710b57cec5SDimitry Andric bool UnquotedLHS = false; 18720b57cec5SDimitry Andric switch (getOpcode()) { 1873e8d8bef9SDimitry Andric case DAG: Result = "!dag"; break; 1874e8d8bef9SDimitry Andric case FILTER: Result = "!filter"; UnquotedLHS = true; break; 18750b57cec5SDimitry Andric case FOREACH: Result = "!foreach"; UnquotedLHS = true; break; 18760b57cec5SDimitry Andric case IF: Result = "!if"; break; 18775f757f3fSDimitry Andric case RANGE: 18785f757f3fSDimitry Andric Result = "!range"; 18795f757f3fSDimitry Andric break; 1880e8d8bef9SDimitry Andric case SUBST: Result = "!subst"; break; 1881e8d8bef9SDimitry Andric case SUBSTR: Result = "!substr"; break; 1882fe6060f1SDimitry Andric case FIND: Result = "!find"; break; 188306c3fb27SDimitry Andric case SETDAGARG: 188406c3fb27SDimitry Andric Result = "!setdagarg"; 188506c3fb27SDimitry Andric break; 188606c3fb27SDimitry Andric case SETDAGNAME: 188706c3fb27SDimitry Andric Result = "!setdagname"; 188806c3fb27SDimitry Andric break; 18890b57cec5SDimitry Andric } 18900b57cec5SDimitry Andric return (Result + "(" + 18910b57cec5SDimitry Andric (UnquotedLHS ? LHS->getAsUnquotedString() : LHS->getAsString()) + 18920b57cec5SDimitry Andric ", " + MHS->getAsString() + ", " + RHS->getAsString() + ")"); 18930b57cec5SDimitry Andric } 18940b57cec5SDimitry Andric 1895fe6060f1SDimitry Andric static void ProfileFoldOpInit(FoldingSetNodeID &ID, Init *Start, Init *List, 1896fe6060f1SDimitry Andric Init *A, Init *B, Init *Expr, RecTy *Type) { 18970b57cec5SDimitry Andric ID.AddPointer(Start); 18980b57cec5SDimitry Andric ID.AddPointer(List); 18990b57cec5SDimitry Andric ID.AddPointer(A); 19000b57cec5SDimitry Andric ID.AddPointer(B); 19010b57cec5SDimitry Andric ID.AddPointer(Expr); 19020b57cec5SDimitry Andric ID.AddPointer(Type); 19030b57cec5SDimitry Andric } 19040b57cec5SDimitry Andric 19050b57cec5SDimitry Andric FoldOpInit *FoldOpInit::get(Init *Start, Init *List, Init *A, Init *B, 19060b57cec5SDimitry Andric Init *Expr, RecTy *Type) { 19070b57cec5SDimitry Andric FoldingSetNodeID ID; 19080b57cec5SDimitry Andric ProfileFoldOpInit(ID, Start, List, A, B, Expr, Type); 19090b57cec5SDimitry Andric 191081ad6265SDimitry Andric detail::RecordKeeperImpl &RK = Start->getRecordKeeper().getImpl(); 19110b57cec5SDimitry Andric void *IP = nullptr; 191281ad6265SDimitry Andric if (FoldOpInit *I = RK.TheFoldOpInitPool.FindNodeOrInsertPos(ID, IP)) 19130b57cec5SDimitry Andric return I; 19140b57cec5SDimitry Andric 191581ad6265SDimitry Andric FoldOpInit *I = new (RK.Allocator) FoldOpInit(Start, List, A, B, Expr, Type); 191681ad6265SDimitry Andric RK.TheFoldOpInitPool.InsertNode(I, IP); 19170b57cec5SDimitry Andric return I; 19180b57cec5SDimitry Andric } 19190b57cec5SDimitry Andric 19200b57cec5SDimitry Andric void FoldOpInit::Profile(FoldingSetNodeID &ID) const { 19210b57cec5SDimitry Andric ProfileFoldOpInit(ID, Start, List, A, B, Expr, getType()); 19220b57cec5SDimitry Andric } 19230b57cec5SDimitry Andric 19240b57cec5SDimitry Andric Init *FoldOpInit::Fold(Record *CurRec) const { 19250b57cec5SDimitry Andric if (ListInit *LI = dyn_cast<ListInit>(List)) { 19260b57cec5SDimitry Andric Init *Accum = Start; 19270b57cec5SDimitry Andric for (Init *Elt : *LI) { 19280b57cec5SDimitry Andric MapResolver R(CurRec); 19290b57cec5SDimitry Andric R.set(A, Accum); 19300b57cec5SDimitry Andric R.set(B, Elt); 19310b57cec5SDimitry Andric Accum = Expr->resolveReferences(R); 19320b57cec5SDimitry Andric } 19330b57cec5SDimitry Andric return Accum; 19340b57cec5SDimitry Andric } 19350b57cec5SDimitry Andric return const_cast<FoldOpInit *>(this); 19360b57cec5SDimitry Andric } 19370b57cec5SDimitry Andric 19380b57cec5SDimitry Andric Init *FoldOpInit::resolveReferences(Resolver &R) const { 19390b57cec5SDimitry Andric Init *NewStart = Start->resolveReferences(R); 19400b57cec5SDimitry Andric Init *NewList = List->resolveReferences(R); 19410b57cec5SDimitry Andric ShadowResolver SR(R); 19420b57cec5SDimitry Andric SR.addShadow(A); 19430b57cec5SDimitry Andric SR.addShadow(B); 19440b57cec5SDimitry Andric Init *NewExpr = Expr->resolveReferences(SR); 19450b57cec5SDimitry Andric 19460b57cec5SDimitry Andric if (Start == NewStart && List == NewList && Expr == NewExpr) 19470b57cec5SDimitry Andric return const_cast<FoldOpInit *>(this); 19480b57cec5SDimitry Andric 19490b57cec5SDimitry Andric return get(NewStart, NewList, A, B, NewExpr, getType()) 19500b57cec5SDimitry Andric ->Fold(R.getCurrentRecord()); 19510b57cec5SDimitry Andric } 19520b57cec5SDimitry Andric 19530b57cec5SDimitry Andric Init *FoldOpInit::getBit(unsigned Bit) const { 19540b57cec5SDimitry Andric return VarBitInit::get(const_cast<FoldOpInit *>(this), Bit); 19550b57cec5SDimitry Andric } 19560b57cec5SDimitry Andric 19570b57cec5SDimitry Andric std::string FoldOpInit::getAsString() const { 19580b57cec5SDimitry Andric return (Twine("!foldl(") + Start->getAsString() + ", " + List->getAsString() + 19590b57cec5SDimitry Andric ", " + A->getAsUnquotedString() + ", " + B->getAsUnquotedString() + 19600b57cec5SDimitry Andric ", " + Expr->getAsString() + ")") 19610b57cec5SDimitry Andric .str(); 19620b57cec5SDimitry Andric } 19630b57cec5SDimitry Andric 19640b57cec5SDimitry Andric static void ProfileIsAOpInit(FoldingSetNodeID &ID, RecTy *CheckType, 19650b57cec5SDimitry Andric Init *Expr) { 19660b57cec5SDimitry Andric ID.AddPointer(CheckType); 19670b57cec5SDimitry Andric ID.AddPointer(Expr); 19680b57cec5SDimitry Andric } 19690b57cec5SDimitry Andric 19700b57cec5SDimitry Andric IsAOpInit *IsAOpInit::get(RecTy *CheckType, Init *Expr) { 19710b57cec5SDimitry Andric 19720b57cec5SDimitry Andric FoldingSetNodeID ID; 19730b57cec5SDimitry Andric ProfileIsAOpInit(ID, CheckType, Expr); 19740b57cec5SDimitry Andric 197581ad6265SDimitry Andric detail::RecordKeeperImpl &RK = Expr->getRecordKeeper().getImpl(); 19760b57cec5SDimitry Andric void *IP = nullptr; 197781ad6265SDimitry Andric if (IsAOpInit *I = RK.TheIsAOpInitPool.FindNodeOrInsertPos(ID, IP)) 19780b57cec5SDimitry Andric return I; 19790b57cec5SDimitry Andric 198081ad6265SDimitry Andric IsAOpInit *I = new (RK.Allocator) IsAOpInit(CheckType, Expr); 198181ad6265SDimitry Andric RK.TheIsAOpInitPool.InsertNode(I, IP); 19820b57cec5SDimitry Andric return I; 19830b57cec5SDimitry Andric } 19840b57cec5SDimitry Andric 19850b57cec5SDimitry Andric void IsAOpInit::Profile(FoldingSetNodeID &ID) const { 19860b57cec5SDimitry Andric ProfileIsAOpInit(ID, CheckType, Expr); 19870b57cec5SDimitry Andric } 19880b57cec5SDimitry Andric 19890b57cec5SDimitry Andric Init *IsAOpInit::Fold() const { 19900b57cec5SDimitry Andric if (TypedInit *TI = dyn_cast<TypedInit>(Expr)) { 19910b57cec5SDimitry Andric // Is the expression type known to be (a subclass of) the desired type? 19920b57cec5SDimitry Andric if (TI->getType()->typeIsConvertibleTo(CheckType)) 199381ad6265SDimitry Andric return IntInit::get(getRecordKeeper(), 1); 19940b57cec5SDimitry Andric 19950b57cec5SDimitry Andric if (isa<RecordRecTy>(CheckType)) { 19960b57cec5SDimitry Andric // If the target type is not a subclass of the expression type, or if 19970b57cec5SDimitry Andric // the expression has fully resolved to a record, we know that it can't 19980b57cec5SDimitry Andric // be of the required type. 19990b57cec5SDimitry Andric if (!CheckType->typeIsConvertibleTo(TI->getType()) || isa<DefInit>(Expr)) 200081ad6265SDimitry Andric return IntInit::get(getRecordKeeper(), 0); 20010b57cec5SDimitry Andric } else { 20020b57cec5SDimitry Andric // We treat non-record types as not castable. 200381ad6265SDimitry Andric return IntInit::get(getRecordKeeper(), 0); 20040b57cec5SDimitry Andric } 20050b57cec5SDimitry Andric } 20060b57cec5SDimitry Andric return const_cast<IsAOpInit *>(this); 20070b57cec5SDimitry Andric } 20080b57cec5SDimitry Andric 20090b57cec5SDimitry Andric Init *IsAOpInit::resolveReferences(Resolver &R) const { 20100b57cec5SDimitry Andric Init *NewExpr = Expr->resolveReferences(R); 20110b57cec5SDimitry Andric if (Expr != NewExpr) 20120b57cec5SDimitry Andric return get(CheckType, NewExpr)->Fold(); 20130b57cec5SDimitry Andric return const_cast<IsAOpInit *>(this); 20140b57cec5SDimitry Andric } 20150b57cec5SDimitry Andric 20160b57cec5SDimitry Andric Init *IsAOpInit::getBit(unsigned Bit) const { 20170b57cec5SDimitry Andric return VarBitInit::get(const_cast<IsAOpInit *>(this), Bit); 20180b57cec5SDimitry Andric } 20190b57cec5SDimitry Andric 20200b57cec5SDimitry Andric std::string IsAOpInit::getAsString() const { 20210b57cec5SDimitry Andric return (Twine("!isa<") + CheckType->getAsString() + ">(" + 20220b57cec5SDimitry Andric Expr->getAsString() + ")") 20230b57cec5SDimitry Andric .str(); 20240b57cec5SDimitry Andric } 20250b57cec5SDimitry Andric 202681ad6265SDimitry Andric static void ProfileExistsOpInit(FoldingSetNodeID &ID, RecTy *CheckType, 202781ad6265SDimitry Andric Init *Expr) { 202881ad6265SDimitry Andric ID.AddPointer(CheckType); 202981ad6265SDimitry Andric ID.AddPointer(Expr); 203081ad6265SDimitry Andric } 203181ad6265SDimitry Andric 203281ad6265SDimitry Andric ExistsOpInit *ExistsOpInit::get(RecTy *CheckType, Init *Expr) { 203381ad6265SDimitry Andric FoldingSetNodeID ID; 203481ad6265SDimitry Andric ProfileExistsOpInit(ID, CheckType, Expr); 203581ad6265SDimitry Andric 203681ad6265SDimitry Andric detail::RecordKeeperImpl &RK = Expr->getRecordKeeper().getImpl(); 203781ad6265SDimitry Andric void *IP = nullptr; 203881ad6265SDimitry Andric if (ExistsOpInit *I = RK.TheExistsOpInitPool.FindNodeOrInsertPos(ID, IP)) 203981ad6265SDimitry Andric return I; 204081ad6265SDimitry Andric 204181ad6265SDimitry Andric ExistsOpInit *I = new (RK.Allocator) ExistsOpInit(CheckType, Expr); 204281ad6265SDimitry Andric RK.TheExistsOpInitPool.InsertNode(I, IP); 204381ad6265SDimitry Andric return I; 204481ad6265SDimitry Andric } 204581ad6265SDimitry Andric 204681ad6265SDimitry Andric void ExistsOpInit::Profile(FoldingSetNodeID &ID) const { 204781ad6265SDimitry Andric ProfileExistsOpInit(ID, CheckType, Expr); 204881ad6265SDimitry Andric } 204981ad6265SDimitry Andric 205081ad6265SDimitry Andric Init *ExistsOpInit::Fold(Record *CurRec, bool IsFinal) const { 205181ad6265SDimitry Andric if (StringInit *Name = dyn_cast<StringInit>(Expr)) { 205281ad6265SDimitry Andric 205306c3fb27SDimitry Andric // Look up all defined records to see if we can find one. 205406c3fb27SDimitry Andric Record *D = CheckType->getRecordKeeper().getDef(Name->getValue()); 205506c3fb27SDimitry Andric if (D) { 205606c3fb27SDimitry Andric // Check if types are compatible. 205706c3fb27SDimitry Andric return IntInit::get(getRecordKeeper(), 205806c3fb27SDimitry Andric DefInit::get(D)->getType()->typeIsA(CheckType)); 205906c3fb27SDimitry Andric } 206006c3fb27SDimitry Andric 206106c3fb27SDimitry Andric if (CurRec) { 206281ad6265SDimitry Andric // Self-references are allowed, but their resolution is delayed until 206381ad6265SDimitry Andric // the final resolve to ensure that we get the correct type for them. 206481ad6265SDimitry Andric auto *Anonymous = dyn_cast<AnonymousNameInit>(CurRec->getNameInit()); 206581ad6265SDimitry Andric if (Name == CurRec->getNameInit() || 206681ad6265SDimitry Andric (Anonymous && Name == Anonymous->getNameInit())) { 206781ad6265SDimitry Andric if (!IsFinal) 206881ad6265SDimitry Andric return const_cast<ExistsOpInit *>(this); 206981ad6265SDimitry Andric 207081ad6265SDimitry Andric // No doubt that there exists a record, so we should check if types are 207106c3fb27SDimitry Andric // compatible. 207281ad6265SDimitry Andric return IntInit::get(getRecordKeeper(), 207381ad6265SDimitry Andric CurRec->getType()->typeIsA(CheckType)); 207481ad6265SDimitry Andric } 207506c3fb27SDimitry Andric } 207681ad6265SDimitry Andric 207781ad6265SDimitry Andric if (IsFinal) 207881ad6265SDimitry Andric return IntInit::get(getRecordKeeper(), 0); 207981ad6265SDimitry Andric return const_cast<ExistsOpInit *>(this); 208081ad6265SDimitry Andric } 208181ad6265SDimitry Andric return const_cast<ExistsOpInit *>(this); 208281ad6265SDimitry Andric } 208381ad6265SDimitry Andric 208481ad6265SDimitry Andric Init *ExistsOpInit::resolveReferences(Resolver &R) const { 208581ad6265SDimitry Andric Init *NewExpr = Expr->resolveReferences(R); 208681ad6265SDimitry Andric if (Expr != NewExpr || R.isFinal()) 208781ad6265SDimitry Andric return get(CheckType, NewExpr)->Fold(R.getCurrentRecord(), R.isFinal()); 208881ad6265SDimitry Andric return const_cast<ExistsOpInit *>(this); 208981ad6265SDimitry Andric } 209081ad6265SDimitry Andric 209181ad6265SDimitry Andric Init *ExistsOpInit::getBit(unsigned Bit) const { 209281ad6265SDimitry Andric return VarBitInit::get(const_cast<ExistsOpInit *>(this), Bit); 209381ad6265SDimitry Andric } 209481ad6265SDimitry Andric 209581ad6265SDimitry Andric std::string ExistsOpInit::getAsString() const { 209681ad6265SDimitry Andric return (Twine("!exists<") + CheckType->getAsString() + ">(" + 209781ad6265SDimitry Andric Expr->getAsString() + ")") 209881ad6265SDimitry Andric .str(); 209981ad6265SDimitry Andric } 210081ad6265SDimitry Andric 21010b57cec5SDimitry Andric RecTy *TypedInit::getFieldType(StringInit *FieldName) const { 21020b57cec5SDimitry Andric if (RecordRecTy *RecordType = dyn_cast<RecordRecTy>(getType())) { 21030b57cec5SDimitry Andric for (Record *Rec : RecordType->getClasses()) { 21040b57cec5SDimitry Andric if (RecordVal *Field = Rec->getValue(FieldName)) 21050b57cec5SDimitry Andric return Field->getType(); 21060b57cec5SDimitry Andric } 21070b57cec5SDimitry Andric } 21080b57cec5SDimitry Andric return nullptr; 21090b57cec5SDimitry Andric } 21100b57cec5SDimitry Andric 21110b57cec5SDimitry Andric Init * 21120b57cec5SDimitry Andric TypedInit::convertInitializerTo(RecTy *Ty) const { 21130b57cec5SDimitry Andric if (getType() == Ty || getType()->typeIsA(Ty)) 21140b57cec5SDimitry Andric return const_cast<TypedInit *>(this); 21150b57cec5SDimitry Andric 21160b57cec5SDimitry Andric if (isa<BitRecTy>(getType()) && isa<BitsRecTy>(Ty) && 21170b57cec5SDimitry Andric cast<BitsRecTy>(Ty)->getNumBits() == 1) 211881ad6265SDimitry Andric return BitsInit::get(getRecordKeeper(), {const_cast<TypedInit *>(this)}); 21190b57cec5SDimitry Andric 21200b57cec5SDimitry Andric return nullptr; 21210b57cec5SDimitry Andric } 21220b57cec5SDimitry Andric 21230b57cec5SDimitry Andric Init *TypedInit::convertInitializerBitRange(ArrayRef<unsigned> Bits) const { 21240b57cec5SDimitry Andric BitsRecTy *T = dyn_cast<BitsRecTy>(getType()); 21250b57cec5SDimitry Andric if (!T) return nullptr; // Cannot subscript a non-bits variable. 21260b57cec5SDimitry Andric unsigned NumBits = T->getNumBits(); 21270b57cec5SDimitry Andric 21280b57cec5SDimitry Andric SmallVector<Init *, 16> NewBits; 21290b57cec5SDimitry Andric NewBits.reserve(Bits.size()); 21300b57cec5SDimitry Andric for (unsigned Bit : Bits) { 21310b57cec5SDimitry Andric if (Bit >= NumBits) 21320b57cec5SDimitry Andric return nullptr; 21330b57cec5SDimitry Andric 21340b57cec5SDimitry Andric NewBits.push_back(VarBitInit::get(const_cast<TypedInit *>(this), Bit)); 21350b57cec5SDimitry Andric } 213681ad6265SDimitry Andric return BitsInit::get(getRecordKeeper(), NewBits); 21370b57cec5SDimitry Andric } 21380b57cec5SDimitry Andric 21390b57cec5SDimitry Andric Init *TypedInit::getCastTo(RecTy *Ty) const { 21400b57cec5SDimitry Andric // Handle the common case quickly 21410b57cec5SDimitry Andric if (getType() == Ty || getType()->typeIsA(Ty)) 21420b57cec5SDimitry Andric return const_cast<TypedInit *>(this); 21430b57cec5SDimitry Andric 21440b57cec5SDimitry Andric if (Init *Converted = convertInitializerTo(Ty)) { 21450b57cec5SDimitry Andric assert(!isa<TypedInit>(Converted) || 21460b57cec5SDimitry Andric cast<TypedInit>(Converted)->getType()->typeIsA(Ty)); 21470b57cec5SDimitry Andric return Converted; 21480b57cec5SDimitry Andric } 21490b57cec5SDimitry Andric 21500b57cec5SDimitry Andric if (!getType()->typeIsConvertibleTo(Ty)) 21510b57cec5SDimitry Andric return nullptr; 21520b57cec5SDimitry Andric 21530b57cec5SDimitry Andric return UnOpInit::get(UnOpInit::CAST, const_cast<TypedInit *>(this), Ty) 21540b57cec5SDimitry Andric ->Fold(nullptr); 21550b57cec5SDimitry Andric } 21560b57cec5SDimitry Andric 21570b57cec5SDimitry Andric VarInit *VarInit::get(StringRef VN, RecTy *T) { 215881ad6265SDimitry Andric Init *Value = StringInit::get(T->getRecordKeeper(), VN); 21590b57cec5SDimitry Andric return VarInit::get(Value, T); 21600b57cec5SDimitry Andric } 21610b57cec5SDimitry Andric 21620b57cec5SDimitry Andric VarInit *VarInit::get(Init *VN, RecTy *T) { 216381ad6265SDimitry Andric detail::RecordKeeperImpl &RK = T->getRecordKeeper().getImpl(); 216481ad6265SDimitry Andric VarInit *&I = RK.TheVarInitPool[std::make_pair(T, VN)]; 21650b57cec5SDimitry Andric if (!I) 216681ad6265SDimitry Andric I = new (RK.Allocator) VarInit(VN, T); 21670b57cec5SDimitry Andric return I; 21680b57cec5SDimitry Andric } 21690b57cec5SDimitry Andric 21700b57cec5SDimitry Andric StringRef VarInit::getName() const { 21710b57cec5SDimitry Andric StringInit *NameString = cast<StringInit>(getNameInit()); 21720b57cec5SDimitry Andric return NameString->getValue(); 21730b57cec5SDimitry Andric } 21740b57cec5SDimitry Andric 21750b57cec5SDimitry Andric Init *VarInit::getBit(unsigned Bit) const { 217681ad6265SDimitry Andric if (getType() == BitRecTy::get(getRecordKeeper())) 21770b57cec5SDimitry Andric return const_cast<VarInit*>(this); 21780b57cec5SDimitry Andric return VarBitInit::get(const_cast<VarInit*>(this), Bit); 21790b57cec5SDimitry Andric } 21800b57cec5SDimitry Andric 21810b57cec5SDimitry Andric Init *VarInit::resolveReferences(Resolver &R) const { 21820b57cec5SDimitry Andric if (Init *Val = R.resolve(VarName)) 21830b57cec5SDimitry Andric return Val; 21840b57cec5SDimitry Andric return const_cast<VarInit *>(this); 21850b57cec5SDimitry Andric } 21860b57cec5SDimitry Andric 21870b57cec5SDimitry Andric VarBitInit *VarBitInit::get(TypedInit *T, unsigned B) { 218881ad6265SDimitry Andric detail::RecordKeeperImpl &RK = T->getRecordKeeper().getImpl(); 218981ad6265SDimitry Andric VarBitInit *&I = RK.TheVarBitInitPool[std::make_pair(T, B)]; 21900b57cec5SDimitry Andric if (!I) 219181ad6265SDimitry Andric I = new (RK.Allocator) VarBitInit(T, B); 21920b57cec5SDimitry Andric return I; 21930b57cec5SDimitry Andric } 21940b57cec5SDimitry Andric 21950b57cec5SDimitry Andric std::string VarBitInit::getAsString() const { 21960b57cec5SDimitry Andric return TI->getAsString() + "{" + utostr(Bit) + "}"; 21970b57cec5SDimitry Andric } 21980b57cec5SDimitry Andric 21990b57cec5SDimitry Andric Init *VarBitInit::resolveReferences(Resolver &R) const { 22000b57cec5SDimitry Andric Init *I = TI->resolveReferences(R); 22010b57cec5SDimitry Andric if (TI != I) 22020b57cec5SDimitry Andric return I->getBit(getBitNum()); 22030b57cec5SDimitry Andric 22040b57cec5SDimitry Andric return const_cast<VarBitInit*>(this); 22050b57cec5SDimitry Andric } 22060b57cec5SDimitry Andric 22070b57cec5SDimitry Andric DefInit::DefInit(Record *D) 22080b57cec5SDimitry Andric : TypedInit(IK_DefInit, D->getType()), Def(D) {} 22090b57cec5SDimitry Andric 22100b57cec5SDimitry Andric DefInit *DefInit::get(Record *R) { 22110b57cec5SDimitry Andric return R->getDefInit(); 22120b57cec5SDimitry Andric } 22130b57cec5SDimitry Andric 22140b57cec5SDimitry Andric Init *DefInit::convertInitializerTo(RecTy *Ty) const { 22150b57cec5SDimitry Andric if (auto *RRT = dyn_cast<RecordRecTy>(Ty)) 22160b57cec5SDimitry Andric if (getType()->typeIsConvertibleTo(RRT)) 22170b57cec5SDimitry Andric return const_cast<DefInit *>(this); 22180b57cec5SDimitry Andric return nullptr; 22190b57cec5SDimitry Andric } 22200b57cec5SDimitry Andric 22210b57cec5SDimitry Andric RecTy *DefInit::getFieldType(StringInit *FieldName) const { 22220b57cec5SDimitry Andric if (const RecordVal *RV = Def->getValue(FieldName)) 22230b57cec5SDimitry Andric return RV->getType(); 22240b57cec5SDimitry Andric return nullptr; 22250b57cec5SDimitry Andric } 22260b57cec5SDimitry Andric 22275ffd83dbSDimitry Andric std::string DefInit::getAsString() const { return std::string(Def->getName()); } 22280b57cec5SDimitry Andric 222906c3fb27SDimitry Andric static void ProfileVarDefInit(FoldingSetNodeID &ID, Record *Class, 223006c3fb27SDimitry Andric ArrayRef<ArgumentInit *> Args) { 22310b57cec5SDimitry Andric ID.AddInteger(Args.size()); 22320b57cec5SDimitry Andric ID.AddPointer(Class); 22330b57cec5SDimitry Andric 22340b57cec5SDimitry Andric for (Init *I : Args) 22350b57cec5SDimitry Andric ID.AddPointer(I); 22360b57cec5SDimitry Andric } 22370b57cec5SDimitry Andric 223881ad6265SDimitry Andric VarDefInit::VarDefInit(Record *Class, unsigned N) 223981ad6265SDimitry Andric : TypedInit(IK_VarDefInit, RecordRecTy::get(Class)), Class(Class), 224081ad6265SDimitry Andric NumArgs(N) {} 224181ad6265SDimitry Andric 224206c3fb27SDimitry Andric VarDefInit *VarDefInit::get(Record *Class, ArrayRef<ArgumentInit *> Args) { 22430b57cec5SDimitry Andric FoldingSetNodeID ID; 22440b57cec5SDimitry Andric ProfileVarDefInit(ID, Class, Args); 22450b57cec5SDimitry Andric 224681ad6265SDimitry Andric detail::RecordKeeperImpl &RK = Class->getRecords().getImpl(); 22470b57cec5SDimitry Andric void *IP = nullptr; 224881ad6265SDimitry Andric if (VarDefInit *I = RK.TheVarDefInitPool.FindNodeOrInsertPos(ID, IP)) 22490b57cec5SDimitry Andric return I; 22500b57cec5SDimitry Andric 225106c3fb27SDimitry Andric void *Mem = RK.Allocator.Allocate( 225206c3fb27SDimitry Andric totalSizeToAlloc<ArgumentInit *>(Args.size()), alignof(VarDefInit)); 22530b57cec5SDimitry Andric VarDefInit *I = new (Mem) VarDefInit(Class, Args.size()); 22540b57cec5SDimitry Andric std::uninitialized_copy(Args.begin(), Args.end(), 225506c3fb27SDimitry Andric I->getTrailingObjects<ArgumentInit *>()); 225681ad6265SDimitry Andric RK.TheVarDefInitPool.InsertNode(I, IP); 22570b57cec5SDimitry Andric return I; 22580b57cec5SDimitry Andric } 22590b57cec5SDimitry Andric 22600b57cec5SDimitry Andric void VarDefInit::Profile(FoldingSetNodeID &ID) const { 22610b57cec5SDimitry Andric ProfileVarDefInit(ID, Class, args()); 22620b57cec5SDimitry Andric } 22630b57cec5SDimitry Andric 22640b57cec5SDimitry Andric DefInit *VarDefInit::instantiate() { 22650b57cec5SDimitry Andric if (!Def) { 22660b57cec5SDimitry Andric RecordKeeper &Records = Class->getRecords(); 22675f757f3fSDimitry Andric auto NewRecOwner = 22685f757f3fSDimitry Andric std::make_unique<Record>(Records.getNewAnonymousName(), Class->getLoc(), 22695f757f3fSDimitry Andric Records, Record::RK_AnonymousDef); 22700b57cec5SDimitry Andric Record *NewRec = NewRecOwner.get(); 22710b57cec5SDimitry Andric 22720b57cec5SDimitry Andric // Copy values from class to instance 22730b57cec5SDimitry Andric for (const RecordVal &Val : Class->getValues()) 22740b57cec5SDimitry Andric NewRec->addValue(Val); 22750b57cec5SDimitry Andric 2276fe6060f1SDimitry Andric // Copy assertions from class to instance. 2277fe6060f1SDimitry Andric NewRec->appendAssertions(Class); 2278fe6060f1SDimitry Andric 22795f757f3fSDimitry Andric // Copy dumps from class to instance. 22805f757f3fSDimitry Andric NewRec->appendDumps(Class); 22815f757f3fSDimitry Andric 22820b57cec5SDimitry Andric // Substitute and resolve template arguments 22830b57cec5SDimitry Andric ArrayRef<Init *> TArgs = Class->getTemplateArgs(); 22840b57cec5SDimitry Andric MapResolver R(NewRec); 22850b57cec5SDimitry Andric 2286*0fca6ea1SDimitry Andric for (Init *Arg : TArgs) { 2287*0fca6ea1SDimitry Andric R.set(Arg, NewRec->getValue(Arg)->getValue()); 2288*0fca6ea1SDimitry Andric NewRec->removeValue(Arg); 228906c3fb27SDimitry Andric } 22900b57cec5SDimitry Andric 229106c3fb27SDimitry Andric for (auto *Arg : args()) { 229206c3fb27SDimitry Andric if (Arg->isPositional()) 229306c3fb27SDimitry Andric R.set(TArgs[Arg->getIndex()], Arg->getValue()); 229406c3fb27SDimitry Andric if (Arg->isNamed()) 229506c3fb27SDimitry Andric R.set(Arg->getName(), Arg->getValue()); 22960b57cec5SDimitry Andric } 22970b57cec5SDimitry Andric 22980b57cec5SDimitry Andric NewRec->resolveReferences(R); 22990b57cec5SDimitry Andric 23000b57cec5SDimitry Andric // Add superclasses. 23010b57cec5SDimitry Andric ArrayRef<std::pair<Record *, SMRange>> SCs = Class->getSuperClasses(); 23020b57cec5SDimitry Andric for (const auto &SCPair : SCs) 23030b57cec5SDimitry Andric NewRec->addSuperClass(SCPair.first, SCPair.second); 23040b57cec5SDimitry Andric 23050b57cec5SDimitry Andric NewRec->addSuperClass(Class, 23060b57cec5SDimitry Andric SMRange(Class->getLoc().back(), 23070b57cec5SDimitry Andric Class->getLoc().back())); 23080b57cec5SDimitry Andric 23090b57cec5SDimitry Andric // Resolve internal references and store in record keeper 23100b57cec5SDimitry Andric NewRec->resolveReferences(); 23110b57cec5SDimitry Andric Records.addDef(std::move(NewRecOwner)); 23120b57cec5SDimitry Andric 2313fe6060f1SDimitry Andric // Check the assertions. 2314fe6060f1SDimitry Andric NewRec->checkRecordAssertions(); 2315fe6060f1SDimitry Andric 23165f757f3fSDimitry Andric // Check the assertions. 23175f757f3fSDimitry Andric NewRec->emitRecordDumps(); 23185f757f3fSDimitry Andric 23190b57cec5SDimitry Andric Def = DefInit::get(NewRec); 23200b57cec5SDimitry Andric } 23210b57cec5SDimitry Andric 23220b57cec5SDimitry Andric return Def; 23230b57cec5SDimitry Andric } 23240b57cec5SDimitry Andric 23250b57cec5SDimitry Andric Init *VarDefInit::resolveReferences(Resolver &R) const { 23260b57cec5SDimitry Andric TrackUnresolvedResolver UR(&R); 23270b57cec5SDimitry Andric bool Changed = false; 232806c3fb27SDimitry Andric SmallVector<ArgumentInit *, 8> NewArgs; 23290b57cec5SDimitry Andric NewArgs.reserve(args_size()); 23300b57cec5SDimitry Andric 233106c3fb27SDimitry Andric for (ArgumentInit *Arg : args()) { 233206c3fb27SDimitry Andric auto *NewArg = cast<ArgumentInit>(Arg->resolveReferences(UR)); 23330b57cec5SDimitry Andric NewArgs.push_back(NewArg); 23340b57cec5SDimitry Andric Changed |= NewArg != Arg; 23350b57cec5SDimitry Andric } 23360b57cec5SDimitry Andric 23370b57cec5SDimitry Andric if (Changed) { 23380b57cec5SDimitry Andric auto New = VarDefInit::get(Class, NewArgs); 23390b57cec5SDimitry Andric if (!UR.foundUnresolved()) 23400b57cec5SDimitry Andric return New->instantiate(); 23410b57cec5SDimitry Andric return New; 23420b57cec5SDimitry Andric } 23430b57cec5SDimitry Andric return const_cast<VarDefInit *>(this); 23440b57cec5SDimitry Andric } 23450b57cec5SDimitry Andric 23460b57cec5SDimitry Andric Init *VarDefInit::Fold() const { 23470b57cec5SDimitry Andric if (Def) 23480b57cec5SDimitry Andric return Def; 23490b57cec5SDimitry Andric 23500b57cec5SDimitry Andric TrackUnresolvedResolver R; 23510b57cec5SDimitry Andric for (Init *Arg : args()) 23520b57cec5SDimitry Andric Arg->resolveReferences(R); 23530b57cec5SDimitry Andric 23540b57cec5SDimitry Andric if (!R.foundUnresolved()) 23550b57cec5SDimitry Andric return const_cast<VarDefInit *>(this)->instantiate(); 23560b57cec5SDimitry Andric return const_cast<VarDefInit *>(this); 23570b57cec5SDimitry Andric } 23580b57cec5SDimitry Andric 23590b57cec5SDimitry Andric std::string VarDefInit::getAsString() const { 23600b57cec5SDimitry Andric std::string Result = Class->getNameInitAsString() + "<"; 23610b57cec5SDimitry Andric const char *sep = ""; 23620b57cec5SDimitry Andric for (Init *Arg : args()) { 23630b57cec5SDimitry Andric Result += sep; 23640b57cec5SDimitry Andric sep = ", "; 23650b57cec5SDimitry Andric Result += Arg->getAsString(); 23660b57cec5SDimitry Andric } 23670b57cec5SDimitry Andric return Result + ">"; 23680b57cec5SDimitry Andric } 23690b57cec5SDimitry Andric 23700b57cec5SDimitry Andric FieldInit *FieldInit::get(Init *R, StringInit *FN) { 237181ad6265SDimitry Andric detail::RecordKeeperImpl &RK = R->getRecordKeeper().getImpl(); 237281ad6265SDimitry Andric FieldInit *&I = RK.TheFieldInitPool[std::make_pair(R, FN)]; 2373349cc55cSDimitry Andric if (!I) 237481ad6265SDimitry Andric I = new (RK.Allocator) FieldInit(R, FN); 23750b57cec5SDimitry Andric return I; 23760b57cec5SDimitry Andric } 23770b57cec5SDimitry Andric 23780b57cec5SDimitry Andric Init *FieldInit::getBit(unsigned Bit) const { 237981ad6265SDimitry Andric if (getType() == BitRecTy::get(getRecordKeeper())) 23800b57cec5SDimitry Andric return const_cast<FieldInit*>(this); 23810b57cec5SDimitry Andric return VarBitInit::get(const_cast<FieldInit*>(this), Bit); 23820b57cec5SDimitry Andric } 23830b57cec5SDimitry Andric 23840b57cec5SDimitry Andric Init *FieldInit::resolveReferences(Resolver &R) const { 23850b57cec5SDimitry Andric Init *NewRec = Rec->resolveReferences(R); 23860b57cec5SDimitry Andric if (NewRec != Rec) 23870b57cec5SDimitry Andric return FieldInit::get(NewRec, FieldName)->Fold(R.getCurrentRecord()); 23880b57cec5SDimitry Andric return const_cast<FieldInit *>(this); 23890b57cec5SDimitry Andric } 23900b57cec5SDimitry Andric 23910b57cec5SDimitry Andric Init *FieldInit::Fold(Record *CurRec) const { 23920b57cec5SDimitry Andric if (DefInit *DI = dyn_cast<DefInit>(Rec)) { 23930b57cec5SDimitry Andric Record *Def = DI->getDef(); 23940b57cec5SDimitry Andric if (Def == CurRec) 23950b57cec5SDimitry Andric PrintFatalError(CurRec->getLoc(), 23960b57cec5SDimitry Andric Twine("Attempting to access field '") + 23970b57cec5SDimitry Andric FieldName->getAsUnquotedString() + "' of '" + 23980b57cec5SDimitry Andric Rec->getAsString() + "' is a forbidden self-reference"); 23990b57cec5SDimitry Andric Init *FieldVal = Def->getValue(FieldName)->getValue(); 2400fe6060f1SDimitry Andric if (FieldVal->isConcrete()) 24010b57cec5SDimitry Andric return FieldVal; 24020b57cec5SDimitry Andric } 24030b57cec5SDimitry Andric return const_cast<FieldInit *>(this); 24040b57cec5SDimitry Andric } 24050b57cec5SDimitry Andric 24065ffd83dbSDimitry Andric bool FieldInit::isConcrete() const { 24075ffd83dbSDimitry Andric if (DefInit *DI = dyn_cast<DefInit>(Rec)) { 24085ffd83dbSDimitry Andric Init *FieldVal = DI->getDef()->getValue(FieldName)->getValue(); 24095ffd83dbSDimitry Andric return FieldVal->isConcrete(); 24105ffd83dbSDimitry Andric } 24115ffd83dbSDimitry Andric return false; 24125ffd83dbSDimitry Andric } 24135ffd83dbSDimitry Andric 24140b57cec5SDimitry Andric static void ProfileCondOpInit(FoldingSetNodeID &ID, 24150b57cec5SDimitry Andric ArrayRef<Init *> CondRange, 24160b57cec5SDimitry Andric ArrayRef<Init *> ValRange, 24170b57cec5SDimitry Andric const RecTy *ValType) { 24180b57cec5SDimitry Andric assert(CondRange.size() == ValRange.size() && 24190b57cec5SDimitry Andric "Number of conditions and values must match!"); 24200b57cec5SDimitry Andric ID.AddPointer(ValType); 24210b57cec5SDimitry Andric ArrayRef<Init *>::iterator Case = CondRange.begin(); 24220b57cec5SDimitry Andric ArrayRef<Init *>::iterator Val = ValRange.begin(); 24230b57cec5SDimitry Andric 24240b57cec5SDimitry Andric while (Case != CondRange.end()) { 24250b57cec5SDimitry Andric ID.AddPointer(*Case++); 24260b57cec5SDimitry Andric ID.AddPointer(*Val++); 24270b57cec5SDimitry Andric } 24280b57cec5SDimitry Andric } 24290b57cec5SDimitry Andric 24300b57cec5SDimitry Andric void CondOpInit::Profile(FoldingSetNodeID &ID) const { 2431bdd1243dSDimitry Andric ProfileCondOpInit(ID, ArrayRef(getTrailingObjects<Init *>(), NumConds), 2432bdd1243dSDimitry Andric ArrayRef(getTrailingObjects<Init *>() + NumConds, NumConds), 24330b57cec5SDimitry Andric ValType); 24340b57cec5SDimitry Andric } 24350b57cec5SDimitry Andric 243681ad6265SDimitry Andric CondOpInit *CondOpInit::get(ArrayRef<Init *> CondRange, 24370b57cec5SDimitry Andric ArrayRef<Init *> ValRange, RecTy *Ty) { 24380b57cec5SDimitry Andric assert(CondRange.size() == ValRange.size() && 24390b57cec5SDimitry Andric "Number of conditions and values must match!"); 24400b57cec5SDimitry Andric 24410b57cec5SDimitry Andric FoldingSetNodeID ID; 24420b57cec5SDimitry Andric ProfileCondOpInit(ID, CondRange, ValRange, Ty); 24430b57cec5SDimitry Andric 244481ad6265SDimitry Andric detail::RecordKeeperImpl &RK = Ty->getRecordKeeper().getImpl(); 24450b57cec5SDimitry Andric void *IP = nullptr; 244681ad6265SDimitry Andric if (CondOpInit *I = RK.TheCondOpInitPool.FindNodeOrInsertPos(ID, IP)) 24470b57cec5SDimitry Andric return I; 24480b57cec5SDimitry Andric 244981ad6265SDimitry Andric void *Mem = RK.Allocator.Allocate( 2450349cc55cSDimitry Andric totalSizeToAlloc<Init *>(2 * CondRange.size()), alignof(BitsInit)); 24510b57cec5SDimitry Andric CondOpInit *I = new(Mem) CondOpInit(CondRange.size(), Ty); 24520b57cec5SDimitry Andric 24530b57cec5SDimitry Andric std::uninitialized_copy(CondRange.begin(), CondRange.end(), 24540b57cec5SDimitry Andric I->getTrailingObjects<Init *>()); 24550b57cec5SDimitry Andric std::uninitialized_copy(ValRange.begin(), ValRange.end(), 24560b57cec5SDimitry Andric I->getTrailingObjects<Init *>()+CondRange.size()); 245781ad6265SDimitry Andric RK.TheCondOpInitPool.InsertNode(I, IP); 24580b57cec5SDimitry Andric return I; 24590b57cec5SDimitry Andric } 24600b57cec5SDimitry Andric 24610b57cec5SDimitry Andric Init *CondOpInit::resolveReferences(Resolver &R) const { 24620b57cec5SDimitry Andric SmallVector<Init*, 4> NewConds; 24630b57cec5SDimitry Andric bool Changed = false; 24640b57cec5SDimitry Andric for (const Init *Case : getConds()) { 24650b57cec5SDimitry Andric Init *NewCase = Case->resolveReferences(R); 24660b57cec5SDimitry Andric NewConds.push_back(NewCase); 24670b57cec5SDimitry Andric Changed |= NewCase != Case; 24680b57cec5SDimitry Andric } 24690b57cec5SDimitry Andric 24700b57cec5SDimitry Andric SmallVector<Init*, 4> NewVals; 24710b57cec5SDimitry Andric for (const Init *Val : getVals()) { 24720b57cec5SDimitry Andric Init *NewVal = Val->resolveReferences(R); 24730b57cec5SDimitry Andric NewVals.push_back(NewVal); 24740b57cec5SDimitry Andric Changed |= NewVal != Val; 24750b57cec5SDimitry Andric } 24760b57cec5SDimitry Andric 24770b57cec5SDimitry Andric if (Changed) 24780b57cec5SDimitry Andric return (CondOpInit::get(NewConds, NewVals, 24790b57cec5SDimitry Andric getValType()))->Fold(R.getCurrentRecord()); 24800b57cec5SDimitry Andric 24810b57cec5SDimitry Andric return const_cast<CondOpInit *>(this); 24820b57cec5SDimitry Andric } 24830b57cec5SDimitry Andric 24840b57cec5SDimitry Andric Init *CondOpInit::Fold(Record *CurRec) const { 248581ad6265SDimitry Andric RecordKeeper &RK = getRecordKeeper(); 24860b57cec5SDimitry Andric for ( unsigned i = 0; i < NumConds; ++i) { 24870b57cec5SDimitry Andric Init *Cond = getCond(i); 24880b57cec5SDimitry Andric Init *Val = getVal(i); 24890b57cec5SDimitry Andric 24900b57cec5SDimitry Andric if (IntInit *CondI = dyn_cast_or_null<IntInit>( 249181ad6265SDimitry Andric Cond->convertInitializerTo(IntRecTy::get(RK)))) { 24920b57cec5SDimitry Andric if (CondI->getValue()) 24930b57cec5SDimitry Andric return Val->convertInitializerTo(getValType()); 249481ad6265SDimitry Andric } else { 24950b57cec5SDimitry Andric return const_cast<CondOpInit *>(this); 24960b57cec5SDimitry Andric } 249781ad6265SDimitry Andric } 24980b57cec5SDimitry Andric 24990b57cec5SDimitry Andric PrintFatalError(CurRec->getLoc(), 250006c3fb27SDimitry Andric CurRec->getNameInitAsString() + 25010b57cec5SDimitry Andric " does not have any true condition in:" + 25020b57cec5SDimitry Andric this->getAsString()); 25030b57cec5SDimitry Andric return nullptr; 25040b57cec5SDimitry Andric } 25050b57cec5SDimitry Andric 25060b57cec5SDimitry Andric bool CondOpInit::isConcrete() const { 25070b57cec5SDimitry Andric for (const Init *Case : getConds()) 25080b57cec5SDimitry Andric if (!Case->isConcrete()) 25090b57cec5SDimitry Andric return false; 25100b57cec5SDimitry Andric 25110b57cec5SDimitry Andric for (const Init *Val : getVals()) 25120b57cec5SDimitry Andric if (!Val->isConcrete()) 25130b57cec5SDimitry Andric return false; 25140b57cec5SDimitry Andric 25150b57cec5SDimitry Andric return true; 25160b57cec5SDimitry Andric } 25170b57cec5SDimitry Andric 25180b57cec5SDimitry Andric bool CondOpInit::isComplete() const { 25190b57cec5SDimitry Andric for (const Init *Case : getConds()) 25200b57cec5SDimitry Andric if (!Case->isComplete()) 25210b57cec5SDimitry Andric return false; 25220b57cec5SDimitry Andric 25230b57cec5SDimitry Andric for (const Init *Val : getVals()) 25240b57cec5SDimitry Andric if (!Val->isConcrete()) 25250b57cec5SDimitry Andric return false; 25260b57cec5SDimitry Andric 25270b57cec5SDimitry Andric return true; 25280b57cec5SDimitry Andric } 25290b57cec5SDimitry Andric 25300b57cec5SDimitry Andric std::string CondOpInit::getAsString() const { 25310b57cec5SDimitry Andric std::string Result = "!cond("; 25320b57cec5SDimitry Andric for (unsigned i = 0; i < getNumConds(); i++) { 25330b57cec5SDimitry Andric Result += getCond(i)->getAsString() + ": "; 25340b57cec5SDimitry Andric Result += getVal(i)->getAsString(); 25350b57cec5SDimitry Andric if (i != getNumConds()-1) 25360b57cec5SDimitry Andric Result += ", "; 25370b57cec5SDimitry Andric } 25380b57cec5SDimitry Andric return Result + ")"; 25390b57cec5SDimitry Andric } 25400b57cec5SDimitry Andric 25410b57cec5SDimitry Andric Init *CondOpInit::getBit(unsigned Bit) const { 25420b57cec5SDimitry Andric return VarBitInit::get(const_cast<CondOpInit *>(this), Bit); 25430b57cec5SDimitry Andric } 25440b57cec5SDimitry Andric 25450b57cec5SDimitry Andric static void ProfileDagInit(FoldingSetNodeID &ID, Init *V, StringInit *VN, 25460b57cec5SDimitry Andric ArrayRef<Init *> ArgRange, 25470b57cec5SDimitry Andric ArrayRef<StringInit *> NameRange) { 25480b57cec5SDimitry Andric ID.AddPointer(V); 25490b57cec5SDimitry Andric ID.AddPointer(VN); 25500b57cec5SDimitry Andric 25510b57cec5SDimitry Andric ArrayRef<Init *>::iterator Arg = ArgRange.begin(); 25520b57cec5SDimitry Andric ArrayRef<StringInit *>::iterator Name = NameRange.begin(); 25530b57cec5SDimitry Andric while (Arg != ArgRange.end()) { 25540b57cec5SDimitry Andric assert(Name != NameRange.end() && "Arg name underflow!"); 25550b57cec5SDimitry Andric ID.AddPointer(*Arg++); 25560b57cec5SDimitry Andric ID.AddPointer(*Name++); 25570b57cec5SDimitry Andric } 25580b57cec5SDimitry Andric assert(Name == NameRange.end() && "Arg name overflow!"); 25590b57cec5SDimitry Andric } 25600b57cec5SDimitry Andric 2561349cc55cSDimitry Andric DagInit *DagInit::get(Init *V, StringInit *VN, ArrayRef<Init *> ArgRange, 25620b57cec5SDimitry Andric ArrayRef<StringInit *> NameRange) { 2563bdd1243dSDimitry Andric assert(ArgRange.size() == NameRange.size()); 25640b57cec5SDimitry Andric FoldingSetNodeID ID; 25650b57cec5SDimitry Andric ProfileDagInit(ID, V, VN, ArgRange, NameRange); 25660b57cec5SDimitry Andric 256781ad6265SDimitry Andric detail::RecordKeeperImpl &RK = V->getRecordKeeper().getImpl(); 25680b57cec5SDimitry Andric void *IP = nullptr; 256981ad6265SDimitry Andric if (DagInit *I = RK.TheDagInitPool.FindNodeOrInsertPos(ID, IP)) 25700b57cec5SDimitry Andric return I; 25710b57cec5SDimitry Andric 257281ad6265SDimitry Andric void *Mem = RK.Allocator.Allocate( 2573349cc55cSDimitry Andric totalSizeToAlloc<Init *, StringInit *>(ArgRange.size(), NameRange.size()), 2574349cc55cSDimitry Andric alignof(BitsInit)); 25750b57cec5SDimitry Andric DagInit *I = new (Mem) DagInit(V, VN, ArgRange.size(), NameRange.size()); 25760b57cec5SDimitry Andric std::uninitialized_copy(ArgRange.begin(), ArgRange.end(), 25770b57cec5SDimitry Andric I->getTrailingObjects<Init *>()); 25780b57cec5SDimitry Andric std::uninitialized_copy(NameRange.begin(), NameRange.end(), 25790b57cec5SDimitry Andric I->getTrailingObjects<StringInit *>()); 258081ad6265SDimitry Andric RK.TheDagInitPool.InsertNode(I, IP); 25810b57cec5SDimitry Andric return I; 25820b57cec5SDimitry Andric } 25830b57cec5SDimitry Andric 25840b57cec5SDimitry Andric DagInit * 25850b57cec5SDimitry Andric DagInit::get(Init *V, StringInit *VN, 25860b57cec5SDimitry Andric ArrayRef<std::pair<Init*, StringInit*>> args) { 25870b57cec5SDimitry Andric SmallVector<Init *, 8> Args; 25880b57cec5SDimitry Andric SmallVector<StringInit *, 8> Names; 25890b57cec5SDimitry Andric 25900b57cec5SDimitry Andric for (const auto &Arg : args) { 25910b57cec5SDimitry Andric Args.push_back(Arg.first); 25920b57cec5SDimitry Andric Names.push_back(Arg.second); 25930b57cec5SDimitry Andric } 25940b57cec5SDimitry Andric 25950b57cec5SDimitry Andric return DagInit::get(V, VN, Args, Names); 25960b57cec5SDimitry Andric } 25970b57cec5SDimitry Andric 25980b57cec5SDimitry Andric void DagInit::Profile(FoldingSetNodeID &ID) const { 2599bdd1243dSDimitry Andric ProfileDagInit(ID, Val, ValName, 2600bdd1243dSDimitry Andric ArrayRef(getTrailingObjects<Init *>(), NumArgs), 2601bdd1243dSDimitry Andric ArrayRef(getTrailingObjects<StringInit *>(), NumArgNames)); 26020b57cec5SDimitry Andric } 26030b57cec5SDimitry Andric 26048bcb0991SDimitry Andric Record *DagInit::getOperatorAsDef(ArrayRef<SMLoc> Loc) const { 26058bcb0991SDimitry Andric if (DefInit *DefI = dyn_cast<DefInit>(Val)) 26068bcb0991SDimitry Andric return DefI->getDef(); 26078bcb0991SDimitry Andric PrintFatalError(Loc, "Expected record as operator"); 26088bcb0991SDimitry Andric return nullptr; 26098bcb0991SDimitry Andric } 26108bcb0991SDimitry Andric 261106c3fb27SDimitry Andric std::optional<unsigned> DagInit::getArgNo(StringRef Name) const { 261206c3fb27SDimitry Andric for (unsigned i = 0, e = getNumArgs(); i < e; ++i) { 261306c3fb27SDimitry Andric StringInit *ArgName = getArgName(i); 261406c3fb27SDimitry Andric if (ArgName && ArgName->getValue() == Name) 261506c3fb27SDimitry Andric return i; 261606c3fb27SDimitry Andric } 261706c3fb27SDimitry Andric return std::nullopt; 261806c3fb27SDimitry Andric } 261906c3fb27SDimitry Andric 26200b57cec5SDimitry Andric Init *DagInit::resolveReferences(Resolver &R) const { 26210b57cec5SDimitry Andric SmallVector<Init*, 8> NewArgs; 26220b57cec5SDimitry Andric NewArgs.reserve(arg_size()); 26230b57cec5SDimitry Andric bool ArgsChanged = false; 26240b57cec5SDimitry Andric for (const Init *Arg : getArgs()) { 26250b57cec5SDimitry Andric Init *NewArg = Arg->resolveReferences(R); 26260b57cec5SDimitry Andric NewArgs.push_back(NewArg); 26270b57cec5SDimitry Andric ArgsChanged |= NewArg != Arg; 26280b57cec5SDimitry Andric } 26290b57cec5SDimitry Andric 26300b57cec5SDimitry Andric Init *Op = Val->resolveReferences(R); 26310b57cec5SDimitry Andric if (Op != Val || ArgsChanged) 26320b57cec5SDimitry Andric return DagInit::get(Op, ValName, NewArgs, getArgNames()); 26330b57cec5SDimitry Andric 26340b57cec5SDimitry Andric return const_cast<DagInit *>(this); 26350b57cec5SDimitry Andric } 26360b57cec5SDimitry Andric 26370b57cec5SDimitry Andric bool DagInit::isConcrete() const { 26380b57cec5SDimitry Andric if (!Val->isConcrete()) 26390b57cec5SDimitry Andric return false; 26400b57cec5SDimitry Andric for (const Init *Elt : getArgs()) { 26410b57cec5SDimitry Andric if (!Elt->isConcrete()) 26420b57cec5SDimitry Andric return false; 26430b57cec5SDimitry Andric } 26440b57cec5SDimitry Andric return true; 26450b57cec5SDimitry Andric } 26460b57cec5SDimitry Andric 26470b57cec5SDimitry Andric std::string DagInit::getAsString() const { 26480b57cec5SDimitry Andric std::string Result = "(" + Val->getAsString(); 26490b57cec5SDimitry Andric if (ValName) 26500b57cec5SDimitry Andric Result += ":" + ValName->getAsUnquotedString(); 26510b57cec5SDimitry Andric if (!arg_empty()) { 26520b57cec5SDimitry Andric Result += " " + getArg(0)->getAsString(); 26530b57cec5SDimitry Andric if (getArgName(0)) Result += ":$" + getArgName(0)->getAsUnquotedString(); 26540b57cec5SDimitry Andric for (unsigned i = 1, e = getNumArgs(); i != e; ++i) { 26550b57cec5SDimitry Andric Result += ", " + getArg(i)->getAsString(); 26560b57cec5SDimitry Andric if (getArgName(i)) Result += ":$" + getArgName(i)->getAsUnquotedString(); 26570b57cec5SDimitry Andric } 26580b57cec5SDimitry Andric } 26590b57cec5SDimitry Andric return Result + ")"; 26600b57cec5SDimitry Andric } 26610b57cec5SDimitry Andric 26620b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 26630b57cec5SDimitry Andric // Other implementations 26640b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 26650b57cec5SDimitry Andric 2666e8d8bef9SDimitry Andric RecordVal::RecordVal(Init *N, RecTy *T, FieldKind K) 2667e8d8bef9SDimitry Andric : Name(N), TyAndKind(T, K) { 266881ad6265SDimitry Andric setValue(UnsetInit::get(N->getRecordKeeper())); 2669e8d8bef9SDimitry Andric assert(Value && "Cannot create unset value for current type!"); 2670e8d8bef9SDimitry Andric } 2671e8d8bef9SDimitry Andric 2672e8d8bef9SDimitry Andric // This constructor accepts the same arguments as the above, but also 2673e8d8bef9SDimitry Andric // a source location. 2674e8d8bef9SDimitry Andric RecordVal::RecordVal(Init *N, SMLoc Loc, RecTy *T, FieldKind K) 2675e8d8bef9SDimitry Andric : Name(N), Loc(Loc), TyAndKind(T, K) { 267681ad6265SDimitry Andric setValue(UnsetInit::get(N->getRecordKeeper())); 26770b57cec5SDimitry Andric assert(Value && "Cannot create unset value for current type!"); 26780b57cec5SDimitry Andric } 26790b57cec5SDimitry Andric 26800b57cec5SDimitry Andric StringRef RecordVal::getName() const { 26810b57cec5SDimitry Andric return cast<StringInit>(getNameInit())->getValue(); 26820b57cec5SDimitry Andric } 26830b57cec5SDimitry Andric 2684e8d8bef9SDimitry Andric std::string RecordVal::getPrintType() const { 268581ad6265SDimitry Andric if (getType() == StringRecTy::get(getRecordKeeper())) { 2686e8d8bef9SDimitry Andric if (auto *StrInit = dyn_cast<StringInit>(Value)) { 2687e8d8bef9SDimitry Andric if (StrInit->hasCodeFormat()) 2688e8d8bef9SDimitry Andric return "code"; 2689e8d8bef9SDimitry Andric else 2690e8d8bef9SDimitry Andric return "string"; 2691e8d8bef9SDimitry Andric } else { 2692e8d8bef9SDimitry Andric return "string"; 2693e8d8bef9SDimitry Andric } 2694e8d8bef9SDimitry Andric } else { 2695e8d8bef9SDimitry Andric return TyAndKind.getPointer()->getAsString(); 2696e8d8bef9SDimitry Andric } 2697e8d8bef9SDimitry Andric } 2698e8d8bef9SDimitry Andric 26990b57cec5SDimitry Andric bool RecordVal::setValue(Init *V) { 27000b57cec5SDimitry Andric if (V) { 27010b57cec5SDimitry Andric Value = V->getCastTo(getType()); 27020b57cec5SDimitry Andric if (Value) { 27030b57cec5SDimitry Andric assert(!isa<TypedInit>(Value) || 27040b57cec5SDimitry Andric cast<TypedInit>(Value)->getType()->typeIsA(getType())); 27050b57cec5SDimitry Andric if (BitsRecTy *BTy = dyn_cast<BitsRecTy>(getType())) { 27060b57cec5SDimitry Andric if (!isa<BitsInit>(Value)) { 27070b57cec5SDimitry Andric SmallVector<Init *, 64> Bits; 27080b57cec5SDimitry Andric Bits.reserve(BTy->getNumBits()); 2709e8d8bef9SDimitry Andric for (unsigned I = 0, E = BTy->getNumBits(); I < E; ++I) 2710e8d8bef9SDimitry Andric Bits.push_back(Value->getBit(I)); 271181ad6265SDimitry Andric Value = BitsInit::get(V->getRecordKeeper(), Bits); 27120b57cec5SDimitry Andric } 27130b57cec5SDimitry Andric } 27140b57cec5SDimitry Andric } 27150b57cec5SDimitry Andric return Value == nullptr; 27160b57cec5SDimitry Andric } 27170b57cec5SDimitry Andric Value = nullptr; 27180b57cec5SDimitry Andric return false; 27190b57cec5SDimitry Andric } 27200b57cec5SDimitry Andric 2721e8d8bef9SDimitry Andric // This version of setValue takes a source location and resets the 2722e8d8bef9SDimitry Andric // location in the RecordVal. 2723e8d8bef9SDimitry Andric bool RecordVal::setValue(Init *V, SMLoc NewLoc) { 2724e8d8bef9SDimitry Andric Loc = NewLoc; 2725e8d8bef9SDimitry Andric if (V) { 2726e8d8bef9SDimitry Andric Value = V->getCastTo(getType()); 2727e8d8bef9SDimitry Andric if (Value) { 2728e8d8bef9SDimitry Andric assert(!isa<TypedInit>(Value) || 2729e8d8bef9SDimitry Andric cast<TypedInit>(Value)->getType()->typeIsA(getType())); 2730e8d8bef9SDimitry Andric if (BitsRecTy *BTy = dyn_cast<BitsRecTy>(getType())) { 2731e8d8bef9SDimitry Andric if (!isa<BitsInit>(Value)) { 2732e8d8bef9SDimitry Andric SmallVector<Init *, 64> Bits; 2733e8d8bef9SDimitry Andric Bits.reserve(BTy->getNumBits()); 2734e8d8bef9SDimitry Andric for (unsigned I = 0, E = BTy->getNumBits(); I < E; ++I) 2735e8d8bef9SDimitry Andric Bits.push_back(Value->getBit(I)); 273681ad6265SDimitry Andric Value = BitsInit::get(getRecordKeeper(), Bits); 2737e8d8bef9SDimitry Andric } 2738e8d8bef9SDimitry Andric } 2739e8d8bef9SDimitry Andric } 2740e8d8bef9SDimitry Andric return Value == nullptr; 2741e8d8bef9SDimitry Andric } 2742e8d8bef9SDimitry Andric Value = nullptr; 2743e8d8bef9SDimitry Andric return false; 2744e8d8bef9SDimitry Andric } 2745e8d8bef9SDimitry Andric 27460b57cec5SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 27471fd87a68SDimitry Andric #include "llvm/TableGen/Record.h" 27480b57cec5SDimitry Andric LLVM_DUMP_METHOD void RecordVal::dump() const { errs() << *this; } 27490b57cec5SDimitry Andric #endif 27500b57cec5SDimitry Andric 27510b57cec5SDimitry Andric void RecordVal::print(raw_ostream &OS, bool PrintSem) const { 2752e8d8bef9SDimitry Andric if (isNonconcreteOK()) OS << "field "; 2753e8d8bef9SDimitry Andric OS << getPrintType() << " " << getNameInitAsString(); 27540b57cec5SDimitry Andric 27550b57cec5SDimitry Andric if (getValue()) 27560b57cec5SDimitry Andric OS << " = " << *getValue(); 27570b57cec5SDimitry Andric 27580b57cec5SDimitry Andric if (PrintSem) OS << ";\n"; 27590b57cec5SDimitry Andric } 27600b57cec5SDimitry Andric 2761fcaf7f86SDimitry Andric void Record::updateClassLoc(SMLoc Loc) { 2762fcaf7f86SDimitry Andric assert(Locs.size() == 1); 2763fcaf7f86SDimitry Andric ForwardDeclarationLocs.push_back(Locs.front()); 2764fcaf7f86SDimitry Andric 2765fcaf7f86SDimitry Andric Locs.clear(); 2766fcaf7f86SDimitry Andric Locs.push_back(Loc); 2767fcaf7f86SDimitry Andric } 2768fcaf7f86SDimitry Andric 27690b57cec5SDimitry Andric void Record::checkName() { 27700b57cec5SDimitry Andric // Ensure the record name has string type. 27710b57cec5SDimitry Andric const TypedInit *TypedName = cast<const TypedInit>(Name); 27720b57cec5SDimitry Andric if (!isa<StringRecTy>(TypedName->getType())) 27730b57cec5SDimitry Andric PrintFatalError(getLoc(), Twine("Record name '") + Name->getAsString() + 27740b57cec5SDimitry Andric "' is not a string!"); 27750b57cec5SDimitry Andric } 27760b57cec5SDimitry Andric 27770b57cec5SDimitry Andric RecordRecTy *Record::getType() { 27780b57cec5SDimitry Andric SmallVector<Record *, 4> DirectSCs; 27790b57cec5SDimitry Andric getDirectSuperClasses(DirectSCs); 278081ad6265SDimitry Andric return RecordRecTy::get(TrackedRecords, DirectSCs); 27810b57cec5SDimitry Andric } 27820b57cec5SDimitry Andric 27830b57cec5SDimitry Andric DefInit *Record::getDefInit() { 278481ad6265SDimitry Andric if (!CorrespondingDefInit) { 278581ad6265SDimitry Andric CorrespondingDefInit = 278681ad6265SDimitry Andric new (TrackedRecords.getImpl().Allocator) DefInit(this); 278781ad6265SDimitry Andric } 2788e8d8bef9SDimitry Andric return CorrespondingDefInit; 27890b57cec5SDimitry Andric } 27900b57cec5SDimitry Andric 279181ad6265SDimitry Andric unsigned Record::getNewUID(RecordKeeper &RK) { 279281ad6265SDimitry Andric return RK.getImpl().LastRecordID++; 279381ad6265SDimitry Andric } 2794349cc55cSDimitry Andric 27950b57cec5SDimitry Andric void Record::setName(Init *NewName) { 27960b57cec5SDimitry Andric Name = NewName; 27970b57cec5SDimitry Andric checkName(); 27980b57cec5SDimitry Andric // DO NOT resolve record values to the name at this point because 27990b57cec5SDimitry Andric // there might be default values for arguments of this def. Those 28000b57cec5SDimitry Andric // arguments might not have been resolved yet so we don't want to 28010b57cec5SDimitry Andric // prematurely assume values for those arguments were not passed to 28020b57cec5SDimitry Andric // this def. 28030b57cec5SDimitry Andric // 28040b57cec5SDimitry Andric // Nonetheless, it may be that some of this Record's values 28050b57cec5SDimitry Andric // reference the record name. Indeed, the reason for having the 28060b57cec5SDimitry Andric // record name be an Init is to provide this flexibility. The extra 28070b57cec5SDimitry Andric // resolve steps after completely instantiating defs takes care of 28080b57cec5SDimitry Andric // this. See TGParser::ParseDef and TGParser::ParseDefm. 28090b57cec5SDimitry Andric } 28100b57cec5SDimitry Andric 2811e8d8bef9SDimitry Andric // NOTE for the next two functions: 2812e8d8bef9SDimitry Andric // Superclasses are in post-order, so the final one is a direct 2813e8d8bef9SDimitry Andric // superclass. All of its transitive superclases immediately precede it, 2814e8d8bef9SDimitry Andric // so we can step through the direct superclasses in reverse order. 2815e8d8bef9SDimitry Andric 2816e8d8bef9SDimitry Andric bool Record::hasDirectSuperClass(const Record *Superclass) const { 2817e8d8bef9SDimitry Andric ArrayRef<std::pair<Record *, SMRange>> SCs = getSuperClasses(); 2818e8d8bef9SDimitry Andric 2819e8d8bef9SDimitry Andric for (int I = SCs.size() - 1; I >= 0; --I) { 2820e8d8bef9SDimitry Andric const Record *SC = SCs[I].first; 2821e8d8bef9SDimitry Andric if (SC == Superclass) 2822e8d8bef9SDimitry Andric return true; 2823e8d8bef9SDimitry Andric I -= SC->getSuperClasses().size(); 2824e8d8bef9SDimitry Andric } 2825e8d8bef9SDimitry Andric 2826e8d8bef9SDimitry Andric return false; 2827e8d8bef9SDimitry Andric } 2828e8d8bef9SDimitry Andric 28290b57cec5SDimitry Andric void Record::getDirectSuperClasses(SmallVectorImpl<Record *> &Classes) const { 28300b57cec5SDimitry Andric ArrayRef<std::pair<Record *, SMRange>> SCs = getSuperClasses(); 2831e8d8bef9SDimitry Andric 28320b57cec5SDimitry Andric while (!SCs.empty()) { 28330b57cec5SDimitry Andric Record *SC = SCs.back().first; 28340b57cec5SDimitry Andric SCs = SCs.drop_back(1 + SC->getSuperClasses().size()); 28350b57cec5SDimitry Andric Classes.push_back(SC); 28360b57cec5SDimitry Andric } 28370b57cec5SDimitry Andric } 28380b57cec5SDimitry Andric 28390b57cec5SDimitry Andric void Record::resolveReferences(Resolver &R, const RecordVal *SkipVal) { 2840fe6060f1SDimitry Andric Init *OldName = getNameInit(); 2841fe6060f1SDimitry Andric Init *NewName = Name->resolveReferences(R); 2842fe6060f1SDimitry Andric if (NewName != OldName) { 2843fe6060f1SDimitry Andric // Re-register with RecordKeeper. 2844fe6060f1SDimitry Andric setName(NewName); 2845fe6060f1SDimitry Andric } 2846fe6060f1SDimitry Andric 2847fe6060f1SDimitry Andric // Resolve the field values. 28480b57cec5SDimitry Andric for (RecordVal &Value : Values) { 28490b57cec5SDimitry Andric if (SkipVal == &Value) // Skip resolve the same field as the given one 28500b57cec5SDimitry Andric continue; 28510b57cec5SDimitry Andric if (Init *V = Value.getValue()) { 28520b57cec5SDimitry Andric Init *VR = V->resolveReferences(R); 28530b57cec5SDimitry Andric if (Value.setValue(VR)) { 28540b57cec5SDimitry Andric std::string Type; 28550b57cec5SDimitry Andric if (TypedInit *VRT = dyn_cast<TypedInit>(VR)) 28560b57cec5SDimitry Andric Type = 28570b57cec5SDimitry Andric (Twine("of type '") + VRT->getType()->getAsString() + "' ").str(); 2858fe6060f1SDimitry Andric PrintFatalError( 2859fe6060f1SDimitry Andric getLoc(), 2860fe6060f1SDimitry Andric Twine("Invalid value ") + Type + "found when setting field '" + 2861fe6060f1SDimitry Andric Value.getNameInitAsString() + "' of type '" + 28620b57cec5SDimitry Andric Value.getType()->getAsString() + 2863fe6060f1SDimitry Andric "' after resolving references: " + VR->getAsUnquotedString() + 2864fe6060f1SDimitry Andric "\n"); 28650b57cec5SDimitry Andric } 28660b57cec5SDimitry Andric } 28670b57cec5SDimitry Andric } 28680b57cec5SDimitry Andric 2869fe6060f1SDimitry Andric // Resolve the assertion expressions. 2870fe6060f1SDimitry Andric for (auto &Assertion : Assertions) { 2871fe6060f1SDimitry Andric Init *Value = Assertion.Condition->resolveReferences(R); 2872fe6060f1SDimitry Andric Assertion.Condition = Value; 2873fe6060f1SDimitry Andric Value = Assertion.Message->resolveReferences(R); 2874fe6060f1SDimitry Andric Assertion.Message = Value; 2875fe6060f1SDimitry Andric } 28765f757f3fSDimitry Andric // Resolve the dump expressions. 28775f757f3fSDimitry Andric for (auto &Dump : Dumps) { 28785f757f3fSDimitry Andric Init *Value = Dump.Message->resolveReferences(R); 28795f757f3fSDimitry Andric Dump.Message = Value; 28805f757f3fSDimitry Andric } 2881fe6060f1SDimitry Andric } 2882fe6060f1SDimitry Andric 2883fe6060f1SDimitry Andric void Record::resolveReferences(Init *NewName) { 28840b57cec5SDimitry Andric RecordResolver R(*this); 2885fe6060f1SDimitry Andric R.setName(NewName); 28860b57cec5SDimitry Andric R.setFinal(true); 28870b57cec5SDimitry Andric resolveReferences(R); 28880b57cec5SDimitry Andric } 28890b57cec5SDimitry Andric 28900b57cec5SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 28910b57cec5SDimitry Andric LLVM_DUMP_METHOD void Record::dump() const { errs() << *this; } 28920b57cec5SDimitry Andric #endif 28930b57cec5SDimitry Andric 28940b57cec5SDimitry Andric raw_ostream &llvm::operator<<(raw_ostream &OS, const Record &R) { 28950b57cec5SDimitry Andric OS << R.getNameInitAsString(); 28960b57cec5SDimitry Andric 28970b57cec5SDimitry Andric ArrayRef<Init *> TArgs = R.getTemplateArgs(); 28980b57cec5SDimitry Andric if (!TArgs.empty()) { 28990b57cec5SDimitry Andric OS << "<"; 29000b57cec5SDimitry Andric bool NeedComma = false; 29010b57cec5SDimitry Andric for (const Init *TA : TArgs) { 29020b57cec5SDimitry Andric if (NeedComma) OS << ", "; 29030b57cec5SDimitry Andric NeedComma = true; 29040b57cec5SDimitry Andric const RecordVal *RV = R.getValue(TA); 29050b57cec5SDimitry Andric assert(RV && "Template argument record not found??"); 29060b57cec5SDimitry Andric RV->print(OS, false); 29070b57cec5SDimitry Andric } 29080b57cec5SDimitry Andric OS << ">"; 29090b57cec5SDimitry Andric } 29100b57cec5SDimitry Andric 29110b57cec5SDimitry Andric OS << " {"; 29120b57cec5SDimitry Andric ArrayRef<std::pair<Record *, SMRange>> SC = R.getSuperClasses(); 29130b57cec5SDimitry Andric if (!SC.empty()) { 29140b57cec5SDimitry Andric OS << "\t//"; 29150b57cec5SDimitry Andric for (const auto &SuperPair : SC) 29160b57cec5SDimitry Andric OS << " " << SuperPair.first->getNameInitAsString(); 29170b57cec5SDimitry Andric } 29180b57cec5SDimitry Andric OS << "\n"; 29190b57cec5SDimitry Andric 29200b57cec5SDimitry Andric for (const RecordVal &Val : R.getValues()) 2921e8d8bef9SDimitry Andric if (Val.isNonconcreteOK() && !R.isTemplateArg(Val.getNameInit())) 29220b57cec5SDimitry Andric OS << Val; 29230b57cec5SDimitry Andric for (const RecordVal &Val : R.getValues()) 2924e8d8bef9SDimitry Andric if (!Val.isNonconcreteOK() && !R.isTemplateArg(Val.getNameInit())) 29250b57cec5SDimitry Andric OS << Val; 29260b57cec5SDimitry Andric 29270b57cec5SDimitry Andric return OS << "}\n"; 29280b57cec5SDimitry Andric } 29290b57cec5SDimitry Andric 2930e8d8bef9SDimitry Andric SMLoc Record::getFieldLoc(StringRef FieldName) const { 2931e8d8bef9SDimitry Andric const RecordVal *R = getValue(FieldName); 2932e8d8bef9SDimitry Andric if (!R) 2933e8d8bef9SDimitry Andric PrintFatalError(getLoc(), "Record `" + getName() + 2934e8d8bef9SDimitry Andric "' does not have a field named `" + FieldName + "'!\n"); 2935e8d8bef9SDimitry Andric return R->getLoc(); 2936e8d8bef9SDimitry Andric } 2937e8d8bef9SDimitry Andric 29380b57cec5SDimitry Andric Init *Record::getValueInit(StringRef FieldName) const { 29390b57cec5SDimitry Andric const RecordVal *R = getValue(FieldName); 29400b57cec5SDimitry Andric if (!R || !R->getValue()) 29410b57cec5SDimitry Andric PrintFatalError(getLoc(), "Record `" + getName() + 29420b57cec5SDimitry Andric "' does not have a field named `" + FieldName + "'!\n"); 29430b57cec5SDimitry Andric return R->getValue(); 29440b57cec5SDimitry Andric } 29450b57cec5SDimitry Andric 29460b57cec5SDimitry Andric StringRef Record::getValueAsString(StringRef FieldName) const { 2947bdd1243dSDimitry Andric std::optional<StringRef> S = getValueAsOptionalString(FieldName); 294881ad6265SDimitry Andric if (!S) 29490b57cec5SDimitry Andric PrintFatalError(getLoc(), "Record `" + getName() + 29500b57cec5SDimitry Andric "' does not have a field named `" + FieldName + "'!\n"); 2951bdd1243dSDimitry Andric return *S; 2952e8d8bef9SDimitry Andric } 2953e8d8bef9SDimitry Andric 2954bdd1243dSDimitry Andric std::optional<StringRef> 2955e8d8bef9SDimitry Andric Record::getValueAsOptionalString(StringRef FieldName) const { 2956e8d8bef9SDimitry Andric const RecordVal *R = getValue(FieldName); 2957e8d8bef9SDimitry Andric if (!R || !R->getValue()) 2958bdd1243dSDimitry Andric return std::nullopt; 2959e8d8bef9SDimitry Andric if (isa<UnsetInit>(R->getValue())) 2960bdd1243dSDimitry Andric return std::nullopt; 29610b57cec5SDimitry Andric 29620b57cec5SDimitry Andric if (StringInit *SI = dyn_cast<StringInit>(R->getValue())) 29630b57cec5SDimitry Andric return SI->getValue(); 29640b57cec5SDimitry Andric 2965e8d8bef9SDimitry Andric PrintFatalError(getLoc(), 2966e8d8bef9SDimitry Andric "Record `" + getName() + "', ` field `" + FieldName + 2967e8d8bef9SDimitry Andric "' exists but does not have a string initializer!"); 29680b57cec5SDimitry Andric } 29690b57cec5SDimitry Andric 29700b57cec5SDimitry Andric BitsInit *Record::getValueAsBitsInit(StringRef FieldName) const { 29710b57cec5SDimitry Andric const RecordVal *R = getValue(FieldName); 29720b57cec5SDimitry Andric if (!R || !R->getValue()) 29730b57cec5SDimitry Andric PrintFatalError(getLoc(), "Record `" + getName() + 29740b57cec5SDimitry Andric "' does not have a field named `" + FieldName + "'!\n"); 29750b57cec5SDimitry Andric 29760b57cec5SDimitry Andric if (BitsInit *BI = dyn_cast<BitsInit>(R->getValue())) 29770b57cec5SDimitry Andric return BI; 2978e8d8bef9SDimitry Andric PrintFatalError(getLoc(), "Record `" + getName() + "', field `" + FieldName + 2979e8d8bef9SDimitry Andric "' exists but does not have a bits value"); 29800b57cec5SDimitry Andric } 29810b57cec5SDimitry Andric 29820b57cec5SDimitry Andric ListInit *Record::getValueAsListInit(StringRef FieldName) const { 29830b57cec5SDimitry Andric const RecordVal *R = getValue(FieldName); 29840b57cec5SDimitry Andric if (!R || !R->getValue()) 29850b57cec5SDimitry Andric PrintFatalError(getLoc(), "Record `" + getName() + 29860b57cec5SDimitry Andric "' does not have a field named `" + FieldName + "'!\n"); 29870b57cec5SDimitry Andric 29880b57cec5SDimitry Andric if (ListInit *LI = dyn_cast<ListInit>(R->getValue())) 29890b57cec5SDimitry Andric return LI; 2990e8d8bef9SDimitry Andric PrintFatalError(getLoc(), "Record `" + getName() + "', field `" + FieldName + 2991e8d8bef9SDimitry Andric "' exists but does not have a list value"); 29920b57cec5SDimitry Andric } 29930b57cec5SDimitry Andric 29940b57cec5SDimitry Andric std::vector<Record*> 29950b57cec5SDimitry Andric Record::getValueAsListOfDefs(StringRef FieldName) const { 29960b57cec5SDimitry Andric ListInit *List = getValueAsListInit(FieldName); 29970b57cec5SDimitry Andric std::vector<Record*> Defs; 29980b57cec5SDimitry Andric for (Init *I : List->getValues()) { 29990b57cec5SDimitry Andric if (DefInit *DI = dyn_cast<DefInit>(I)) 30000b57cec5SDimitry Andric Defs.push_back(DI->getDef()); 30010b57cec5SDimitry Andric else 30020b57cec5SDimitry Andric PrintFatalError(getLoc(), "Record `" + getName() + "', field `" + 30030b57cec5SDimitry Andric FieldName + "' list is not entirely DefInit!"); 30040b57cec5SDimitry Andric } 30050b57cec5SDimitry Andric return Defs; 30060b57cec5SDimitry Andric } 30070b57cec5SDimitry Andric 30080b57cec5SDimitry Andric int64_t Record::getValueAsInt(StringRef FieldName) const { 30090b57cec5SDimitry Andric const RecordVal *R = getValue(FieldName); 30100b57cec5SDimitry Andric if (!R || !R->getValue()) 30110b57cec5SDimitry Andric PrintFatalError(getLoc(), "Record `" + getName() + 30120b57cec5SDimitry Andric "' does not have a field named `" + FieldName + "'!\n"); 30130b57cec5SDimitry Andric 30140b57cec5SDimitry Andric if (IntInit *II = dyn_cast<IntInit>(R->getValue())) 30150b57cec5SDimitry Andric return II->getValue(); 30160b57cec5SDimitry Andric PrintFatalError(getLoc(), Twine("Record `") + getName() + "', field `" + 30170b57cec5SDimitry Andric FieldName + 3018e8d8bef9SDimitry Andric "' exists but does not have an int value: " + 30190b57cec5SDimitry Andric R->getValue()->getAsString()); 30200b57cec5SDimitry Andric } 30210b57cec5SDimitry Andric 30220b57cec5SDimitry Andric std::vector<int64_t> 30230b57cec5SDimitry Andric Record::getValueAsListOfInts(StringRef FieldName) const { 30240b57cec5SDimitry Andric ListInit *List = getValueAsListInit(FieldName); 30250b57cec5SDimitry Andric std::vector<int64_t> Ints; 30260b57cec5SDimitry Andric for (Init *I : List->getValues()) { 30270b57cec5SDimitry Andric if (IntInit *II = dyn_cast<IntInit>(I)) 30280b57cec5SDimitry Andric Ints.push_back(II->getValue()); 30290b57cec5SDimitry Andric else 30300b57cec5SDimitry Andric PrintFatalError(getLoc(), 30310b57cec5SDimitry Andric Twine("Record `") + getName() + "', field `" + FieldName + 3032e8d8bef9SDimitry Andric "' exists but does not have a list of ints value: " + 30330b57cec5SDimitry Andric I->getAsString()); 30340b57cec5SDimitry Andric } 30350b57cec5SDimitry Andric return Ints; 30360b57cec5SDimitry Andric } 30370b57cec5SDimitry Andric 30380b57cec5SDimitry Andric std::vector<StringRef> 30390b57cec5SDimitry Andric Record::getValueAsListOfStrings(StringRef FieldName) const { 30400b57cec5SDimitry Andric ListInit *List = getValueAsListInit(FieldName); 30410b57cec5SDimitry Andric std::vector<StringRef> Strings; 30420b57cec5SDimitry Andric for (Init *I : List->getValues()) { 30430b57cec5SDimitry Andric if (StringInit *SI = dyn_cast<StringInit>(I)) 30440b57cec5SDimitry Andric Strings.push_back(SI->getValue()); 30450b57cec5SDimitry Andric else 30460b57cec5SDimitry Andric PrintFatalError(getLoc(), 30470b57cec5SDimitry Andric Twine("Record `") + getName() + "', field `" + FieldName + 3048e8d8bef9SDimitry Andric "' exists but does not have a list of strings value: " + 30490b57cec5SDimitry Andric I->getAsString()); 30500b57cec5SDimitry Andric } 30510b57cec5SDimitry Andric return Strings; 30520b57cec5SDimitry Andric } 30530b57cec5SDimitry Andric 30540b57cec5SDimitry Andric Record *Record::getValueAsDef(StringRef FieldName) const { 30550b57cec5SDimitry Andric const RecordVal *R = getValue(FieldName); 30560b57cec5SDimitry Andric if (!R || !R->getValue()) 30570b57cec5SDimitry Andric PrintFatalError(getLoc(), "Record `" + getName() + 30580b57cec5SDimitry Andric "' does not have a field named `" + FieldName + "'!\n"); 30590b57cec5SDimitry Andric 30600b57cec5SDimitry Andric if (DefInit *DI = dyn_cast<DefInit>(R->getValue())) 30610b57cec5SDimitry Andric return DI->getDef(); 30620b57cec5SDimitry Andric PrintFatalError(getLoc(), "Record `" + getName() + "', field `" + 30630b57cec5SDimitry Andric FieldName + "' does not have a def initializer!"); 30640b57cec5SDimitry Andric } 30650b57cec5SDimitry Andric 3066480093f4SDimitry Andric Record *Record::getValueAsOptionalDef(StringRef FieldName) const { 3067480093f4SDimitry Andric const RecordVal *R = getValue(FieldName); 3068480093f4SDimitry Andric if (!R || !R->getValue()) 3069480093f4SDimitry Andric PrintFatalError(getLoc(), "Record `" + getName() + 3070480093f4SDimitry Andric "' does not have a field named `" + FieldName + "'!\n"); 3071480093f4SDimitry Andric 3072480093f4SDimitry Andric if (DefInit *DI = dyn_cast<DefInit>(R->getValue())) 3073480093f4SDimitry Andric return DI->getDef(); 3074480093f4SDimitry Andric if (isa<UnsetInit>(R->getValue())) 3075480093f4SDimitry Andric return nullptr; 3076480093f4SDimitry Andric PrintFatalError(getLoc(), "Record `" + getName() + "', field `" + 3077480093f4SDimitry Andric FieldName + "' does not have either a def initializer or '?'!"); 3078480093f4SDimitry Andric } 3079480093f4SDimitry Andric 3080480093f4SDimitry Andric 30810b57cec5SDimitry Andric bool Record::getValueAsBit(StringRef FieldName) const { 30820b57cec5SDimitry Andric const RecordVal *R = getValue(FieldName); 30830b57cec5SDimitry Andric if (!R || !R->getValue()) 30840b57cec5SDimitry Andric PrintFatalError(getLoc(), "Record `" + getName() + 30850b57cec5SDimitry Andric "' does not have a field named `" + FieldName + "'!\n"); 30860b57cec5SDimitry Andric 30870b57cec5SDimitry Andric if (BitInit *BI = dyn_cast<BitInit>(R->getValue())) 30880b57cec5SDimitry Andric return BI->getValue(); 30890b57cec5SDimitry Andric PrintFatalError(getLoc(), "Record `" + getName() + "', field `" + 30900b57cec5SDimitry Andric FieldName + "' does not have a bit initializer!"); 30910b57cec5SDimitry Andric } 30920b57cec5SDimitry Andric 30930b57cec5SDimitry Andric bool Record::getValueAsBitOrUnset(StringRef FieldName, bool &Unset) const { 30940b57cec5SDimitry Andric const RecordVal *R = getValue(FieldName); 30950b57cec5SDimitry Andric if (!R || !R->getValue()) 30960b57cec5SDimitry Andric PrintFatalError(getLoc(), "Record `" + getName() + 30970b57cec5SDimitry Andric "' does not have a field named `" + FieldName.str() + "'!\n"); 30980b57cec5SDimitry Andric 30990b57cec5SDimitry Andric if (isa<UnsetInit>(R->getValue())) { 31000b57cec5SDimitry Andric Unset = true; 31010b57cec5SDimitry Andric return false; 31020b57cec5SDimitry Andric } 31030b57cec5SDimitry Andric Unset = false; 31040b57cec5SDimitry Andric if (BitInit *BI = dyn_cast<BitInit>(R->getValue())) 31050b57cec5SDimitry Andric return BI->getValue(); 31060b57cec5SDimitry Andric PrintFatalError(getLoc(), "Record `" + getName() + "', field `" + 31070b57cec5SDimitry Andric FieldName + "' does not have a bit initializer!"); 31080b57cec5SDimitry Andric } 31090b57cec5SDimitry Andric 31100b57cec5SDimitry Andric DagInit *Record::getValueAsDag(StringRef FieldName) const { 31110b57cec5SDimitry Andric const RecordVal *R = getValue(FieldName); 31120b57cec5SDimitry Andric if (!R || !R->getValue()) 31130b57cec5SDimitry Andric PrintFatalError(getLoc(), "Record `" + getName() + 31140b57cec5SDimitry Andric "' does not have a field named `" + FieldName + "'!\n"); 31150b57cec5SDimitry Andric 31160b57cec5SDimitry Andric if (DagInit *DI = dyn_cast<DagInit>(R->getValue())) 31170b57cec5SDimitry Andric return DI; 31180b57cec5SDimitry Andric PrintFatalError(getLoc(), "Record `" + getName() + "', field `" + 31190b57cec5SDimitry Andric FieldName + "' does not have a dag initializer!"); 31200b57cec5SDimitry Andric } 31210b57cec5SDimitry Andric 3122fe6060f1SDimitry Andric // Check all record assertions: For each one, resolve the condition 3123fe6060f1SDimitry Andric // and message, then call CheckAssert(). 3124fe6060f1SDimitry Andric // Note: The condition and message are probably already resolved, 3125fe6060f1SDimitry Andric // but resolving again allows calls before records are resolved. 3126fe6060f1SDimitry Andric void Record::checkRecordAssertions() { 3127fe6060f1SDimitry Andric RecordResolver R(*this); 3128fe6060f1SDimitry Andric R.setFinal(true); 3129fe6060f1SDimitry Andric 3130349cc55cSDimitry Andric for (const auto &Assertion : getAssertions()) { 3131fe6060f1SDimitry Andric Init *Condition = Assertion.Condition->resolveReferences(R); 3132fe6060f1SDimitry Andric Init *Message = Assertion.Message->resolveReferences(R); 3133fe6060f1SDimitry Andric CheckAssert(Assertion.Loc, Condition, Message); 3134fe6060f1SDimitry Andric } 3135fe6060f1SDimitry Andric } 3136fe6060f1SDimitry Andric 31375f757f3fSDimitry Andric void Record::emitRecordDumps() { 31385f757f3fSDimitry Andric RecordResolver R(*this); 31395f757f3fSDimitry Andric R.setFinal(true); 31405f757f3fSDimitry Andric 31415f757f3fSDimitry Andric for (const auto &Dump : getDumps()) { 31425f757f3fSDimitry Andric Init *Message = Dump.Message->resolveReferences(R); 31435f757f3fSDimitry Andric dumpMessage(Dump.Loc, Message); 31445f757f3fSDimitry Andric } 31455f757f3fSDimitry Andric } 31465f757f3fSDimitry Andric 3147349cc55cSDimitry Andric // Report a warning if the record has unused template arguments. 3148349cc55cSDimitry Andric void Record::checkUnusedTemplateArgs() { 3149349cc55cSDimitry Andric for (const Init *TA : getTemplateArgs()) { 3150349cc55cSDimitry Andric const RecordVal *Arg = getValue(TA); 3151349cc55cSDimitry Andric if (!Arg->isUsed()) 3152349cc55cSDimitry Andric PrintWarning(Arg->getLoc(), 3153349cc55cSDimitry Andric "unused template argument: " + Twine(Arg->getName())); 3154349cc55cSDimitry Andric } 3155349cc55cSDimitry Andric } 3156349cc55cSDimitry Andric 315781ad6265SDimitry Andric RecordKeeper::RecordKeeper() 315881ad6265SDimitry Andric : Impl(std::make_unique<detail::RecordKeeperImpl>(*this)) {} 315981ad6265SDimitry Andric RecordKeeper::~RecordKeeper() = default; 316081ad6265SDimitry Andric 31610b57cec5SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 31620b57cec5SDimitry Andric LLVM_DUMP_METHOD void RecordKeeper::dump() const { errs() << *this; } 31630b57cec5SDimitry Andric #endif 31640b57cec5SDimitry Andric 31650b57cec5SDimitry Andric raw_ostream &llvm::operator<<(raw_ostream &OS, const RecordKeeper &RK) { 31660b57cec5SDimitry Andric OS << "------------- Classes -----------------\n"; 31670b57cec5SDimitry Andric for (const auto &C : RK.getClasses()) 31680b57cec5SDimitry Andric OS << "class " << *C.second; 31690b57cec5SDimitry Andric 31700b57cec5SDimitry Andric OS << "------------- Defs -----------------\n"; 31710b57cec5SDimitry Andric for (const auto &D : RK.getDefs()) 31720b57cec5SDimitry Andric OS << "def " << *D.second; 31730b57cec5SDimitry Andric return OS; 31740b57cec5SDimitry Andric } 31750b57cec5SDimitry Andric 31760b57cec5SDimitry Andric /// GetNewAnonymousName - Generate a unique anonymous name that can be used as 31770b57cec5SDimitry Andric /// an identifier. 31780b57cec5SDimitry Andric Init *RecordKeeper::getNewAnonymousName() { 317981ad6265SDimitry Andric return AnonymousNameInit::get(*this, getImpl().AnonCounter++); 31800b57cec5SDimitry Andric } 31810b57cec5SDimitry Andric 3182e8d8bef9SDimitry Andric // These functions implement the phase timing facility. Starting a timer 3183e8d8bef9SDimitry Andric // when one is already running stops the running one. 3184e8d8bef9SDimitry Andric 3185e8d8bef9SDimitry Andric void RecordKeeper::startTimer(StringRef Name) { 3186e8d8bef9SDimitry Andric if (TimingGroup) { 3187e8d8bef9SDimitry Andric if (LastTimer && LastTimer->isRunning()) { 3188e8d8bef9SDimitry Andric LastTimer->stopTimer(); 3189e8d8bef9SDimitry Andric if (BackendTimer) { 3190e8d8bef9SDimitry Andric LastTimer->clear(); 3191e8d8bef9SDimitry Andric BackendTimer = false; 3192e8d8bef9SDimitry Andric } 3193e8d8bef9SDimitry Andric } 3194e8d8bef9SDimitry Andric 3195e8d8bef9SDimitry Andric LastTimer = new Timer("", Name, *TimingGroup); 3196e8d8bef9SDimitry Andric LastTimer->startTimer(); 3197e8d8bef9SDimitry Andric } 3198e8d8bef9SDimitry Andric } 3199e8d8bef9SDimitry Andric 3200e8d8bef9SDimitry Andric void RecordKeeper::stopTimer() { 3201e8d8bef9SDimitry Andric if (TimingGroup) { 3202e8d8bef9SDimitry Andric assert(LastTimer && "No phase timer was started"); 3203e8d8bef9SDimitry Andric LastTimer->stopTimer(); 3204e8d8bef9SDimitry Andric } 3205e8d8bef9SDimitry Andric } 3206e8d8bef9SDimitry Andric 3207e8d8bef9SDimitry Andric void RecordKeeper::startBackendTimer(StringRef Name) { 3208e8d8bef9SDimitry Andric if (TimingGroup) { 3209e8d8bef9SDimitry Andric startTimer(Name); 3210e8d8bef9SDimitry Andric BackendTimer = true; 3211e8d8bef9SDimitry Andric } 3212e8d8bef9SDimitry Andric } 3213e8d8bef9SDimitry Andric 3214e8d8bef9SDimitry Andric void RecordKeeper::stopBackendTimer() { 3215e8d8bef9SDimitry Andric if (TimingGroup) { 3216e8d8bef9SDimitry Andric if (BackendTimer) { 3217e8d8bef9SDimitry Andric stopTimer(); 3218e8d8bef9SDimitry Andric BackendTimer = false; 3219e8d8bef9SDimitry Andric } 3220e8d8bef9SDimitry Andric } 3221e8d8bef9SDimitry Andric } 3222e8d8bef9SDimitry Andric 322381ad6265SDimitry Andric std::vector<Record *> 322481ad6265SDimitry Andric RecordKeeper::getAllDerivedDefinitions(StringRef ClassName) const { 3225e8d8bef9SDimitry Andric // We cache the record vectors for single classes. Many backends request 3226e8d8bef9SDimitry Andric // the same vectors multiple times. 3227e8d8bef9SDimitry Andric auto Pair = ClassRecordsMap.try_emplace(ClassName); 3228e8d8bef9SDimitry Andric if (Pair.second) 3229bdd1243dSDimitry Andric Pair.first->second = getAllDerivedDefinitions(ArrayRef(ClassName)); 3230e8d8bef9SDimitry Andric 3231e8d8bef9SDimitry Andric return Pair.first->second; 3232e8d8bef9SDimitry Andric } 3233e8d8bef9SDimitry Andric 3234e8d8bef9SDimitry Andric std::vector<Record *> RecordKeeper::getAllDerivedDefinitions( 3235e8d8bef9SDimitry Andric ArrayRef<StringRef> ClassNames) const { 3236e8d8bef9SDimitry Andric SmallVector<Record *, 2> ClassRecs; 3237e8d8bef9SDimitry Andric std::vector<Record *> Defs; 3238e8d8bef9SDimitry Andric 3239e8d8bef9SDimitry Andric assert(ClassNames.size() > 0 && "At least one class must be passed."); 3240e8d8bef9SDimitry Andric for (const auto &ClassName : ClassNames) { 32410b57cec5SDimitry Andric Record *Class = getClass(ClassName); 32420b57cec5SDimitry Andric if (!Class) 3243e8d8bef9SDimitry Andric PrintFatalError("The class '" + ClassName + "' is not defined\n"); 3244e8d8bef9SDimitry Andric ClassRecs.push_back(Class); 3245e8d8bef9SDimitry Andric } 32460b57cec5SDimitry Andric 3247e8d8bef9SDimitry Andric for (const auto &OneDef : getDefs()) { 3248e8d8bef9SDimitry Andric if (all_of(ClassRecs, [&OneDef](const Record *Class) { 3249e8d8bef9SDimitry Andric return OneDef.second->isSubClassOf(Class); 3250e8d8bef9SDimitry Andric })) 3251e8d8bef9SDimitry Andric Defs.push_back(OneDef.second.get()); 3252e8d8bef9SDimitry Andric } 32530b57cec5SDimitry Andric 3254*0fca6ea1SDimitry Andric llvm::sort(Defs, LessRecord()); 325506c3fb27SDimitry Andric 32560b57cec5SDimitry Andric return Defs; 32570b57cec5SDimitry Andric } 32580b57cec5SDimitry Andric 325981ad6265SDimitry Andric std::vector<Record *> 326081ad6265SDimitry Andric RecordKeeper::getAllDerivedDefinitionsIfDefined(StringRef ClassName) const { 326181ad6265SDimitry Andric return getClass(ClassName) ? getAllDerivedDefinitions(ClassName) 326281ad6265SDimitry Andric : std::vector<Record *>(); 326381ad6265SDimitry Andric } 326481ad6265SDimitry Andric 32650b57cec5SDimitry Andric Init *MapResolver::resolve(Init *VarName) { 32660b57cec5SDimitry Andric auto It = Map.find(VarName); 32670b57cec5SDimitry Andric if (It == Map.end()) 32680b57cec5SDimitry Andric return nullptr; 32690b57cec5SDimitry Andric 32700b57cec5SDimitry Andric Init *I = It->second.V; 32710b57cec5SDimitry Andric 32720b57cec5SDimitry Andric if (!It->second.Resolved && Map.size() > 1) { 32730b57cec5SDimitry Andric // Resolve mutual references among the mapped variables, but prevent 32740b57cec5SDimitry Andric // infinite recursion. 32750b57cec5SDimitry Andric Map.erase(It); 32760b57cec5SDimitry Andric I = I->resolveReferences(*this); 32770b57cec5SDimitry Andric Map[VarName] = {I, true}; 32780b57cec5SDimitry Andric } 32790b57cec5SDimitry Andric 32800b57cec5SDimitry Andric return I; 32810b57cec5SDimitry Andric } 32820b57cec5SDimitry Andric 32830b57cec5SDimitry Andric Init *RecordResolver::resolve(Init *VarName) { 32840b57cec5SDimitry Andric Init *Val = Cache.lookup(VarName); 32850b57cec5SDimitry Andric if (Val) 32860b57cec5SDimitry Andric return Val; 32870b57cec5SDimitry Andric 3288fe6060f1SDimitry Andric if (llvm::is_contained(Stack, VarName)) 32890b57cec5SDimitry Andric return nullptr; // prevent infinite recursion 32900b57cec5SDimitry Andric 32910b57cec5SDimitry Andric if (RecordVal *RV = getCurrentRecord()->getValue(VarName)) { 32920b57cec5SDimitry Andric if (!isa<UnsetInit>(RV->getValue())) { 32930b57cec5SDimitry Andric Val = RV->getValue(); 32940b57cec5SDimitry Andric Stack.push_back(VarName); 32950b57cec5SDimitry Andric Val = Val->resolveReferences(*this); 32960b57cec5SDimitry Andric Stack.pop_back(); 32970b57cec5SDimitry Andric } 3298fe6060f1SDimitry Andric } else if (Name && VarName == getCurrentRecord()->getNameInit()) { 3299fe6060f1SDimitry Andric Stack.push_back(VarName); 3300fe6060f1SDimitry Andric Val = Name->resolveReferences(*this); 3301fe6060f1SDimitry Andric Stack.pop_back(); 33020b57cec5SDimitry Andric } 33030b57cec5SDimitry Andric 33040b57cec5SDimitry Andric Cache[VarName] = Val; 33050b57cec5SDimitry Andric return Val; 33060b57cec5SDimitry Andric } 33070b57cec5SDimitry Andric 33080b57cec5SDimitry Andric Init *TrackUnresolvedResolver::resolve(Init *VarName) { 33090b57cec5SDimitry Andric Init *I = nullptr; 33100b57cec5SDimitry Andric 33110b57cec5SDimitry Andric if (R) { 33120b57cec5SDimitry Andric I = R->resolve(VarName); 33130b57cec5SDimitry Andric if (I && !FoundUnresolved) { 33140b57cec5SDimitry Andric // Do not recurse into the resolved initializer, as that would change 33150b57cec5SDimitry Andric // the behavior of the resolver we're delegating, but do check to see 33160b57cec5SDimitry Andric // if there are unresolved variables remaining. 33170b57cec5SDimitry Andric TrackUnresolvedResolver Sub; 33180b57cec5SDimitry Andric I->resolveReferences(Sub); 33190b57cec5SDimitry Andric FoundUnresolved |= Sub.FoundUnresolved; 33200b57cec5SDimitry Andric } 33210b57cec5SDimitry Andric } 33220b57cec5SDimitry Andric 33230b57cec5SDimitry Andric if (!I) 33240b57cec5SDimitry Andric FoundUnresolved = true; 33250b57cec5SDimitry Andric return I; 33260b57cec5SDimitry Andric } 33270b57cec5SDimitry Andric 33280b57cec5SDimitry Andric Init *HasReferenceResolver::resolve(Init *VarName) 33290b57cec5SDimitry Andric { 33300b57cec5SDimitry Andric if (VarName == VarNameToTrack) 33310b57cec5SDimitry Andric Found = true; 33320b57cec5SDimitry Andric return nullptr; 33330b57cec5SDimitry Andric } 3334