22#include "llvm/Config/llvm-config.h"
43#define DEBUG_TYPE "tblgen-records"
123 OS <<
"Total allocator memory = " <<
Allocator.getTotalMemory() <<
"\n\n";
125 OS <<
"Number of records instantiated = " <<
LastRecordID <<
'\n';
126 OS <<
"Number of anonymous records = " <<
AnonCounter <<
'\n';
133#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
139 ListTy =
new (RK.getImpl().Allocator)
ListRecTy(
this);
144 assert(RHS &&
"NULL pointer");
145 return Kind == RHS->getRecTyKind();
151 return &RK.getImpl().SharedBitRecTy;
158 return BitsTy->getNumBits() == 1;
168 Ty =
new (RKImpl.
Allocator) BitsRecTy(RK, Sz);
173 return "bits<" +
utostr(Size) +
">";
184 return &RK.getImpl().SharedIntRecTy;
193 return &RK.getImpl().SharedStringRecTy;
206 return "list<" + ElementTy->getAsString() +
">";
211 return ElementTy->typeIsConvertibleTo(ListTy->getElementType());
222 return &RK.getImpl().SharedDagRecTy;
231 ID.AddInteger(Classes.
size());
232 for (
const Record *R : Classes)
237 : RecTy(RecordRecTyKind, RK), NumClasses(Classes.
size()) {
244 if (UnsortedClasses.
empty())
251 return LHS->getNameInitAsString() < RHS->getNameInitAsString();
258 if (RecordRecTy *Ty = ThePool.
lookup(ID, Token))
263 for (
unsigned i = 0; i < Classes.
size(); ++i) {
264 for (
unsigned j = 0; j < Classes.
size(); ++j) {
267 assert(&Classes[0]->getRecords() == &Classes[i]->getRecords());
273 RecordRecTy *Ty =
new (Mem) RecordRecTy(RK, Classes);
274 ThePool.
insert(Ty, Token);
279 assert(Class &&
"unexpected null class");
280 return get(Class->getRecords(), {Class});
289 return getClasses()[0]->getNameInitAsString();
291 std::string Str =
"{";
295 Str += R->getNameInitAsString();
303 return MySuperClass == Class || MySuperClass->
isSubClassOf(Class);
316 return isSubClassOf(TargetClass);
329 while (!Stack.empty()) {
330 const Record *R = Stack.pop_back_val();
332 if (T2->isSubClassOf(R))
350 assert(T1 !=
nullptr &&
"Invalid record type");
351 if (T1->typeIsConvertibleTo(T2))
354 assert(T2 !=
nullptr &&
"Invalid record type");
355 if (T2->typeIsConvertibleTo(T1))
360 const RecTy *NewType =
361 resolveTypes(ListTy1->getElementType(), ListTy2->getElementType());
374void Init::anchor() {}
376#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
382 return TyInit->getType()->getRecordKeeper();
384 return ArgInit->getRecordKeeper();
389 return &RK.getImpl().TheUnsetInit;
400 auto I = Aux.index();
403 ID.AddInteger(std::get<ArgumentInit::Positional>(Aux));
405 ID.AddPointer(std::get<ArgumentInit::Named>(Aux));
406 ID.AddPointer(
Value);
429 const Init *NewValue = Value->resolveReferences(R);
430 if (NewValue != Value)
449 if (BRT->getNumBits() == 1)
458 ID.AddInteger(
Range.size());
481 BitsInit *
I =
new (Mem) BitsInit(RK, Bits);
499 if (
getNumBits() != BRT->getNumBits())
return nullptr;
516 Result |=
static_cast<int64_t
>(Bit->getValue()) << Idx;
526 Result |=
static_cast<int64_t
>(Bit->getValue()) << Idx;
534 for (
auto [Bit, NewBit] :
zip_equal(Bits, NewBits)) {
553 std::string Result =
"{ ";
558 Result += Bit->getAsString();
562 return Result +
" }";
571 const Init *CachedBitVarRef =
nullptr;
572 const Init *CachedBitVarResolved =
nullptr;
578 if (CurBitVar->getBitVar() != CachedBitVarRef) {
579 CachedBitVarRef = CurBitVar->getBitVar();
582 assert(CachedBitVarResolved &&
"Unresolved bitvar reference");
583 NewBit = CachedBitVarResolved->
getBit(CurBitVar->getBitNum());
586 NewBit = CurBit->resolveReferences(R)->getBit(0);
603 I =
new (RK.
getImpl().Allocator) IntInit(RK, V);
613 return (NumBits >=
sizeof(
Value) * 8) ||
614 (
Value >> NumBits == 0) || (
Value >> (NumBits-1) == -1);
623 if (Val != 0 && Val != 1)
return nullptr;
634 for (
unsigned i = 0; i != BRT->getNumBits(); ++i)
647 for (
auto [Bit, NewBit] :
zip_equal(Bits, NewBits)) {
657 return new (RK.
getImpl().Allocator) AnonymousNameInit(RK, V);
665 return "anonymous_" +
utostr(Value);
670 auto *New = R.resolve(Old);
671 New = New ? New : Old;
674 return Anonymous->getNameInit();
683 auto &Entry = *InitMap.
try_emplace(V,
nullptr).first;
685 Entry.second =
new (RKImpl.
Allocator) StringInit(RK, Entry.getKey(), Fmt);
698 const RecTy *EltTy) {
699 ID.AddInteger(Elements.size());
700 ID.AddPointer(EltTy);
702 for (
const Init *
E : Elements)
713 const RecTy *EltTy) {
727 ListInit *
I =
new (Mem) ListInit(Elements, EltTy);
743 Elements.reserve(
size());
748 const RecTy *ElementType = LRT->getElementType();
750 if (
const Init *CI =
I->convertInitializerTo(ElementType)) {
751 Elements.push_back(CI);
776 Resolved.reserve(
size());
782 Resolved.push_back(E);
801 std::string Result =
"[";
803 for (
const Init *Element : *
this) {
818 ID.AddInteger(Opcode);
845 if (LHS->isConcrete()) {
850 OS << *Def->getDef();
890 (Anonymous && Name == Anonymous->getNameInit())) {
897 auto PrintFatalErrorHelper = [CurRec](
const Twine &
T) {
906 PrintFatalErrorHelper(
Twine(
"Undefined reference to record: '") +
907 Name->getValue() +
"'\n");
914 PrintFatalErrorHelper(
Twine(
"Expected type '") +
930 if (LHS->isConcrete())
942 assert(!LHSl->empty() &&
"Empty list in head");
943 return LHSl->getElement(0);
949 assert(!LHSl->empty() &&
"Empty list in tail");
953 LHSl->getElementType());
980 if (!TI->getType()->typeIsA(
getType())) {
986 return Dag->getOperator();
993 return Dag->getName();
1000 int64_t LHSv = LHSi->getValue();
1003 "Illegal operation: logtwo is undefined "
1004 "on arguments less than or equal to 0");
1008 "Log of an int64_t must be smaller than INT64_MAX");
1022 [](
const ListInit *
List) -> std::optional<std::vector<const Init *>> {
1023 std::vector<const Init *> Flattened;
1025 for (
const Init *InnerInit :
List->getElements()) {
1028 return std::nullopt;
1034 auto Flattened = Flatten(LHSList);
1036 return ListInit::get(*Flattened, InnerListTy->getElementType());
1048 ->Fold(R.getCurrentRecord(), R.isFinal());
1056 case NOT: Result =
"!not";
break;
1057 case HEAD: Result =
"!head";
break;
1058 case TAIL: Result =
"!tail";
break;
1059 case SIZE: Result =
"!size";
break;
1060 case EMPTY: Result =
"!empty";
break;
1061 case GETDAGOP: Result =
"!getdagop";
break;
1063 Result =
"!getdagopname";
1065 case LOG2 : Result =
"!logtwo";
break;
1067 Result =
"!listflatten";
1073 Result =
"!tolower";
1076 Result =
"!toupper";
1079 Result =
"!initialized";
1082 return Result +
"(" + LHS->getAsString() +
")";
1088 ID.AddInteger(Opcode);
1091 ID.AddPointer(
Type);
1116 Concat.append(I1->getValue());
1124 if (List->size() == 0)
1132 for (
const Init *Elem : List->getElements().drop_front()) {
1137 Result.append(Element->getValue());
1146 if (List->size() == 0)
1149 List->getElement(0)->convertInitializerTo(
IntRecTy::get(RK)));
1154 for (
const Init *Elem : List->getElements().drop_front()) {
1160 Result.append(Element->getAsString());
1193 const Init *RHS)
const {
1204 Result = LHSi->getValue() == RHSi->getValue();
1207 Result = LHSi->getValue() != RHSi->getValue();
1210 Result = LHSi->getValue() <= RHSi->getValue();
1213 Result = LHSi->getValue() < RHSi->getValue();
1216 Result = LHSi->getValue() >= RHSi->getValue();
1219 Result = LHSi->getValue() > RHSi->getValue();
1235 Result = LHSs->getValue() == RHSs->getValue();
1238 Result = LHSs->getValue() != RHSs->getValue();
1241 Result = LHSs->getValue() <= RHSs->getValue();
1244 Result = LHSs->getValue() < RHSs->getValue();
1247 Result = LHSs->getValue() >= RHSs->getValue();
1250 Result = LHSs->getValue() > RHSs->getValue();
1263 return (
Opc ==
EQ) ? LHSd == RHSd : LHSd != RHSd;
1266 return std::nullopt;
1269static std::optional<unsigned>
1273 int64_t Pos = Idx->getValue();
1277 (
Twine(
"index ") + std::to_string(Pos) +
Twine(
" is negative")).str();
1278 return std::nullopt;
1280 if (Pos >= Dag->getNumArgs()) {
1282 Error = (
Twine(
"index ") + std::to_string(Pos) +
1283 " is out of range (dag has " +
1284 std::to_string(Dag->getNumArgs()) +
" arguments)")
1286 return std::nullopt;
1293 auto ArgNo = Dag->getArgNo(Name->getValue());
1296 Error = (
Twine(
"key '") + Name->getValue() +
Twine(
"' is not found")).str();
1297 return std::nullopt;
1313 if (LOp && ROp && LOp->getDef() != ROp->getDef()) {
1315 LHSs->getAsString() +
"' vs. '" + RHSs->getAsString() +
1318 const Init *
Op = LOp ? LOp : ROp;
1326 const auto *NameInit = LHSs->getName();
1328 NameInit = RHSs->getName();
1342 StringRef RegexStr = RegexInit->getValue();
1344 if (!Matcher.isValid())
1348 Matcher.match(StrInit->getValue()));
1365 if (
Count->getValue() < 0)
1378 for (
const Init *EltLHS : *LHSs) {
1380 for (
const Init *EltRHS : *RHSs) {
1381 if (std::optional<bool> Result =
CompareInit(
EQ, EltLHS, EltRHS)) {
1389 Args.push_back(EltLHS);
1398 if (!TheList || !Idx)
1400 auto i = Idx->getValue();
1401 if (i < 0 || i >= (ssize_t)TheList->size())
1403 return TheList->getElement(i);
1408 if (!TheList || !SliceIdxs)
1411 Args.reserve(SliceIdxs->size());
1412 for (
auto *
I : *SliceIdxs) {
1416 auto i =
II->getValue();
1417 if (i < 0 || i >= (ssize_t)TheList->size())
1419 Args.push_back(TheList->getElement(i));
1429 int64_t Start = LHSi->getValue();
1430 int64_t End = RHSi->getValue();
1436 Args.reserve(End - Start + 1);
1437 for (
auto i = Start; i <= End; ++i)
1441 Args.reserve(Start - End + 1);
1442 for (
auto i = Start; i >= End; --i)
1445 }
else if (Start < End) {
1447 Args.reserve(End - Start);
1448 for (
auto i = Start; i < End; ++i)
1465 if (
List && Delim) {
1494 assert(*ArgNo < Dag->getNumArgs());
1496 const Init *Arg = Dag->getArg(*ArgNo);
1498 if (!TI->getType()->typeIsConvertibleTo(
getType()))
1508 int64_t Pos = Idx->getValue();
1509 if (Pos < 0 || Pos >= Dag->getNumArgs()) {
1512 Twine(
"!getdagname index is out of range 0...") +
1513 std::to_string(Dag->getNumArgs() - 1) +
": " +
1514 std::to_string(Pos));
1516 const Init *ArgName = Dag->getArgName(Pos);
1535 Dag->getArgNames());
1553 int64_t LHSv = LHSi->getValue(), RHSv = RHSi->getValue();
1557 case ADD: Result = LHSv + RHSv;
break;
1558 case SUB: Result = LHSv - RHSv;
break;
1559 case MUL: Result = LHSv * RHSv;
break;
1563 "Illegal operation: division by zero");
1564 else if (LHSv ==
INT64_MIN && RHSv == -1)
1566 "Illegal operation: INT64_MIN / -1");
1568 Result = LHSv / RHSv;
1570 case AND: Result = LHSv & RHSv;
break;
1571 case OR: Result = LHSv | RHSv;
break;
1572 case XOR: Result = LHSv ^ RHSv;
break;
1574 if (RHSv < 0 || RHSv >= 64)
1576 "Illegal operation: out of bounds shift");
1577 Result = (uint64_t)LHSv << (uint64_t)RHSv;
1580 if (RHSv < 0 || RHSv >= 64)
1582 "Illegal operation: out of bounds shift");
1583 Result = LHSv >> (uint64_t)RHSv;
1586 if (RHSv < 0 || RHSv >= 64)
1588 "Illegal operation: out of bounds shift");
1589 Result = (uint64_t)LHSv >> (uint64_t)RHSv;
1615 if ((
Opc ==
AND && !LHSi->getValue()) ||
1616 (
Opc ==
OR && LHSi->getValue() == -1))
1623 if (LHS != NewLHS || RHS != NewRHS)
1625 ->Fold(R.getCurrentRecord());
1634 return LHS->getAsString() +
"[" + RHS->getAsString() +
"]";
1636 return LHS->getAsString() +
"..." + RHS->getAsString();
1637 case CONCAT: Result =
"!con";
break;
1641 case ADD: Result =
"!add";
break;
1642 case SUB: Result =
"!sub";
break;
1643 case MUL: Result =
"!mul";
break;
1644 case DIV: Result =
"!div";
break;
1645 case AND: Result =
"!and";
break;
1646 case OR: Result =
"!or";
break;
1647 case XOR: Result =
"!xor";
break;
1648 case SHL: Result =
"!shl";
break;
1649 case SRA: Result =
"!sra";
break;
1650 case SRL: Result =
"!srl";
break;
1651 case EQ: Result =
"!eq";
break;
1652 case NE: Result =
"!ne";
break;
1653 case LE: Result =
"!le";
break;
1654 case LT: Result =
"!lt";
break;
1655 case GE: Result =
"!ge";
break;
1656 case GT: Result =
"!gt";
break;
1657 case LISTCONCAT: Result =
"!listconcat";
break;
1658 case LISTSPLAT: Result =
"!listsplat";
break;
1660 Result =
"!listremove";
1662 case STRCONCAT: Result =
"!strconcat";
break;
1663 case INTERLEAVE: Result =
"!interleave";
break;
1664 case SETDAGOP: Result =
"!setdagop";
break;
1666 Result =
"!setdagopname";
1672 Result =
"!getdagname";
1675 return Result +
"(" + LHS->getAsString() +
", " + RHS->getAsString() +
")";
1681 ID.AddInteger(Opcode);
1685 ID.AddPointer(
Type);
1712 return RHS->resolveReferences(R);
1717 bool Change =
false;
1751 for (
const Init *&Item : NewList) {
1753 if (NewItem != Item)
1770 for (
const Init *Item : MHSl->getElements()) {
1774 if (
const auto *IncludeInt =
1777 if (IncludeInt->getValue())
1796 using KV = std::pair<const Init *, const Init *>;
1799 for (
const Init *Item : MHSl->getElements()) {
1806 if (KeyedList.
empty())
1813 for (
auto &[
Key, Item] : KeyedList) {
1835 for (
auto &[
Key, Item] : KeyedList)
1836 Result.push_back(Item);
1856 if (LHSd && MHSd && RHSd) {
1857 const Record *Val = RHSd->getDef();
1858 if (LHSd->getAsString() == RHSd->getAsString())
1859 Val = MHSd->getDef();
1862 if (LHSv && MHSv && RHSv) {
1863 std::string Val = RHSv->getName().str();
1864 if (LHSv->getAsString() == RHSv->getAsString())
1865 Val = MHSv->getName().str();
1868 if (LHSs && MHSs && RHSs) {
1869 std::string Val = RHSs->getValue().str();
1871 std::string::size_type Idx = 0;
1873 std::string::size_type Found = Val.find(LHSs->getValue(), Idx);
1874 if (Found == std::string::npos)
1876 Val.replace(Found, LHSs->getValue().size(), MHSs->getValue().str());
1877 Idx = Found + MHSs->getValue().size();
1906 if (LHSi->getValue())
1922 if (MHSok && RHSok && (!MHSl || !RHSl || MHSl->size() == RHSl->size())) {
1924 unsigned Size = MHSl ? MHSl->size() : RHSl->size();
1925 for (
unsigned i = 0; i !=
Size; ++i) {
1941 if (!LHSi || !MHSi || !RHSi)
1944 auto Start = LHSi->getValue();
1945 auto End = MHSi->getValue();
1946 auto Step = RHSi->getValue();
1951 if (Start < End && Step > 0) {
1952 Args.reserve((End - Start) / Step);
1953 for (
auto I = Start;
I < End;
I += Step)
1955 }
else if (Start > End && Step < 0) {
1956 Args.reserve((Start - End) / -Step);
1957 for (
auto I = Start;
I > End;
I += Step)
1969 if (LHSs && MHSi && RHSi) {
1970 int64_t StringSize = LHSs->getValue().size();
1971 int64_t Start = MHSi->getValue();
1972 int64_t
Length = RHSi->getValue();
1973 if (Start < 0 || Start > StringSize)
1975 Twine(
"!substr start position is out of range 0...") +
1976 std::to_string(StringSize) +
": " +
1977 std::to_string(Start));
1990 if (LHSs && MHSs && RHSi) {
1991 int64_t SourceSize = LHSs->getValue().size();
1992 int64_t Start = RHSi->getValue();
1993 if (Start < 0 || Start > SourceSize)
1995 Twine(
"!find start position is out of range 0...") +
1996 std::to_string(SourceSize) +
": " +
1997 std::to_string(Start));
1998 auto I = LHSs->getValue().find(MHSs->getValue(), Start);
1999 if (
I == std::string::npos)
2014 assert(*ArgNo < Dag->getNumArgs());
2018 return DagInit::get(Dag->getOperator(), Dag->getName(), Args,
2019 Dag->getArgNames());
2032 assert(*ArgNo < Dag->getNumArgs());
2036 return DagInit::get(Dag->getOperator(), Dag->getName(), Dag->getArgs(),
2053 if (
Value->getValue())
2054 return MHS->resolveReferences(R);
2055 return RHS->resolveReferences(R);
2070 if (LHS != lhs || MHS != mhs || RHS != rhs)
2072 ->Fold(R.getCurrentRecord());
2078 bool UnquotedLHS =
false;
2080 case DAG: Result =
"!dag";
break;
2081 case FILTER: Result =
"!filter"; UnquotedLHS =
true;
break;
2082 case FOREACH: Result =
"!foreach"; UnquotedLHS =
true;
break;
2087 case IF: Result =
"!if";
break;
2091 case SUBST: Result =
"!subst";
break;
2092 case SUBSTR: Result =
"!substr";
break;
2093 case FIND: Result =
"!find";
break;
2095 Result =
"!setdagarg";
2098 Result =
"!setdagname";
2101 return (Result +
"(" +
2102 (UnquotedLHS ? LHS->getAsUnquotedString() : LHS->getAsString()) +
2103 ", " + MHS->getAsString() +
", " + RHS->getAsString() +
")");
2109 ID.AddPointer(Start);
2110 ID.AddPointer(List);
2113 ID.AddPointer(Expr);
2114 ID.AddPointer(
Type);
2128 FoldOpInit *
I =
new (RK.
Allocator) FoldOpInit(Start, List, A, B, Expr,
Type);
2139 const Init *Accum = Start;
2140 for (
const Init *Elt : *LI) {
2157 const Init *
NewExpr = Expr->resolveReferences(SR);
2159 if (Start == NewStart && List == NewList && Expr ==
NewExpr)
2163 ->
Fold(R.getCurrentRecord());
2173 return (
Twine(
"!foldl(") + Start->getAsString() +
", " + List->getAsString() +
2174 ", " + A->getAsUnquotedString() +
", " + B->getAsUnquotedString() +
2175 ", " + Expr->getAsString() +
")")
2182 ID.AddPointer(Expr);
2195 IsAOpInit *
I =
new (RK.
Allocator) IsAOpInit(CheckType, Expr);
2207 if (TI->getType()->typeIsConvertibleTo(CheckType))
2214 if ((!CheckType->typeIsConvertibleTo(TI->getType()) &&
2215 Expr->isConcrete()) ||
2238 return (
Twine(
"!isa<") + CheckType->getAsString() +
">(" +
2239 Expr->getAsString() +
")")
2246 ID.AddPointer(Expr);
2259 ExistsOpInit *
I =
new (RK.
Allocator) ExistsOpInit(CheckType, Expr);
2271 const Record *
D = CheckType->getRecordKeeper().getDef(Name->getValue());
2275 D->getDefInit()->getType()->typeIsA(CheckType));
2283 (Anonymous && Name == Anonymous->getNameInit())) {
2302 if (Expr !=
NewExpr || R.isFinal())
2303 return get(CheckType,
NewExpr)->
Fold(R.getCurrentRecord(), R.isFinal());
2312 return (
Twine(
"!exists<") + CheckType->getAsString() +
">(" +
2313 Expr->getAsString() +
")")
2319 ID.AddPointer(
Type);
2320 ID.AddPointer(
Regex);
2324 const Init *Regex) {
2333 InstancesOpInit *
I =
new (RK.
Allocator) InstancesOpInit(Type, Regex);
2343 if (CurRec && !IsFinal)
2350 StringRef RegexStr = RegexInit->getValue();
2352 if (!Matcher.isValid())
2358 if (Matcher.match(Def->getName()))
2366 if (Regex != NewRegex || R.isFinal())
2367 return get(Type, NewRegex)->
Fold(R.getCurrentRecord(), R.isFinal());
2372 return "!instances<" + Type->
getAsString() +
">(" + Regex->getAsString() +
2380 return Field->getType();
2400 if (!
T)
return nullptr;
2401 unsigned NumBits =
T->getNumBits();
2405 for (
unsigned Bit : Bits) {
2425 if (!
getType()->typeIsConvertibleTo(Ty))
2446 return NameString->getValue();
2456 if (
const Init *Val = R.resolve(VarName))
2470 return TI->getAsString() +
"{" +
utostr(Bit) +
"}";
2474 const Init *
I = TI->resolveReferences(R);
2481DefInit::DefInit(
const Record *
D)
2486 if (
getType()->typeIsConvertibleTo(RRT))
2493 return RV->getType();
2501 ID.AddInteger(Args.size());
2502 ID.AddPointer(Class);
2504 for (
const Init *
I : Args)
2527 VarDefInit *
I =
new (Mem) VarDefInit(Loc, Class, Args);
2536const DefInit *VarDefInit::instantiate() {
2541 auto NewRecOwner = std::make_unique<Record>(
2543 Record *NewRec = NewRecOwner.get();
2546 for (
const RecordVal &Val : Class->getValues())
2559 for (
const Init *Arg : TArgs) {
2564 for (
auto *Arg :
args()) {
2565 if (Arg->isPositional())
2566 R.set(TArgs[Arg->getIndex()], Arg->getValue());
2568 R.set(Arg->getName(), Arg->getValue());
2575 Class, SMRange(Class->getLoc().back(), Class->getLoc().back()));
2579 Records.addDef(std::move(NewRecOwner));
2605 return const_cast<VarDefInit *
>(New)->instantiate();
2617 Arg->resolveReferences(R);
2619 if (!R.foundUnresolved())
2620 return const_cast<VarDefInit *
>(
this)->instantiate();
2625 std::string Result = Class->getNameInitAsString() +
"<";
2629 Result += Arg->getAsString();
2631 return Result +
">";
2657 const Record *Def = DI->getDef();
2660 Twine(
"Attempting to access field '") +
2661 FieldName->getAsUnquotedString() +
"' of '" +
2662 Rec->getAsString() +
"' is a forbidden self-reference");
2663 const Init *FieldVal = Def->getValue(FieldName)->getValue();
2672 const Init *FieldVal = DI->getDef()->getValue(FieldName)->getValue();
2681 const RecTy *ValType) {
2683 "Number of conditions and values must match!");
2684 ID.AddPointer(ValType);
2686 for (
const auto &[
Cond, Val] :
zip(Conds, Vals)) {
2687 ID.AddPointer(
Cond);
2708 "Number of conditions and values must match!");
2720 CondOpInit *
I =
new (Mem) CondOpInit(Conds,
Values, Ty);
2731 const Init *NewCond =
Cond->resolveReferences(R);
2742 if (NewCondVal->getValue()) {
2762 if (CondI->getValue())
2763 return Val->convertInitializerTo(
getValType());
2771 " does not have any true condition in:" +
2772 this->getAsString());
2778 return std::get<0>(Pair)->isConcrete() && std::get<1>(Pair)->isConcrete();
2784 return std::get<0>(Pair)->isComplete() && std::get<1>(Pair)->isComplete();
2789 std::string Result =
"!cond(";
2793 Result +=
Cond->getAsString() +
": ";
2794 Result += Val->getAsString();
2796 return Result +
")";
2811 for (
auto [Arg, Name] :
zip_equal(Args, ArgNames)) {
2813 ID.AddPointer(Name);
2821 ValName(VN), NumArgs(
Args.
size()) {
2830 "Number of DAG args and arg names must match!");
2842 Args.size(), ArgNames.
size()),
2844 DagInit *
I =
new (Mem) DagInit(V, VN, Args, ArgNames);
2851 ArrayRef<std::pair<const Init *, const StringInit *>> ArgAndNames) {
2863 return DefI->getDef();
2871 return ArgName && ArgName->
getValue() == Name;
2873 if (It == ArgNames.
end())
2874 return std::nullopt;
2875 return std::distance(ArgNames.
begin(), It);
2881 bool ArgsChanged =
false;
2885 ArgsChanged |= NewArg != Arg;
2888 const Init *
Op = Val->resolveReferences(R);
2889 if (
Op != Val || ArgsChanged)
2896 if (!Val->isConcrete())
2902 std::string Result =
"(" + Val->getAsString();
2904 Result +=
":$" + ValName->getAsUnquotedString();
2910 Result += Arg->getAsString();
2912 Result +=
":$" + Name->getAsUnquotedString();
2915 return Result +
")";
2923 : Name(
N), TyAndKind(
T, K) {
2925 assert(Value &&
"Cannot create unset value for current type!");
2931 : Name(
N), Loc(Loc), TyAndKind(
T, K) {
2933 assert(Value &&
"Cannot create unset value for current type!");
2943 if (StrInit->hasCodeFormat())
2951 return TyAndKind.getPointer()->getAsString();
2972 for (
unsigned I = 0, E = BTy->getNumBits();
I < E; ++
I)
2973 Bits[
I] = Value->getBit(
I);
2987#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
2998 if (PrintSem) OS <<
";\n";
3002 assert(Locs.size() == 1);
3003 ForwardDeclarationLocs.push_back(Locs.front());
3006 Locs.push_back(
Loc);
3009void Record::checkName() {
3014 "' is not a string!");
3024 if (!CorrespondingDefInit) {
3025 CorrespondingDefInit =
3026 new (TrackedRecords.getImpl().Allocator)
DefInit(
this);
3028 return CorrespondingDefInit;
3054 if (NewName != OldName) {
3061 if (SkipVal == &
Value)
3065 if (
Value.setValue(VR)) {
3069 (
Twine(
"of type '") + VRT->getType()->getAsString() +
"' ").str();
3072 Twine(
"Invalid value ") +
Type +
"found when setting field '" +
3073 Value.getNameInitAsString() +
"' of type '" +
3083 const Init *
Value = Assertion.Condition->resolveReferences(R);
3084 Assertion.Condition =
Value;
3085 Value = Assertion.Message->resolveReferences(R);
3086 Assertion.Message =
Value;
3090 const Init *
Value = Dump.Message->resolveReferences(R);
3091 Dump.Message =
Value;
3102#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
3107 OS << R.getNameInitAsString();
3110 if (!TArgs.
empty()) {
3113 for (
const Init *TA : TArgs) {
3115 assert(RV &&
"Template argument record not found??");
3117 RV->
print(OS,
false);
3123 std::vector<const Record *> SCs = R.getSuperClasses();
3126 for (
const Record *SC : SCs)
3127 OS <<
" " << SC->getNameInitAsString();
3131 for (
const RecordVal &Val : R.getValues())
3132 if (Val.isNonconcreteOK() && !R.isTemplateArg(Val.getNameInit()))
3134 for (
const RecordVal &Val : R.getValues())
3135 if (!Val.isNonconcreteOK() && !R.isTemplateArg(Val.getNameInit()))
3145 "' does not have a field named `" + FieldName +
"'!\n");
3151 if (!R || !R->getValue())
3153 "' does not have a field named `" + FieldName +
"'!\n");
3154 return R->getValue();
3160 return SI->getValue();
3162 "' exists but does not have a string value");
3165std::optional<StringRef>
3168 if (!R || !R->getValue())
3169 return std::nullopt;
3171 return std::nullopt;
3174 return SI->getValue();
3177 "Record `" +
getName() +
"', ` field `" + FieldName +
3178 "' exists but does not have a string initializer!");
3186 "' exists but does not have a bits value");
3194 "' exists but does not have a list value");
3197std::vector<const Record *>
3200 std::vector<const Record *> Defs;
3201 for (
const Init *
I :
List->getElements()) {
3203 Defs.push_back(DI->getDef());
3207 "' list is not entirely DefInit!");
3215 return II->getValue();
3218 Twine(
"Record `") +
getName() +
"', field `" + FieldName +
3219 "' exists but does not have an int value: " +
I->getAsString());
3225 std::vector<int64_t> Ints;
3226 for (
const Init *
I :
List->getElements()) {
3228 Ints.push_back(
II->getValue());
3231 Twine(
"Record `") +
getName() +
"', field `" + FieldName +
3232 "' exists but does not have a list of ints value: " +
3238std::vector<StringRef>
3241 std::vector<StringRef> Strings;
3242 for (
const Init *
I :
List->getElements()) {
3244 Strings.push_back(
SI->getValue());
3247 Twine(
"Record `") +
getName() +
"', field `" + FieldName +
3248 "' exists but does not have a list of strings value: " +
3257 return DI->getDef();
3259 FieldName +
"' does not have a def initializer!");
3265 return DI->getDef();
3269 FieldName +
"' does not have either a def initializer or '?'!");
3275 return BI->getValue();
3277 FieldName +
"' does not have a bit initializer!");
3288 return BI->getValue();
3290 FieldName +
"' does not have a bit initializer!");
3298 FieldName +
"' does not have a dag initializer!");
3309 bool AnyFailed =
false;
3313 AnyFailed |=
CheckAssert(Assertion.Loc, Condition, Message);
3321 PrintError(
this,
"assertion failed in this record");
3329 const Init *Message = Dump.Message->resolveReferences(R);
3345 : Impl(
std::make_unique<
detail::RecordKeeperImpl>(*this)),
3350#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
3355 OS <<
"------------- Classes -----------------\n";
3357 OS <<
"class " << *
C;
3359 OS <<
"------------- Defs -----------------\n";
3375 auto [Iter, Inserted] = Cache.try_emplace(ClassName.
str());
3378 return Iter->second;
3381std::vector<const Record *>
3384 std::vector<const Record *> Defs;
3386 assert(ClassNames.
size() > 0 &&
"At least one class must be passed.");
3387 for (
StringRef ClassName : ClassNames) {
3394 for (
const auto &OneDef :
getDefs()) {
3396 return OneDef.second->isSubClassOf(Class);
3398 Defs.push_back(OneDef.second.get());
3412 Impl->dumpAllocationStats(OS);
3416 auto It = Map.find(VarName);
3417 if (It == Map.end())
3420 const Init *
I = It->second.V;
3422 if (!It->second.Resolved && Map.size() > 1) {
3426 I =
I->resolveReferences(*
this);
3427 Map[VarName] = {
I,
true};
3434 const Init *Val = Cache.lookup(VarName);
3443 Val = RV->getValue();
3444 Stack.push_back(VarName);
3449 Stack.push_back(VarName);
3454 Cache[VarName] = Val;
3459 const Init *
I =
nullptr;
3462 I = R->resolve(VarName);
3463 if (
I && !FoundUnresolved) {
3468 I->resolveReferences(
Sub);
3469 FoundUnresolved |=
Sub.FoundUnresolved;
3474 FoundUnresolved =
true;
3479 if (VarName == VarNameToTrack)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file defines the StringMap class.
This file defines the BumpPtrAllocator interface.
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
This file defines the DenseMap class.
This file defines a hash set that can be used to remove duplication of nodes in a graph.
static constexpr Value * getValue(Ty &ValueOrUse)
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
uint64_t IntrinsicInst * II
OptimizedStructLayoutField Field
const SmallVectorImpl< MachineOperand > & Cond
static const Init * SortHelper(const Init *LHS, const Init *MHS, const Init *RHS, const RecTy *Type, const Record *CurRec)
static void ProfileBitsInit(FoldingSetNodeID &ID, ArrayRef< const Init * > Range)
static bool canFitInBitfield(int64_t Value, unsigned NumBits)
static void ProfileCondOpInit(FoldingSetNodeID &ID, ArrayRef< const Init * > Conds, ArrayRef< const Init * > Vals, const RecTy *ValType)
static void ProfileListInit(FoldingSetNodeID &ID, ArrayRef< const Init * > Elements, const RecTy *EltTy)
static std::optional< unsigned > getDagArgNoByKey(const DagInit *Dag, const Init *Key, std::string &Error)
static void ProfileBinOpInit(FoldingSetNodeID &ID, unsigned Opcode, const Init *LHS, const Init *RHS, const RecTy *Type)
static const StringInit * ConcatStringInits(const StringInit *I0, const StringInit *I1)
static void ProfileTernOpInit(FoldingSetNodeID &ID, unsigned Opcode, const Init *LHS, const Init *MHS, const Init *RHS, const RecTy *Type)
static void ProfileExistsOpInit(FoldingSetNodeID &ID, const RecTy *CheckType, const Init *Expr)
static const ListInit * ConcatListInits(const ListInit *LHS, const ListInit *RHS)
static const StringInit * interleaveStringList(const ListInit *List, const StringInit *Delim)
static void ProfileDagInit(FoldingSetNodeID &ID, const Init *V, const StringInit *VN, ArrayRef< const Init * > Args, ArrayRef< const StringInit * > ArgNames)
static void ProfileFoldOpInit(FoldingSetNodeID &ID, const Init *Start, const Init *List, const Init *A, const Init *B, const Init *Expr, const RecTy *Type)
static void ProfileInstancesOpInit(FoldingSetNodeID &ID, const RecTy *Type, const Init *Regex)
static void ProfileUnOpInit(FoldingSetNodeID &ID, unsigned Opcode, const Init *Op, const RecTy *Type)
static void ProfileArgumentInit(FoldingSetNodeID &ID, const Init *Value, ArgAuxType Aux)
static const Init * ForeachDagApply(const Init *LHS, const DagInit *MHSd, const Init *RHS, const Record *CurRec)
static const Init * FilterHelper(const Init *LHS, const Init *MHS, const Init *RHS, const RecTy *Type, const Record *CurRec)
static const Init * ItemApply(const Init *LHS, const Init *MHSe, const Init *RHS, const Record *CurRec)
static const RecordRecTy * resolveRecordTypes(const RecordRecTy *T1, const RecordRecTy *T2)
static void ProfileRecordRecTy(FoldingSetNodeID &ID, ArrayRef< const Record * > Classes)
static const Init * ForeachHelper(const Init *LHS, const Init *MHS, const Init *RHS, const RecTy *Type, const Record *CurRec)
static void ProfileVarDefInit(FoldingSetNodeID &ID, const Record *Class, ArrayRef< const ArgumentInit * > Args)
static void ProfileIsAOpInit(FoldingSetNodeID &ID, const RecTy *CheckType, const Init *Expr)
static const StringInit * interleaveIntList(const ListInit *List, const StringInit *Delim)
This file defines the SmallString class.
This file defines the SmallVector class.
FunctionLoweringInfo::StatepointRelocationRecord RecordType
static SymbolRef::Type getType(const Symbol *Sym)
static constexpr int Concat[]
static AnonymousNameInit * get(RecordKeeper &RK, unsigned)
const StringInit * getNameInit() const
const Init * resolveReferences(Resolver &R) const override
This function is used by classes that refer to other variables which may not be defined at the time t...
std::string getAsString() const override
Convert this value to a literal form.
const ArgumentInit * cloneWithValue(const Init *Value) const
void Profile(FoldingSetNodeID &ID) const
static const ArgumentInit * get(const Init *Value, ArgAuxType Aux)
ArgumentInit(const Init *Value, ArgAuxType Aux)
const Init * resolveReferences(Resolver &R) const override
This function is used by classes that refer to other variables which may not be defined at the time t...
Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
Get the array size.
bool empty() const
Check if the array is empty.
static const BinOpInit * get(BinaryOp opc, const Init *lhs, const Init *rhs, const RecTy *Type)
void Profile(FoldingSetNodeID &ID) const
const Init * resolveReferences(Resolver &R) const override
This function is used by classes that refer to other variables which may not be defined at the time t...
static const Init * getStrConcat(const Init *lhs, const Init *rhs)
std::string getAsString() const override
Convert this value to a literal form.
BinaryOp getOpcode() const
const Init * getRHS() const
std::optional< bool > CompareInit(unsigned Opc, const Init *LHS, const Init *RHS) const
const Init * getLHS() const
static const Init * getListConcat(const TypedInit *lhs, const Init *rhs)
const Init * Fold(const Record *CurRec) const
'true'/'false' - Represent a concrete initializer for a bit.
static BitInit * get(RecordKeeper &RK, bool V)
const Init * convertInitializerTo(const RecTy *Ty) const override
Convert to a value whose type is Ty, or return null if this is not possible.
'bit' - Represent a single bit
static const BitRecTy * get(RecordKeeper &RK)
bool typeIsConvertibleTo(const RecTy *RHS) const override
Return true if all values of 'this' type can be converted to the specified type.
'{ a, b, c }' - Represents an initializer for a BitsRecTy value.
void Profile(FoldingSetNodeID &ID) const
std::string getAsString() const override
Convert this value to a literal form.
bool isComplete() const override
Is this a complete value with no unset (uninitialized) subvalues?
unsigned getNumBits() const
std::optional< int64_t > convertInitializerToInt() const
const Init * getBit(unsigned Bit) const override
Get the Init value of the specified bit.
const Init * convertInitializerBitRange(ArrayRef< unsigned > Bits) const override
This function is used to implement the bit range selection operator.
const Init * resolveReferences(Resolver &R) const override
This function is used by classes that refer to other variables which may not be defined at the time t...
const Init * convertInitializerTo(const RecTy *Ty) const override
Convert to a value whose type is Ty, or return null if this is not possible.
ArrayRef< const Init * > getBits() const
uint64_t convertKnownBitsToInt() const
bool allInComplete() const
static BitsInit * get(RecordKeeper &RK, ArrayRef< const Init * > Range)
bool isConcrete() const override
Is this a concrete and fully resolved value without any references or stuck operations?
'bits<n>' - Represent a fixed number of bits
bool typeIsConvertibleTo(const RecTy *RHS) const override
Return true if all values of 'this' type can be converted to the specified type.
static const BitsRecTy * get(RecordKeeper &RK, unsigned Sz)
std::string getAsString() const override
const Init * Fold(const Record *CurRec) const
auto getCondAndVals() const
ArrayRef< const Init * > getVals() const
const Init * resolveReferences(Resolver &R) const override
This function is used by classes that refer to other variables which may not be defined at the time t...
const Init * getBit(unsigned Bit) const override
Get the Init value of the specified bit.
bool isConcrete() const override
Is this a concrete and fully resolved value without any references or stuck operations?
void Profile(FoldingSetNodeID &ID) const
std::string getAsString() const override
Convert this value to a literal form.
static const CondOpInit * get(ArrayRef< const Init * > Conds, ArrayRef< const Init * > Values, const RecTy *Type)
const RecTy * getValType() const
bool isComplete() const override
Is this a complete value with no unset (uninitialized) subvalues?
ArrayRef< const Init * > getConds() const
(v a, b) - Represent a DAG tree value.
bool isConcrete() const override
Is this a concrete and fully resolved value without any references or stuck operations?
std::optional< unsigned > getArgNo(StringRef Name) const
This method looks up the specified argument name and returns its argument number or std::nullopt if t...
const StringInit * getName() const
void Profile(FoldingSetNodeID &ID) const
const Init * getOperator() const
const Init * resolveReferences(Resolver &R) const override
This function is used by classes that refer to other variables which may not be defined at the time t...
ArrayRef< const StringInit * > getArgNames() const
static const DagInit * get(const Init *V, const StringInit *VN, ArrayRef< const Init * > Args, ArrayRef< const StringInit * > ArgNames)
const Record * getOperatorAsDef(ArrayRef< SMLoc > Loc) const
auto getArgAndNames() const
ArrayRef< const Init * > getArgs() const
std::string getAsString() const override
Convert this value to a literal form.
'dag' - Represent a dag fragment
std::string getAsString() const override
static const DagRecTy * get(RecordKeeper &RK)
AL - Represent a reference to a 'def' in the description.
std::string getAsString() const override
Convert this value to a literal form.
const RecTy * getFieldType(const StringInit *FieldName) const override
This function is used to implement the FieldInit class.
const Init * convertInitializerTo(const RecTy *Ty) const override
Convert to a value whose type is Ty, or return null if this is not possible.
Lightweight error class with error context and mandatory checking.
void Profile(FoldingSetNodeID &ID) const
static const ExistsOpInit * get(const RecTy *CheckType, const Init *Expr)
std::string getAsString() const override
Convert this value to a literal form.
const Init * resolveReferences(Resolver &R) const override
This function is used by classes that refer to other variables which may not be defined at the time t...
const Init * Fold(const Record *CurRec, bool IsFinal=false) const
const Init * getBit(unsigned Bit) const override
Get the Init value of the specified bit.
X.Y - Represent a reference to a subfield of a variable.
const Init * Fold(const Record *CurRec) const
const Init * getBit(unsigned Bit) const override
Get the Init value of the specified bit.
static const FieldInit * get(const Init *R, const StringInit *FN)
const Init * resolveReferences(Resolver &R) const override
This function is used by classes that refer to other variables which may not be defined at the time t...
bool isConcrete() const override
Is this a concrete and fully resolved value without any references or stuck operations?
const Init * Fold(const Record *CurRec) const
std::string getAsString() const override
Convert this value to a literal form.
static const FoldOpInit * get(const Init *Start, const Init *List, const Init *A, const Init *B, const Init *Expr, const RecTy *Type)
const Init * getBit(unsigned Bit) const override
Get the Init value of the specified bit.
const Init * resolveReferences(Resolver &R) const override
This function is used by classes that refer to other variables which may not be defined at the time t...
void Profile(FoldingSetNodeID &ID) const
void insert(T *N, FoldingSetInsertToken Token)
Insert the specified node into the folding set, knowing that it is not already in the folding set.
T * lookup(const FoldingSetNodeID &ID, FoldingSetInsertToken &Token)
Look up the node specified by ID.
Insertion token: a failed lookup fills it in, the matching insert consumes it.
This class is used to gather all the unique data bits of a node.
const Init * resolve(const Init *VarName) override
Return the initializer for the given variable name (should normally be a StringInit),...
virtual const Init * resolveReferences(Resolver &R) const
This function is used by classes that refer to other variables which may not be defined at the time t...
virtual std::string getAsUnquotedString() const
Convert this value to a literal form, without adding quotes around a string.
void dump() const
Debugging method that may be called through a debugger; just invokes print on stderr.
void print(raw_ostream &OS) const
Print this value.
virtual std::string getAsString() const =0
Convert this value to a literal form.
virtual bool isConcrete() const
Is this a concrete and fully resolved value without any references or stuck operations?
virtual bool isComplete() const
Is this a complete value with no unset (uninitialized) subvalues?
virtual const Init * getBit(unsigned Bit) const =0
Get the Init value of the specified bit.
virtual const Init * convertInitializerTo(const RecTy *Ty) const =0
Convert to a value whose type is Ty, or return null if this is not possible.
virtual const Init * getCastTo(const RecTy *Ty) const =0
If this value is convertible to type Ty, return a value whose type is Ty, generating a !...
RecordKeeper & getRecordKeeper() const
Get the record keeper that initialized this Init.
Init(InitKind K, uint8_t Opc=0)
void Profile(FoldingSetNodeID &ID) const
const Init * Fold(const Record *CurRec, bool IsFinal=false) const
const Init * resolveReferences(Resolver &R) const override
This function is used by classes that refer to other variables which may not be defined at the time t...
std::string getAsString() const override
Convert this value to a literal form.
static const InstancesOpInit * get(const RecTy *Type, const Init *Regex)
static IntInit * get(RecordKeeper &RK, int64_t V)
const Init * convertInitializerBitRange(ArrayRef< unsigned > Bits) const override
This function is used to implement the bit range selection operator.
std::string getAsString() const override
Convert this value to a literal form.
const Init * convertInitializerTo(const RecTy *Ty) const override
Convert to a value whose type is Ty, or return null if this is not possible.
'int' - Represent an integer value of no particular size
static const IntRecTy * get(RecordKeeper &RK)
bool typeIsConvertibleTo(const RecTy *RHS) const override
Return true if all values of 'this' type can be converted to the specified type.
static const IsAOpInit * get(const RecTy *CheckType, const Init *Expr)
void Profile(FoldingSetNodeID &ID) const
const Init * resolveReferences(Resolver &R) const override
This function is used by classes that refer to other variables which may not be defined at the time t...
std::string getAsString() const override
Convert this value to a literal form.
const Init * getBit(unsigned Bit) const override
Get the Init value of the specified bit.
const Init * Fold() const
[AL, AH, CL] - Represent a list of defs
std::string getAsString() const override
Convert this value to a literal form.
const RecTy * getElementType() const
static const ListInit * get(ArrayRef< const Init * > Range, const RecTy *EltTy)
bool isConcrete() const override
Is this a concrete and fully resolved value without any references or stuck operations?
bool isComplete() const override
Is this a complete value with no unset (uninitialized) subvalues?
const Init * resolveReferences(Resolver &R) const override
This method is used by classes that refer to other variables which may not be defined at the time the...
const Init * convertInitializerTo(const RecTy *Ty) const override
Convert to a value whose type is Ty, or return null if this is not possible.
void Profile(FoldingSetNodeID &ID) const
const Record * getElementAsRecord(unsigned Idx) const
ArrayRef< const Init * > getElements() const
const Init * getElement(unsigned Idx) const
'list<Ty>' - Represent a list of element values, all of which must be of the specified type.
const RecTy * getElementType() const
bool typeIsA(const RecTy *RHS) const override
Return true if 'this' type is equal to or a subtype of RHS.
std::string getAsString() const override
bool typeIsConvertibleTo(const RecTy *RHS) const override
Return true if all values of 'this' type can be converted to the specified type.
A helper class to return the specified delimiter string after the first invocation of operator String...
Resolve arbitrary mappings.
const Init * resolve(const Init *VarName) override
Return the initializer for the given variable name (should normally be a StringInit),...
const Init * getBit(unsigned Bit) const final
Get the Init value of the specified bit.
RecordKeeper & getRecordKeeper() const
Return the RecordKeeper that uniqued this Type.
virtual bool typeIsA(const RecTy *RHS) const
Return true if 'this' type is equal to or a subtype of RHS.
virtual bool typeIsConvertibleTo(const RecTy *RHS) const
Return true if all values of 'this' type can be converted to the specified type.
RecTyKind
Subclass discriminator (for dyn_cast<> et al.)
RecTy(RecTyKind K, RecordKeeper &RK)
virtual std::string getAsString() const =0
const ListRecTy * getListTy() const
Returns the type representing list<thistype>.
const Record * getClass(StringRef Name) const
Get the class with the specified name.
const RecordMap & getClasses() const
Get the map of classes.
const Init * getNewAnonymousName()
GetNewAnonymousName - Generate a unique anonymous name that can be used as an identifier.
const RecordMap & getDefs() const
Get the map of records (defs).
detail::RecordKeeperImpl & getImpl()
Return the internal implementation of the RecordKeeper.
void dumpAllocationStats(raw_ostream &OS) const
ArrayRef< const Record * > getAllDerivedDefinitionsIfDefined(StringRef ClassName) const
Get all the concrete records that inherit from specified class, if the class is defined.
const Record * getDef(StringRef Name) const
Get the concrete record with the specified name.
ArrayRef< const Record * > getAllDerivedDefinitions(StringRef ClassName) const
Get all the concrete records that inherit from the one specified class.
'[classname]' - Type of record values that have zero or more superclasses.
bool typeIsConvertibleTo(const RecTy *RHS) const override
Return true if all values of 'this' type can be converted to the specified type.
bool isSubClassOf(const Record *Class) const
ArrayRef< const Record * > getClasses() const
void Profile(FoldingSetNodeID &ID) const
std::string getAsString() const override
bool typeIsA(const RecTy *RHS) const override
Return true if 'this' type is equal to or a subtype of RHS.
static const RecordRecTy * get(RecordKeeper &RK, ArrayRef< const Record * > Classes)
Get the record type with the given non-redundant list of superclasses.
Resolve all variables from a record except for unset variables.
const Init * resolve(const Init *VarName) override
Return the initializer for the given variable name (should normally be a StringInit),...
This class represents a field in a record, including its name, type, value, and source location.
std::string getNameInitAsString() const
Get the name of the field as a std::string.
bool isNonconcreteOK() const
Is this a field where nonconcrete values are okay?
bool setValue(const Init *V)
Set the value of the field from an Init.
SMLoc getLoc() const
Get the source location of the point where the field was defined.
const Init * getValue() const
Get the value of the field as an Init.
StringRef getName() const
Get the name of the field as a StringRef.
void print(raw_ostream &OS, bool PrintSem=true) const
Print the value to an output stream, possibly with a semicolon.
RecordVal(const Init *N, const RecTy *T, FieldKind K)
const Init * getNameInit() const
Get the name of the field as an Init.
std::string getPrintType() const
Get the type of the field for printing purposes.
const RecTy * getType() const
Get the type of the field value as a RecTy.
std::vector< int64_t > getValueAsListOfInts(StringRef FieldName) const
This method looks up the specified field and returns its value as a vector of integers,...
const RecordRecTy * getType() const
const Init * getValueInit(StringRef FieldName) const
Return the initializer for a value with the specified name, or throw an exception if the field does n...
bool getValueAsBitOrUnset(StringRef FieldName, bool &Unset) const
This method looks up the specified field and returns its value as a bit.
bool getValueAsBit(StringRef FieldName) const
This method looks up the specified field and returns its value as a bit, throwing an exception if the...
static unsigned getNewUID(RecordKeeper &RK)
ArrayRef< SMLoc > getLoc() const
void checkUnusedTemplateArgs()
ArrayRef< DumpInfo > getDumps() const
std::vector< const Record * > getValueAsListOfDefs(StringRef FieldName) const
This method looks up the specified field and returns its value as a vector of records,...
ArrayRef< AssertionInfo > getAssertions() const
std::string getNameInitAsString() const
const Record * getValueAsDef(StringRef FieldName) const
This method looks up the specified field and returns its value as a Record, throwing an exception if ...
const DagInit * getValueAsDag(StringRef FieldName) const
This method looks up the specified field and returns its value as an Dag, throwing an exception if th...
std::vector< StringRef > getValueAsListOfStrings(StringRef FieldName) const
This method looks up the specified field and returns its value as a vector of strings,...
const RecordVal * getValue(const Init *Name) const
void addValue(const RecordVal &RV)
const Record * getValueAsOptionalDef(StringRef FieldName) const
This method looks up the specified field and returns its value as a Record, returning null if the fie...
ArrayRef< std::pair< const Record *, SMRange > > getDirectSuperClasses() const
Return the direct superclasses of this record.
StringRef getName() const
Record(const Init *N, ArrayRef< SMLoc > locs, RecordKeeper &records, RecordKind Kind=RK_Def)
void setName(const Init *Name)
const ListInit * getValueAsListInit(StringRef FieldName) const
This method looks up the specified field and returns its value as a ListInit, throwing an exception i...
void appendDumps(const Record *Rec)
bool isSubClassOf(const Record *R) const
DefInit * getDefInit() const
get the corresponding DefInit.
SMLoc getFieldLoc(StringRef FieldName) const
Return the source location for the named field.
void resolveReferences(const Init *NewName=nullptr)
If there are any field references that refer to fields that have been filled in, we can propagate the...
std::optional< StringRef > getValueAsOptionalString(StringRef FieldName) const
This method looks up the specified field and returns its value as a string, throwing an exception if ...
void removeValue(const Init *Name)
ArrayRef< const Init * > getTemplateArgs() const
void updateClassLoc(SMLoc Loc)
const BitsInit * getValueAsBitsInit(StringRef FieldName) const
This method looks up the specified field and returns its value as a BitsInit, throwing an exception i...
void addDirectSuperClass(const Record *R, SMRange Range)
void appendAssertions(const Record *Rec)
const Init * getNameInit() const
int64_t getValueAsInt(StringRef FieldName) const
This method looks up the specified field and returns its value as an int64_t, throwing an exception i...
void checkRecordAssertions()
StringRef getValueAsString(StringRef FieldName) const
This method looks up the specified field and returns its value as a string, throwing an exception if ...
Interface for looking up the initializer for a variable name, used by Init::resolveReferences.
const Record * getCurrentRecord() const
Represents a location in source code.
Delegate resolving to a sub-resolver, but shadow some variable names.
void addShadow(const Init *Key)
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
reference emplace_back(ArgTypes &&... Args)
void reserve(size_type N)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
"foo" - Represent an initialization by a string value.
static const StringInit * get(RecordKeeper &RK, StringRef, StringFormat Fmt=SF_String)
StringFormat getFormat() const
StringRef getValue() const
static StringFormat determineFormat(StringFormat Fmt1, StringFormat Fmt2)
const Init * convertInitializerTo(const RecTy *Ty) const override
Convert to a value whose type is Ty, or return null if this is not possible.
StringMap - This is an unconventional map that is specialized for handling keys that are "strings",...
std::pair< iterator, bool > try_emplace(StringRef Key, ArgsTy &&...Args)
Emplace a new element for the specified key into the map if the key isn't already in the map.
'string' - Represent an string value
std::string getAsString() const override
static const StringRecTy * get(RecordKeeper &RK)
bool typeIsConvertibleTo(const RecTy *RHS) const override
Return true if all values of 'this' type can be converted to the specified type.
Represent a constant reference to a string, i.e.
std::string str() const
Get the contents as an std::string.
const Init * Fold(const Record *CurRec) const
const Init * getLHS() const
void Profile(FoldingSetNodeID &ID) const
const Init * getMHS() const
const Init * getRHS() const
static const TernOpInit * get(TernaryOp opc, const Init *lhs, const Init *mhs, const Init *rhs, const RecTy *Type)
std::string getAsString() const override
Convert this value to a literal form.
const Init * resolveReferences(Resolver &R) const override
This function is used by classes that refer to other variables which may not be defined at the time t...
TernaryOp getOpcode() const
(Optionally) delegate resolving to a sub-resolver, and keep track whether there were unresolved refer...
const Init * resolve(const Init *VarName) override
Return the initializer for the given variable name (should normally be a StringInit),...
bool foundUnresolved() const
TrackUnresolvedResolver(Resolver *R=nullptr)
See the file comment for details on the usage of the TrailingObjects type.
static constexpr std::enable_if_t< std::is_same_v< Foo< TrailingTys... >, Foo< Tys... > >, size_t > totalSizeToAlloc(typename trailing_objects_internal::ExtractSecondType< TrailingTys, size_t >::type... Counts)
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
The instances of the Type class are immutable: once they are created, they are never changed.
This is the common superclass of types that have a specific, explicit type, stored in ValueTy.
const RecTy * getFieldType(const StringInit *FieldName) const override
This method is used to implement the FieldInit class.
TypedInit(InitKind K, const RecTy *T, uint8_t Opc=0)
const Init * convertInitializerBitRange(ArrayRef< unsigned > Bits) const override
This function is used to implement the bit range selection operator.
RecordKeeper & getRecordKeeper() const
Get the record keeper that initialized this Init.
const Init * getCastTo(const RecTy *Ty) const override
If this value is convertible to type Ty, return a value whose type is Ty, generating a !...
const Init * convertInitializerTo(const RecTy *Ty) const override
Convert to a value whose type is Ty, or return null if this is not possible.
const RecTy * getType() const
Get the type of the Init as a RecTy.
const Init * getOperand() const
UnaryOp getOpcode() const
static const UnOpInit * get(UnaryOp opc, const Init *lhs, const RecTy *Type)
void Profile(FoldingSetNodeID &ID) const
const Init * resolveReferences(Resolver &R) const override
This function is used by classes that refer to other variables which may not be defined at the time t...
std::string getAsString() const override
Convert this value to a literal form.
const Init * Fold(const Record *CurRec, bool IsFinal=false) const
'?' - Represents an uninitialized value.
const Init * getCastTo(const RecTy *Ty) const override
If this value is convertible to type Ty, return a value whose type is Ty, generating a !...
const Init * convertInitializerTo(const RecTy *Ty) const override
Convert to a value whose type is Ty, or return null if this is not possible.
static UnsetInit * get(RecordKeeper &RK)
Get the singleton unset Init.
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
Opcode{0} - Represent access to one bit of a variable or field.
static const VarBitInit * get(const TypedInit *T, unsigned B)
unsigned getBitNum() const
std::string getAsString() const override
Convert this value to a literal form.
const Init * resolveReferences(Resolver &R) const override
This function is used by classes that refer to other variables which may not be defined at the time t...
ArrayRef< const ArgumentInit * > args() const
static const VarDefInit * get(SMLoc Loc, const Record *Class, ArrayRef< const ArgumentInit * > Args)
const Init * resolveReferences(Resolver &R) const override
This function is used by classes that refer to other variables which may not be defined at the time t...
const Init * Fold() const
void Profile(FoldingSetNodeID &ID) const
std::string getAsString() const override
Convert this value to a literal form.
'Opcode' - Represent a reference to an entire variable object.
static const VarInit * get(StringRef VN, const RecTy *T)
const Init * getBit(unsigned Bit) const override
Get the Init value of the specified bit.
StringRef getName() const
const Init * getNameInit() const
const Init * resolveReferences(Resolver &R) const override
This method is used by classes that refer to other variables which may not be defined at the time the...
This class implements an extremely fast bulk output stream that can only output to a stream.
A raw_ostream that writes to an std::string.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
llvm::SmallVector< std::shared_ptr< RecordsSlice >, 4 > Records
This is an optimization pass for GlobalISel generic memory operations.
detail::zippy< detail::zip_shortest, T, U, Args... > zip(T &&t, U &&u, Args &&...args)
zip iterator for two or more iteratable types.
void stable_sort(R &&Range)
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
Printable print(const GCNRegPressure &RP, const GCNSubtarget *ST=nullptr, unsigned DynamicVGPRBlockSize=0)
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
detail::zippy< detail::zip_first, T, U, Args... > zip_equal(T &&t, U &&u, Args &&...args)
zip iterator that assumes that all iteratees have the same length.
RelativeUniformCounterPtr Values
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI void PrintFatalError(const Twine &Msg)
LLVM_ABI void PrintError(const Twine &Msg)
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
std::string utostr(uint64_t X, bool isNeg=false)
auto uninitialized_copy(R &&Src, IterTy Dst)
unsigned Log2_64(uint64_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
LLVM_ABI bool CheckAssert(SMLoc Loc, const Init *Condition, const Init *Message)
auto dyn_cast_or_null(const Y &Val)
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI void PrintWarning(const Twine &Msg)
auto reverse(ContainerTy &&C)
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
void sort(IteratorTy Start, IteratorTy End)
auto make_first_range(ContainerTy &&c)
Given a container of pairs, return a range over the first elements.
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
@ Sub
Subtraction of integers.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
DWARFExpression::Operation Op
raw_ostream & operator<<(raw_ostream &OS, const APFixedPoint &FX)
ArrayRef(const T &OneElt) -> ArrayRef< T >
auto make_second_range(ContainerTy &&c)
Given a container of pairs, return a range over the second elements.
LLVM_ABI void dumpMessage(SMLoc Loc, const Init *Message)
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
const RecTy * resolveTypes(const RecTy *T1, const RecTy *T2)
Find a common type that T1 and T2 convert to.
BumpPtrAllocatorImpl<> BumpPtrAllocator
The standard BumpPtrAllocator which just uses the default template parameters.
std::variant< unsigned, const Init * > ArgAuxType
std::string itostr(int64_t X)
FoldingSetImpl< T, Trait > FoldingSet
This template class is used to instantiate a specialized implementation of the folding set to the nod...
Implement std::hash so that hash_code can be used in STL containers.
This class represents the internal implementation of the RecordKeeper.
StringMap< const StringInit *, BumpPtrAllocator & > StringInitCodePool
StringRecTy SharedStringRecTy
FoldingSet< ListInit > TheListInitPool
FoldingSet< BitsInit > TheBitsInitPool
BumpPtrAllocator Allocator
std::map< int64_t, IntInit * > TheIntInitPool
FoldingSet< ArgumentInit > TheArgumentInitPool
FoldingSet< UnOpInit > TheUnOpInitPool
DenseMap< std::pair< const Init *, const StringInit * >, FieldInit * > TheFieldInitPool
std::vector< BitsRecTy * > SharedBitsRecTys
FoldingSet< RecordRecTy > RecordTypePool
FoldingSet< VarDefInit > TheVarDefInitPool
RecordKeeperImpl(RecordKeeper &RK)
StringMap< const StringInit *, BumpPtrAllocator & > StringInitStringPool
FoldingSet< TernOpInit > TheTernOpInitPool
FoldingSet< InstancesOpInit > TheInstancesOpInitPool
void dumpAllocationStats(raw_ostream &OS) const
FoldingSet< ExistsOpInit > TheExistsOpInitPool
DenseMap< std::pair< const RecTy *, const Init * >, VarInit * > TheVarInitPool
FoldingSet< IsAOpInit > TheIsAOpInitPool
FoldingSet< DagInit > TheDagInitPool
DenseMap< std::pair< const TypedInit *, unsigned >, VarBitInit * > TheVarBitInitPool
FoldingSet< CondOpInit > TheCondOpInitPool
FoldingSet< BinOpInit > TheBinOpInitPool
FoldingSet< FoldOpInit > TheFoldOpInitPool
Sorting predicate to sort record pointers by name.