22#include "llvm/Config/llvm-config.h"
43#define DEBUG_TYPE "tblgen-records"
123 OS <<
"Bytes allocated = " <<
Allocator.getBytesAllocated() <<
'\n';
124 OS <<
"Total allocator memory = " <<
Allocator.getTotalMemory() <<
"\n\n";
126 OS <<
"Number of records instantiated = " <<
LastRecordID <<
'\n';
127 OS <<
"Number of anonymous records = " <<
AnonCounter <<
'\n';
134#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
140 ListTy =
new (RK.getImpl().Allocator)
ListRecTy(
this);
145 assert(RHS &&
"NULL pointer");
146 return Kind == RHS->getRecTyKind();
152 return &RK.getImpl().SharedBitRecTy;
159 return BitsTy->getNumBits() == 1;
169 Ty =
new (RKImpl.
Allocator) BitsRecTy(RK, Sz);
174 return "bits<" +
utostr(Size) +
">";
185 return &RK.getImpl().SharedIntRecTy;
194 return &RK.getImpl().SharedStringRecTy;
207 return "list<" + ElementTy->getAsString() +
">";
212 return ElementTy->typeIsConvertibleTo(ListTy->getElementType());
223 return &RK.getImpl().SharedDagRecTy;
232 ID.AddInteger(Classes.
size());
233 for (
const Record *R : Classes)
238 : RecTy(RecordRecTyKind, RK), NumClasses(Classes.
size()) {
245 if (UnsortedClasses.
empty())
252 return LHS->getNameInitAsString() < RHS->getNameInitAsString();
264 for (
unsigned i = 0; i < Classes.
size(); ++i) {
265 for (
unsigned j = 0; j < Classes.
size(); ++j) {
268 assert(&Classes[0]->getRecords() == &Classes[i]->getRecords());
274 RecordRecTy *Ty =
new (Mem) RecordRecTy(RK, Classes);
280 assert(Class &&
"unexpected null class");
281 return get(Class->getRecords(), {Class});
290 return getClasses()[0]->getNameInitAsString();
292 std::string Str =
"{";
296 Str += R->getNameInitAsString();
304 return MySuperClass == Class || MySuperClass->
isSubClassOf(Class);
317 return isSubClassOf(TargetClass);
330 while (!Stack.empty()) {
331 const Record *R = Stack.pop_back_val();
333 if (T2->isSubClassOf(R))
351 assert(T1 !=
nullptr &&
"Invalid record type");
352 if (T1->typeIsConvertibleTo(T2))
355 assert(T2 !=
nullptr &&
"Invalid record type");
356 if (T2->typeIsConvertibleTo(T1))
361 const RecTy *NewType =
362 resolveTypes(ListTy1->getElementType(), ListTy2->getElementType());
375void Init::anchor() {}
377#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
383 return TyInit->getType()->getRecordKeeper();
385 return ArgInit->getRecordKeeper();
390 return &RK.getImpl().TheUnsetInit;
401 auto I = Aux.index();
404 ID.AddInteger(std::get<ArgumentInit::Positional>(Aux));
406 ID.AddPointer(std::get<ArgumentInit::Named>(Aux));
431 const Init *NewValue = Value->resolveReferences(R);
432 if (NewValue != Value)
451 if (BRT->getNumBits() == 1)
483 BitsInit *
I =
new (Mem) BitsInit(RK, Bits);
501 if (
getNumBits() != BRT->getNumBits())
return nullptr;
518 Result |=
static_cast<int64_t
>(Bit->getValue()) << Idx;
528 Result |=
static_cast<int64_t
>(Bit->getValue()) << Idx;
536 for (
auto [Bit, NewBit] :
zip_equal(Bits, NewBits)) {
555 std::string Result =
"{ ";
560 Result += Bit->getAsString();
564 return Result +
" }";
573 const Init *CachedBitVarRef =
nullptr;
574 const Init *CachedBitVarResolved =
nullptr;
580 if (CurBitVar->getBitVar() != CachedBitVarRef) {
581 CachedBitVarRef = CurBitVar->getBitVar();
584 assert(CachedBitVarResolved &&
"Unresolved bitvar reference");
585 NewBit = CachedBitVarResolved->
getBit(CurBitVar->getBitNum());
588 NewBit = CurBit->resolveReferences(R)->getBit(0);
605 I =
new (RK.
getImpl().Allocator) IntInit(RK, V);
615 return (NumBits >=
sizeof(
Value) * 8) ||
616 (
Value >> NumBits == 0) || (
Value >> (NumBits-1) == -1);
625 if (Val != 0 && Val != 1)
return nullptr;
636 for (
unsigned i = 0; i != BRT->getNumBits(); ++i)
649 for (
auto [Bit, NewBit] :
zip_equal(Bits, NewBits)) {
659 return new (RK.
getImpl().Allocator) AnonymousNameInit(RK, V);
667 return "anonymous_" +
utostr(Value);
672 auto *New = R.resolve(Old);
673 New = New ? New : Old;
676 return Anonymous->getNameInit();
685 auto &Entry = *InitMap.
try_emplace(V,
nullptr).first;
687 Entry.second =
new (RKImpl.
Allocator) StringInit(RK, Entry.getKey(), Fmt);
700 const RecTy *EltTy) {
701 ID.AddInteger(Elements.size());
702 ID.AddPointer(EltTy);
704 for (
const Init *
E : Elements)
715 const RecTy *EltTy) {
729 ListInit *
I =
new (Mem) ListInit(Elements, EltTy);
745 Elements.reserve(
size());
750 const RecTy *ElementType = LRT->getElementType();
752 if (
const Init *CI =
I->convertInitializerTo(ElementType)) {
753 Elements.push_back(CI);
777 Resolved.reserve(
size());
783 Resolved.push_back(E);
802 std::string Result =
"[";
804 for (
const Init *Element : *
this) {
819 ID.AddInteger(Opcode);
846 if (LHS->isConcrete()) {
851 OS << *Def->getDef();
891 (Anonymous && Name == Anonymous->getNameInit())) {
898 auto PrintFatalErrorHelper = [CurRec](
const Twine &
T) {
907 PrintFatalErrorHelper(
Twine(
"Undefined reference to record: '") +
908 Name->getValue() +
"'\n");
915 PrintFatalErrorHelper(
Twine(
"Expected type '") +
931 if (LHS->isConcrete())
943 assert(!LHSl->empty() &&
"Empty list in head");
944 return LHSl->getElement(0);
950 assert(!LHSl->empty() &&
"Empty list in tail");
954 LHSl->getElementType());
981 if (!TI->getType()->typeIsA(
getType())) {
987 return Dag->getOperator();
994 return Dag->getName();
1001 int64_t LHSv = LHSi->getValue();
1004 "Illegal operation: logtwo is undefined "
1005 "on arguments less than or equal to 0");
1009 "Log of an int64_t must be smaller than INT64_MAX");
1023 [](
const ListInit *
List) -> std::optional<std::vector<const Init *>> {
1024 std::vector<const Init *> Flattened;
1026 for (
const Init *InnerInit :
List->getElements()) {
1029 return std::nullopt;
1035 auto Flattened = Flatten(LHSList);
1037 return ListInit::get(*Flattened, InnerListTy->getElementType());
1049 ->Fold(R.getCurrentRecord(), R.isFinal());
1057 case NOT: Result =
"!not";
break;
1058 case HEAD: Result =
"!head";
break;
1059 case TAIL: Result =
"!tail";
break;
1060 case SIZE: Result =
"!size";
break;
1061 case EMPTY: Result =
"!empty";
break;
1062 case GETDAGOP: Result =
"!getdagop";
break;
1064 Result =
"!getdagopname";
1066 case LOG2 : Result =
"!logtwo";
break;
1068 Result =
"!listflatten";
1074 Result =
"!tolower";
1077 Result =
"!toupper";
1080 Result =
"!initialized";
1083 return Result +
"(" + LHS->getAsString() +
")";
1089 ID.AddInteger(Opcode);
1117 Concat.append(I1->getValue());
1125 if (List->size() == 0)
1133 for (
const Init *Elem : List->getElements().drop_front()) {
1138 Result.append(Element->getValue());
1147 if (List->size() == 0)
1150 List->getElement(0)->convertInitializerTo(
IntRecTy::get(RK)));
1155 for (
const Init *Elem : List->getElements().drop_front()) {
1161 Result.append(Element->getAsString());
1194 const Init *RHS)
const {
1205 Result = LHSi->getValue() == RHSi->getValue();
1208 Result = LHSi->getValue() != RHSi->getValue();
1211 Result = LHSi->getValue() <= RHSi->getValue();
1214 Result = LHSi->getValue() < RHSi->getValue();
1217 Result = LHSi->getValue() >= RHSi->getValue();
1220 Result = LHSi->getValue() > RHSi->getValue();
1236 Result = LHSs->getValue() == RHSs->getValue();
1239 Result = LHSs->getValue() != RHSs->getValue();
1242 Result = LHSs->getValue() <= RHSs->getValue();
1245 Result = LHSs->getValue() < RHSs->getValue();
1248 Result = LHSs->getValue() >= RHSs->getValue();
1251 Result = LHSs->getValue() > RHSs->getValue();
1264 return (
Opc ==
EQ) ? LHSd == RHSd : LHSd != RHSd;
1267 return std::nullopt;
1270static std::optional<unsigned>
1274 int64_t Pos = Idx->getValue();
1278 (
Twine(
"index ") + std::to_string(Pos) +
Twine(
" is negative")).str();
1279 return std::nullopt;
1281 if (Pos >= Dag->getNumArgs()) {
1283 Error = (
Twine(
"index ") + std::to_string(Pos) +
1284 " is out of range (dag has " +
1285 std::to_string(Dag->getNumArgs()) +
" arguments)")
1287 return std::nullopt;
1294 auto ArgNo = Dag->getArgNo(Name->getValue());
1297 Error = (
Twine(
"key '") + Name->getValue() +
Twine(
"' is not found")).str();
1298 return std::nullopt;
1314 if (LOp && ROp && LOp->getDef() != ROp->getDef()) {
1316 LHSs->getAsString() +
"' vs. '" + RHSs->getAsString() +
1319 const Init *
Op = LOp ? LOp : ROp;
1327 const auto *NameInit = LHSs->getName();
1329 NameInit = RHSs->getName();
1343 StringRef RegexStr = RegexInit->getValue();
1349 Matcher.
match(StrInit->getValue()));
1366 if (
Count->getValue() < 0)
1379 for (
const Init *EltLHS : *LHSs) {
1381 for (
const Init *EltRHS : *RHSs) {
1382 if (std::optional<bool> Result =
CompareInit(
EQ, EltLHS, EltRHS)) {
1390 Args.push_back(EltLHS);
1399 if (!TheList || !Idx)
1401 auto i = Idx->getValue();
1402 if (i < 0 || i >= (ssize_t)TheList->size())
1404 return TheList->getElement(i);
1409 if (!TheList || !SliceIdxs)
1412 Args.reserve(SliceIdxs->size());
1413 for (
auto *
I : *SliceIdxs) {
1417 auto i =
II->getValue();
1418 if (i < 0 || i >= (ssize_t)TheList->size())
1420 Args.push_back(TheList->getElement(i));
1430 int64_t Start = LHSi->getValue();
1431 int64_t End = RHSi->getValue();
1437 Args.reserve(End - Start + 1);
1438 for (
auto i = Start; i <= End; ++i)
1442 Args.reserve(Start - End + 1);
1443 for (
auto i = Start; i >= End; --i)
1446 }
else if (Start < End) {
1448 Args.reserve(End - Start);
1449 for (
auto i = Start; i < End; ++i)
1466 if (
List && Delim) {
1495 assert(*ArgNo < Dag->getNumArgs());
1497 const Init *Arg = Dag->getArg(*ArgNo);
1499 if (!TI->getType()->typeIsConvertibleTo(
getType()))
1509 int64_t Pos = Idx->getValue();
1510 if (Pos < 0 || Pos >= Dag->getNumArgs()) {
1513 Twine(
"!getdagname index is out of range 0...") +
1514 std::to_string(Dag->getNumArgs() - 1) +
": " +
1515 std::to_string(Pos));
1517 const Init *ArgName = Dag->getArgName(Pos);
1536 Dag->getArgNames());
1554 int64_t LHSv = LHSi->getValue(), RHSv = RHSi->getValue();
1558 case ADD: Result = LHSv + RHSv;
break;
1559 case SUB: Result = LHSv - RHSv;
break;
1560 case MUL: Result = LHSv * RHSv;
break;
1564 "Illegal operation: division by zero");
1565 else if (LHSv ==
INT64_MIN && RHSv == -1)
1567 "Illegal operation: INT64_MIN / -1");
1569 Result = LHSv / RHSv;
1571 case AND: Result = LHSv & RHSv;
break;
1572 case OR: Result = LHSv | RHSv;
break;
1573 case XOR: Result = LHSv ^ RHSv;
break;
1575 if (RHSv < 0 || RHSv >= 64)
1577 "Illegal operation: out of bounds shift");
1581 if (RHSv < 0 || RHSv >= 64)
1583 "Illegal operation: out of bounds shift");
1587 if (RHSv < 0 || RHSv >= 64)
1589 "Illegal operation: out of bounds shift");
1616 if ((
Opc ==
AND && !LHSi->getValue()) ||
1617 (
Opc ==
OR && LHSi->getValue() == -1))
1624 if (LHS != NewLHS || RHS != NewRHS)
1626 ->Fold(R.getCurrentRecord());
1635 return LHS->getAsString() +
"[" + RHS->getAsString() +
"]";
1637 return LHS->getAsString() +
"..." + RHS->getAsString();
1638 case CONCAT: Result =
"!con";
break;
1642 case ADD: Result =
"!add";
break;
1643 case SUB: Result =
"!sub";
break;
1644 case MUL: Result =
"!mul";
break;
1645 case DIV: Result =
"!div";
break;
1646 case AND: Result =
"!and";
break;
1647 case OR: Result =
"!or";
break;
1648 case XOR: Result =
"!xor";
break;
1649 case SHL: Result =
"!shl";
break;
1650 case SRA: Result =
"!sra";
break;
1651 case SRL: Result =
"!srl";
break;
1652 case EQ: Result =
"!eq";
break;
1653 case NE: Result =
"!ne";
break;
1654 case LE: Result =
"!le";
break;
1655 case LT: Result =
"!lt";
break;
1656 case GE: Result =
"!ge";
break;
1657 case GT: Result =
"!gt";
break;
1658 case LISTCONCAT: Result =
"!listconcat";
break;
1659 case LISTSPLAT: Result =
"!listsplat";
break;
1661 Result =
"!listremove";
1663 case STRCONCAT: Result =
"!strconcat";
break;
1664 case INTERLEAVE: Result =
"!interleave";
break;
1665 case SETDAGOP: Result =
"!setdagop";
break;
1667 Result =
"!setdagopname";
1673 Result =
"!getdagname";
1676 return Result +
"(" + LHS->getAsString() +
", " + RHS->getAsString() +
")";
1682 ID.AddInteger(Opcode);
1713 return RHS->resolveReferences(R);
1718 bool Change =
false;
1752 for (
const Init *&Item : NewList) {
1754 if (NewItem != Item)
1771 for (
const Init *Item : MHSl->getElements()) {
1775 if (
const auto *IncludeInt =
1778 if (IncludeInt->getValue())
1806 if (LHSd && MHSd && RHSd) {
1807 const Record *Val = RHSd->getDef();
1808 if (LHSd->getAsString() == RHSd->getAsString())
1809 Val = MHSd->getDef();
1812 if (LHSv && MHSv && RHSv) {
1813 std::string Val = RHSv->getName().str();
1814 if (LHSv->getAsString() == RHSv->getAsString())
1815 Val = MHSv->getName().str();
1818 if (LHSs && MHSs && RHSs) {
1819 std::string Val = RHSs->getValue().str();
1821 std::string::size_type Idx = 0;
1823 std::string::size_type Found = Val.find(LHSs->getValue(), Idx);
1824 if (Found == std::string::npos)
1826 Val.replace(Found, LHSs->getValue().size(), MHSs->getValue().str());
1827 Idx = Found + MHSs->getValue().size();
1850 if (LHSi->getValue())
1866 if (MHSok && RHSok && (!MHSl || !RHSl || MHSl->size() == RHSl->size())) {
1868 unsigned Size = MHSl ? MHSl->size() : RHSl->size();
1869 for (
unsigned i = 0; i !=
Size; ++i) {
1885 if (!LHSi || !MHSi || !RHSi)
1888 auto Start = LHSi->getValue();
1889 auto End = MHSi->getValue();
1890 auto Step = RHSi->getValue();
1895 if (Start < End && Step > 0) {
1896 Args.reserve((End - Start) / Step);
1897 for (
auto I = Start;
I < End;
I += Step)
1899 }
else if (Start > End && Step < 0) {
1900 Args.reserve((Start - End) / -Step);
1901 for (
auto I = Start;
I > End;
I += Step)
1913 if (LHSs && MHSi && RHSi) {
1914 int64_t StringSize = LHSs->getValue().size();
1915 int64_t Start = MHSi->getValue();
1916 int64_t
Length = RHSi->getValue();
1917 if (Start < 0 || Start > StringSize)
1919 Twine(
"!substr start position is out of range 0...") +
1920 std::to_string(StringSize) +
": " +
1921 std::to_string(Start));
1934 if (LHSs && MHSs && RHSi) {
1935 int64_t SourceSize = LHSs->getValue().size();
1936 int64_t Start = RHSi->getValue();
1937 if (Start < 0 || Start > SourceSize)
1939 Twine(
"!find start position is out of range 0...") +
1940 std::to_string(SourceSize) +
": " +
1941 std::to_string(Start));
1942 auto I = LHSs->getValue().find(MHSs->getValue(), Start);
1943 if (
I == std::string::npos)
1958 assert(*ArgNo < Dag->getNumArgs());
1962 return DagInit::get(Dag->getOperator(), Dag->getName(), Args,
1963 Dag->getArgNames());
1976 assert(*ArgNo < Dag->getNumArgs());
1980 return DagInit::get(Dag->getOperator(), Dag->getName(), Dag->getArgs(),
1997 if (
Value->getValue())
1998 return MHS->resolveReferences(R);
1999 return RHS->resolveReferences(R);
2014 if (LHS != lhs || MHS != mhs || RHS != rhs)
2016 ->Fold(R.getCurrentRecord());
2022 bool UnquotedLHS =
false;
2024 case DAG: Result =
"!dag";
break;
2025 case FILTER: Result =
"!filter"; UnquotedLHS =
true;
break;
2026 case FOREACH: Result =
"!foreach"; UnquotedLHS =
true;
break;
2027 case IF: Result =
"!if";
break;
2031 case SUBST: Result =
"!subst";
break;
2032 case SUBSTR: Result =
"!substr";
break;
2033 case FIND: Result =
"!find";
break;
2035 Result =
"!setdagarg";
2038 Result =
"!setdagname";
2041 return (Result +
"(" +
2042 (UnquotedLHS ? LHS->getAsUnquotedString() : LHS->getAsString()) +
2043 ", " + MHS->getAsString() +
", " + RHS->getAsString() +
")");
2049 ID.AddPointer(Start);
2050 ID.AddPointer(List);
2053 ID.AddPointer(Expr);
2068 FoldOpInit *
I =
new (RK.
Allocator) FoldOpInit(Start, List, A, B, Expr,
Type);
2079 const Init *Accum = Start;
2080 for (
const Init *Elt : *LI) {
2097 const Init *
NewExpr = Expr->resolveReferences(SR);
2099 if (Start == NewStart && List == NewList && Expr ==
NewExpr)
2103 ->
Fold(R.getCurrentRecord());
2111 return (
Twine(
"!foldl(") + Start->getAsString() +
", " + List->getAsString() +
2112 ", " + A->getAsUnquotedString() +
", " + B->getAsUnquotedString() +
2113 ", " + Expr->getAsString() +
")")
2120 ID.AddPointer(Expr);
2133 IsAOpInit *
I =
new (RK.
Allocator) IsAOpInit(CheckType, Expr);
2145 if (TI->getType()->typeIsConvertibleTo(CheckType))
2152 if ((!CheckType->typeIsConvertibleTo(TI->getType()) &&
2153 Expr->isConcrete()) ||
2176 return (
Twine(
"!isa<") + CheckType->getAsString() +
">(" +
2177 Expr->getAsString() +
")")
2184 ID.AddPointer(Expr);
2194 if (
const ExistsOpInit *
I =
2198 ExistsOpInit *
I =
new (RK.
Allocator) ExistsOpInit(CheckType, Expr);
2210 const Record *
D = CheckType->getRecordKeeper().getDef(Name->getValue());
2214 D->getDefInit()->getType()->typeIsA(CheckType));
2222 (Anonymous && Name == Anonymous->getNameInit())) {
2241 if (Expr !=
NewExpr || R.isFinal())
2242 return get(CheckType,
NewExpr)->
Fold(R.getCurrentRecord(), R.isFinal());
2251 return (
Twine(
"!exists<") + CheckType->getAsString() +
">(" +
2252 Expr->getAsString() +
")")
2263 const Init *Regex) {
2269 if (
const InstancesOpInit *
I =
2273 InstancesOpInit *
I =
new (RK.
Allocator) InstancesOpInit(Type, Regex);
2283 if (CurRec && !IsFinal)
2290 StringRef RegexStr = RegexInit->getValue();
2298 if (Matcher.
match(Def->getName()))
2306 if (Regex != NewRegex || R.isFinal())
2307 return get(Type, NewRegex)->
Fold(R.getCurrentRecord(), R.isFinal());
2316 return "!instances<" + Type->getAsString() +
">(" + Regex->getAsString() +
2324 return Field->getType();
2344 if (!
T)
return nullptr;
2345 unsigned NumBits =
T->getNumBits();
2349 for (
unsigned Bit : Bits) {
2369 if (!
getType()->typeIsConvertibleTo(Ty))
2390 return NameString->getValue();
2400 if (
const Init *Val = R.resolve(VarName))
2414 return TI->getAsString() +
"{" +
utostr(Bit) +
"}";
2418 const Init *
I = TI->resolveReferences(R);
2425DefInit::DefInit(
const Record *
D)
2430 if (
getType()->typeIsConvertibleTo(RRT))
2437 return RV->getType();
2445 ID.AddInteger(Args.size());
2446 ID.AddPointer(Class);
2448 for (
const Init *
I : Args)
2471 VarDefInit *
I =
new (Mem) VarDefInit(Loc, Class, Args);
2480const DefInit *VarDefInit::instantiate() {
2485 auto NewRecOwner = std::make_unique<Record>(
2487 Record *NewRec = NewRecOwner.get();
2490 for (
const RecordVal &Val : Class->getValues())
2503 for (
const Init *Arg : TArgs) {
2508 for (
auto *Arg :
args()) {
2509 if (Arg->isPositional())
2510 R.set(TArgs[Arg->getIndex()], Arg->getValue());
2512 R.set(Arg->getName(), Arg->getValue());
2519 Class, SMRange(Class->getLoc().back(), Class->getLoc().back()));
2523 Records.addDef(std::move(NewRecOwner));
2549 return const_cast<VarDefInit *
>(New)->instantiate();
2561 Arg->resolveReferences(R);
2563 if (!R.foundUnresolved())
2564 return const_cast<VarDefInit *
>(
this)->instantiate();
2569 std::string Result = Class->getNameInitAsString() +
"<";
2573 Result += Arg->getAsString();
2575 return Result +
">";
2601 const Record *Def = DI->getDef();
2604 Twine(
"Attempting to access field '") +
2605 FieldName->getAsUnquotedString() +
"' of '" +
2606 Rec->getAsString() +
"' is a forbidden self-reference");
2607 const Init *FieldVal = Def->getValue(FieldName)->getValue();
2616 const Init *FieldVal = DI->getDef()->getValue(FieldName)->getValue();
2625 const RecTy *ValType) {
2627 "Number of conditions and values must match!");
2628 ID.AddPointer(ValType);
2630 for (
const auto &[
Cond, Val] :
zip(Conds, Vals)) {
2652 "Number of conditions and values must match!");
2664 CondOpInit *
I =
new (Mem) CondOpInit(Conds, Values, Ty);
2675 const Init *NewCond =
Cond->resolveReferences(R);
2696 if (CondI->getValue())
2697 return Val->convertInitializerTo(
getValType());
2705 " does not have any true condition in:" +
2706 this->getAsString());
2712 return std::get<0>(Pair)->isConcrete() && std::get<1>(Pair)->isConcrete();
2718 return std::get<0>(Pair)->isComplete() && std::get<1>(Pair)->isComplete();
2723 std::string Result =
"!cond(";
2727 Result +=
Cond->getAsString() +
": ";
2728 Result += Val->getAsString();
2730 return Result +
")";
2743 for (
auto [Arg, Name] :
zip_equal(Args, ArgNames)) {
2745 ID.AddPointer(Name);
2753 ValName(VN), NumArgs(
Args.
size()) {
2762 "Number of DAG args and arg names must match!");
2774 Args.size(), ArgNames.
size()),
2776 DagInit *
I =
new (Mem) DagInit(V, VN, Args, ArgNames);
2783 ArrayRef<std::pair<const Init *, const StringInit *>> ArgAndNames) {
2795 return DefI->getDef();
2803 return ArgName && ArgName->
getValue() == Name;
2805 if (It == ArgNames.
end())
2806 return std::nullopt;
2807 return std::distance(ArgNames.
begin(), It);
2813 bool ArgsChanged =
false;
2817 ArgsChanged |= NewArg != Arg;
2820 const Init *
Op = Val->resolveReferences(R);
2821 if (
Op != Val || ArgsChanged)
2828 if (!Val->isConcrete())
2834 std::string Result =
"(" + Val->getAsString();
2836 Result +=
":$" + ValName->getAsUnquotedString();
2842 Result += Arg->getAsString();
2844 Result +=
":$" + Name->getAsUnquotedString();
2847 return Result +
")";
2855 : Name(
N), TyAndKind(
T, K) {
2857 assert(Value &&
"Cannot create unset value for current type!");
2863 : Name(
N), Loc(Loc), TyAndKind(
T, K) {
2865 assert(Value &&
"Cannot create unset value for current type!");
2875 if (StrInit->hasCodeFormat())
2883 return TyAndKind.getPointer()->getAsString();
2893 Value = V->getCastTo(
getType());
2903 for (
unsigned I = 0, E = BTy->getNumBits();
I < E; ++
I)
2904 Bits[
I] = Value->getBit(
I);
2918#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
2929 if (PrintSem) OS <<
";\n";
2933 assert(Locs.size() == 1);
2934 ForwardDeclarationLocs.push_back(Locs.front());
2937 Locs.push_back(
Loc);
2940void Record::checkName() {
2945 "' is not a string!");
2955 if (!CorrespondingDefInit) {
2956 CorrespondingDefInit =
2957 new (TrackedRecords.getImpl().Allocator)
DefInit(
this);
2959 return CorrespondingDefInit;
2985 if (NewName != OldName) {
2992 if (SkipVal == &
Value)
2996 if (
Value.setValue(VR)) {
3000 (
Twine(
"of type '") + VRT->getType()->getAsString() +
"' ").str();
3003 Twine(
"Invalid value ") +
Type +
"found when setting field '" +
3004 Value.getNameInitAsString() +
"' of type '" +
3014 const Init *
Value = Assertion.Condition->resolveReferences(R);
3015 Assertion.Condition =
Value;
3016 Value = Assertion.Message->resolveReferences(R);
3017 Assertion.Message =
Value;
3021 const Init *
Value = Dump.Message->resolveReferences(R);
3022 Dump.Message =
Value;
3033#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
3038 OS << R.getNameInitAsString();
3041 if (!TArgs.
empty()) {
3044 for (
const Init *TA : TArgs) {
3046 assert(RV &&
"Template argument record not found??");
3048 RV->
print(OS,
false);
3054 std::vector<const Record *> SCs = R.getSuperClasses();
3057 for (
const Record *SC : SCs)
3058 OS <<
" " << SC->getNameInitAsString();
3062 for (
const RecordVal &Val : R.getValues())
3063 if (Val.isNonconcreteOK() && !R.isTemplateArg(Val.getNameInit()))
3065 for (
const RecordVal &Val : R.getValues())
3066 if (!Val.isNonconcreteOK() && !R.isTemplateArg(Val.getNameInit()))
3076 "' does not have a field named `" + FieldName +
"'!\n");
3082 if (!R || !R->getValue())
3084 "' does not have a field named `" + FieldName +
"'!\n");
3085 return R->getValue();
3091 return SI->getValue();
3093 "' exists but does not have a string value");
3096std::optional<StringRef>
3099 if (!R || !R->getValue())
3100 return std::nullopt;
3102 return std::nullopt;
3105 return SI->getValue();
3108 "Record `" +
getName() +
"', ` field `" + FieldName +
3109 "' exists but does not have a string initializer!");
3117 "' exists but does not have a bits value");
3125 "' exists but does not have a list value");
3128std::vector<const Record *>
3131 std::vector<const Record *> Defs;
3132 for (
const Init *
I :
List->getElements()) {
3134 Defs.push_back(DI->getDef());
3138 "' list is not entirely DefInit!");
3146 return II->getValue();
3149 Twine(
"Record `") +
getName() +
"', field `" + FieldName +
3150 "' exists but does not have an int value: " +
I->getAsString());
3156 std::vector<int64_t> Ints;
3157 for (
const Init *
I :
List->getElements()) {
3159 Ints.push_back(
II->getValue());
3162 Twine(
"Record `") +
getName() +
"', field `" + FieldName +
3163 "' exists but does not have a list of ints value: " +
3169std::vector<StringRef>
3172 std::vector<StringRef> Strings;
3173 for (
const Init *
I :
List->getElements()) {
3175 Strings.push_back(
SI->getValue());
3178 Twine(
"Record `") +
getName() +
"', field `" + FieldName +
3179 "' exists but does not have a list of strings value: " +
3188 return DI->getDef();
3190 FieldName +
"' does not have a def initializer!");
3196 return DI->getDef();
3200 FieldName +
"' does not have either a def initializer or '?'!");
3206 return BI->getValue();
3208 FieldName +
"' does not have a bit initializer!");
3219 return BI->getValue();
3221 FieldName +
"' does not have a bit initializer!");
3229 FieldName +
"' does not have a dag initializer!");
3240 bool AnyFailed =
false;
3244 AnyFailed |=
CheckAssert(Assertion.Loc, Condition, Message);
3252 PrintError(
this,
"assertion failed in this record");
3260 const Init *Message = Dump.Message->resolveReferences(R);
3276 : Impl(
std::make_unique<
detail::RecordKeeperImpl>(*this)),
3281#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
3286 OS <<
"------------- Classes -----------------\n";
3288 OS <<
"class " << *
C;
3290 OS <<
"------------- Defs -----------------\n";
3306 auto [Iter, Inserted] = Cache.try_emplace(ClassName.
str());
3309 return Iter->second;
3312std::vector<const Record *>
3315 std::vector<const Record *> Defs;
3317 assert(ClassNames.
size() > 0 &&
"At least one class must be passed.");
3318 for (
StringRef ClassName : ClassNames) {
3325 for (
const auto &OneDef :
getDefs()) {
3327 return OneDef.second->isSubClassOf(Class);
3329 Defs.push_back(OneDef.second.get());
3343 Impl->dumpAllocationStats(OS);
3347 auto It = Map.find(VarName);
3348 if (It == Map.end())
3351 const Init *
I = It->second.V;
3353 if (!It->second.Resolved && Map.size() > 1) {
3357 I =
I->resolveReferences(*
this);
3358 Map[VarName] = {
I,
true};
3365 const Init *Val = Cache.lookup(VarName);
3374 Val = RV->getValue();
3375 Stack.push_back(VarName);
3380 Stack.push_back(VarName);
3385 Cache[VarName] = Val;
3390 const Init *
I =
nullptr;
3393 I = R->resolve(VarName);
3394 if (
I && !FoundUnresolved) {
3399 I->resolveReferences(
Sub);
3400 FoundUnresolved |=
Sub.FoundUnresolved;
3405 FoundUnresolved =
true;
3410 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< 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.
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
uint64_t IntrinsicInst * II
OptimizedStructLayoutField Field
const SmallVectorImpl< MachineOperand > & Cond
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...
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - Get the array size.
bool empty() const
empty - 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 InsertNode(T *N, void *InsertPos)
InsertNode - Insert the specified node into the folding set, knowing that it is not already in the fo...
T * FindNodeOrInsertPos(const FoldingSetNodeID &ID, void *&InsertPos)
FindNodeOrInsertPos - Look up the node specified by ID.
FoldingSetNodeID - This class is used to gather all the unique data bits of a node.
FoldingSet - This template class is used to instantiate a specialized implementation of the folding s...
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.
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 * 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...
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.
RecordKeeper & getRecordKeeper() const
Get the record keeper used to unique this value.
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 ...
LLVM_ABI bool isValid(std::string &Error) const
isValid - returns the error encountered during regex compilation, if any.
LLVM_ABI bool match(StringRef String, SmallVectorImpl< StringRef > *Matches=nullptr, std::string *Error=nullptr) const
matches - Match the regex against a given String.
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.
StringRef - Represent a constant reference to a string, i.e.
std::string str() const
str - 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.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ C
The default llvm calling convention, compatible with C.
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.
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.
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.
void PrintFatalError(const Twine &Msg)
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.
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.
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.
FunctionAddr VTableAddr Count
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.
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.
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
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.