22#include "llvm/Config/llvm-config.h"
42#define DEBUG_TYPE "tblgen-records"
122 OS <<
"Total allocator memory = " <<
Allocator.getTotalMemory() <<
"\n\n";
124 OS <<
"Number of records instantiated = " <<
LastRecordID <<
'\n';
125 OS <<
"Number of anonymous records = " <<
AnonCounter <<
'\n';
132#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
138 ListTy =
new (RK.getImpl().Allocator)
ListRecTy(
this);
143 assert(RHS &&
"NULL pointer");
144 return Kind == RHS->getRecTyKind();
150 return &RK.getImpl().SharedBitRecTy;
157 return BitsTy->getNumBits() == 1;
167 Ty =
new (RKImpl.
Allocator) BitsRecTy(RK, Sz);
172 return "bits<" +
utostr(Size) +
">";
183 return &RK.getImpl().SharedIntRecTy;
192 return &RK.getImpl().SharedStringRecTy;
205 return "list<" + ElementTy->getAsString() +
">";
210 return ElementTy->typeIsConvertibleTo(ListTy->getElementType());
221 return &RK.getImpl().SharedDagRecTy;
229 :
RecTy(RecordRecTyKind, RK), NumClasses(Classes.
size()) {
236 if (UnsortedClasses.
empty())
243 return LHS->getNameInitAsString() < RHS->getNameInitAsString();
247 if (RecordRecTy *Ty = ThePool.
lookup(Classes, Token))
252 for (
unsigned i = 0; i < Classes.
size(); ++i) {
253 for (
unsigned j = 0; j < Classes.
size(); ++j) {
256 assert(&Classes[0]->getRecords() == &Classes[i]->getRecords());
262 RecordRecTy *Ty =
new (Mem) RecordRecTy(RK, Classes);
263 ThePool.
insert(Ty, Token);
268 assert(Class &&
"unexpected null class");
269 return get(Class->getRecords(), {Class});
274 return getClasses()[0]->getNameInitAsString();
276 std::string Str =
"{";
280 Str += R->getNameInitAsString();
288 return MySuperClass == Class || MySuperClass->
isSubClassOf(Class);
301 return isSubClassOf(TargetClass);
314 while (!Stack.empty()) {
315 const Record *R = Stack.pop_back_val();
317 if (T2->isSubClassOf(R))
335 assert(T1 !=
nullptr &&
"Invalid record type");
336 if (T1->typeIsConvertibleTo(T2))
339 assert(T2 !=
nullptr &&
"Invalid record type");
340 if (T2->typeIsConvertibleTo(T1))
345 const RecTy *NewType =
346 resolveTypes(ListTy1->getElementType(), ListTy2->getElementType());
359void Init::anchor() {}
361#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
367 return TyInit->getType()->getRecordKeeper();
369 return ArgInit->getRecordKeeper();
374 return &RK.getImpl().TheUnsetInit;
399 const Init *NewValue = Value->resolveReferences(R);
400 if (NewValue != Value)
419 if (BRT->getNumBits() == 1)
428 NumBits(Bits.
size()) {
442 BitsInit *
I =
new (Mem) BitsInit(RK, Bits);
456 if (
getNumBits() != BRT->getNumBits())
return nullptr;
473 Result |=
static_cast<int64_t
>(Bit->getValue()) << Idx;
483 Result |=
static_cast<int64_t
>(Bit->getValue()) << Idx;
491 for (
auto [Bit, NewBit] :
zip_equal(Bits, NewBits)) {
510 std::string Result =
"{ ";
515 Result += Bit->getAsString();
519 return Result +
" }";
531 const Init *CachedBitVarRef =
nullptr;
532 const Init *CachedBitVarResolved =
nullptr;
538 if (CurBitVar->getBitVar() != CachedBitVarRef) {
539 CachedBitVarRef = CurBitVar->getBitVar();
542 assert(CachedBitVarResolved &&
"Unresolved bitvar reference");
543 NewBit = CachedBitVarResolved->
getBit(CurBitVar->getBitNum());
546 NewBit = CurBit->resolveReferences(R)->getBit(0);
563 I =
new (RK.
getImpl().Allocator) IntInit(RK, V);
573 return (NumBits >=
sizeof(
Value) * 8) ||
574 (
Value >> NumBits == 0) || (
Value >> (NumBits-1) == -1);
583 if (Val != 0 && Val != 1)
return nullptr;
594 for (
unsigned i = 0; i != BRT->getNumBits(); ++i)
607 for (
auto [Bit, NewBit] :
zip_equal(Bits, NewBits)) {
617 return new (RK.
getImpl().Allocator) AnonymousNameInit(RK, V);
625 return "anonymous_" +
utostr(Value);
630 auto *New = R.resolve(Old);
631 New = New ? New : Old;
634 return Anonymous->getNameInit();
643 auto &Entry = *InitMap.
try_emplace(V,
nullptr).first;
645 Entry.second =
new (RKImpl.
Allocator) StringInit(RK, Entry.getKey(), Fmt);
658 NumElements(Elements.
size()) {
665 const RecTy *EltTy) {
676 ListInit *
I =
new (Mem) ListInit(Elements, EltTy);
687 Elements.reserve(
size());
692 const RecTy *ElementType = LRT->getElementType();
694 if (
const Init *CI =
I->convertInitializerTo(ElementType)) {
695 Elements.push_back(CI);
723 Resolved.reserve(
size());
729 Resolved.push_back(E);
748 std::string Result =
"[";
750 for (
const Init *Element : *
this) {
778 if (LHS->isConcrete()) {
783 OS << *Def->getDef();
823 (Anonymous && Name == Anonymous->getNameInit())) {
830 auto PrintFatalErrorHelper = [CurRec](
const Twine &
T) {
839 PrintFatalErrorHelper(
Twine(
"Undefined reference to record: '") +
840 Name->getValue() +
"'\n");
847 PrintFatalErrorHelper(
Twine(
"Expected type '") +
863 if (LHS->isConcrete())
875 assert(!LHSl->empty() &&
"Empty list in head");
876 return LHSl->getElement(0);
882 assert(!LHSl->empty() &&
"Empty list in tail");
886 LHSl->getElementType());
913 if (!TI->getType()->typeIsA(
getType())) {
919 return Dag->getOperator();
926 return Dag->getName();
933 int64_t LHSv = LHSi->getValue();
936 "Illegal operation: logtwo is undefined "
937 "on arguments less than or equal to 0");
941 "Log of an int64_t must be smaller than INT64_MAX");
955 [](
const ListInit *
List) -> std::optional<std::vector<const Init *>> {
956 std::vector<const Init *> Flattened;
958 for (
const Init *InnerInit :
List->getElements()) {
967 auto Flattened = Flatten(LHSList);
969 return ListInit::get(*Flattened, InnerListTy->getElementType());
981 ->Fold(R.getCurrentRecord(), R.isFinal());
989 case NOT: Result =
"!not";
break;
990 case HEAD: Result =
"!head";
break;
991 case TAIL: Result =
"!tail";
break;
992 case SIZE: Result =
"!size";
break;
993 case EMPTY: Result =
"!empty";
break;
994 case GETDAGOP: Result =
"!getdagop";
break;
996 Result =
"!getdagopname";
998 case LOG2 : Result =
"!logtwo";
break;
1000 Result =
"!listflatten";
1006 Result =
"!tolower";
1009 Result =
"!toupper";
1012 Result =
"!initialized";
1015 return Result +
"(" + LHS->getAsString() +
")";
1022 if (
const BinOpInit *
I =
1034 Concat.append(I1->getValue());
1042 if (List->size() == 0)
1050 for (
const Init *Elem : List->getElements().drop_front()) {
1055 Result.append(Element->getValue());
1064 if (List->size() == 0)
1067 List->getElement(0)->convertInitializerTo(
IntRecTy::get(RK)));
1072 for (
const Init *Elem : List->getElements().drop_front()) {
1078 Result.append(Element->getAsString());
1111 const Init *RHS)
const {
1122 Result = LHSi->getValue() == RHSi->getValue();
1125 Result = LHSi->getValue() != RHSi->getValue();
1128 Result = LHSi->getValue() <= RHSi->getValue();
1131 Result = LHSi->getValue() < RHSi->getValue();
1134 Result = LHSi->getValue() >= RHSi->getValue();
1137 Result = LHSi->getValue() > RHSi->getValue();
1153 Result = LHSs->getValue() == RHSs->getValue();
1156 Result = LHSs->getValue() != RHSs->getValue();
1159 Result = LHSs->getValue() <= RHSs->getValue();
1162 Result = LHSs->getValue() < RHSs->getValue();
1165 Result = LHSs->getValue() >= RHSs->getValue();
1168 Result = LHSs->getValue() > RHSs->getValue();
1181 return (
Opc ==
EQ) ? LHSd == RHSd : LHSd != RHSd;
1184 return std::nullopt;
1187static std::optional<unsigned>
1191 int64_t Pos = Idx->getValue();
1195 (
Twine(
"index ") + std::to_string(Pos) +
Twine(
" is negative")).str();
1196 return std::nullopt;
1198 if (Pos >= Dag->getNumArgs()) {
1200 Error = (
Twine(
"index ") + std::to_string(Pos) +
1201 " is out of range (dag has " +
1202 std::to_string(Dag->getNumArgs()) +
" arguments)")
1204 return std::nullopt;
1211 auto ArgNo = Dag->getArgNo(Name->getValue());
1214 Error = (
Twine(
"key '") + Name->getValue() +
Twine(
"' is not found")).str();
1215 return std::nullopt;
1231 if (LOp && ROp && LOp->getDef() != ROp->getDef()) {
1233 LHSs->getAsString() +
"' vs. '" + RHSs->getAsString() +
1236 const Init *
Op = LOp ? LOp : ROp;
1244 const auto *NameInit = LHSs->getName();
1246 NameInit = RHSs->getName();
1260 StringRef RegexStr = RegexInit->getValue();
1262 if (!Matcher.isValid())
1266 Matcher.match(StrInit->getValue()));
1283 if (
Count->getValue() < 0)
1296 for (
const Init *EltLHS : *LHSs) {
1298 for (
const Init *EltRHS : *RHSs) {
1299 if (std::optional<bool> Result =
CompareInit(
EQ, EltLHS, EltRHS)) {
1307 Args.push_back(EltLHS);
1316 if (!TheList || !Idx)
1318 auto i = Idx->getValue();
1319 if (i < 0 || i >= (ssize_t)TheList->size())
1321 return TheList->getElement(i);
1326 if (!TheList || !SliceIdxs)
1329 Args.reserve(SliceIdxs->size());
1330 for (
auto *
I : *SliceIdxs) {
1334 auto i =
II->getValue();
1335 if (i < 0 || i >= (ssize_t)TheList->size())
1337 Args.push_back(TheList->getElement(i));
1347 int64_t Start = LHSi->getValue();
1348 int64_t
End = RHSi->getValue();
1354 Args.reserve(
End - Start + 1);
1355 for (
auto i = Start; i <=
End; ++i)
1359 Args.reserve(Start -
End + 1);
1360 for (
auto i = Start; i >=
End; --i)
1363 }
else if (Start <
End) {
1365 Args.reserve(
End - Start);
1366 for (
auto i = Start; i <
End; ++i)
1383 if (
List && Delim) {
1412 assert(*ArgNo < Dag->getNumArgs());
1414 const Init *Arg = Dag->getArg(*ArgNo);
1416 if (!TI->getType()->typeIsConvertibleTo(
getType()))
1426 int64_t Pos = Idx->getValue();
1427 if (Pos < 0 || Pos >= Dag->getNumArgs()) {
1430 Twine(
"!getdagname index is out of range 0...") +
1431 std::to_string(Dag->getNumArgs() - 1) +
": " +
1432 std::to_string(Pos));
1434 const Init *ArgName = Dag->getArgName(Pos);
1453 Dag->getArgNames());
1471 int64_t LHSv = LHSi->getValue(), RHSv = RHSi->getValue();
1475 case ADD: Result = LHSv + RHSv;
break;
1476 case SUB: Result = LHSv - RHSv;
break;
1477 case MUL: Result = LHSv * RHSv;
break;
1481 "Illegal operation: division by zero");
1482 else if (LHSv ==
INT64_MIN && RHSv == -1)
1484 "Illegal operation: INT64_MIN / -1");
1486 Result = LHSv / RHSv;
1488 case AND: Result = LHSv & RHSv;
break;
1489 case OR: Result = LHSv | RHSv;
break;
1490 case XOR: Result = LHSv ^ RHSv;
break;
1492 if (RHSv < 0 || RHSv >= 64)
1494 "Illegal operation: out of bounds shift");
1495 Result = (uint64_t)LHSv << (uint64_t)RHSv;
1498 if (RHSv < 0 || RHSv >= 64)
1500 "Illegal operation: out of bounds shift");
1501 Result = LHSv >> (uint64_t)RHSv;
1504 if (RHSv < 0 || RHSv >= 64)
1506 "Illegal operation: out of bounds shift");
1507 Result = (uint64_t)LHSv >> (uint64_t)RHSv;
1533 if ((
Opc ==
AND && !LHSi->getValue()) ||
1534 (
Opc ==
OR && LHSi->getValue() == -1))
1541 if (LHS != NewLHS || RHS != NewRHS)
1543 ->Fold(R.getCurrentRecord());
1552 return LHS->getAsString() +
"[" + RHS->getAsString() +
"]";
1554 return LHS->getAsString() +
"..." + RHS->getAsString();
1555 case CONCAT: Result =
"!con";
break;
1559 case ADD: Result =
"!add";
break;
1560 case SUB: Result =
"!sub";
break;
1561 case MUL: Result =
"!mul";
break;
1562 case DIV: Result =
"!div";
break;
1563 case AND: Result =
"!and";
break;
1564 case OR: Result =
"!or";
break;
1565 case XOR: Result =
"!xor";
break;
1566 case SHL: Result =
"!shl";
break;
1567 case SRA: Result =
"!sra";
break;
1568 case SRL: Result =
"!srl";
break;
1569 case EQ: Result =
"!eq";
break;
1570 case NE: Result =
"!ne";
break;
1571 case LE: Result =
"!le";
break;
1572 case LT: Result =
"!lt";
break;
1573 case GE: Result =
"!ge";
break;
1574 case GT: Result =
"!gt";
break;
1575 case LISTCONCAT: Result =
"!listconcat";
break;
1576 case LISTSPLAT: Result =
"!listsplat";
break;
1578 Result =
"!listremove";
1580 case STRCONCAT: Result =
"!strconcat";
break;
1581 case INTERLEAVE: Result =
"!interleave";
break;
1582 case SETDAGOP: Result =
"!setdagop";
break;
1584 Result =
"!setdagopname";
1590 Result =
"!getdagname";
1593 return Result +
"(" + LHS->getAsString() +
", " + RHS->getAsString() +
")";
1614 return RHS->resolveReferences(R);
1619 bool Change =
false;
1653 for (
const Init *&Item : NewList) {
1655 if (NewItem != Item)
1672 for (
const Init *Item : MHSl->getElements()) {
1676 if (
const auto *IncludeInt =
1679 if (IncludeInt->getValue())
1698 using KV = std::pair<const Init *, const Init *>;
1701 for (
const Init *Item : MHSl->getElements()) {
1708 if (KeyedList.
empty())
1715 for (
auto &[
Key, Item] : KeyedList) {
1737 for (
auto &[
Key, Item] : KeyedList)
1738 Result.push_back(Item);
1758 if (LHSd && MHSd && RHSd) {
1759 const Record *Val = RHSd->getDef();
1760 if (LHSd->getAsString() == RHSd->getAsString())
1761 Val = MHSd->getDef();
1764 if (LHSv && MHSv && RHSv) {
1765 std::string Val = RHSv->getName().str();
1766 if (LHSv->getAsString() == RHSv->getAsString())
1767 Val = MHSv->getName().str();
1770 if (LHSs && MHSs && RHSs) {
1771 std::string Val = RHSs->getValue().str();
1773 std::string::size_type Idx = 0;
1775 std::string::size_type Found = Val.find(LHSs->getValue(), Idx);
1776 if (Found == std::string::npos)
1778 Val.replace(Found, LHSs->getValue().size(), MHSs->getValue().str());
1779 Idx = Found + MHSs->getValue().size();
1808 if (LHSi->getValue())
1824 if (MHSok && RHSok && (!MHSl || !RHSl || MHSl->size() == RHSl->size())) {
1826 unsigned Size = MHSl ? MHSl->size() : RHSl->size();
1827 for (
unsigned i = 0; i !=
Size; ++i) {
1843 if (!LHSi || !MHSi || !RHSi)
1846 auto Start = LHSi->getValue();
1847 auto End = MHSi->getValue();
1848 auto Step = RHSi->getValue();
1853 if (Start < End && Step > 0) {
1854 Args.reserve((
End - Start) / Step);
1855 for (
auto I = Start;
I <
End;
I += Step)
1857 }
else if (Start >
End && Step < 0) {
1858 Args.reserve((Start -
End) / -Step);
1859 for (
auto I = Start;
I >
End;
I += Step)
1871 if (LHSs && MHSi && RHSi) {
1872 int64_t StringSize = LHSs->getValue().size();
1873 int64_t Start = MHSi->getValue();
1874 int64_t
Length = RHSi->getValue();
1875 if (Start < 0 || Start > StringSize)
1877 Twine(
"!substr start position is out of range 0...") +
1878 std::to_string(StringSize) +
": " +
1879 std::to_string(Start));
1892 if (LHSs && MHSs && RHSi) {
1893 int64_t SourceSize = LHSs->getValue().size();
1894 int64_t Start = RHSi->getValue();
1895 if (Start < 0 || Start > SourceSize)
1897 Twine(
"!find start position is out of range 0...") +
1898 std::to_string(SourceSize) +
": " +
1899 std::to_string(Start));
1900 auto I = LHSs->getValue().find(MHSs->getValue(), Start);
1901 if (
I == std::string::npos)
1916 assert(*ArgNo < Dag->getNumArgs());
1920 return DagInit::get(Dag->getOperator(), Dag->getName(), Args,
1921 Dag->getArgNames());
1934 assert(*ArgNo < Dag->getNumArgs());
1938 return DagInit::get(Dag->getOperator(), Dag->getName(), Dag->getArgs(),
1955 if (
Value->getValue())
1956 return MHS->resolveReferences(R);
1957 return RHS->resolveReferences(R);
1972 if (LHS != lhs || MHS != mhs || RHS != rhs)
1974 ->Fold(R.getCurrentRecord());
1980 bool UnquotedLHS =
false;
1982 case DAG: Result =
"!dag";
break;
1983 case FILTER: Result =
"!filter"; UnquotedLHS =
true;
break;
1984 case FOREACH: Result =
"!foreach"; UnquotedLHS =
true;
break;
1989 case IF: Result =
"!if";
break;
1993 case SUBST: Result =
"!subst";
break;
1994 case SUBSTR: Result =
"!substr";
break;
1995 case FIND: Result =
"!find";
break;
1997 Result =
"!setdagarg";
2000 Result =
"!setdagname";
2003 return (Result +
"(" +
2004 (UnquotedLHS ? LHS->getAsUnquotedString() : LHS->getAsString()) +
2005 ", " + MHS->getAsString() +
", " + RHS->getAsString() +
")");
2013 if (
const FoldOpInit *
I =
2017 FoldOpInit *
I =
new (RK.
Allocator) FoldOpInit(Start, List, A, B, Expr,
Type);
2024 const Init *Accum = Start;
2025 for (
const Init *Elt : *LI) {
2042 const Init *
NewExpr = Expr->resolveReferences(SR);
2044 if (Start == NewStart && List == NewList && Expr ==
NewExpr)
2048 ->
Fold(R.getCurrentRecord());
2058 return (
Twine(
"!foldl(") + Start->getAsString() +
", " + List->getAsString() +
2059 ", " + A->getAsUnquotedString() +
", " + B->getAsUnquotedString() +
2060 ", " + Expr->getAsString() +
")")
2071 IsAOpInit *
I =
new (RK.
Allocator) IsAOpInit(CheckType, Expr);
2079 if (TI->getType()->typeIsConvertibleTo(CheckType))
2086 if ((!CheckType->typeIsConvertibleTo(TI->getType()) &&
2087 Expr->isConcrete()) ||
2110 return (
Twine(
"!isa<") + CheckType->getAsString() +
">(" +
2111 Expr->getAsString() +
")")
2119 if (
const ExistsOpInit *
I =
2123 ExistsOpInit *
I =
new (RK.
Allocator) ExistsOpInit(CheckType, Expr);
2131 const Record *
D = CheckType->getRecordKeeper().getDef(Name->getValue());
2135 D->getDefInit()->getType()->typeIsA(CheckType));
2143 (Anonymous && Name == Anonymous->getNameInit())) {
2162 if (Expr !=
NewExpr || R.isFinal())
2163 return get(CheckType,
NewExpr)->
Fold(R.getCurrentRecord(), R.isFinal());
2172 return (
Twine(
"!exists<") + CheckType->getAsString() +
">(" +
2173 Expr->getAsString() +
")")
2178 const Init *Regex) {
2181 if (
const InstancesOpInit *
I =
2185 InstancesOpInit *
I =
new (RK.
Allocator) InstancesOpInit(Type, Regex);
2191 if (CurRec && !IsFinal)
2198 StringRef RegexStr = RegexInit->getValue();
2200 if (!Matcher.isValid())
2206 if (Matcher.match(Def->getName()))
2214 if (Regex != NewRegex || R.isFinal())
2215 return get(Type, NewRegex)->
Fold(R.getCurrentRecord(), R.isFinal());
2220 return "!instances<" + Type->
getAsString() +
">(" + Regex->getAsString() +
2228 return Field->getType();
2248 if (!
T)
return nullptr;
2249 unsigned NumBits =
T->getNumBits();
2253 for (
unsigned Bit : Bits) {
2273 if (!
getType()->typeIsConvertibleTo(Ty))
2294 return NameString->getValue();
2304 if (
const Init *Val = R.resolve(VarName))
2318 return TI->getAsString() +
"{" +
utostr(Bit) +
"}";
2322 const Init *
I = TI->resolveReferences(R);
2329DefInit::DefInit(
const Record *
D)
2334 if (
getType()->typeIsConvertibleTo(RRT))
2341 return RV->getType();
2350 NumArgs(Args.
size()) {
2363 VarDefInit *
I =
new (Mem) VarDefInit(Loc, Class, Args);
2368const DefInit *VarDefInit::instantiate() {
2373 auto NewRecOwner = std::make_unique<Record>(
2375 Record *NewRec = NewRecOwner.get();
2378 for (
const RecordVal &Val : Class->getValues())
2391 for (
const Init *Arg : TArgs) {
2396 for (
auto *Arg :
args()) {
2397 if (Arg->isPositional())
2398 R.set(TArgs[Arg->getIndex()], Arg->getValue());
2400 R.set(Arg->getName(), Arg->getValue());
2407 Class, SMRange(Class->getLoc().back(), Class->getLoc().back()));
2411 Records.addDef(std::move(NewRecOwner));
2437 return const_cast<VarDefInit *
>(New)->instantiate();
2449 Arg->resolveReferences(R);
2451 if (!R.foundUnresolved())
2452 return const_cast<VarDefInit *
>(
this)->instantiate();
2457 std::string Result = Class->getNameInitAsString() +
"<";
2461 Result += Arg->getAsString();
2463 return Result +
">";
2489 const Record *Def = DI->getDef();
2492 Twine(
"Attempting to access field '") +
2493 FieldName->getAsUnquotedString() +
"' of '" +
2494 Rec->getAsString() +
"' is a forbidden self-reference");
2495 const Init *FieldVal = Def->getValue(FieldName)->getValue();
2504 const Init *FieldVal = DI->getDef()->getValue(FieldName)->getValue();
2522 "Number of conditions and values must match!");
2526 if (
const CondOpInit *
I =
2532 CondOpInit *
I =
new (Mem) CondOpInit(Conds,
Values, Ty);
2543 const Init *NewCond =
Cond->resolveReferences(R);
2554 if (NewCondVal->getValue()) {
2574 if (CondI->getValue())
2575 return Val->convertInitializerTo(
getValType());
2583 " does not have any true condition in:" +
2584 this->getAsString());
2590 return std::get<0>(Pair)->isConcrete() && std::get<1>(Pair)->isConcrete();
2596 return std::get<0>(Pair)->isComplete() && std::get<1>(Pair)->isComplete();
2601 std::string Result =
"!cond(";
2605 Result +=
Cond->getAsString() +
": ";
2606 Result += Val->getAsString();
2608 return Result +
")";
2621 ValName(VN), NumArgs(Args.
size()) {
2625 V->isTriviallyResolved() &&
2633 "Number of DAG args and arg names must match!");
2637 if (
const DagInit *
I =
2643 Args.size(), ArgNames.
size()),
2645 DagInit *
I =
new (Mem) DagInit(V, VN, Args, ArgNames);
2652 ArrayRef<std::pair<const Init *, const StringInit *>> ArgAndNames) {
2660 return DefI->getDef();
2668 return ArgName && ArgName->
getValue() == Name;
2670 if (It == ArgNames.
end())
2671 return std::nullopt;
2672 return std::distance(ArgNames.
begin(), It);
2681 bool ArgsChanged =
false;
2685 ArgsChanged |= NewArg != Arg;
2688 const Init *
Op = Val->resolveReferences(R);
2689 if (
Op != Val || ArgsChanged)
2696 if (!Val->isConcrete())
2702 std::string Result =
"(" + Val->getAsString();
2704 Result +=
":$" + ValName->getAsUnquotedString();
2712 Result +=
":$" + Name->getAsUnquotedString();
2715 return Result +
")";
2723 : Name(
N), TyAndFlags(
T,
K) {
2725 assert(Value &&
"Cannot create unset value for current type!");
2731 : Name(
N), Loc(Loc), TyAndFlags(
T,
K) {
2733 assert(Value &&
"Cannot create unset value for current type!");
2743 if (StrInit->hasCodeFormat())
2772 for (
unsigned I = 0, E = BTy->getNumBits();
I < E; ++
I)
2773 Bits[
I] = Value->getBit(
I);
2787#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
2798 if (PrintSem) OS <<
";\n";
2802 assert(Locs.size() == 1);
2803 ForwardDeclarationLocs.push_back(Locs.front());
2806 Locs.push_back(
Loc);
2809void Record::checkName() {
2814 "' is not a string!");
2824 if (!CorrespondingDefInit) {
2825 CorrespondingDefInit =
2826 new (TrackedRecords.getImpl().Allocator)
DefInit(
this);
2828 return CorrespondingDefInit;
2854 if (NewName != OldName) {
2861 if (SkipVal == &
Value)
2865 if (
Value.setValue(VR)) {
2869 (
Twine(
"of type '") + VRT->getType()->getAsString() +
"' ").str();
2872 Twine(
"Invalid value ") +
Type +
"found when setting field '" +
2873 Value.getNameInitAsString() +
"' of type '" +
2883 const Init *
Value = Assertion.Condition->resolveReferences(R);
2884 Assertion.Condition =
Value;
2885 Value = Assertion.Message->resolveReferences(R);
2886 Assertion.Message =
Value;
2890 const Init *
Value = Dump.Message->resolveReferences(R);
2891 Dump.Message =
Value;
2902#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
2907 OS << R.getNameInitAsString();
2910 if (!TArgs.
empty()) {
2913 for (
const Init *TA : TArgs) {
2915 assert(RV &&
"Template argument record not found??");
2917 RV->
print(OS,
false);
2923 std::vector<const Record *> SCs = R.getSuperClasses();
2926 for (
const Record *SC : SCs)
2927 OS <<
" " << SC->getNameInitAsString();
2931 for (
const RecordVal &Val : R.getValues())
2932 if (Val.isNonconcreteOK() && !R.isTemplateArg(Val.getNameInit()))
2934 for (
const RecordVal &Val : R.getValues())
2935 if (!Val.isNonconcreteOK() && !R.isTemplateArg(Val.getNameInit()))
2945 "' does not have a field named `" + FieldName +
"'!\n");
2951 if (!R || !R->getValue())
2953 "' does not have a field named `" + FieldName +
"'!\n");
2954 return R->getValue();
2960 return SI->getValue();
2962 "' exists but does not have a string value");
2965std::optional<StringRef>
2968 if (!R || !R->getValue())
2969 return std::nullopt;
2971 return std::nullopt;
2974 return SI->getValue();
2977 "Record `" +
getName() +
"', ` field `" + FieldName +
2978 "' exists but does not have a string initializer!");
2986 "' exists but does not have a bits value");
2994 "' exists but does not have a list value");
2997std::vector<const Record *>
3000 std::vector<const Record *> Defs;
3001 for (
const Init *
I :
List->getElements()) {
3003 Defs.push_back(DI->getDef());
3007 "' list is not entirely DefInit!");
3015 return II->getValue();
3018 Twine(
"Record `") +
getName() +
"', field `" + FieldName +
3019 "' exists but does not have an int value: " +
I->getAsString());
3025 std::vector<int64_t> Ints;
3026 for (
const Init *
I :
List->getElements()) {
3028 Ints.push_back(
II->getValue());
3031 Twine(
"Record `") +
getName() +
"', field `" + FieldName +
3032 "' exists but does not have a list of ints value: " +
3038std::vector<StringRef>
3041 std::vector<StringRef> Strings;
3042 for (
const Init *
I :
List->getElements()) {
3044 Strings.push_back(
SI->getValue());
3047 Twine(
"Record `") +
getName() +
"', field `" + FieldName +
3048 "' exists but does not have a list of strings value: " +
3057 return DI->getDef();
3059 FieldName +
"' does not have a def initializer!");
3065 return DI->getDef();
3069 FieldName +
"' does not have either a def initializer or '?'!");
3075 return BI->getValue();
3077 FieldName +
"' does not have a bit initializer!");
3088 return BI->getValue();
3090 FieldName +
"' does not have a bit initializer!");
3098 FieldName +
"' does not have a dag initializer!");
3109 bool AnyFailed =
false;
3113 AnyFailed |=
CheckAssert(Assertion.Loc, Condition, Message);
3121 PrintError(
this,
"assertion failed in this record");
3129 const Init *Message = Dump.Message->resolveReferences(R);
3145 : Impl(
std::make_unique<
detail::RecordKeeperImpl>(*this)),
3150#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
3155 OS <<
"------------- Classes -----------------\n";
3157 OS <<
"class " << *
C;
3159 OS <<
"------------- Defs -----------------\n";
3175 auto [Iter, Inserted] = Cache.try_emplace(ClassName.
str());
3178 return Iter->second;
3181std::vector<const Record *>
3184 std::vector<const Record *> Defs;
3186 assert(ClassNames.
size() > 0 &&
"At least one class must be passed.");
3187 for (
StringRef ClassName : ClassNames) {
3194 for (
const auto &OneDef :
getDefs()) {
3196 return OneDef.second->isSubClassOf(Class);
3198 Defs.push_back(OneDef.second.get());
3212 Impl->dumpAllocationStats(OS);
3216 auto It = Map.find(VarName);
3217 if (It == Map.end())
3220 const Init *
I = It->second.V;
3222 if (!It->second.Resolved && Map.size() > 1) {
3226 I =
I->resolveReferences(*
this);
3227 Map[VarName] = {
I,
true};
3234 const Init *Val = Cache.lookup(VarName);
3243 Val = RV->getValue();
3244 Stack.push_back(VarName);
3249 Stack.push_back(VarName);
3254 Cache[VarName] = Val;
3259 const Init *
I =
nullptr;
3262 I = R->resolve(VarName);
3263 if (
I && !FoundUnresolved) {
3268 I->resolveReferences(
Sub);
3269 FoundUnresolved |=
Sub.FoundUnresolved;
3274 FoundUnresolved =
true;
3279 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...
bool isTriviallyResolved() const
Return true if resolveReferences returns this value unchanged with any resolver.
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.
bool TriviallyResolved
Set if resolveReferences returns this value unchanged with any resolver.
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.
@ End
Run the machine verifier once, at the end of the pipeline.
std::variant< unsigned, const Init * > ArgAuxType
constexpr detail::IsaCheckPredicate< Types... > IsaPred
Function object wrapper for the llvm::isa type check.
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
UniquingSet< UnOpInit > TheUnOpInitPool
UniquingSet< ArgumentInit > TheArgumentInitPool
DenseMap< std::pair< const Init *, const StringInit * >, FieldInit * > TheFieldInitPool
DenseMap< int64_t, IntInit * > TheIntInitPool
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.