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())
215 UnsortedClasses.
end());
217 return LHS->getNameInitAsString() <
RHS->getNameInitAsString();
229 for (
unsigned i = 0; i < Classes.
size(); ++i) {
230 for (
unsigned j = 0; j < Classes.
size(); ++j) {
233 assert(&Classes[0]->getRecords() == &Classes[i]->getRecords());
240 std::uninitialized_copy(Classes.
begin(), Classes.
end(),
246 assert(Class &&
"unexpected null class");
247 return get(Class->getRecords(), Class);
256 return getClasses()[0]->getNameInitAsString();
258 std::string Str =
"{";
264 Str += R->getNameInitAsString();
272 return MySuperClass == Class ||
286 return isSubClassOf(TargetClass);
298 while (!Stack.empty()) {
299 Record *R = Stack.pop_back_val();
304 R->getDirectSuperClasses(Stack);
316 if (
RecordRecTy *RecTy2 = dyn_cast<RecordRecTy>(T2))
320 assert(
T1 !=
nullptr &&
"Invalid record type");
321 if (
T1->typeIsConvertibleTo(T2))
324 assert(T2 !=
nullptr &&
"Invalid record type");
328 if (
ListRecTy *ListTy1 = dyn_cast<ListRecTy>(
T1)) {
329 if (
ListRecTy *ListTy2 = dyn_cast<ListRecTy>(T2)) {
331 ListTy2->getElementType());
344void Init::anchor() {}
346#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
351 if (
auto *TyInit = dyn_cast<TypedInit>(
this))
352 return TyInit->getType()->getRecordKeeper();
353 if (
auto *ArgInit = dyn_cast<ArgumentInit>(
this))
354 return ArgInit->getRecordKeeper();
355 return cast<UnsetInit>(
this)->getRecordKeeper();
372 auto I = Aux.index();
375 ID.AddInteger(std::get<ArgumentInit::Positional>(Aux));
377 ID.AddPointer(std::get<ArgumentInit::Named>(Aux));
401 Init *NewValue =
Value->resolveReferences(R);
402 if (NewValue !=
Value)
413 if (isa<BitRecTy>(Ty))
414 return const_cast<BitInit *
>(
this);
416 if (isa<IntRecTy>(Ty))
419 if (
auto *BRT = dyn_cast<BitsRecTy>(Ty)) {
421 if (BRT->getNumBits() == 1)
430 ID.AddInteger(Range.size());
432 for (
Init *
I : Range)
448 std::uninitialized_copy(Range.begin(), Range.end(),
449 I->getTrailingObjects<
Init *>());
459 if (isa<BitRecTy>(Ty)) {
464 if (
auto *BRT = dyn_cast<BitsRecTy>(Ty)) {
467 if (
getNumBits() != BRT->getNumBits())
return nullptr;
468 return const_cast<BitsInit *
>(
this);
471 if (isa<IntRecTy>(Ty)) {
473 for (
unsigned i = 0, e =
getNumBits(); i != e; ++i)
474 if (
auto *Bit = dyn_cast<BitInit>(
getBit(i)))
475 Result |=
static_cast<int64_t
>(Bit->getValue()) << i;
488 for (
unsigned i = 0, e = Bits.size(); i != e; ++i) {
491 NewBits[i] =
getBit(Bits[i]);
497 for (
unsigned i = 0, e =
getNumBits(); i != e; ++i) {
505 std::string Result =
"{ ";
506 for (
unsigned i = 0, e =
getNumBits(); i != e; ++i) {
507 if (i) Result +=
", ";
509 Result += Bit->getAsString();
513 return Result +
" }";
519 bool Changed =
false;
522 Init *CachedBitVarRef =
nullptr;
523 Init *CachedBitVarResolved =
nullptr;
525 for (
unsigned i = 0, e =
getNumBits(); i != e; ++i) {
527 Init *NewBit = CurBit;
529 if (
VarBitInit *CurBitVar = dyn_cast<VarBitInit>(CurBit)) {
530 if (CurBitVar->getBitVar() != CachedBitVarRef) {
531 CachedBitVarRef = CurBitVar->getBitVar();
534 assert(CachedBitVarResolved &&
"Unresolved bitvar reference");
535 NewBit = CachedBitVarResolved->
getBit(CurBitVar->getBitNum());
541 if (isa<UnsetInit>(NewBit) && R.keepUnsetBits())
544 Changed |= CurBit != NewBit;
550 return const_cast<BitsInit *
>(
this);
561 return itostr(
Value);
566 return (NumBits >=
sizeof(
Value) * 8) ||
567 (
Value >> NumBits == 0) || (
Value >> (NumBits-1) == -1);
571 if (isa<IntRecTy>(Ty))
572 return const_cast<IntInit *
>(
this);
574 if (isa<BitRecTy>(Ty)) {
576 if (Val != 0 && Val != 1)
return nullptr;
580 if (
auto *BRT = dyn_cast<BitsRecTy>(Ty)) {
587 for (
unsigned i = 0; i != BRT->getNumBits(); ++i)
601 for (
unsigned i = 0, e = Bits.size(); i != e; ++i) {
620 return "anonymous_" + utostr(
Value);
624 auto *Old =
const_cast<Init *
>(
static_cast<const Init *
>(
this));
625 auto *New = R.resolve(Old);
626 New = New ? New : Old;
628 if (
auto *Anonymous = dyn_cast<AnonymousNameInit>(New))
629 return Anonymous->getNameInit();
637 auto &Entry = *InitMap.insert(std::make_pair(V,
nullptr)).first;
644 if (isa<StringRecTy>(Ty))
653 ID.AddInteger(Range.size());
654 ID.AddPointer(EltTy);
656 for (
Init *
I : Range)
669 assert(Range.empty() || !isa<TypedInit>(Range[0]) ||
670 cast<TypedInit>(Range[0])->getType()->typeIsConvertibleTo(EltTy));
675 std::uninitialized_copy(Range.begin(), Range.end(),
676 I->getTrailingObjects<
Init *>());
682 RecTy *EltTy = cast<ListRecTy>(
getType())->getElementType();
691 if (
auto *LRT = dyn_cast<ListRecTy>(Ty)) {
697 bool Changed =
false;
698 RecTy *ElementType = LRT->getElementType();
700 if (
Init *CI =
I->convertInitializerTo(ElementType)) {
701 Elements.push_back(CI);
716 assert(i < NumValues &&
"List element index out of range!");
725 Resolved.reserve(
size());
726 bool Changed =
false;
729 Init *
E = CurElt->resolveReferences(R);
730 Changed |=
E != CurElt;
731 Resolved.push_back(
E);
736 return const_cast<ListInit *
>(
this);
740 for (
Init *Element : *
this) {
748 for (
Init *Element : *
this) {
756 std::string Result =
"[";
757 const char *sep =
"";
758 for (
Init *Element : *
this) {
768 return const_cast<OpInit*
>(
this);
774 ID.AddInteger(Opcode);
803 if (
const auto *Def = dyn_cast<DefInit>(LHS)) {
806 OS << *Def->getDef();
820 if (
StringInit *LHSs = dyn_cast<StringInit>(LHS))
824 if (
StringInit *LHSs = dyn_cast<StringInit>(LHS))
828 if (isa<StringRecTy>(
getType())) {
829 if (
StringInit *LHSs = dyn_cast<StringInit>(LHS))
832 if (
DefInit *LHSd = dyn_cast<DefInit>(LHS))
835 if (
IntInit *LHSi = dyn_cast_or_null<IntInit>(
839 }
else if (isa<RecordRecTy>(
getType())) {
845 auto *Anonymous = dyn_cast<AnonymousNameInit>(CurRec->
getNameInit());
847 (Anonymous &&
Name == Anonymous->getNameInit())) {
854 auto PrintFatalErrorHelper = [CurRec](
const Twine &
T) {
863 PrintFatalErrorHelper(
Twine(
"Undefined reference to record: '") +
864 Name->getValue() +
"'\n");
871 PrintFatalErrorHelper(
Twine(
"Expected type '") +
885 if (
IntInit *LHSi = dyn_cast_or_null<IntInit>(
891 if (
ListInit *LHSl = dyn_cast<ListInit>(LHS)) {
892 assert(!LHSl->empty() &&
"Empty list in head");
893 return LHSl->getElement(0);
898 if (
ListInit *LHSl = dyn_cast<ListInit>(LHS)) {
899 assert(!LHSl->empty() &&
"Empty list in tail");
902 return ListInit::get(LHSl->getValues().slice(1), LHSl->getElementType());
907 if (
ListInit *LHSl = dyn_cast<ListInit>(LHS))
909 if (
DagInit *LHSd = dyn_cast<DagInit>(LHS))
911 if (
StringInit *LHSs = dyn_cast<StringInit>(LHS))
916 if (
ListInit *LHSl = dyn_cast<ListInit>(LHS))
918 if (
DagInit *LHSd = dyn_cast<DagInit>(LHS))
920 if (
StringInit *LHSs = dyn_cast<StringInit>(LHS))
925 if (
DagInit *Dag = dyn_cast<DagInit>(LHS)) {
928 auto *TI = cast<TypedInit>(Dag->getOperator());
929 if (!TI->getType()->typeIsA(
getType())) {
932 "', got '" + TI->getType()->getAsString() +
935 return Dag->getOperator();
941 if (
IntInit *LHSi = dyn_cast_or_null<IntInit>(
943 int64_t LHSv = LHSi->getValue();
946 "Illegal operation: logtwo is undefined "
947 "on arguments less than or equal to 0");
951 "Log of an int64_t must be smaller than INT64_MAX");
957 return const_cast<UnOpInit *
>(
this);
965 ->Fold(R.getCurrentRecord(), R.isFinal());
966 return const_cast<UnOpInit *
>(
this);
973 case NOT: Result =
"!not";
break;
974 case HEAD: Result =
"!head";
break;
975 case TAIL: Result =
"!tail";
break;
976 case SIZE: Result =
"!size";
break;
977 case EMPTY: Result =
"!empty";
break;
978 case GETDAGOP: Result =
"!getdagop";
break;
979 case LOG2 : Result =
"!logtwo";
break;
996 ID.AddInteger(Opcode);
1023 Concat.append(I1->getValue());
1031 if (
List->size() == 0)
1039 for (
unsigned I = 1,
E =
List->size();
I <
E; ++
I) {
1044 Result.append(Element->
getValue());
1053 if (
List->size() == 0)
1055 IntInit *Element = dyn_cast_or_null<IntInit>(
1061 for (
unsigned I = 1,
E =
List->size();
I <
E; ++
I) {
1063 IntInit *Element = dyn_cast_or_null<IntInit>(
1074 if (
const StringInit *I0s = dyn_cast<StringInit>(I0))
1075 if (
const StringInit *I1s = dyn_cast<StringInit>(I1))
1093 if (
const ListInit *LHSList = dyn_cast<ListInit>(
LHS))
1094 if (
const ListInit *RHSList = dyn_cast<ListInit>(
RHS))
1102 IntInit *LHSi = dyn_cast_or_null<IntInit>(
1104 IntInit *RHSi = dyn_cast_or_null<IntInit>(
1170 return (
Opc ==
EQ) ? LHSd == RHSd : LHSd != RHSd;
1173 return std::nullopt;
1177 std::string &
Error) {
1180 int64_t Pos =
Idx->getValue();
1184 (
Twine(
"index ") + std::to_string(Pos) +
Twine(
" is negative")).str();
1185 return std::nullopt;
1187 if (Pos >= Dag->getNumArgs()) {
1189 Error = (
Twine(
"index ") + std::to_string(Pos) +
1190 " is out of range (dag has " +
1191 std::to_string(Dag->getNumArgs()) +
" arguments)")
1193 return std::nullopt;
1197 assert(isa<StringInit>(Key));
1200 auto ArgNo = Dag->getArgNo(
Name->getValue());
1204 return std::nullopt;
1212 DagInit *LHSs = dyn_cast<DagInit>(LHS);
1213 DagInit *RHSs = dyn_cast<DagInit>(RHS);
1217 if ((!LOp && !isa<UnsetInit>(LHSs->
getOperator())) ||
1225 Init *
Op = LOp ? LOp : ROp;
1231 for (
unsigned i = 0, e = LHSs->
getNumArgs(); i != e; ++i) {
1232 Args.push_back(LHSs->
getArg(i));
1235 for (
unsigned i = 0, e = RHSs->
getNumArgs(); i != e; ++i) {
1236 Args.push_back(RHSs->
getArg(i));
1244 ListInit *LHSs = dyn_cast<ListInit>(LHS);
1245 ListInit *RHSs = dyn_cast<ListInit>(RHS);
1264 ListInit *LHSs = dyn_cast<ListInit>(LHS);
1265 ListInit *RHSs = dyn_cast<ListInit>(RHS);
1268 for (
Init *EltLHS : *LHSs) {
1270 for (
Init *EltRHS : *RHSs) {
1271 if (std::optional<bool> Result =
CompareInit(
EQ, EltLHS, EltRHS)) {
1279 Args.push_back(EltLHS);
1286 auto *TheList = dyn_cast<ListInit>(LHS);
1287 auto *
Idx = dyn_cast<IntInit>(RHS);
1288 if (!TheList || !
Idx)
1290 auto i =
Idx->getValue();
1291 if (i < 0 || i >= (ssize_t)TheList->size())
1293 return TheList->getElement(i);
1296 auto *TheList = dyn_cast<ListInit>(LHS);
1297 auto *SliceIdxs = dyn_cast<ListInit>(RHS);
1298 if (!TheList || !SliceIdxs)
1301 Args.reserve(SliceIdxs->size());
1302 for (
auto *
I : *SliceIdxs) {
1303 auto *II = dyn_cast<IntInit>(
I);
1306 auto i = II->getValue();
1307 if (i < 0 || i >= (ssize_t)TheList->size())
1309 Args.push_back(TheList->getElement(i));
1314 auto *LHSi = dyn_cast<IntInit>(LHS);
1315 auto *RHSi = dyn_cast<IntInit>(RHS);
1319 auto Start = LHSi->getValue();
1320 auto End = RHSi->getValue();
1326 Args.reserve(
End - Start + 1);
1327 for (
auto i = Start; i <=
End; ++i)
1331 Args.reserve(Start -
End + 1);
1332 for (
auto i = Start; i >=
End; --i)
1335 }
else if (Start <
End) {
1337 Args.reserve(
End - Start);
1338 for (
auto i = Start; i <
End; ++i)
1346 StringInit *LHSs = dyn_cast<StringInit>(LHS);
1347 StringInit *RHSs = dyn_cast<StringInit>(RHS);
1354 StringInit *Delim = dyn_cast<StringInit>(RHS);
1355 if (
List && Delim) {
1357 if (isa<StringRecTy>(
List->getElementType()))
1377 DagInit *Dag = dyn_cast<DagInit>(LHS);
1378 if (Dag && isa<IntInit, StringInit>(RHS)) {
1384 assert(*ArgNo < Dag->getNumArgs());
1386 Init *Arg = Dag->getArg(*ArgNo);
1387 if (
auto *TI = dyn_cast<TypedInit>(Arg))
1388 if (!TI->getType()->typeIsConvertibleTo(
getType()))
1395 DagInit *Dag = dyn_cast<DagInit>(LHS);
1398 int64_t Pos =
Idx->getValue();
1399 if (Pos < 0 || Pos >= Dag->getNumArgs()) {
1402 Twine(
"!getdagname index is out of range 0...") +
1403 std::to_string(Dag->getNumArgs() - 1) +
": " +
1404 std::to_string(Pos));
1406 Init *ArgName = Dag->getArgName(Pos);
1414 DagInit *Dag = dyn_cast<DagInit>(LHS);
1419 for (
unsigned i = 0, e = Dag->getNumArgs(); i != e; ++i) {
1420 Args.push_back(Dag->getArg(i));
1437 IntInit *LHSi = dyn_cast_or_null<IntInit>(
1439 IntInit *RHSi = dyn_cast_or_null<IntInit>(
1446 case ADD: Result = LHSv + RHSv;
break;
1447 case SUB: Result = LHSv - RHSv;
break;
1448 case MUL: Result = LHSv * RHSv;
break;
1452 "Illegal operation: division by zero");
1453 else if (LHSv ==
INT64_MIN && RHSv == -1)
1455 "Illegal operation: INT64_MIN / -1");
1457 Result = LHSv / RHSv;
1459 case AND: Result = LHSv & RHSv;
break;
1460 case OR: Result = LHSv | RHSv;
break;
1461 case XOR: Result = LHSv ^ RHSv;
break;
1463 case SRA: Result = LHSv >> RHSv;
break;
1479 if (LHS != lhs || RHS != rhs)
1481 ->Fold(R.getCurrentRecord());
1493 case CONCAT: Result =
"!con";
break;
1494 case ADD: Result =
"!add";
break;
1495 case SUB: Result =
"!sub";
break;
1496 case MUL: Result =
"!mul";
break;
1497 case DIV: Result =
"!div";
break;
1498 case AND: Result =
"!and";
break;
1499 case OR: Result =
"!or";
break;
1500 case XOR: Result =
"!xor";
break;
1501 case SHL: Result =
"!shl";
break;
1502 case SRA: Result =
"!sra";
break;
1503 case SRL: Result =
"!srl";
break;
1504 case EQ: Result =
"!eq";
break;
1505 case NE: Result =
"!ne";
break;
1506 case LE: Result =
"!le";
break;
1507 case LT: Result =
"!lt";
break;
1508 case GE: Result =
"!ge";
break;
1509 case GT: Result =
"!gt";
break;
1510 case LISTCONCAT: Result =
"!listconcat";
break;
1511 case LISTSPLAT: Result =
"!listsplat";
break;
1513 Result =
"!listremove";
1515 case STRCONCAT: Result =
"!strconcat";
break;
1516 case INTERLEAVE: Result =
"!interleave";
break;
1517 case SETDAGOP: Result =
"!setdagop";
break;
1522 Result =
"!getdagname";
1531 ID.AddInteger(Opcode);
1560 return RHS->resolveReferences(R);
1565 bool Change =
false;
1571 for (
unsigned int i = 0; i < MHSd->
getNumArgs(); ++i) {
1576 if (
DagInit *Argd = dyn_cast<DagInit>(Arg))
1581 NewArgs.
push_back(std::make_pair(NewArg, ArgName));
1594 if (
DagInit *MHSd = dyn_cast<DagInit>(MHS))
1597 if (
ListInit *MHSl = dyn_cast<ListInit>(MHS)) {
1600 for (
Init *&Item : NewList) {
1602 if (NewItem != Item)
1615 if (
ListInit *MHSl = dyn_cast<ListInit>(MHS)) {
1618 for (
Init *Item : MHSl->getValues()) {
1623 dyn_cast_or_null<IntInit>(
Include->convertInitializerTo(
1625 if (IncludeInt->getValue())
1641 DefInit *LHSd = dyn_cast<DefInit>(LHS);
1642 VarInit *LHSv = dyn_cast<VarInit>(LHS);
1643 StringInit *LHSs = dyn_cast<StringInit>(LHS);
1645 DefInit *MHSd = dyn_cast<DefInit>(MHS);
1646 VarInit *MHSv = dyn_cast<VarInit>(MHS);
1647 StringInit *MHSs = dyn_cast<StringInit>(MHS);
1649 DefInit *RHSd = dyn_cast<DefInit>(RHS);
1650 VarInit *RHSv = dyn_cast<VarInit>(RHS);
1651 StringInit *RHSs = dyn_cast<StringInit>(RHS);
1653 if (LHSd && MHSd && RHSd) {
1659 if (LHSv && MHSv && RHSv) {
1660 std::string Val = std::string(RHSv->
getName());
1662 Val = std::string(MHSv->
getName());
1665 if (LHSs && MHSs && RHSs) {
1666 std::string Val = std::string(RHSs->
getValue());
1668 std::string::size_type found;
1669 std::string::size_type idx = 0;
1671 found = Val.find(std::string(LHSs->
getValue()), idx);
1672 if (found == std::string::npos)
1697 if (
IntInit *LHSi = dyn_cast_or_null<IntInit>(
1699 if (LHSi->getValue())
1707 ListInit *MHSl = dyn_cast<ListInit>(MHS);
1708 ListInit *RHSl = dyn_cast<ListInit>(RHS);
1709 bool MHSok = MHSl || isa<UnsetInit>(MHS);
1710 bool RHSok = RHSl || isa<UnsetInit>(RHS);
1712 if (isa<UnsetInit>(MHS) && isa<UnsetInit>(RHS))
1715 if (MHSok && RHSok && (!MHSl || !RHSl || MHSl->
size() == RHSl->
size())) {
1718 for (
unsigned i = 0; i !=
Size; ++i) {
1721 if (!isa<StringInit>(
Name) && !isa<UnsetInit>(
Name))
1723 Children.emplace_back(
Node, dyn_cast<StringInit>(
Name));
1731 auto *LHSi = dyn_cast<IntInit>(LHS);
1732 auto *MHSi = dyn_cast<IntInit>(MHS);
1733 auto *RHSi = dyn_cast<IntInit>(RHS);
1734 if (!LHSi || !MHSi || !RHSi)
1737 auto Start = LHSi->getValue();
1738 auto End = MHSi->getValue();
1739 auto Step = RHSi->getValue();
1744 if (Start < End && Step > 0) {
1745 Args.reserve((
End - Start) / Step);
1746 for (
auto I = Start;
I <
End;
I += Step)
1748 }
else if (Start >
End && Step < 0) {
1749 Args.reserve((Start -
End) / -Step);
1750 for (
auto I = Start;
I >
End;
I += Step)
1759 StringInit *LHSs = dyn_cast<StringInit>(LHS);
1760 IntInit *MHSi = dyn_cast<IntInit>(MHS);
1761 IntInit *RHSi = dyn_cast<IntInit>(RHS);
1762 if (LHSs && MHSi && RHSi) {
1766 if (Start < 0 || Start > StringSize)
1768 Twine(
"!substr start position is out of range 0...") +
1769 std::to_string(StringSize) +
": " +
1770 std::to_string(Start));
1780 StringInit *LHSs = dyn_cast<StringInit>(LHS);
1781 StringInit *MHSs = dyn_cast<StringInit>(MHS);
1782 IntInit *RHSi = dyn_cast<IntInit>(RHS);
1783 if (LHSs && MHSs && RHSi) {
1786 if (Start < 0 || Start > SourceSize)
1788 Twine(
"!find start position is out of range 0...") +
1789 std::to_string(SourceSize) +
": " +
1790 std::to_string(Start));
1792 if (
I == std::string::npos)
1800 DagInit *Dag = dyn_cast<DagInit>(LHS);
1801 if (Dag && isa<IntInit, StringInit>(MHS)) {
1807 assert(*ArgNo < Dag->getNumArgs());
1812 return DagInit::get(Dag->getOperator(), Dag->getName(), Args, Names);
1818 DagInit *Dag = dyn_cast<DagInit>(LHS);
1819 if (Dag && isa<IntInit, StringInit>(MHS)) {
1825 assert(*ArgNo < Dag->getNumArgs());
1829 Names[*ArgNo] = dyn_cast<StringInit>(RHS);
1830 return DagInit::get(Dag->getOperator(), Dag->getName(), Args, Names);
1846 if (
Value->getValue())
1863 if (LHS != lhs || MHS != mhs || RHS != rhs)
1865 ->Fold(R.getCurrentRecord());
1871 bool UnquotedLHS =
false;
1873 case DAG: Result =
"!dag";
break;
1874 case FILTER: Result =
"!filter"; UnquotedLHS =
true;
break;
1875 case FOREACH: Result =
"!foreach"; UnquotedLHS =
true;
break;
1876 case IF: Result =
"!if";
break;
1880 case SUBST: Result =
"!subst";
break;
1881 case SUBSTR: Result =
"!substr";
break;
1882 case FIND: Result =
"!find";
break;
1884 Result =
"!setdagarg";
1887 Result =
"!setdagname";
1890 return (Result +
"(" +
1897 ID.AddPointer(Start);
1901 ID.AddPointer(Expr);
1925 if (
ListInit *LI = dyn_cast<ListInit>(List)) {
1926 Init *Accum = Start;
1927 for (
Init *Elt : *LI) {
1946 if (Start == NewStart && List == NewList && Expr ==
NewExpr)
1950 ->
Fold(R.getCurrentRecord());
1967 ID.AddPointer(Expr);
1990 if (
TypedInit *TI = dyn_cast<TypedInit>(Expr)) {
1992 if (TI->getType()->typeIsConvertibleTo(CheckType))
1995 if (isa<RecordRecTy>(CheckType)) {
2029 ID.AddPointer(Expr);
2064 auto *Anonymous = dyn_cast<AnonymousNameInit>(CurRec->
getNameInit());
2066 (Anonymous &&
Name == Anonymous->getNameInit())) {
2086 if (Expr !=
NewExpr || R.isFinal())
2087 return get(CheckType,
NewExpr)->
Fold(R.getCurrentRecord(), R.isFinal());
2105 return Field->getType();
2116 if (isa<BitRecTy>(
getType()) && isa<BitsRecTy>(Ty) &&
2117 cast<BitsRecTy>(Ty)->getNumBits() == 1)
2125 if (!
T)
return nullptr;
2126 unsigned NumBits =
T->getNumBits();
2130 for (
unsigned Bit : Bits) {
2145 assert(!isa<TypedInit>(Converted) ||
2146 cast<TypedInit>(Converted)->
getType()->typeIsA(Ty));
2150 if (!
getType()->typeIsConvertibleTo(Ty))
2177 return const_cast<VarInit*
>(
this);
2182 if (
Init *Val = R.resolve(VarName))
2184 return const_cast<VarInit *
>(
this);
2196 return TI->
getAsString() +
"{" + utostr(Bit) +
"}";
2211 return R->getDefInit();
2215 if (
auto *RRT = dyn_cast<RecordRecTy>(Ty))
2216 if (
getType()->typeIsConvertibleTo(RRT))
2217 return const_cast<DefInit *
>(
this);
2223 return RV->getType();
2231 ID.AddInteger(Args.size());
2232 ID.AddPointer(Class);
2234 for (
Init *
I : Args)
2238VarDefInit::VarDefInit(
Record *Class,
unsigned N)
2252 totalSizeToAlloc<ArgumentInit *>(Args.size()),
alignof(
VarDefInit));
2254 std::uninitialized_copy(Args.begin(), Args.end(),
2264DefInit *VarDefInit::instantiate() {
2268 std::make_unique<Record>(Records.getNewAnonymousName(), Class->
getLoc(),
2270 Record *NewRec = NewRecOwner.get();
2286 for (
unsigned I = 0,
E = TArgs.
size();
I !=
E; ++
I) {
2291 for (
auto *Arg :
args()) {
2292 if (Arg->isPositional())
2293 R.set(TArgs[Arg->getIndex()], Arg->getValue());
2295 R.set(Arg->getName(), Arg->getValue());
2302 for (
const auto &SCPair : SCs)
2307 Class->
getLoc().back()));
2311 Records.addDef(std::move(NewRecOwner));
2327 bool Changed =
false;
2332 auto *NewArg = cast<ArgumentInit>(Arg->resolveReferences(UR));
2334 Changed |= NewArg != Arg;
2340 return New->instantiate();
2352 Arg->resolveReferences(R);
2354 if (!R.foundUnresolved())
2355 return const_cast<VarDefInit *
>(
this)->instantiate();
2361 const char *sep =
"";
2365 Result += Arg->getAsString();
2367 return Result +
">";
2392 if (
DefInit *DI = dyn_cast<DefInit>(Rec)) {
2393 Record *Def = DI->getDef();
2396 Twine(
"Attempting to access field '") +
2398 Rec->
getAsString() +
"' is a forbidden self-reference");
2399 Init *FieldVal = Def->getValue(FieldName)->getValue();
2407 if (
DefInit *DI = dyn_cast<DefInit>(Rec)) {
2408 Init *FieldVal = DI->getDef()->getValue(FieldName)->getValue();
2417 const RecTy *ValType) {
2419 "Number of conditions and values must match!");
2420 ID.AddPointer(ValType);
2424 while (Case != CondRange.
end()) {
2425 ID.AddPointer(*Case++);
2426 ID.AddPointer(*Val++);
2432 ArrayRef(getTrailingObjects<Init *>() + NumConds, NumConds),
2439 "Number of conditions and values must match!");
2450 totalSizeToAlloc<Init *>(2 * CondRange.
size()),
alignof(
BitsInit));
2453 std::uninitialized_copy(CondRange.
begin(), CondRange.
end(),
2454 I->getTrailingObjects<
Init *>());
2455 std::uninitialized_copy(ValRange.
begin(), ValRange.
end(),
2456 I->getTrailingObjects<
Init *>()+CondRange.
size());
2463 bool Changed =
false;
2467 Changed |= NewCase != Case;
2474 Changed |= NewVal != Val;
2486 for (
unsigned i = 0; i < NumConds; ++i) {
2490 if (
IntInit *CondI = dyn_cast_or_null<IntInit>(
2492 if (CondI->getValue())
2501 " does not have any true condition in:" +
2502 this->getAsString());
2508 if (!Case->isConcrete())
2512 if (!Val->isConcrete())
2520 if (!Case->isComplete())
2524 if (!Val->isConcrete())
2531 std::string Result =
"!cond(";
2538 return Result +
")";
2553 while (Arg != ArgRange.
end()) {
2555 ID.AddPointer(*Arg++);
2573 totalSizeToAlloc<Init *, StringInit *>(ArgRange.
size(), NameRange.
size()),
2576 std::uninitialized_copy(ArgRange.
begin(), ArgRange.
end(),
2577 I->getTrailingObjects<
Init *>());
2578 std::uninitialized_copy(NameRange.
begin(), NameRange.
end(),
2590 for (
const auto &Arg :
args) {
2591 Args.push_back(Arg.first);
2600 ArrayRef(getTrailingObjects<Init *>(), NumArgs),
2601 ArrayRef(getTrailingObjects<StringInit *>(), NumArgNames));
2605 if (
DefInit *DefI = dyn_cast<DefInit>(Val))
2606 return DefI->getDef();
2612 for (
unsigned i = 0, e =
getNumArgs(); i < e; ++i) {
2617 return std::nullopt;
2623 bool ArgsChanged =
false;
2627 ArgsChanged |= NewArg != Arg;
2631 if (
Op != Val || ArgsChanged)
2634 return const_cast<DagInit *
>(
this);
2641 if (!Elt->isConcrete())
2654 for (
unsigned i = 1, e =
getNumArgs(); i != e; ++i) {
2659 return Result +
")";
2667 :
Name(
N), TyAndKind(
T, K) {
2669 assert(
Value &&
"Cannot create unset value for current type!");
2675 :
Name(
N), Loc(Loc), TyAndKind(
T, K) {
2677 assert(
Value &&
"Cannot create unset value for current type!");
2681 return cast<StringInit>(
getNameInit())->getValue();
2686 if (
auto *StrInit = dyn_cast<StringInit>(
Value)) {
2687 if (StrInit->hasCodeFormat())
2695 return TyAndKind.getPointer()->getAsString();
2706 if (!isa<BitsInit>(
Value)) {
2708 Bits.reserve(BTy->getNumBits());
2709 for (
unsigned I = 0,
E = BTy->getNumBits();
I <
E; ++
I)
2710 Bits.push_back(
Value->getBit(
I));
2715 return Value ==
nullptr;
2731 if (!isa<BitsInit>(
Value)) {
2733 Bits.reserve(BTy->getNumBits());
2734 for (
unsigned I = 0,
E = BTy->getNumBits();
I <
E; ++
I)
2735 Bits.push_back(
Value->getBit(
I));
2740 return Value ==
nullptr;
2746#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
2758 if (PrintSem)
OS <<
";\n";
2762 assert(Locs.size() == 1);
2763 ForwardDeclarationLocs.push_back(Locs.front());
2766 Locs.push_back(Loc);
2769void Record::checkName() {
2771 const TypedInit *TypedName = cast<const TypedInit>(Name);
2772 if (!isa<StringRecTy>(TypedName->
getType()))
2774 "' is not a string!");
2784 if (!CorrespondingDefInit) {
2785 CorrespondingDefInit =
2788 return CorrespondingDefInit;
2819 for (
int I = SCs.
size() - 1;
I >= 0; --
I) {
2820 const Record *SC = SCs[
I].first;
2821 if (SC == Superclass)
2823 I -= SC->getSuperClasses().size();
2832 while (!SCs.
empty()) {
2834 SCs = SCs.
drop_back(1 + SC->getSuperClasses().size());
2842 if (NewName != OldName) {
2849 if (SkipVal == &
Value)
2852 Init *VR = V->resolveReferences(R);
2853 if (
Value.setValue(VR)) {
2855 if (
TypedInit *VRT = dyn_cast<TypedInit>(VR))
2857 (
Twine(
"of type '") + VRT->getType()->getAsString() +
"' ").str();
2860 Twine(
"Invalid value ") +
Type +
"found when setting field '" +
2861 Value.getNameInitAsString() +
"' of type '" +
2870 for (
auto &Assertion : Assertions) {
2871 Init *
Value = Assertion.Condition->resolveReferences(R);
2872 Assertion.Condition =
Value;
2873 Value = Assertion.Message->resolveReferences(R);
2874 Assertion.Message =
Value;
2877 for (
auto &Dump : Dumps) {
2878 Init *
Value = Dump.Message->resolveReferences(R);
2879 Dump.Message =
Value;
2890#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
2895 OS << R.getNameInitAsString();
2898 if (!TArgs.
empty()) {
2900 bool NeedComma =
false;
2901 for (
const Init *TA : TArgs) {
2902 if (NeedComma)
OS <<
", ";
2905 assert(RV &&
"Template argument record not found??");
2915 for (
const auto &SuperPair : SC)
2916 OS <<
" " << SuperPair.first->getNameInitAsString();
2920 for (
const RecordVal &Val : R.getValues())
2921 if (Val.isNonconcreteOK() && !R.isTemplateArg(Val.getNameInit()))
2923 for (
const RecordVal &Val : R.getValues())
2924 if (!Val.isNonconcreteOK() && !R.isTemplateArg(Val.getNameInit()))
2934 "' does not have a field named `" + FieldName +
"'!\n");
2940 if (!R || !R->getValue())
2942 "' does not have a field named `" + FieldName +
"'!\n");
2943 return R->getValue();
2950 "' does not have a field named `" + FieldName +
"'!\n");
2954std::optional<StringRef>
2957 if (!R || !R->getValue())
2958 return std::nullopt;
2959 if (isa<UnsetInit>(R->getValue()))
2960 return std::nullopt;
2962 if (
StringInit *SI = dyn_cast<StringInit>(R->getValue()))
2963 return SI->getValue();
2966 "Record `" +
getName() +
"', ` field `" + FieldName +
2967 "' exists but does not have a string initializer!");
2972 if (!R || !R->getValue())
2974 "' does not have a field named `" + FieldName +
"'!\n");
2976 if (
BitsInit *BI = dyn_cast<BitsInit>(R->getValue()))
2979 "' exists but does not have a bits value");
2984 if (!R || !R->getValue())
2986 "' does not have a field named `" + FieldName +
"'!\n");
2988 if (
ListInit *LI = dyn_cast<ListInit>(R->getValue()))
2991 "' exists but does not have a list value");
2997 std::vector<Record*> Defs;
2999 if (
DefInit *DI = dyn_cast<DefInit>(
I))
3000 Defs.push_back(DI->getDef());
3003 FieldName +
"' list is not entirely DefInit!");
3010 if (!R || !R->getValue())
3012 "' does not have a field named `" + FieldName +
"'!\n");
3014 if (
IntInit *II = dyn_cast<IntInit>(R->getValue()))
3015 return II->getValue();
3018 "' exists but does not have an int value: " +
3019 R->getValue()->getAsString());
3025 std::vector<int64_t> Ints;
3027 if (
IntInit *II = dyn_cast<IntInit>(
I))
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;
3044 Strings.push_back(SI->getValue());
3047 Twine(
"Record `") +
getName() +
"', field `" + FieldName +
3048 "' exists but does not have a list of strings value: " +
3056 if (!R || !R->getValue())
3058 "' does not have a field named `" + FieldName +
"'!\n");
3060 if (
DefInit *DI = dyn_cast<DefInit>(R->getValue()))
3061 return DI->getDef();
3063 FieldName +
"' does not have a def initializer!");
3068 if (!R || !R->getValue())
3070 "' does not have a field named `" + FieldName +
"'!\n");
3072 if (
DefInit *DI = dyn_cast<DefInit>(R->getValue()))
3073 return DI->getDef();
3074 if (isa<UnsetInit>(R->getValue()))
3077 FieldName +
"' does not have either a def initializer or '?'!");
3083 if (!R || !R->getValue())
3085 "' does not have a field named `" + FieldName +
"'!\n");
3087 if (
BitInit *BI = dyn_cast<BitInit>(R->getValue()))
3088 return BI->getValue();
3090 FieldName +
"' does not have a bit initializer!");
3095 if (!R || !R->getValue())
3097 "' does not have a field named `" + FieldName.
str() +
"'!\n");
3099 if (isa<UnsetInit>(R->getValue())) {
3104 if (
BitInit *BI = dyn_cast<BitInit>(R->getValue()))
3105 return BI->getValue();
3107 FieldName +
"' does not have a bit initializer!");
3112 if (!R || !R->getValue())
3114 "' does not have a field named `" + FieldName +
"'!\n");
3116 if (
DagInit *DI = dyn_cast<DagInit>(R->getValue()))
3119 FieldName +
"' does not have a dag initializer!");
3141 for (
const auto &Dump :
getDumps()) {
3142 Init *Message = Dump.Message->resolveReferences(R);
3158 : Impl(
std::make_unique<detail::RecordKeeperImpl>(*this)) {}
3161#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
3166 OS <<
"------------- Classes -----------------\n";
3168 OS <<
"class " << *
C.second;
3170 OS <<
"------------- Defs -----------------\n";
3172 OS <<
"def " << *
D.second;
3187 if (LastTimer && LastTimer->
isRunning()) {
3191 BackendTimer =
false;
3195 LastTimer =
new Timer(
"",
Name, *TimingGroup);
3202 assert(LastTimer &&
"No phase timer was started");
3210 BackendTimer =
true;
3218 BackendTimer =
false;
3223std::vector<Record *>
3227 auto Pair = ClassRecordsMap.try_emplace(ClassName);
3231 return Pair.first->second;
3237 std::vector<Record *> Defs;
3239 assert(ClassNames.
size() > 0 &&
"At least one class must be passed.");
3240 for (
const auto &ClassName : ClassNames) {
3247 for (
const auto &OneDef :
getDefs()) {
3249 return OneDef.second->isSubClassOf(Class);
3251 Defs.push_back(OneDef.second.get());
3261std::vector<Record *>
3264 : std::vector<Record *>();
3268 auto It = Map.find(VarName);
3269 if (It == Map.end())
3272 Init *
I = It->second.V;
3274 if (!It->second.Resolved && Map.size() > 1) {
3278 I =
I->resolveReferences(*
this);
3279 Map[VarName] = {
I,
true};
3286 Init *Val = Cache.lookup(VarName);
3294 if (!isa<UnsetInit>(RV->getValue())) {
3295 Val = RV->getValue();
3296 Stack.push_back(VarName);
3301 Stack.push_back(VarName);
3306 Cache[VarName] = Val;
3315 if (
I && !FoundUnresolved) {
3320 I->resolveReferences(Sub);
3321 FoundUnresolved |= Sub.FoundUnresolved;
3326 FoundUnresolved =
true;
3332 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")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#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.
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.
StringRef getName() const
Return a constant reference to the value's name.
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 ...
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