22#include "llvm/Config/llvm-config.h"
41#define DEBUG_TYPE "tblgen-records"
103#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
115 return Kind ==
RHS->getRecTyKind();
128 return BitsTy->getNumBits() == 1;
143 return "bits<" + utostr(Size) +
">";
148 return cast<BitsRecTy>(
RHS)->Size == Size;
180 if (
const auto *ListTy = dyn_cast<ListRecTy>(
RHS))
201 ID.AddInteger(Classes.
size());
209 if (UnsortedClasses.
empty())
216 return LHS->getNameInitAsString() <
RHS->getNameInitAsString();
228 for (
unsigned i = 0; i < Classes.
size(); ++i) {
229 for (
unsigned j = 0; j < Classes.
size(); ++j) {
232 assert(&Classes[0]->getRecords() == &Classes[i]->getRecords());
239 std::uninitialized_copy(Classes.
begin(), Classes.
end(),
245 assert(Class &&
"unexpected null class");
246 return get(Class->getRecords(), Class);
255 return getClasses()[0]->getNameInitAsString();
257 std::string Str =
"{";
263 Str += R->getNameInitAsString();
271 return MySuperClass == Class ||
285 return isSubClassOf(TargetClass);
297 while (!Stack.empty()) {
298 Record *R = Stack.pop_back_val();
303 R->getDirectSuperClasses(Stack);
315 if (
RecordRecTy *RecTy2 = dyn_cast<RecordRecTy>(T2))
319 assert(
T1 !=
nullptr &&
"Invalid record type");
320 if (
T1->typeIsConvertibleTo(T2))
323 assert(T2 !=
nullptr &&
"Invalid record type");
327 if (
ListRecTy *ListTy1 = dyn_cast<ListRecTy>(
T1)) {
328 if (
ListRecTy *ListTy2 = dyn_cast<ListRecTy>(T2)) {
330 ListTy2->getElementType());
343void Init::anchor() {}
345#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
350 if (
auto *TyInit = dyn_cast<TypedInit>(
this))
351 return TyInit->getType()->getRecordKeeper();
352 if (
auto *ArgInit = dyn_cast<ArgumentInit>(
this))
353 return ArgInit->getRecordKeeper();
354 return cast<UnsetInit>(
this)->getRecordKeeper();
371 auto I = Aux.index();
374 ID.AddInteger(std::get<ArgumentInit::Positional>(Aux));
376 ID.AddPointer(std::get<ArgumentInit::Named>(Aux));
400 Init *NewValue =
Value->resolveReferences(R);
401 if (NewValue !=
Value)
412 if (isa<BitRecTy>(Ty))
413 return const_cast<BitInit *
>(
this);
415 if (isa<IntRecTy>(Ty))
418 if (
auto *BRT = dyn_cast<BitsRecTy>(Ty)) {
420 if (BRT->getNumBits() == 1)
447 std::uninitialized_copy(
Range.begin(),
Range.end(),
448 I->getTrailingObjects<
Init *>());
458 if (isa<BitRecTy>(Ty)) {
463 if (
auto *BRT = dyn_cast<BitsRecTy>(Ty)) {
466 if (
getNumBits() != BRT->getNumBits())
return nullptr;
467 return const_cast<BitsInit *
>(
this);
470 if (isa<IntRecTy>(Ty)) {
472 for (
unsigned i = 0, e =
getNumBits(); i != e; ++i)
473 if (
auto *Bit = dyn_cast<BitInit>(
getBit(i)))
474 Result |=
static_cast<int64_t
>(Bit->getValue()) << i;
487 for (
unsigned i = 0, e = Bits.size(); i != e; ++i) {
490 NewBits[i] =
getBit(Bits[i]);
496 for (
unsigned i = 0, e =
getNumBits(); i != e; ++i) {
504 std::string Result =
"{ ";
505 for (
unsigned i = 0, e =
getNumBits(); i != e; ++i) {
506 if (i) Result +=
", ";
508 Result += Bit->getAsString();
512 return Result +
" }";
518 bool Changed =
false;
521 Init *CachedBitVarRef =
nullptr;
522 Init *CachedBitVarResolved =
nullptr;
524 for (
unsigned i = 0, e =
getNumBits(); i != e; ++i) {
526 Init *NewBit = CurBit;
528 if (
VarBitInit *CurBitVar = dyn_cast<VarBitInit>(CurBit)) {
529 if (CurBitVar->getBitVar() != CachedBitVarRef) {
530 CachedBitVarRef = CurBitVar->getBitVar();
533 assert(CachedBitVarResolved &&
"Unresolved bitvar reference");
534 NewBit = CachedBitVarResolved->
getBit(CurBitVar->getBitNum());
540 if (isa<UnsetInit>(NewBit) && R.keepUnsetBits())
543 Changed |= CurBit != NewBit;
549 return const_cast<BitsInit *
>(
this);
560 return itostr(
Value);
565 return (NumBits >=
sizeof(
Value) * 8) ||
566 (
Value >> NumBits == 0) || (
Value >> (NumBits-1) == -1);
570 if (isa<IntRecTy>(Ty))
571 return const_cast<IntInit *
>(
this);
573 if (isa<BitRecTy>(Ty)) {
575 if (Val != 0 && Val != 1)
return nullptr;
579 if (
auto *BRT = dyn_cast<BitsRecTy>(Ty)) {
586 for (
unsigned i = 0; i != BRT->getNumBits(); ++i)
600 for (
unsigned i = 0, e = Bits.size(); i != e; ++i) {
619 return "anonymous_" + utostr(
Value);
623 auto *Old =
const_cast<Init *
>(
static_cast<const Init *
>(
this));
624 auto *New = R.resolve(Old);
625 New = New ? New : Old;
627 if (
auto *Anonymous = dyn_cast<AnonymousNameInit>(New))
628 return Anonymous->getNameInit();
636 auto &Entry = *InitMap.insert(std::make_pair(V,
nullptr)).first;
643 if (isa<StringRecTy>(Ty))
653 ID.AddPointer(EltTy);
669 cast<TypedInit>(
Range[0])->getType()->typeIsConvertibleTo(EltTy));
674 std::uninitialized_copy(
Range.begin(),
Range.end(),
675 I->getTrailingObjects<
Init *>());
681 RecTy *EltTy = cast<ListRecTy>(
getType())->getElementType();
690 if (
auto *LRT = dyn_cast<ListRecTy>(Ty)) {
696 bool Changed =
false;
697 RecTy *ElementType = LRT->getElementType();
699 if (
Init *CI =
I->convertInitializerTo(ElementType)) {
700 Elements.push_back(CI);
715 assert(i < NumValues &&
"List element index out of range!");
724 Resolved.reserve(
size());
725 bool Changed =
false;
729 Changed |= E != CurElt;
730 Resolved.push_back(E);
735 return const_cast<ListInit *
>(
this);
739 for (
Init *Element : *
this) {
747 for (
Init *Element : *
this) {
755 std::string Result =
"[";
756 const char *sep =
"";
757 for (
Init *Element : *
this) {
767 return const_cast<OpInit*
>(
this);
773 ID.AddInteger(Opcode);
802 if (
const auto *Def = dyn_cast<DefInit>(LHS)) {
805 OS << *Def->getDef();
819 if (
StringInit *LHSs = dyn_cast<StringInit>(LHS))
823 if (
StringInit *LHSs = dyn_cast<StringInit>(LHS))
827 if (isa<StringRecTy>(
getType())) {
828 if (
StringInit *LHSs = dyn_cast<StringInit>(LHS))
831 if (
DefInit *LHSd = dyn_cast<DefInit>(LHS))
834 if (
IntInit *LHSi = dyn_cast_or_null<IntInit>(
838 }
else if (isa<RecordRecTy>(
getType())) {
844 auto *Anonymous = dyn_cast<AnonymousNameInit>(CurRec->
getNameInit());
846 (Anonymous &&
Name == Anonymous->getNameInit())) {
853 auto PrintFatalErrorHelper = [CurRec](
const Twine &
T) {
862 PrintFatalErrorHelper(
Twine(
"Undefined reference to record: '") +
863 Name->getValue() +
"'\n");
870 PrintFatalErrorHelper(
Twine(
"Expected type '") +
884 if (
IntInit *LHSi = dyn_cast_or_null<IntInit>(
890 if (
ListInit *LHSl = dyn_cast<ListInit>(LHS)) {
891 assert(!LHSl->empty() &&
"Empty list in head");
892 return LHSl->getElement(0);
897 if (
ListInit *LHSl = dyn_cast<ListInit>(LHS)) {
898 assert(!LHSl->empty() &&
"Empty list in tail");
901 return ListInit::get(LHSl->getValues().slice(1), LHSl->getElementType());
906 if (
ListInit *LHSl = dyn_cast<ListInit>(LHS))
908 if (
DagInit *LHSd = dyn_cast<DagInit>(LHS))
910 if (
StringInit *LHSs = dyn_cast<StringInit>(LHS))
915 if (
ListInit *LHSl = dyn_cast<ListInit>(LHS))
917 if (
DagInit *LHSd = dyn_cast<DagInit>(LHS))
919 if (
StringInit *LHSs = dyn_cast<StringInit>(LHS))
924 if (
DagInit *Dag = dyn_cast<DagInit>(LHS)) {
927 auto *TI = cast<TypedInit>(Dag->getOperator());
928 if (!TI->getType()->typeIsA(
getType())) {
931 "', got '" + TI->getType()->getAsString() +
934 return Dag->getOperator();
940 if (
IntInit *LHSi = dyn_cast_or_null<IntInit>(
942 int64_t LHSv = LHSi->getValue();
945 "Illegal operation: logtwo is undefined "
946 "on arguments less than or equal to 0");
950 "Log of an int64_t must be smaller than INT64_MAX");
956 return const_cast<UnOpInit *
>(
this);
964 ->Fold(R.getCurrentRecord(), R.isFinal());
965 return const_cast<UnOpInit *
>(
this);
972 case NOT: Result =
"!not";
break;
973 case HEAD: Result =
"!head";
break;
974 case TAIL: Result =
"!tail";
break;
975 case SIZE: Result =
"!size";
break;
976 case EMPTY: Result =
"!empty";
break;
977 case GETDAGOP: Result =
"!getdagop";
break;
978 case LOG2 : Result =
"!logtwo";
break;
995 ID.AddInteger(Opcode);
1022 Concat.append(I1->getValue());
1030 if (
List->size() == 0)
1038 for (
unsigned I = 1, E =
List->size();
I < E; ++
I) {
1043 Result.append(Element->
getValue());
1052 if (
List->size() == 0)
1054 IntInit *Element = dyn_cast_or_null<IntInit>(
1060 for (
unsigned I = 1, E =
List->size();
I < E; ++
I) {
1062 IntInit *Element = dyn_cast_or_null<IntInit>(
1073 if (
const StringInit *I0s = dyn_cast<StringInit>(I0))
1074 if (
const StringInit *I1s = dyn_cast<StringInit>(I1))
1092 if (
const ListInit *LHSList = dyn_cast<ListInit>(
LHS))
1093 if (
const ListInit *RHSList = dyn_cast<ListInit>(
RHS))
1101 IntInit *LHSi = dyn_cast_or_null<IntInit>(
1103 IntInit *RHSi = dyn_cast_or_null<IntInit>(
1169 return (
Opc ==
EQ) ? LHSd == RHSd : LHSd != RHSd;
1172 return std::nullopt;
1176 std::string &
Error) {
1179 int64_t Pos =
Idx->getValue();
1183 (
Twine(
"index ") + std::to_string(Pos) +
Twine(
" is negative")).str();
1184 return std::nullopt;
1186 if (Pos >= Dag->getNumArgs()) {
1188 Error = (
Twine(
"index ") + std::to_string(Pos) +
1189 " is out of range (dag has " +
1190 std::to_string(Dag->getNumArgs()) +
" arguments)")
1192 return std::nullopt;
1196 assert(isa<StringInit>(Key));
1199 auto ArgNo = Dag->getArgNo(
Name->getValue());
1203 return std::nullopt;
1211 DagInit *LHSs = dyn_cast<DagInit>(LHS);
1212 DagInit *RHSs = dyn_cast<DagInit>(RHS);
1216 if ((!LOp && !isa<UnsetInit>(LHSs->
getOperator())) ||
1224 Init *
Op = LOp ? LOp : ROp;
1230 for (
unsigned i = 0, e = LHSs->
getNumArgs(); i != e; ++i) {
1231 Args.push_back(LHSs->
getArg(i));
1234 for (
unsigned i = 0, e = RHSs->
getNumArgs(); i != e; ++i) {
1235 Args.push_back(RHSs->
getArg(i));
1243 ListInit *LHSs = dyn_cast<ListInit>(LHS);
1244 ListInit *RHSs = dyn_cast<ListInit>(RHS);
1263 ListInit *LHSs = dyn_cast<ListInit>(LHS);
1264 ListInit *RHSs = dyn_cast<ListInit>(RHS);
1267 for (
Init *EltLHS : *LHSs) {
1269 for (
Init *EltRHS : *RHSs) {
1270 if (std::optional<bool> Result =
CompareInit(
EQ, EltLHS, EltRHS)) {
1278 Args.push_back(EltLHS);
1285 auto *TheList = dyn_cast<ListInit>(LHS);
1286 auto *
Idx = dyn_cast<IntInit>(RHS);
1287 if (!TheList || !
Idx)
1289 auto i =
Idx->getValue();
1290 if (i < 0 || i >= (ssize_t)TheList->size())
1292 return TheList->getElement(i);
1295 auto *TheList = dyn_cast<ListInit>(LHS);
1296 auto *SliceIdxs = dyn_cast<ListInit>(RHS);
1297 if (!TheList || !SliceIdxs)
1300 Args.reserve(SliceIdxs->size());
1301 for (
auto *
I : *SliceIdxs) {
1302 auto *
II = dyn_cast<IntInit>(
I);
1305 auto i =
II->getValue();
1306 if (i < 0 || i >= (ssize_t)TheList->size())
1308 Args.push_back(TheList->getElement(i));
1313 auto *LHSi = dyn_cast<IntInit>(LHS);
1314 auto *RHSi = dyn_cast<IntInit>(RHS);
1318 auto Start = LHSi->getValue();
1319 auto End = RHSi->getValue();
1325 Args.reserve(
End - Start + 1);
1326 for (
auto i = Start; i <=
End; ++i)
1330 Args.reserve(Start -
End + 1);
1331 for (
auto i = Start; i >=
End; --i)
1334 }
else if (Start <
End) {
1336 Args.reserve(
End - Start);
1337 for (
auto i = Start; i <
End; ++i)
1345 StringInit *LHSs = dyn_cast<StringInit>(LHS);
1346 StringInit *RHSs = dyn_cast<StringInit>(RHS);
1353 StringInit *Delim = dyn_cast<StringInit>(RHS);
1354 if (
List && Delim) {
1356 if (isa<StringRecTy>(
List->getElementType()))
1376 DagInit *Dag = dyn_cast<DagInit>(LHS);
1377 if (Dag && isa<IntInit, StringInit>(RHS)) {
1383 assert(*ArgNo < Dag->getNumArgs());
1385 Init *Arg = Dag->getArg(*ArgNo);
1386 if (
auto *TI = dyn_cast<TypedInit>(Arg))
1387 if (!TI->getType()->typeIsConvertibleTo(
getType()))
1394 DagInit *Dag = dyn_cast<DagInit>(LHS);
1397 int64_t Pos =
Idx->getValue();
1398 if (Pos < 0 || Pos >= Dag->getNumArgs()) {
1401 Twine(
"!getdagname index is out of range 0...") +
1402 std::to_string(Dag->getNumArgs() - 1) +
": " +
1403 std::to_string(Pos));
1405 Init *ArgName = Dag->getArgName(Pos);
1413 DagInit *Dag = dyn_cast<DagInit>(LHS);
1418 for (
unsigned i = 0, e = Dag->getNumArgs(); i != e; ++i) {
1419 Args.push_back(Dag->getArg(i));
1436 IntInit *LHSi = dyn_cast_or_null<IntInit>(
1438 IntInit *RHSi = dyn_cast_or_null<IntInit>(
1445 case ADD: Result = LHSv + RHSv;
break;
1446 case SUB: Result = LHSv - RHSv;
break;
1447 case MUL: Result = LHSv * RHSv;
break;
1451 "Illegal operation: division by zero");
1452 else if (LHSv ==
INT64_MIN && RHSv == -1)
1454 "Illegal operation: INT64_MIN / -1");
1456 Result = LHSv / RHSv;
1458 case AND: Result = LHSv & RHSv;
break;
1459 case OR: Result = LHSv | RHSv;
break;
1460 case XOR: Result = LHSv ^ RHSv;
break;
1462 case SRA: Result = LHSv >> RHSv;
break;
1478 if (LHS != lhs || RHS != rhs)
1480 ->Fold(R.getCurrentRecord());
1492 case CONCAT: Result =
"!con";
break;
1493 case ADD: Result =
"!add";
break;
1494 case SUB: Result =
"!sub";
break;
1495 case MUL: Result =
"!mul";
break;
1496 case DIV: Result =
"!div";
break;
1497 case AND: Result =
"!and";
break;
1498 case OR: Result =
"!or";
break;
1499 case XOR: Result =
"!xor";
break;
1500 case SHL: Result =
"!shl";
break;
1501 case SRA: Result =
"!sra";
break;
1502 case SRL: Result =
"!srl";
break;
1503 case EQ: Result =
"!eq";
break;
1504 case NE: Result =
"!ne";
break;
1505 case LE: Result =
"!le";
break;
1506 case LT: Result =
"!lt";
break;
1507 case GE: Result =
"!ge";
break;
1508 case GT: Result =
"!gt";
break;
1509 case LISTCONCAT: Result =
"!listconcat";
break;
1510 case LISTSPLAT: Result =
"!listsplat";
break;
1512 Result =
"!listremove";
1514 case STRCONCAT: Result =
"!strconcat";
break;
1515 case INTERLEAVE: Result =
"!interleave";
break;
1516 case SETDAGOP: Result =
"!setdagop";
break;
1521 Result =
"!getdagname";
1530 ID.AddInteger(Opcode);
1559 return RHS->resolveReferences(R);
1564 bool Change =
false;
1570 for (
unsigned int i = 0; i < MHSd->
getNumArgs(); ++i) {
1575 if (
DagInit *Argd = dyn_cast<DagInit>(Arg))
1580 NewArgs.
push_back(std::make_pair(NewArg, ArgName));
1593 if (
DagInit *MHSd = dyn_cast<DagInit>(MHS))
1596 if (
ListInit *MHSl = dyn_cast<ListInit>(MHS)) {
1599 for (
Init *&Item : NewList) {
1601 if (NewItem != Item)
1614 if (
ListInit *MHSl = dyn_cast<ListInit>(MHS)) {
1617 for (
Init *Item : MHSl->getValues()) {
1622 dyn_cast_or_null<IntInit>(
Include->convertInitializerTo(
1624 if (IncludeInt->getValue())
1640 DefInit *LHSd = dyn_cast<DefInit>(LHS);
1641 VarInit *LHSv = dyn_cast<VarInit>(LHS);
1642 StringInit *LHSs = dyn_cast<StringInit>(LHS);
1644 DefInit *MHSd = dyn_cast<DefInit>(MHS);
1645 VarInit *MHSv = dyn_cast<VarInit>(MHS);
1646 StringInit *MHSs = dyn_cast<StringInit>(MHS);
1648 DefInit *RHSd = dyn_cast<DefInit>(RHS);
1649 VarInit *RHSv = dyn_cast<VarInit>(RHS);
1650 StringInit *RHSs = dyn_cast<StringInit>(RHS);
1652 if (LHSd && MHSd && RHSd) {
1658 if (LHSv && MHSv && RHSv) {
1659 std::string Val = std::string(RHSv->
getName());
1661 Val = std::string(MHSv->
getName());
1664 if (LHSs && MHSs && RHSs) {
1665 std::string Val = std::string(RHSs->
getValue());
1667 std::string::size_type found;
1668 std::string::size_type idx = 0;
1670 found = Val.find(std::string(LHSs->
getValue()), idx);
1671 if (found == std::string::npos)
1696 if (
IntInit *LHSi = dyn_cast_or_null<IntInit>(
1698 if (LHSi->getValue())
1706 ListInit *MHSl = dyn_cast<ListInit>(MHS);
1707 ListInit *RHSl = dyn_cast<ListInit>(RHS);
1708 bool MHSok = MHSl || isa<UnsetInit>(MHS);
1709 bool RHSok = RHSl || isa<UnsetInit>(RHS);
1711 if (isa<UnsetInit>(MHS) && isa<UnsetInit>(RHS))
1714 if (MHSok && RHSok && (!MHSl || !RHSl || MHSl->
size() == RHSl->
size())) {
1717 for (
unsigned i = 0; i !=
Size; ++i) {
1720 if (!isa<StringInit>(
Name) && !isa<UnsetInit>(
Name))
1722 Children.emplace_back(
Node, dyn_cast<StringInit>(
Name));
1730 auto *LHSi = dyn_cast<IntInit>(LHS);
1731 auto *MHSi = dyn_cast<IntInit>(MHS);
1732 auto *RHSi = dyn_cast<IntInit>(RHS);
1733 if (!LHSi || !MHSi || !RHSi)
1736 auto Start = LHSi->getValue();
1737 auto End = MHSi->getValue();
1738 auto Step = RHSi->getValue();
1743 if (Start < End && Step > 0) {
1744 Args.reserve((
End - Start) / Step);
1745 for (
auto I = Start;
I <
End;
I += Step)
1747 }
else if (Start >
End && Step < 0) {
1748 Args.reserve((Start -
End) / -Step);
1749 for (
auto I = Start;
I >
End;
I += Step)
1758 StringInit *LHSs = dyn_cast<StringInit>(LHS);
1759 IntInit *MHSi = dyn_cast<IntInit>(MHS);
1760 IntInit *RHSi = dyn_cast<IntInit>(RHS);
1761 if (LHSs && MHSi && RHSi) {
1765 if (Start < 0 || Start > StringSize)
1767 Twine(
"!substr start position is out of range 0...") +
1768 std::to_string(StringSize) +
": " +
1769 std::to_string(Start));
1779 StringInit *LHSs = dyn_cast<StringInit>(LHS);
1780 StringInit *MHSs = dyn_cast<StringInit>(MHS);
1781 IntInit *RHSi = dyn_cast<IntInit>(RHS);
1782 if (LHSs && MHSs && RHSi) {
1785 if (Start < 0 || Start > SourceSize)
1787 Twine(
"!find start position is out of range 0...") +
1788 std::to_string(SourceSize) +
": " +
1789 std::to_string(Start));
1791 if (
I == std::string::npos)
1799 DagInit *Dag = dyn_cast<DagInit>(LHS);
1800 if (Dag && isa<IntInit, StringInit>(MHS)) {
1806 assert(*ArgNo < Dag->getNumArgs());
1811 return DagInit::get(Dag->getOperator(), Dag->getName(), Args, Names);
1817 DagInit *Dag = dyn_cast<DagInit>(LHS);
1818 if (Dag && isa<IntInit, StringInit>(MHS)) {
1824 assert(*ArgNo < Dag->getNumArgs());
1828 Names[*ArgNo] = dyn_cast<StringInit>(RHS);
1829 return DagInit::get(Dag->getOperator(), Dag->getName(), Args, Names);
1845 if (
Value->getValue())
1862 if (LHS != lhs || MHS != mhs || RHS != rhs)
1864 ->Fold(R.getCurrentRecord());
1870 bool UnquotedLHS =
false;
1872 case DAG: Result =
"!dag";
break;
1873 case FILTER: Result =
"!filter"; UnquotedLHS =
true;
break;
1874 case FOREACH: Result =
"!foreach"; UnquotedLHS =
true;
break;
1875 case IF: Result =
"!if";
break;
1879 case SUBST: Result =
"!subst";
break;
1880 case SUBSTR: Result =
"!substr";
break;
1881 case FIND: Result =
"!find";
break;
1883 Result =
"!setdagarg";
1886 Result =
"!setdagname";
1889 return (Result +
"(" +
1896 ID.AddPointer(Start);
1900 ID.AddPointer(Expr);
1924 if (
ListInit *LI = dyn_cast<ListInit>(List)) {
1925 Init *Accum = Start;
1926 for (
Init *Elt : *LI) {
1945 if (Start == NewStart && List == NewList && Expr ==
NewExpr)
1949 ->
Fold(R.getCurrentRecord());
1966 ID.AddPointer(Expr);
1989 if (
TypedInit *TI = dyn_cast<TypedInit>(Expr)) {
1991 if (TI->getType()->typeIsConvertibleTo(CheckType))
1994 if (isa<RecordRecTy>(CheckType)) {
2028 ID.AddPointer(Expr);
2063 auto *Anonymous = dyn_cast<AnonymousNameInit>(CurRec->
getNameInit());
2065 (Anonymous &&
Name == Anonymous->getNameInit())) {
2085 if (Expr !=
NewExpr || R.isFinal())
2086 return get(CheckType,
NewExpr)->
Fold(R.getCurrentRecord(), R.isFinal());
2104 return Field->getType();
2115 if (isa<BitRecTy>(
getType()) && isa<BitsRecTy>(Ty) &&
2116 cast<BitsRecTy>(Ty)->getNumBits() == 1)
2124 if (!
T)
return nullptr;
2125 unsigned NumBits =
T->getNumBits();
2129 for (
unsigned Bit : Bits) {
2144 assert(!isa<TypedInit>(Converted) ||
2145 cast<TypedInit>(Converted)->
getType()->typeIsA(Ty));
2149 if (!
getType()->typeIsConvertibleTo(Ty))
2176 return const_cast<VarInit*
>(
this);
2181 if (
Init *Val = R.resolve(VarName))
2183 return const_cast<VarInit *
>(
this);
2195 return TI->
getAsString() +
"{" + utostr(Bit) +
"}";
2210 return R->getDefInit();
2214 if (
auto *RRT = dyn_cast<RecordRecTy>(Ty))
2215 if (
getType()->typeIsConvertibleTo(RRT))
2216 return const_cast<DefInit *
>(
this);
2222 return RV->getType();
2230 ID.AddInteger(Args.size());
2231 ID.AddPointer(Class);
2233 for (
Init *
I : Args)
2237VarDefInit::VarDefInit(
Record *Class,
unsigned N)
2251 totalSizeToAlloc<ArgumentInit *>(Args.size()),
alignof(
VarDefInit));
2253 std::uninitialized_copy(Args.begin(), Args.end(),
2263DefInit *VarDefInit::instantiate() {
2267 std::make_unique<Record>(Records.getNewAnonymousName(), Class->
getLoc(),
2269 Record *NewRec = NewRecOwner.get();
2285 for (
Init *Arg : TArgs) {
2290 for (
auto *Arg :
args()) {
2291 if (Arg->isPositional())
2292 R.set(TArgs[Arg->getIndex()], Arg->getValue());
2294 R.set(Arg->getName(), Arg->getValue());
2301 for (
const auto &SCPair : SCs)
2306 Class->
getLoc().back()));
2310 Records.addDef(std::move(NewRecOwner));
2326 bool Changed =
false;
2331 auto *NewArg = cast<ArgumentInit>(Arg->resolveReferences(UR));
2333 Changed |= NewArg != Arg;
2339 return New->instantiate();
2351 Arg->resolveReferences(R);
2353 if (!R.foundUnresolved())
2354 return const_cast<VarDefInit *
>(
this)->instantiate();
2360 const char *sep =
"";
2364 Result += Arg->getAsString();
2366 return Result +
">";
2391 if (
DefInit *DI = dyn_cast<DefInit>(Rec)) {
2392 Record *Def = DI->getDef();
2395 Twine(
"Attempting to access field '") +
2397 Rec->
getAsString() +
"' is a forbidden self-reference");
2398 Init *FieldVal = Def->getValue(FieldName)->getValue();
2406 if (
DefInit *DI = dyn_cast<DefInit>(Rec)) {
2407 Init *FieldVal = DI->getDef()->getValue(FieldName)->getValue();
2416 const RecTy *ValType) {
2418 "Number of conditions and values must match!");
2419 ID.AddPointer(ValType);
2423 while (Case != CondRange.
end()) {
2424 ID.AddPointer(*Case++);
2425 ID.AddPointer(*Val++);
2431 ArrayRef(getTrailingObjects<Init *>() + NumConds, NumConds),
2438 "Number of conditions and values must match!");
2449 totalSizeToAlloc<Init *>(2 * CondRange.
size()),
alignof(
BitsInit));
2452 std::uninitialized_copy(CondRange.
begin(), CondRange.
end(),
2453 I->getTrailingObjects<
Init *>());
2454 std::uninitialized_copy(ValRange.
begin(), ValRange.
end(),
2455 I->getTrailingObjects<
Init *>()+CondRange.
size());
2462 bool Changed =
false;
2466 Changed |= NewCase != Case;
2473 Changed |= NewVal != Val;
2485 for (
unsigned i = 0; i < NumConds; ++i) {
2489 if (
IntInit *CondI = dyn_cast_or_null<IntInit>(
2491 if (CondI->getValue())
2500 " does not have any true condition in:" +
2501 this->getAsString());
2507 if (!Case->isConcrete())
2511 if (!Val->isConcrete())
2519 if (!Case->isComplete())
2523 if (!Val->isConcrete())
2530 std::string Result =
"!cond(";
2537 return Result +
")";
2552 while (Arg != ArgRange.
end()) {
2554 ID.AddPointer(*Arg++);
2572 totalSizeToAlloc<Init *, StringInit *>(ArgRange.
size(), NameRange.
size()),
2575 std::uninitialized_copy(ArgRange.
begin(), ArgRange.
end(),
2576 I->getTrailingObjects<
Init *>());
2577 std::uninitialized_copy(NameRange.
begin(), NameRange.
end(),
2589 for (
const auto &Arg :
args) {
2590 Args.push_back(Arg.first);
2599 ArrayRef(getTrailingObjects<Init *>(), NumArgs),
2600 ArrayRef(getTrailingObjects<StringInit *>(), NumArgNames));
2604 if (
DefInit *DefI = dyn_cast<DefInit>(Val))
2605 return DefI->getDef();
2611 for (
unsigned i = 0, e =
getNumArgs(); i < e; ++i) {
2616 return std::nullopt;
2622 bool ArgsChanged =
false;
2626 ArgsChanged |= NewArg != Arg;
2630 if (
Op != Val || ArgsChanged)
2633 return const_cast<DagInit *
>(
this);
2640 if (!Elt->isConcrete())
2653 for (
unsigned i = 1, e =
getNumArgs(); i != e; ++i) {
2658 return Result +
")";
2666 :
Name(
N), TyAndKind(
T, K) {
2668 assert(
Value &&
"Cannot create unset value for current type!");
2674 :
Name(
N), Loc(Loc), TyAndKind(
T, K) {
2676 assert(
Value &&
"Cannot create unset value for current type!");
2680 return cast<StringInit>(
getNameInit())->getValue();
2685 if (
auto *StrInit = dyn_cast<StringInit>(
Value)) {
2686 if (StrInit->hasCodeFormat())
2694 return TyAndKind.getPointer()->getAsString();
2705 if (!isa<BitsInit>(
Value)) {
2707 Bits.reserve(BTy->getNumBits());
2708 for (
unsigned I = 0, E = BTy->getNumBits();
I < E; ++
I)
2709 Bits.push_back(
Value->getBit(
I));
2714 return Value ==
nullptr;
2730 if (!isa<BitsInit>(
Value)) {
2732 Bits.reserve(BTy->getNumBits());
2733 for (
unsigned I = 0, E = BTy->getNumBits();
I < E; ++
I)
2734 Bits.push_back(
Value->getBit(
I));
2739 return Value ==
nullptr;
2745#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
2757 if (PrintSem)
OS <<
";\n";
2761 assert(Locs.size() == 1);
2762 ForwardDeclarationLocs.push_back(Locs.front());
2765 Locs.push_back(Loc);
2768void Record::checkName() {
2770 const TypedInit *TypedName = cast<const TypedInit>(Name);
2771 if (!isa<StringRecTy>(TypedName->
getType()))
2773 "' is not a string!");
2783 if (!CorrespondingDefInit) {
2784 CorrespondingDefInit =
2787 return CorrespondingDefInit;
2818 for (
int I = SCs.
size() - 1;
I >= 0; --
I) {
2819 const Record *SC = SCs[
I].first;
2820 if (SC == Superclass)
2822 I -= SC->getSuperClasses().size();
2831 while (!SCs.
empty()) {
2833 SCs = SCs.
drop_back(1 + SC->getSuperClasses().size());
2841 if (NewName != OldName) {
2848 if (SkipVal == &
Value)
2851 Init *VR = V->resolveReferences(R);
2852 if (
Value.setValue(VR)) {
2854 if (
TypedInit *VRT = dyn_cast<TypedInit>(VR))
2856 (
Twine(
"of type '") + VRT->getType()->getAsString() +
"' ").str();
2859 Twine(
"Invalid value ") +
Type +
"found when setting field '" +
2860 Value.getNameInitAsString() +
"' of type '" +
2869 for (
auto &Assertion : Assertions) {
2870 Init *
Value = Assertion.Condition->resolveReferences(R);
2871 Assertion.Condition =
Value;
2872 Value = Assertion.Message->resolveReferences(R);
2873 Assertion.Message =
Value;
2876 for (
auto &Dump : Dumps) {
2877 Init *
Value = Dump.Message->resolveReferences(R);
2878 Dump.Message =
Value;
2889#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
2894 OS << R.getNameInitAsString();
2897 if (!TArgs.
empty()) {
2899 bool NeedComma =
false;
2900 for (
const Init *TA : TArgs) {
2901 if (NeedComma)
OS <<
", ";
2904 assert(RV &&
"Template argument record not found??");
2914 for (
const auto &SuperPair : SC)
2915 OS <<
" " << SuperPair.first->getNameInitAsString();
2919 for (
const RecordVal &Val : R.getValues())
2920 if (Val.isNonconcreteOK() && !R.isTemplateArg(Val.getNameInit()))
2922 for (
const RecordVal &Val : R.getValues())
2923 if (!Val.isNonconcreteOK() && !R.isTemplateArg(Val.getNameInit()))
2933 "' does not have a field named `" + FieldName +
"'!\n");
2939 if (!R || !R->getValue())
2941 "' does not have a field named `" + FieldName +
"'!\n");
2942 return R->getValue();
2949 "' does not have a field named `" + FieldName +
"'!\n");
2953std::optional<StringRef>
2956 if (!R || !R->getValue())
2957 return std::nullopt;
2958 if (isa<UnsetInit>(R->getValue()))
2959 return std::nullopt;
2961 if (
StringInit *SI = dyn_cast<StringInit>(R->getValue()))
2962 return SI->getValue();
2965 "Record `" +
getName() +
"', ` field `" + FieldName +
2966 "' exists but does not have a string initializer!");
2971 if (!R || !R->getValue())
2973 "' does not have a field named `" + FieldName +
"'!\n");
2975 if (
BitsInit *BI = dyn_cast<BitsInit>(R->getValue()))
2978 "' exists but does not have a bits value");
2983 if (!R || !R->getValue())
2985 "' does not have a field named `" + FieldName +
"'!\n");
2987 if (
ListInit *LI = dyn_cast<ListInit>(R->getValue()))
2990 "' exists but does not have a list value");
2996 std::vector<Record*> Defs;
2998 if (
DefInit *DI = dyn_cast<DefInit>(
I))
2999 Defs.push_back(DI->getDef());
3002 FieldName +
"' list is not entirely DefInit!");
3009 if (!R || !R->getValue())
3011 "' does not have a field named `" + FieldName +
"'!\n");
3013 if (
IntInit *
II = dyn_cast<IntInit>(R->getValue()))
3014 return II->getValue();
3017 "' exists but does not have an int value: " +
3018 R->getValue()->getAsString());
3024 std::vector<int64_t> Ints;
3027 Ints.push_back(
II->getValue());
3030 Twine(
"Record `") +
getName() +
"', field `" + FieldName +
3031 "' exists but does not have a list of ints value: " +
3037std::vector<StringRef>
3040 std::vector<StringRef> Strings;
3043 Strings.push_back(SI->getValue());
3046 Twine(
"Record `") +
getName() +
"', field `" + FieldName +
3047 "' exists but does not have a list of strings value: " +
3055 if (!R || !R->getValue())
3057 "' does not have a field named `" + FieldName +
"'!\n");
3059 if (
DefInit *DI = dyn_cast<DefInit>(R->getValue()))
3060 return DI->getDef();
3062 FieldName +
"' does not have a def initializer!");
3067 if (!R || !R->getValue())
3069 "' does not have a field named `" + FieldName +
"'!\n");
3071 if (
DefInit *DI = dyn_cast<DefInit>(R->getValue()))
3072 return DI->getDef();
3073 if (isa<UnsetInit>(R->getValue()))
3076 FieldName +
"' does not have either a def initializer or '?'!");
3082 if (!R || !R->getValue())
3084 "' does not have a field named `" + FieldName +
"'!\n");
3086 if (
BitInit *BI = dyn_cast<BitInit>(R->getValue()))
3087 return BI->getValue();
3089 FieldName +
"' does not have a bit initializer!");
3094 if (!R || !R->getValue())
3096 "' does not have a field named `" + FieldName.
str() +
"'!\n");
3098 if (isa<UnsetInit>(R->getValue())) {
3103 if (
BitInit *BI = dyn_cast<BitInit>(R->getValue()))
3104 return BI->getValue();
3106 FieldName +
"' does not have a bit initializer!");
3111 if (!R || !R->getValue())
3113 "' does not have a field named `" + FieldName +
"'!\n");
3115 if (
DagInit *DI = dyn_cast<DagInit>(R->getValue()))
3118 FieldName +
"' does not have a dag initializer!");
3140 for (
const auto &Dump :
getDumps()) {
3141 Init *Message = Dump.Message->resolveReferences(R);
3157 : Impl(
std::make_unique<
detail::RecordKeeperImpl>(*this)) {}
3160#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
3165 OS <<
"------------- Classes -----------------\n";
3167 OS <<
"class " << *
C.second;
3169 OS <<
"------------- Defs -----------------\n";
3171 OS <<
"def " << *
D.second;
3186 if (LastTimer && LastTimer->
isRunning()) {
3190 BackendTimer =
false;
3194 LastTimer =
new Timer(
"",
Name, *TimingGroup);
3201 assert(LastTimer &&
"No phase timer was started");
3209 BackendTimer =
true;
3217 BackendTimer =
false;
3222std::vector<Record *>
3226 auto Pair = ClassRecordsMap.try_emplace(ClassName);
3230 return Pair.first->second;
3236 std::vector<Record *> Defs;
3238 assert(ClassNames.
size() > 0 &&
"At least one class must be passed.");
3239 for (
const auto &ClassName : ClassNames) {
3246 for (
const auto &OneDef :
getDefs()) {
3248 return OneDef.second->isSubClassOf(Class);
3250 Defs.push_back(OneDef.second.get());
3258std::vector<Record *>
3261 : std::vector<Record *>();
3265 auto It = Map.find(VarName);
3266 if (It == Map.end())
3269 Init *
I = It->second.V;
3271 if (!It->second.Resolved && Map.size() > 1) {
3275 I =
I->resolveReferences(*
this);
3276 Map[VarName] = {
I,
true};
3283 Init *Val = Cache.lookup(VarName);
3291 if (!isa<UnsetInit>(RV->getValue())) {
3292 Val = RV->getValue();
3293 Stack.push_back(VarName);
3298 Stack.push_back(VarName);
3303 Cache[VarName] = Val;
3312 if (
I && !FoundUnresolved) {
3317 I->resolveReferences(Sub);
3318 FoundUnresolved |= Sub.FoundUnresolved;
3323 FoundUnresolved =
true;
3329 if (VarName == VarNameToTrack)
This file defines the StringMap class.
This file defines the BumpPtrAllocator interface.
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
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
const SmallVectorImpl< MachineOperand > & Cond
static void ProfileVarDefInit(FoldingSetNodeID &ID, Record *Class, ArrayRef< ArgumentInit * > Args)
static bool canFitInBitfield(int64_t Value, unsigned NumBits)
static StringInit * interleaveIntList(const ListInit *List, const StringInit *Delim)
static void ProfileExistsOpInit(FoldingSetNodeID &ID, RecTy *CheckType, Init *Expr)
static std::optional< unsigned > getDagArgNoByKey(DagInit *Dag, Init *Key, std::string &Error)
static void ProfileBinOpInit(FoldingSetNodeID &ID, unsigned Opcode, Init *LHS, Init *RHS, RecTy *Type)
static void ProfileTernOpInit(FoldingSetNodeID &ID, unsigned Opcode, Init *LHS, Init *MHS, Init *RHS, RecTy *Type)
static StringInit * interleaveStringList(const ListInit *List, const StringInit *Delim)
static Init * ItemApply(Init *LHS, Init *MHSe, Init *RHS, Record *CurRec)
static void ProfileRecordRecTy(FoldingSetNodeID &ID, ArrayRef< Record * > Classes)
static StringInit * ConcatStringInits(const StringInit *I0, const StringInit *I1)
static void ProfileIsAOpInit(FoldingSetNodeID &ID, RecTy *CheckType, Init *Expr)
static RecordRecTy * resolveRecordTypes(RecordRecTy *T1, RecordRecTy *T2)
static void ProfileDagInit(FoldingSetNodeID &ID, Init *V, StringInit *VN, ArrayRef< Init * > ArgRange, ArrayRef< StringInit * > NameRange)
static Init * ForeachHelper(Init *LHS, Init *MHS, Init *RHS, RecTy *Type, Record *CurRec)
static Init * FilterHelper(Init *LHS, Init *MHS, Init *RHS, RecTy *Type, Record *CurRec)
static Init * ForeachDagApply(Init *LHS, DagInit *MHSd, Init *RHS, Record *CurRec)
static void ProfileCondOpInit(FoldingSetNodeID &ID, ArrayRef< Init * > CondRange, ArrayRef< Init * > ValRange, const RecTy *ValType)
static void ProfileBitsInit(FoldingSetNodeID &ID, ArrayRef< Init * > Range)
static void ProfileListInit(FoldingSetNodeID &ID, ArrayRef< Init * > Range, RecTy *EltTy)
static ListInit * ConcatListInits(const ListInit *LHS, const ListInit *RHS)
static void ProfileFoldOpInit(FoldingSetNodeID &ID, Init *Start, Init *List, Init *A, Init *B, Init *Expr, RecTy *Type)
static void ProfileArgumentInit(FoldingSetNodeID &ID, Init *Value, ArgAuxType Aux)
static void ProfileUnOpInit(FoldingSetNodeID &ID, unsigned Opcode, Init *Op, RecTy *Type)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static LLVM_ATTRIBUTE_ALWAYS_INLINE bool CheckType(MVT::SimpleValueType VT, SDValue N, const TargetLowering *TLI, const DataLayout &DL)
This file defines the SmallString class.
This file defines the SmallVector class.
static SymbolRef::Type getType(const Symbol *Sym)
static constexpr int Concat[]
"anonymous_n" - Represent an anonymous record name
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...
StringInit * getNameInit() const
static AnonymousNameInit * get(RecordKeeper &RK, unsigned)
std::string getAsString() const override
Convert this value to a literal form.
ArgumentInit * cloneWithValue(Init *Value) const
static ArgumentInit * get(Init *Value, ArgAuxType Aux)
void Profile(FoldingSetNodeID &ID) 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),...
const T & back() const
back - Get the last element.
size_t size() const
size - Get the array size.
ArrayRef< T > drop_back(size_t N=1) const
Drop the last N elements of the array.
bool empty() const
empty - Check if the array is empty.
!op (X, Y) - Combine two inits.
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
std::optional< bool > CompareInit(unsigned Opc, Init *LHS, Init *RHS) const
std::string getAsString() const override
Convert this value to a literal form.
BinaryOp getOpcode() const
Init * Fold(Record *CurRec) const
static Init * getStrConcat(Init *lhs, Init *rhs)
static Init * getListConcat(TypedInit *lhs, Init *rhs)
static BinOpInit * get(BinaryOp opc, Init *lhs, Init *rhs, RecTy *Type)
'true'/'false' - Represent a concrete initializer for a bit.
static BitInit * get(RecordKeeper &RK, bool V)
Init * convertInitializerTo(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 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
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.
Init * getBit(unsigned Bit) const override
Get the Init value of the specified bit.
unsigned getNumBits() const
Init * convertInitializerBitRange(ArrayRef< unsigned > Bits) const override
This function is used to implement the bit range selection operator.
Init * convertInitializerTo(RecTy *Ty) const override
Convert to a value whose type is Ty, or return null if this is not possible.
bool isConcrete() const override
Is this a concrete and fully resolved value without any references or stuck operations?...
static BitsInit * get(RecordKeeper &RK, ArrayRef< Init * > Range)
'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.
std::string getAsString() const override
static BitsRecTy * get(RecordKeeper &RK, unsigned Sz)
Allocate memory in an ever growing pool, as if by bump-pointer.
LLVM_ATTRIBUTE_RETURNS_NONNULL void * Allocate(size_t Size, Align Alignment)
Allocate space at the specified alignment.
!cond(condition_1: value1, ... , condition_n: value) Selects the first value for which condition is t...
Init * getCond(unsigned Num) const
ArrayRef< Init * > getVals() const
static CondOpInit * get(ArrayRef< Init * > C, ArrayRef< Init * > V, RecTy *Type)
ArrayRef< Init * > getConds() const
bool isConcrete() const override
Is this a concrete and fully resolved value without any references or stuck operations?...
void Profile(FoldingSetNodeID &ID) const
Init * getBit(unsigned Bit) const override
Get the Init value of the specified bit.
std::string getAsString() const override
Convert this value to a literal form.
Init * Fold(Record *CurRec) const
unsigned getNumConds() const
RecTy * getValType() const
Init * getVal(unsigned Num) 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 isComplete() const override
Is this a complete value with no unset (uninitialized) subvalues?
This class represents an Operation in the Expression.
(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?...
unsigned getNumArgs() const
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...
Init * getOperator() const
StringInit * getArgName(unsigned Num) const
Record * getOperatorAsDef(ArrayRef< SMLoc > Loc) const
ArrayRef< StringInit * > getArgNames() const
static DagInit * get(Init *V, StringInit *VN, ArrayRef< Init * > ArgRange, ArrayRef< StringInit * > NameRange)
void Profile(FoldingSetNodeID &ID) const
Init * getArg(unsigned Num) const
ArrayRef< Init * > getArgs() 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.
'dag' - Represent a dag fragment
std::string getAsString() const override
static DagRecTy * get(RecordKeeper &RK)
AL - Represent a reference to a 'def' in the description.
Init * convertInitializerTo(RecTy *Ty) const override
Convert to a value whose type is Ty, or return null if this is not possible.
std::string getAsString() const override
Convert this value to a literal form.
RecTy * getFieldType(StringInit *FieldName) const override
This method is used to implement the FieldInit class.
static DefInit * get(Record *)
Lightweight error class with error context and mandatory checking.
!exists<type>(expr) - Dynamically determine if a record of type named expr exists.
void Profile(FoldingSetNodeID &ID) const
Init * Fold(Record *CurRec, bool IsFinal=false) const
static ExistsOpInit * get(RecTy *CheckType, Init *Expr)
std::string getAsString() const override
Convert this value to a literal form.
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...
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.
Init * Fold(Record *CurRec) const
static FieldInit * get(Init *R, StringInit *FN)
Init * getBit(unsigned Bit) const override
Get the Init value of the specified bit.
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?...
!foldl (a, b, expr, start, lst) - Fold over a list.
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...
Init * getBit(unsigned Bit) const override
Get the Init value of the specified bit.
std::string getAsString() const override
Convert this value to a literal form.
Init * Fold(Record *CurRec) const
static FoldOpInit * get(Init *Start, Init *List, Init *A, Init *B, Init *Expr, RecTy *Type)
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...
Init * resolve(Init *VarName) override
Return the initializer for the given variable name (should normally be a StringInit),...
virtual Init * getBit(unsigned Bit) const =0
Get the Init value of the specified bit.
virtual 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?
RecordKeeper & getRecordKeeper() const
Get the record keeper that initialized this Init.
virtual Init * convertInitializerTo(RecTy *Ty) const =0
Convert to a value whose type is Ty, or return null if this is not possible.
'7' - Represent an initialization by a literal integer value.
Init * convertInitializerBitRange(ArrayRef< unsigned > Bits) const override
This function is used to implement the bit range selection operator.
static IntInit * get(RecordKeeper &RK, int64_t V)
Init * convertInitializerTo(RecTy *Ty) const override
Convert to a value whose type is Ty, or return null if this is not possible.
std::string getAsString() const override
Convert this value to a literal form.
'int' - Represent an integer value of no particular size
bool typeIsConvertibleTo(const RecTy *RHS) const override
Return true if all values of 'this' type can be converted to the specified type.
static IntRecTy * get(RecordKeeper &RK)
!isa<type>(expr) - Dynamically determine the type of an expression.
void Profile(FoldingSetNodeID &ID) const
static IsAOpInit * get(RecTy *CheckType, Init *Expr)
std::string getAsString() const override
Convert this value to a literal form.
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...
Init * getBit(unsigned Bit) const override
Get the Init value of the specified bit.
[AL, AH, CL] - Represent a list of defs
std::string getAsString() const override
Convert this value to a literal form.
bool isConcrete() const override
Is this a concrete and fully resolved value without any references or stuck operations?...
static ListInit * get(ArrayRef< Init * > Range, RecTy *EltTy)
RecTy * getElementType() const
Init * getElement(unsigned i) const
bool isComplete() const override
Is this a complete value with no unset (uninitialized) subvalues?
Init * convertInitializerTo(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
ArrayRef< Init * > getValues() const
Record * getElementAsRecord(unsigned i) 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...
'list<Ty>' - Represent a list of element values, all of which must be of the specified type.
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.
RecTy * getElementType() const
Resolve arbitrary mappings.
Init * resolve(Init *VarName) override
Return the initializer for the given variable name (should normally be a StringInit),...
Base class for operators.
Init * getBit(unsigned Bit) const override
Get the Init value of the specified bit.
RecordKeeper & getRecordKeeper() const
Return the RecordKeeper that uniqued this Type.
ListRecTy * getListTy()
Returns the type representing list<thistype>.
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.)
virtual std::string getAsString() const =0
void print(raw_ostream &OS) const
std::vector< Record * > getAllDerivedDefinitions(StringRef ClassName) const
Get all the concrete records that inherit from the one specified class.
Record * getDef(StringRef Name) const
Get the concrete record with the specified name.
const RecordMap & getClasses() const
Get the map of classes.
Record * getClass(StringRef Name) const
Get the class with the specified name.
std::vector< Record * > getAllDerivedDefinitionsIfDefined(StringRef ClassName) const
Get all the concrete records that inherit from specified class, if the class is defined.
const RecordMap & getDefs() const
Get the map of records (defs).
detail::RecordKeeperImpl & getImpl()
Return the internal implementation of the RecordKeeper.
void stopBackendTimer()
Stop timing the overall backend.
void stopTimer()
Stop timing a phase.
void startTimer(StringRef Name)
Start timing a phase. Automatically stops any previous phase timer.
Init * getNewAnonymousName()
GetNewAnonymousName - Generate a unique anonymous name that can be used as an identifier.
void startBackendTimer(StringRef Name)
Start timing the overall backend.
'[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.
void Profile(FoldingSetNodeID &ID) const
static RecordRecTy * get(RecordKeeper &RK, ArrayRef< Record * > Classes)
Get the record type with the given non-redundant list of superclasses.
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.
bool isSubClassOf(Record *Class) const
ArrayRef< Record * > getClasses() const
Resolve all variables from a record except for unset variables.
Init * resolve(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.
bool setValue(Init *V)
Set the value of the field from an Init.
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?
RecordKeeper & getRecordKeeper() const
Get the record keeper used to unique this value.
const SMLoc & getLoc() const
Get the source location of the point where the field was defined.
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.
RecTy * getType() const
Get the type of the field value as a RecTy.
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.
RecordVal(Init *N, RecTy *T, FieldKind K)
Init * getValue() const
Get the value of the field as an Init.
std::vector< int64_t > getValueAsListOfInts(StringRef FieldName) const
This method looks up the specified field and returns its value as a vector of integers,...
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
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< AssertionInfo > getAssertions() const
std::string getNameInitAsString() const
Init * getNameInit() 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 getDirectSuperClasses(SmallVectorImpl< Record * > &Classes) const
Append the direct superclasses of this record to Classes.
RecordKeeper & getRecords() const
BitsInit * getValueAsBitsInit(StringRef FieldName) const
This method looks up the specified field and returns its value as a BitsInit, throwing an exception i...
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
Record * getValueAsDef(StringRef FieldName) const
This method looks up the specified field and returns its value as a Record, throwing an exception if ...
void addValue(const RecordVal &RV)
DagInit * getValueAsDag(StringRef FieldName) const
This method looks up the specified field and returns its value as an Dag, throwing an exception if th...
bool hasDirectSuperClass(const Record *SuperClass) const
Determine whether this record has the specified direct superclass.
StringRef getName() const
void appendDumps(const Record *Rec)
ArrayRef< Init * > getTemplateArgs() const
bool isSubClassOf(const Record *R) 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...
ArrayRef< RecordVal > getValues() const
SMLoc getFieldLoc(StringRef FieldName) const
Return the source location for the named field.
std::vector< Record * > getValueAsListOfDefs(StringRef FieldName) const
This method looks up the specified field and returns its value as a vector of records,...
void addSuperClass(Record *R, SMRange Range)
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 ...
DefInit * getDefInit()
get the corresponding DefInit.
void updateClassLoc(SMLoc Loc)
void resolveReferences(Init *NewName=nullptr)
If there are any field references that refer to fields that have been filled in, we can propagate the...
void appendAssertions(const Record *Rec)
ArrayRef< std::pair< Record *, SMRange > > getSuperClasses() 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 removeValue(Init *Name)
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.
Record * getCurrentRecord() const
virtual Init * resolve(Init *VarName)=0
Return the initializer for the given variable name (should normally be a StringInit),...
Represents a location in source code.
Represents a range in source code.
Delegate resolving to a sub-resolver, but shadow some variable names.
void addShadow(Init *Key)
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
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.
StringFormat getFormat() const
Init * convertInitializerTo(RecTy *Ty) const override
Convert to a value whose type is Ty, or return null if this is not possible.
StringRef getValue() const
static StringFormat determineFormat(StringFormat Fmt1, StringFormat Fmt2)
static StringInit * get(RecordKeeper &RK, StringRef, StringFormat Fmt=SF_String)
std::string getAsUnquotedString() const override
Convert this value to a literal form, without adding quotes around a string.
StringMap - This is an unconventional map that is specialized for handling keys that are "strings",...
'string' - Represent an string value
static StringRecTy * get(RecordKeeper &RK)
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.
StringRef - Represent a constant reference to a string, i.e.
std::string str() const
str - Get the contents as an std::string.
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
constexpr size_t size() const
size - Get the string size.
size_t find(char C, size_t From=0) const
Search for the first character C in the string.
!op (X, Y, Z) - Combine two inits.
Init * Fold(Record *CurRec) const
void Profile(FoldingSetNodeID &ID) const
std::string getAsString() const override
Convert this value to a literal form.
TernaryOp getOpcode() 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 TernOpInit * get(TernaryOp opc, Init *lhs, Init *mhs, Init *rhs, RecTy *Type)
This class is used to track the amount of time spent between invocations of its startTimer()/stopTime...
bool isRunning() const
Check if the timer is currently running.
void stopTimer()
Stop the timer.
void clear()
Clear the timer state.
void startTimer()
Start the timer running.
(Optionally) delegate resolving to a sub-resolver, and keep track whether there were unresolved refer...
bool foundUnresolved() const
Init * resolve(Init *VarName) override
Return the initializer for the given variable name (should normally be a StringInit),...
const T * getTrailingObjects() const
Returns a pointer to the trailing object array of the given type (which must be one of those specifie...
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.
Init * getCastTo(RecTy *Ty) const override
If this value is convertible to type Ty, return a value whose type is Ty, generating a !...
RecTy * getFieldType(StringInit *FieldName) const override
This method is used to implement the FieldInit class.
RecordKeeper & getRecordKeeper() const
Get the record keeper that initialized this Init.
Init * convertInitializerTo(RecTy *Ty) const override
Convert to a value whose type is Ty, or return null if this is not possible.
RecTy * getType() const
Get the type of the Init as a RecTy.
Init * convertInitializerBitRange(ArrayRef< unsigned > Bits) const override
This function is used to implement the bit range selection operator.
!op (X) - Transform an init.
Init * getOperand() const
Init * Fold(Record *CurRec, bool IsFinal=false) const
UnaryOp getOpcode() 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
static UnOpInit * get(UnaryOp opc, Init *lhs, RecTy *Type)
std::string getAsString() const override
Convert this value to a literal form.
'?' - Represents an uninitialized value.
Init * getCastTo(RecTy *Ty) const override
If this value is convertible to type Ty, return a value whose type is Ty, generating a !...
static UnsetInit * get(RecordKeeper &RK)
Get the singleton unset Init.
Init * convertInitializerTo(RecTy *Ty) const override
Convert to a value whose type is Ty, or return null if this is not possible.
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.
unsigned getBitNum() const
std::string getAsString() const override
Convert this value to a literal form.
static VarBitInit * get(TypedInit *T, unsigned B)
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...
classname<targs...> - Represent an uninstantiated anonymous class instantiation.
static VarDefInit * get(Record *Class, ArrayRef< ArgumentInit * > Args)
ArrayRef< 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...
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.
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...
Init * getNameInit() const
StringRef getName() const
std::string getAsString() const override
Convert this value to a literal form.
Init * getBit(unsigned Bit) const override
Get the Init value of the specified bit.
static VarInit * get(StringRef VN, RecTy *T)
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.
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.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
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.
unsigned Log2_64(uint64_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
std::variant< unsigned, Init * > ArgAuxType
void PrintWarning(const Twine &Msg)
RecTy * resolveTypes(RecTy *T1, RecTy *T2)
Find a common type that T1 and T2 convert to.
void CheckAssert(SMLoc Loc, Init *Condition, Init *Message)
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
void sort(IteratorTy Start, IteratorTy End)
void dumpMessage(SMLoc Loc, Init *Message)
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
raw_ostream & operator<<(raw_ostream &OS, const APFixedPoint &FX)
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Implement std::hash so that hash_code can be used in STL containers.
Helper object to track which of three possible relocation mechanisms are used for a particular value ...
Sorting predicate to sort record pointers by name.
This class represents the internal implementation of the RecordKeeper.
FoldingSet< BitsInit > TheBitsInitPool
DenseMap< std::pair< RecTy *, Init * >, VarInit * > TheVarInitPool
StringMap< StringInit *, BumpPtrAllocator & > StringInitCodePool
std::map< int64_t, IntInit * > TheIntInitPool
FoldingSet< FoldOpInit > TheFoldOpInitPool
FoldingSet< IsAOpInit > TheIsAOpInitPool
FoldingSet< DagInit > TheDagInitPool
FoldingSet< CondOpInit > TheCondOpInitPool
FoldingSet< BinOpInit > TheBinOpInitPool
FoldingSet< ArgumentInit > TheArgumentInitPool
StringRecTy SharedStringRecTy
FoldingSet< RecordRecTy > RecordTypePool
FoldingSet< VarDefInit > TheVarDefInitPool
DenseMap< std::pair< TypedInit *, unsigned >, VarBitInit * > TheVarBitInitPool
std::vector< BitsRecTy * > SharedBitsRecTys
FoldingSet< UnOpInit > TheUnOpInitPool
StringMap< StringInit *, BumpPtrAllocator & > StringInitStringPool
FoldingSet< TernOpInit > TheTernOpInitPool
BumpPtrAllocator Allocator
FoldingSet< ExistsOpInit > TheExistsOpInitPool
FoldingSet< ListInit > TheListInitPool
RecordKeeperImpl(RecordKeeper &RK)
DenseMap< std::pair< Init *, StringInit * >, FieldInit * > TheFieldInitPool