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;
230 :
RecTy(RecordRecTyKind, RK), NumClasses(Classes.
size()) {
237 if (UnsortedClasses.
empty())
244 return LHS->getNameInitAsString() < RHS->getNameInitAsString();
248 if (RecordRecTy *Ty = ThePool.
lookup(Classes, Token))
253 for (
unsigned i = 0; i < Classes.
size(); ++i) {
254 for (
unsigned j = 0; j < Classes.
size(); ++j) {
257 assert(&Classes[0]->getRecords() == &Classes[i]->getRecords());
263 RecordRecTy *Ty =
new (Mem) RecordRecTy(RK, Classes);
264 ThePool.
insert(Ty, Token);
269 assert(Class &&
"unexpected null class");
270 return get(Class->getRecords(), {Class});
275 return getClasses()[0]->getNameInitAsString();
277 std::string Str =
"{";
281 Str += R->getNameInitAsString();
289 return MySuperClass == Class || MySuperClass->
isSubClassOf(Class);
302 return isSubClassOf(TargetClass);
315 while (!Stack.empty()) {
316 const Record *R = Stack.pop_back_val();
318 if (T2->isSubClassOf(R))
336 assert(T1 !=
nullptr &&
"Invalid record type");
337 if (T1->typeIsConvertibleTo(T2))
340 assert(T2 !=
nullptr &&
"Invalid record type");
341 if (T2->typeIsConvertibleTo(T1))
346 const RecTy *NewType =
347 resolveTypes(ListTy1->getElementType(), ListTy2->getElementType());
360void Init::anchor() {}
362#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
368 return TyInit->getType()->getRecordKeeper();
370 return ArgInit->getRecordKeeper();
375 return &RK.getImpl().TheUnsetInit;
397 const Init *NewValue = Value->resolveReferences(R);
398 if (NewValue != Value)
417 if (BRT->getNumBits() == 1)
426 NumBits(Bits.
size()) {
438 BitsInit *
I =
new (Mem) BitsInit(RK, Bits);
452 if (
getNumBits() != BRT->getNumBits())
return nullptr;
469 Result |=
static_cast<int64_t
>(Bit->getValue()) << Idx;
479 Result |=
static_cast<int64_t
>(Bit->getValue()) << Idx;
487 for (
auto [Bit, NewBit] :
zip_equal(Bits, NewBits)) {
506 std::string Result =
"{ ";
511 Result += Bit->getAsString();
515 return Result +
" }";
524 const Init *CachedBitVarRef =
nullptr;
525 const Init *CachedBitVarResolved =
nullptr;
531 if (CurBitVar->getBitVar() != CachedBitVarRef) {
532 CachedBitVarRef = CurBitVar->getBitVar();
535 assert(CachedBitVarResolved &&
"Unresolved bitvar reference");
536 NewBit = CachedBitVarResolved->
getBit(CurBitVar->getBitNum());
539 NewBit = CurBit->resolveReferences(R)->getBit(0);
556 I =
new (RK.
getImpl().Allocator) IntInit(RK, V);
566 return (NumBits >=
sizeof(
Value) * 8) ||
567 (
Value >> NumBits == 0) || (
Value >> (NumBits-1) == -1);
576 if (Val != 0 && Val != 1)
return nullptr;
587 for (
unsigned i = 0; i != BRT->getNumBits(); ++i)
600 for (
auto [Bit, NewBit] :
zip_equal(Bits, NewBits)) {
610 return new (RK.
getImpl().Allocator) AnonymousNameInit(RK, V);
618 return "anonymous_" +
utostr(Value);
623 auto *New = R.resolve(Old);
624 New = New ? New : Old;
627 return Anonymous->getNameInit();
636 auto &Entry = *InitMap.
try_emplace(V,
nullptr).first;
638 Entry.second =
new (RKImpl.
Allocator) StringInit(RK, Entry.getKey(), Fmt);
651 NumElements(Elements.
size()) {
656 const RecTy *EltTy) {
667 ListInit *
I =
new (Mem) ListInit(Elements, EltTy);
678 Elements.reserve(
size());
683 const RecTy *ElementType = LRT->getElementType();
685 if (
const Init *CI =
I->convertInitializerTo(ElementType)) {
686 Elements.push_back(CI);
711 Resolved.reserve(
size());
717 Resolved.push_back(E);
736 std::string Result =
"[";
738 for (
const Init *Element : *
this) {
766 if (LHS->isConcrete()) {
771 OS << *Def->getDef();
811 (Anonymous && Name == Anonymous->getNameInit())) {
818 auto PrintFatalErrorHelper = [CurRec](
const Twine &
T) {
827 PrintFatalErrorHelper(
Twine(
"Undefined reference to record: '") +
828 Name->getValue() +
"'\n");
835 PrintFatalErrorHelper(
Twine(
"Expected type '") +
851 if (LHS->isConcrete())
863 assert(!LHSl->empty() &&
"Empty list in head");
864 return LHSl->getElement(0);
870 assert(!LHSl->empty() &&
"Empty list in tail");
874 LHSl->getElementType());
901 if (!TI->getType()->typeIsA(
getType())) {
907 return Dag->getOperator();
914 return Dag->getName();
921 int64_t LHSv = LHSi->getValue();
924 "Illegal operation: logtwo is undefined "
925 "on arguments less than or equal to 0");
929 "Log of an int64_t must be smaller than INT64_MAX");
943 [](
const ListInit *
List) -> std::optional<std::vector<const Init *>> {
944 std::vector<const Init *> Flattened;
946 for (
const Init *InnerInit :
List->getElements()) {
955 auto Flattened = Flatten(LHSList);
957 return ListInit::get(*Flattened, InnerListTy->getElementType());
969 ->Fold(R.getCurrentRecord(), R.isFinal());
977 case NOT: Result =
"!not";
break;
978 case HEAD: Result =
"!head";
break;
979 case TAIL: Result =
"!tail";
break;
980 case SIZE: Result =
"!size";
break;
981 case EMPTY: Result =
"!empty";
break;
982 case GETDAGOP: Result =
"!getdagop";
break;
984 Result =
"!getdagopname";
986 case LOG2 : Result =
"!logtwo";
break;
988 Result =
"!listflatten";
1000 Result =
"!initialized";
1003 return Result +
"(" + LHS->getAsString() +
")";
1010 if (
const BinOpInit *
I =
1022 Concat.append(I1->getValue());
1030 if (List->size() == 0)
1038 for (
const Init *Elem : List->getElements().drop_front()) {
1043 Result.append(Element->getValue());
1052 if (List->size() == 0)
1055 List->getElement(0)->convertInitializerTo(
IntRecTy::get(RK)));
1060 for (
const Init *Elem : List->getElements().drop_front()) {
1066 Result.append(Element->getAsString());
1099 const Init *RHS)
const {
1110 Result = LHSi->getValue() == RHSi->getValue();
1113 Result = LHSi->getValue() != RHSi->getValue();
1116 Result = LHSi->getValue() <= RHSi->getValue();
1119 Result = LHSi->getValue() < RHSi->getValue();
1122 Result = LHSi->getValue() >= RHSi->getValue();
1125 Result = LHSi->getValue() > RHSi->getValue();
1141 Result = LHSs->getValue() == RHSs->getValue();
1144 Result = LHSs->getValue() != RHSs->getValue();
1147 Result = LHSs->getValue() <= RHSs->getValue();
1150 Result = LHSs->getValue() < RHSs->getValue();
1153 Result = LHSs->getValue() >= RHSs->getValue();
1156 Result = LHSs->getValue() > RHSs->getValue();
1169 return (
Opc ==
EQ) ? LHSd == RHSd : LHSd != RHSd;
1172 return std::nullopt;
1175static std::optional<unsigned>
1179 int64_t Pos = Idx->getValue();
1183 (
Twine(
"index ") + std::to_string(Pos) +
Twine(
" is negative")).str();
1184 return std::nullopt;
1186 if (Pos >= Dag->getNumArgs()) {
1188 Error = (
Twine(
"index ") + std::to_string(Pos) +
1189 " is out of range (dag has " +
1190 std::to_string(Dag->getNumArgs()) +
" arguments)")
1192 return std::nullopt;
1199 auto ArgNo = Dag->getArgNo(Name->getValue());
1202 Error = (
Twine(
"key '") + Name->getValue() +
Twine(
"' is not found")).str();
1203 return std::nullopt;
1219 if (LOp && ROp && LOp->getDef() != ROp->getDef()) {
1221 LHSs->getAsString() +
"' vs. '" + RHSs->getAsString() +
1224 const Init *
Op = LOp ? LOp : ROp;
1232 const auto *NameInit = LHSs->getName();
1234 NameInit = RHSs->getName();
1248 StringRef RegexStr = RegexInit->getValue();
1250 if (!Matcher.isValid())
1254 Matcher.match(StrInit->getValue()));
1271 if (
Count->getValue() < 0)
1284 for (
const Init *EltLHS : *LHSs) {
1286 for (
const Init *EltRHS : *RHSs) {
1287 if (std::optional<bool> Result =
CompareInit(
EQ, EltLHS, EltRHS)) {
1295 Args.push_back(EltLHS);
1304 if (!TheList || !Idx)
1306 auto i = Idx->getValue();
1307 if (i < 0 || i >= (ssize_t)TheList->size())
1309 return TheList->getElement(i);
1314 if (!TheList || !SliceIdxs)
1317 Args.reserve(SliceIdxs->size());
1318 for (
auto *
I : *SliceIdxs) {
1322 auto i =
II->getValue();
1323 if (i < 0 || i >= (ssize_t)TheList->size())
1325 Args.push_back(TheList->getElement(i));
1335 int64_t Start = LHSi->getValue();
1336 int64_t End = RHSi->getValue();
1342 Args.reserve(End - Start + 1);
1343 for (
auto i = Start; i <= End; ++i)
1347 Args.reserve(Start - End + 1);
1348 for (
auto i = Start; i >= End; --i)
1351 }
else if (Start < End) {
1353 Args.reserve(End - Start);
1354 for (
auto i = Start; i < End; ++i)
1371 if (
List && Delim) {
1400 assert(*ArgNo < Dag->getNumArgs());
1402 const Init *Arg = Dag->getArg(*ArgNo);
1404 if (!TI->getType()->typeIsConvertibleTo(
getType()))
1414 int64_t Pos = Idx->getValue();
1415 if (Pos < 0 || Pos >= Dag->getNumArgs()) {
1418 Twine(
"!getdagname index is out of range 0...") +
1419 std::to_string(Dag->getNumArgs() - 1) +
": " +
1420 std::to_string(Pos));
1422 const Init *ArgName = Dag->getArgName(Pos);
1441 Dag->getArgNames());
1459 int64_t LHSv = LHSi->getValue(), RHSv = RHSi->getValue();
1463 case ADD: Result = LHSv + RHSv;
break;
1464 case SUB: Result = LHSv - RHSv;
break;
1465 case MUL: Result = LHSv * RHSv;
break;
1469 "Illegal operation: division by zero");
1470 else if (LHSv ==
INT64_MIN && RHSv == -1)
1472 "Illegal operation: INT64_MIN / -1");
1474 Result = LHSv / RHSv;
1476 case AND: Result = LHSv & RHSv;
break;
1477 case OR: Result = LHSv | RHSv;
break;
1478 case XOR: Result = LHSv ^ RHSv;
break;
1480 if (RHSv < 0 || RHSv >= 64)
1482 "Illegal operation: out of bounds shift");
1483 Result = (uint64_t)LHSv << (uint64_t)RHSv;
1486 if (RHSv < 0 || RHSv >= 64)
1488 "Illegal operation: out of bounds shift");
1489 Result = LHSv >> (uint64_t)RHSv;
1492 if (RHSv < 0 || RHSv >= 64)
1494 "Illegal operation: out of bounds shift");
1495 Result = (uint64_t)LHSv >> (uint64_t)RHSv;
1521 if ((
Opc ==
AND && !LHSi->getValue()) ||
1522 (
Opc ==
OR && LHSi->getValue() == -1))
1529 if (LHS != NewLHS || RHS != NewRHS)
1531 ->Fold(R.getCurrentRecord());
1540 return LHS->getAsString() +
"[" + RHS->getAsString() +
"]";
1542 return LHS->getAsString() +
"..." + RHS->getAsString();
1543 case CONCAT: Result =
"!con";
break;
1547 case ADD: Result =
"!add";
break;
1548 case SUB: Result =
"!sub";
break;
1549 case MUL: Result =
"!mul";
break;
1550 case DIV: Result =
"!div";
break;
1551 case AND: Result =
"!and";
break;
1552 case OR: Result =
"!or";
break;
1553 case XOR: Result =
"!xor";
break;
1554 case SHL: Result =
"!shl";
break;
1555 case SRA: Result =
"!sra";
break;
1556 case SRL: Result =
"!srl";
break;
1557 case EQ: Result =
"!eq";
break;
1558 case NE: Result =
"!ne";
break;
1559 case LE: Result =
"!le";
break;
1560 case LT: Result =
"!lt";
break;
1561 case GE: Result =
"!ge";
break;
1562 case GT: Result =
"!gt";
break;
1563 case LISTCONCAT: Result =
"!listconcat";
break;
1564 case LISTSPLAT: Result =
"!listsplat";
break;
1566 Result =
"!listremove";
1568 case STRCONCAT: Result =
"!strconcat";
break;
1569 case INTERLEAVE: Result =
"!interleave";
break;
1570 case SETDAGOP: Result =
"!setdagop";
break;
1572 Result =
"!setdagopname";
1578 Result =
"!getdagname";
1581 return Result +
"(" + LHS->getAsString() +
", " + RHS->getAsString() +
")";
1602 return RHS->resolveReferences(R);
1607 bool Change =
false;
1641 for (
const Init *&Item : NewList) {
1643 if (NewItem != Item)
1660 for (
const Init *Item : MHSl->getElements()) {
1664 if (
const auto *IncludeInt =
1667 if (IncludeInt->getValue())
1686 using KV = std::pair<const Init *, const Init *>;
1689 for (
const Init *Item : MHSl->getElements()) {
1696 if (KeyedList.
empty())
1703 for (
auto &[
Key, Item] : KeyedList) {
1725 for (
auto &[
Key, Item] : KeyedList)
1726 Result.push_back(Item);
1746 if (LHSd && MHSd && RHSd) {
1747 const Record *Val = RHSd->getDef();
1748 if (LHSd->getAsString() == RHSd->getAsString())
1749 Val = MHSd->getDef();
1752 if (LHSv && MHSv && RHSv) {
1753 std::string Val = RHSv->getName().str();
1754 if (LHSv->getAsString() == RHSv->getAsString())
1755 Val = MHSv->getName().str();
1758 if (LHSs && MHSs && RHSs) {
1759 std::string Val = RHSs->getValue().str();
1761 std::string::size_type Idx = 0;
1763 std::string::size_type Found = Val.find(LHSs->getValue(), Idx);
1764 if (Found == std::string::npos)
1766 Val.replace(Found, LHSs->getValue().size(), MHSs->getValue().str());
1767 Idx = Found + MHSs->getValue().size();
1796 if (LHSi->getValue())
1812 if (MHSok && RHSok && (!MHSl || !RHSl || MHSl->size() == RHSl->size())) {
1814 unsigned Size = MHSl ? MHSl->size() : RHSl->size();
1815 for (
unsigned i = 0; i !=
Size; ++i) {
1831 if (!LHSi || !MHSi || !RHSi)
1834 auto Start = LHSi->getValue();
1835 auto End = MHSi->getValue();
1836 auto Step = RHSi->getValue();
1841 if (Start < End && Step > 0) {
1842 Args.reserve((End - Start) / Step);
1843 for (
auto I = Start;
I < End;
I += Step)
1845 }
else if (Start > End && Step < 0) {
1846 Args.reserve((Start - End) / -Step);
1847 for (
auto I = Start;
I > End;
I += Step)
1859 if (LHSs && MHSi && RHSi) {
1860 int64_t StringSize = LHSs->getValue().size();
1861 int64_t Start = MHSi->getValue();
1862 int64_t
Length = RHSi->getValue();
1863 if (Start < 0 || Start > StringSize)
1865 Twine(
"!substr start position is out of range 0...") +
1866 std::to_string(StringSize) +
": " +
1867 std::to_string(Start));
1880 if (LHSs && MHSs && RHSi) {
1881 int64_t SourceSize = LHSs->getValue().size();
1882 int64_t Start = RHSi->getValue();
1883 if (Start < 0 || Start > SourceSize)
1885 Twine(
"!find start position is out of range 0...") +
1886 std::to_string(SourceSize) +
": " +
1887 std::to_string(Start));
1888 auto I = LHSs->getValue().find(MHSs->getValue(), Start);
1889 if (
I == std::string::npos)
1904 assert(*ArgNo < Dag->getNumArgs());
1908 return DagInit::get(Dag->getOperator(), Dag->getName(), Args,
1909 Dag->getArgNames());
1922 assert(*ArgNo < Dag->getNumArgs());
1926 return DagInit::get(Dag->getOperator(), Dag->getName(), Dag->getArgs(),
1943 if (
Value->getValue())
1944 return MHS->resolveReferences(R);
1945 return RHS->resolveReferences(R);
1960 if (LHS != lhs || MHS != mhs || RHS != rhs)
1962 ->Fold(R.getCurrentRecord());
1968 bool UnquotedLHS =
false;
1970 case DAG: Result =
"!dag";
break;
1971 case FILTER: Result =
"!filter"; UnquotedLHS =
true;
break;
1972 case FOREACH: Result =
"!foreach"; UnquotedLHS =
true;
break;
1977 case IF: Result =
"!if";
break;
1981 case SUBST: Result =
"!subst";
break;
1982 case SUBSTR: Result =
"!substr";
break;
1983 case FIND: Result =
"!find";
break;
1985 Result =
"!setdagarg";
1988 Result =
"!setdagname";
1991 return (Result +
"(" +
1992 (UnquotedLHS ? LHS->getAsUnquotedString() : LHS->getAsString()) +
1993 ", " + MHS->getAsString() +
", " + RHS->getAsString() +
")");
2001 if (
const FoldOpInit *
I =
2005 FoldOpInit *
I =
new (RK.
Allocator) FoldOpInit(Start, List, A, B, Expr,
Type);
2012 const Init *Accum = Start;
2013 for (
const Init *Elt : *LI) {
2030 const Init *
NewExpr = Expr->resolveReferences(SR);
2032 if (Start == NewStart && List == NewList && Expr ==
NewExpr)
2036 ->
Fold(R.getCurrentRecord());
2046 return (
Twine(
"!foldl(") + Start->getAsString() +
", " + List->getAsString() +
2047 ", " + A->getAsUnquotedString() +
", " + B->getAsUnquotedString() +
2048 ", " + Expr->getAsString() +
")")
2059 IsAOpInit *
I =
new (RK.
Allocator) IsAOpInit(CheckType, Expr);
2067 if (TI->getType()->typeIsConvertibleTo(CheckType))
2074 if ((!CheckType->typeIsConvertibleTo(TI->getType()) &&
2075 Expr->isConcrete()) ||
2098 return (
Twine(
"!isa<") + CheckType->getAsString() +
">(" +
2099 Expr->getAsString() +
")")
2107 if (
const ExistsOpInit *
I =
2111 ExistsOpInit *
I =
new (RK.
Allocator) ExistsOpInit(CheckType, Expr);
2119 const Record *
D = CheckType->getRecordKeeper().getDef(Name->getValue());
2123 D->getDefInit()->getType()->typeIsA(CheckType));
2131 (Anonymous && Name == Anonymous->getNameInit())) {
2150 if (Expr !=
NewExpr || R.isFinal())
2151 return get(CheckType,
NewExpr)->
Fold(R.getCurrentRecord(), R.isFinal());
2160 return (
Twine(
"!exists<") + CheckType->getAsString() +
">(" +
2161 Expr->getAsString() +
")")
2166 const Init *Regex) {
2169 if (
const InstancesOpInit *
I =
2173 InstancesOpInit *
I =
new (RK.
Allocator) InstancesOpInit(Type, Regex);
2179 if (CurRec && !IsFinal)
2186 StringRef RegexStr = RegexInit->getValue();
2188 if (!Matcher.isValid())
2194 if (Matcher.match(Def->getName()))
2202 if (Regex != NewRegex || R.isFinal())
2203 return get(Type, NewRegex)->
Fold(R.getCurrentRecord(), R.isFinal());
2208 return "!instances<" + Type->
getAsString() +
">(" + Regex->getAsString() +
2216 return Field->getType();
2236 if (!
T)
return nullptr;
2237 unsigned NumBits =
T->getNumBits();
2241 for (
unsigned Bit : Bits) {
2261 if (!
getType()->typeIsConvertibleTo(Ty))
2282 return NameString->getValue();
2292 if (
const Init *Val = R.resolve(VarName))
2306 return TI->getAsString() +
"{" +
utostr(Bit) +
"}";
2310 const Init *
I = TI->resolveReferences(R);
2317DefInit::DefInit(
const Record *
D)
2322 if (
getType()->typeIsConvertibleTo(RRT))
2329 return RV->getType();
2338 NumArgs(Args.
size()) {
2351 VarDefInit *
I =
new (Mem) VarDefInit(Loc, Class, Args);
2356const DefInit *VarDefInit::instantiate() {
2361 auto NewRecOwner = std::make_unique<Record>(
2363 Record *NewRec = NewRecOwner.get();
2366 for (
const RecordVal &Val : Class->getValues())
2379 for (
const Init *Arg : TArgs) {
2384 for (
auto *Arg :
args()) {
2385 if (Arg->isPositional())
2386 R.set(TArgs[Arg->getIndex()], Arg->getValue());
2388 R.set(Arg->getName(), Arg->getValue());
2395 Class, SMRange(Class->getLoc().back(), Class->getLoc().back()));
2399 Records.addDef(std::move(NewRecOwner));
2425 return const_cast<VarDefInit *
>(New)->instantiate();
2437 Arg->resolveReferences(R);
2439 if (!R.foundUnresolved())
2440 return const_cast<VarDefInit *
>(
this)->instantiate();
2445 std::string Result = Class->getNameInitAsString() +
"<";
2449 Result += Arg->getAsString();
2451 return Result +
">";
2477 const Record *Def = DI->getDef();
2480 Twine(
"Attempting to access field '") +
2481 FieldName->getAsUnquotedString() +
"' of '" +
2482 Rec->getAsString() +
"' is a forbidden self-reference");
2483 const Init *FieldVal = Def->getValue(FieldName)->getValue();
2492 const Init *FieldVal = DI->getDef()->getValue(FieldName)->getValue();
2510 "Number of conditions and values must match!");
2514 if (
const CondOpInit *
I =
2520 CondOpInit *
I =
new (Mem) CondOpInit(Conds,
Values, Ty);
2531 const Init *NewCond =
Cond->resolveReferences(R);
2542 if (NewCondVal->getValue()) {
2562 if (CondI->getValue())
2563 return Val->convertInitializerTo(
getValType());
2571 " does not have any true condition in:" +
2572 this->getAsString());
2578 return std::get<0>(Pair)->isConcrete() && std::get<1>(Pair)->isConcrete();
2584 return std::get<0>(Pair)->isComplete() && std::get<1>(Pair)->isComplete();
2589 std::string Result =
"!cond(";
2593 Result +=
Cond->getAsString() +
": ";
2594 Result += Val->getAsString();
2596 return Result +
")";
2609 ValName(VN), NumArgs(Args.
size()) {
2618 "Number of DAG args and arg names must match!");
2622 if (
const DagInit *
I =
2628 Args.size(), ArgNames.
size()),
2630 DagInit *
I =
new (Mem) DagInit(V, VN, Args, ArgNames);
2637 ArrayRef<std::pair<const Init *, const StringInit *>> ArgAndNames) {
2645 return DefI->getDef();
2653 return ArgName && ArgName->
getValue() == Name;
2655 if (It == ArgNames.
end())
2656 return std::nullopt;
2657 return std::distance(ArgNames.
begin(), It);
2663 bool ArgsChanged =
false;
2667 ArgsChanged |= NewArg != Arg;
2670 const Init *
Op = Val->resolveReferences(R);
2671 if (
Op != Val || ArgsChanged)
2678 if (!Val->isConcrete())
2684 std::string Result =
"(" + Val->getAsString();
2686 Result +=
":$" + ValName->getAsUnquotedString();
2692 Result += Arg->getAsString();
2694 Result +=
":$" + Name->getAsUnquotedString();
2697 return Result +
")";
2705 : Name(
N), TyAndKind(
T, K) {
2707 assert(Value &&
"Cannot create unset value for current type!");
2713 : Name(
N), Loc(Loc), TyAndKind(
T, K) {
2715 assert(Value &&
"Cannot create unset value for current type!");
2725 if (StrInit->hasCodeFormat())
2733 return TyAndKind.getPointer()->getAsString();
2754 for (
unsigned I = 0, E = BTy->getNumBits();
I < E; ++
I)
2755 Bits[
I] = Value->getBit(
I);
2769#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
2780 if (PrintSem) OS <<
";\n";
2784 assert(Locs.size() == 1);
2785 ForwardDeclarationLocs.push_back(Locs.front());
2788 Locs.push_back(
Loc);
2791void Record::checkName() {
2796 "' is not a string!");
2806 if (!CorrespondingDefInit) {
2807 CorrespondingDefInit =
2808 new (TrackedRecords.getImpl().Allocator)
DefInit(
this);
2810 return CorrespondingDefInit;
2836 if (NewName != OldName) {
2843 if (SkipVal == &
Value)
2847 if (
Value.setValue(VR)) {
2851 (
Twine(
"of type '") + VRT->getType()->getAsString() +
"' ").str();
2854 Twine(
"Invalid value ") +
Type +
"found when setting field '" +
2855 Value.getNameInitAsString() +
"' of type '" +
2865 const Init *
Value = Assertion.Condition->resolveReferences(R);
2866 Assertion.Condition =
Value;
2867 Value = Assertion.Message->resolveReferences(R);
2868 Assertion.Message =
Value;
2872 const Init *
Value = Dump.Message->resolveReferences(R);
2873 Dump.Message =
Value;
2884#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
2889 OS << R.getNameInitAsString();
2892 if (!TArgs.
empty()) {
2895 for (
const Init *TA : TArgs) {
2897 assert(RV &&
"Template argument record not found??");
2899 RV->
print(OS,
false);
2905 std::vector<const Record *> SCs = R.getSuperClasses();
2908 for (
const Record *SC : SCs)
2909 OS <<
" " << SC->getNameInitAsString();
2913 for (
const RecordVal &Val : R.getValues())
2914 if (Val.isNonconcreteOK() && !R.isTemplateArg(Val.getNameInit()))
2916 for (
const RecordVal &Val : R.getValues())
2917 if (!Val.isNonconcreteOK() && !R.isTemplateArg(Val.getNameInit()))
2927 "' does not have a field named `" + FieldName +
"'!\n");
2933 if (!R || !R->getValue())
2935 "' does not have a field named `" + FieldName +
"'!\n");
2936 return R->getValue();
2942 return SI->getValue();
2944 "' exists but does not have a string value");
2947std::optional<StringRef>
2950 if (!R || !R->getValue())
2951 return std::nullopt;
2953 return std::nullopt;
2956 return SI->getValue();
2959 "Record `" +
getName() +
"', ` field `" + FieldName +
2960 "' exists but does not have a string initializer!");
2968 "' exists but does not have a bits value");
2976 "' exists but does not have a list value");
2979std::vector<const Record *>
2982 std::vector<const Record *> Defs;
2983 for (
const Init *
I :
List->getElements()) {
2985 Defs.push_back(DI->getDef());
2989 "' list is not entirely DefInit!");
2997 return II->getValue();
3000 Twine(
"Record `") +
getName() +
"', field `" + FieldName +
3001 "' exists but does not have an int value: " +
I->getAsString());
3007 std::vector<int64_t> Ints;
3008 for (
const Init *
I :
List->getElements()) {
3010 Ints.push_back(
II->getValue());
3013 Twine(
"Record `") +
getName() +
"', field `" + FieldName +
3014 "' exists but does not have a list of ints value: " +
3020std::vector<StringRef>
3023 std::vector<StringRef> Strings;
3024 for (
const Init *
I :
List->getElements()) {
3026 Strings.push_back(
SI->getValue());
3029 Twine(
"Record `") +
getName() +
"', field `" + FieldName +
3030 "' exists but does not have a list of strings value: " +
3039 return DI->getDef();
3041 FieldName +
"' does not have a def initializer!");
3047 return DI->getDef();
3051 FieldName +
"' does not have either a def initializer or '?'!");
3057 return BI->getValue();
3059 FieldName +
"' does not have a bit initializer!");
3070 return BI->getValue();
3072 FieldName +
"' does not have a bit initializer!");
3080 FieldName +
"' does not have a dag initializer!");
3091 bool AnyFailed =
false;
3095 AnyFailed |=
CheckAssert(Assertion.Loc, Condition, Message);
3103 PrintError(
this,
"assertion failed in this record");
3111 const Init *Message = Dump.Message->resolveReferences(R);
3127 : Impl(
std::make_unique<
detail::RecordKeeperImpl>(*this)),
3132#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
3137 OS <<
"------------- Classes -----------------\n";
3139 OS <<
"class " << *
C;
3141 OS <<
"------------- Defs -----------------\n";
3157 auto [Iter, Inserted] = Cache.try_emplace(ClassName.
str());
3160 return Iter->second;
3163std::vector<const Record *>
3166 std::vector<const Record *> Defs;
3168 assert(ClassNames.
size() > 0 &&
"At least one class must be passed.");
3169 for (
StringRef ClassName : ClassNames) {
3176 for (
const auto &OneDef :
getDefs()) {
3178 return OneDef.second->isSubClassOf(Class);
3180 Defs.push_back(OneDef.second.get());
3194 Impl->dumpAllocationStats(OS);
3198 auto It = Map.find(VarName);
3199 if (It == Map.end())
3202 const Init *
I = It->second.V;
3204 if (!It->second.Resolved && Map.size() > 1) {
3208 I =
I->resolveReferences(*
this);
3209 Map[VarName] = {
I,
true};
3216 const Init *Val = Cache.lookup(VarName);
3225 Val = RV->getValue();
3226 Stack.push_back(VarName);
3231 Stack.push_back(VarName);
3236 Cache[VarName] = Val;
3241 const Init *
I =
nullptr;
3244 I = R->resolve(VarName);
3245 if (
I && !FoundUnresolved) {
3250 I->resolveReferences(
Sub);
3251 FoundUnresolved |=
Sub.FoundUnresolved;
3256 FoundUnresolved =
true;
3261 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< 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)
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 bool canFitInBitfield(int64_t Value, unsigned NumBits)
static std::optional< unsigned > getDagArgNoByKey(const DagInit *Dag, const Init *Key, std::string &Error)
static const StringInit * ConcatStringInits(const StringInit *I0, const StringInit *I1)
static const ListInit * ConcatListInits(const ListInit *LHS, const ListInit *RHS)
static const StringInit * interleaveStringList(const ListInit *List, const StringInit *Delim)
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 const Init * ForeachHelper(const Init *LHS, const Init *MHS, const Init *RHS, const RecTy *Type, const Record *CurRec)
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
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)
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
std::optional< bool > CompareInit(unsigned Opc, const Init *LHS, const Init *RHS) 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.
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
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?
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?
(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
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.
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...
Insertion token: a failed lookup fills it in, the matching insert consumes it.
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)
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)
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.
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
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
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)
const T * getTrailingObjects() const
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.
UnaryOp getOpcode() const
static const UnOpInit * get(UnaryOp opc, const Init *lhs, const RecTy *Type)
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
A uniquing set that compares nodes against a typed key rather than a serialized FoldingSetNodeID.
T * lookup(const KeyTy &Key, FoldingSetInsertToken &Token)
Look up Key.
void insert(T *N, FoldingSetInsertToken Token)
Insert N, which must key identically to the lookup that produced Token.
'?' - 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
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.
llvm::SmallVector< std::shared_ptr< RecordsSlice >, 4 > Records
This is an optimization pass for GlobalISel generic memory operations.
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)
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
UniquingSet< ExistsOpInit > TheExistsOpInitPool
UniquingSet< CondOpInit > TheCondOpInitPool
BumpPtrAllocator Allocator
std::map< int64_t, IntInit * > TheIntInitPool
UniquingSet< UnOpInit > TheUnOpInitPool
UniquingSet< ArgumentInit > TheArgumentInitPool
DenseMap< std::pair< const Init *, const StringInit * >, FieldInit * > TheFieldInitPool
UniquingSet< FoldOpInit > TheFoldOpInitPool
UniquingSet< IsAOpInit > TheIsAOpInitPool
std::vector< BitsRecTy * > SharedBitsRecTys
UniquingSet< ListInit > TheListInitPool
UniquingSet< BitsInit > TheBitsInitPool
RecordKeeperImpl(RecordKeeper &RK)
UniquingSet< DagInit > TheDagInitPool
StringMap< const StringInit *, BumpPtrAllocator & > StringInitStringPool
UniquingSet< TernOpInit > TheTernOpInitPool
UniquingSet< BinOpInit > TheBinOpInitPool
void dumpAllocationStats(raw_ostream &OS) const
DenseMap< std::pair< const RecTy *, const Init * >, VarInit * > TheVarInitPool
UniquingSet< VarDefInit > TheVarDefInitPool
UniquingSet< InstancesOpInit > TheInstancesOpInitPool
UniquingSet< RecordRecTy > RecordTypePool
DenseMap< std::pair< const TypedInit *, unsigned >, VarBitInit * > TheVarBitInitPool
Sorting predicate to sort record pointers by name.