22#include "llvm/Config/llvm-config.h"
43#define DEBUG_TYPE "tblgen-records"
127 OS <<
"Bytes allocated = " <<
Allocator.getBytesAllocated() <<
'\n';
128 OS <<
"Total allocator memory = " <<
Allocator.getTotalMemory() <<
"\n\n";
130 OS <<
"Number of records instantiated = " <<
LastRecordID <<
'\n';
131 OS <<
"Number of anonymous records = " <<
AnonCounter <<
'\n';
138#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
144 ListTy =
new (RK.getImpl().Allocator)
ListRecTy(
this);
149 assert(RHS &&
"NULL pointer");
150 return Kind == RHS->getRecTyKind();
156 return &RK.getImpl().SharedBitRecTy;
163 return BitsTy->getNumBits() == 1;
173 Ty =
new (RKImpl.
Allocator) BitsRecTy(RK, Sz);
178 return "bits<" +
utostr(Size) +
">";
189 return &RK.getImpl().SharedIntRecTy;
198 return &RK.getImpl().SharedStringRecTy;
211 return "list<" + ElementTy->getAsString() +
">";
216 return ElementTy->typeIsConvertibleTo(ListTy->getElementType());
227 return &RK.getImpl().SharedDagRecTy;
236 ID.AddInteger(Classes.
size());
237 for (
const Record *R : Classes)
242 :
RecTy(RecordRecTyKind, RK), NumClasses(Classes.
size()) {
249 if (UnsortedClasses.
empty())
256 return LHS->getNameInitAsString() < RHS->getNameInitAsString();
268 for (
unsigned i = 0; i < Classes.
size(); ++i) {
269 for (
unsigned j = 0; j < Classes.
size(); ++j) {
272 assert(&Classes[0]->getRecords() == &Classes[i]->getRecords());
278 RecordRecTy *Ty =
new (Mem) RecordRecTy(RK, Classes);
284 assert(Class &&
"unexpected null class");
285 return get(Class->getRecords(), {Class});
294 return getClasses()[0]->getNameInitAsString();
296 std::string Str =
"{";
300 Str += R->getNameInitAsString();
308 return MySuperClass == Class || MySuperClass->
isSubClassOf(Class);
321 return isSubClassOf(TargetClass);
334 while (!Stack.empty()) {
335 const Record *R = Stack.pop_back_val();
337 if (T2->isSubClassOf(R))
355 assert(T1 !=
nullptr &&
"Invalid record type");
356 if (T1->typeIsConvertibleTo(T2))
359 assert(T2 !=
nullptr &&
"Invalid record type");
360 if (T2->typeIsConvertibleTo(T1))
365 const RecTy *NewType =
366 resolveTypes(ListTy1->getElementType(), ListTy2->getElementType());
379void Init::anchor() {}
381#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
387 return TyInit->getType()->getRecordKeeper();
389 return ArgInit->getRecordKeeper();
394 return &RK.getImpl().TheUnsetInit;
405 auto I = Aux.index();
408 ID.AddInteger(std::get<ArgumentInit::Positional>(Aux));
410 ID.AddPointer(std::get<ArgumentInit::Named>(Aux));
435 const Init *NewValue = Value->resolveReferences(R);
436 if (NewValue != Value)
455 if (BRT->getNumBits() == 1)
487 BitsInit *
I =
new (Mem) BitsInit(RK, Bits);
505 if (
getNumBits() != BRT->getNumBits())
return nullptr;
522 Result |=
static_cast<int64_t
>(Bit->getValue()) << Idx;
532 Result |=
static_cast<int64_t
>(Bit->getValue()) << Idx;
540 for (
auto [Bit, NewBit] :
zip_equal(Bits, NewBits)) {
559 std::string Result =
"{ ";
564 Result += Bit->getAsString();
568 return Result +
" }";
577 const Init *CachedBitVarRef =
nullptr;
578 const Init *CachedBitVarResolved =
nullptr;
584 if (CurBitVar->getBitVar() != CachedBitVarRef) {
585 CachedBitVarRef = CurBitVar->getBitVar();
588 assert(CachedBitVarResolved &&
"Unresolved bitvar reference");
589 NewBit = CachedBitVarResolved->
getBit(CurBitVar->getBitNum());
592 NewBit = CurBit->resolveReferences(R)->getBit(0);
609 I =
new (RK.
getImpl().Allocator) IntInit(RK, V);
619 return (NumBits >=
sizeof(
Value) * 8) ||
620 (
Value >> NumBits == 0) || (
Value >> (NumBits-1) == -1);
629 if (Val != 0 && Val != 1)
return nullptr;
640 for (
unsigned i = 0; i != BRT->getNumBits(); ++i)
653 for (
auto [Bit, NewBit] :
zip_equal(Bits, NewBits)) {
663 return new (RK.
getImpl().Allocator) AnonymousNameInit(RK, V);
671 return "anonymous_" +
utostr(Value);
676 auto *New = R.resolve(Old);
677 New = New ? New : Old;
680 return Anonymous->getNameInit();
689 auto &Entry = *InitMap.try_emplace(V,
nullptr).first;
691 Entry.second =
new (RKImpl.
Allocator) StringInit(RK, Entry.getKey(), Fmt);
704 const RecTy *EltTy) {
705 ID.AddInteger(Elements.size());
706 ID.AddPointer(EltTy);
708 for (
const Init *
E : Elements)
719 const RecTy *EltTy) {
733 ListInit *
I =
new (Mem) ListInit(Elements, EltTy);
749 Elements.reserve(
size());
754 const RecTy *ElementType = LRT->getElementType();
756 if (
const Init *CI =
I->convertInitializerTo(ElementType)) {
757 Elements.push_back(CI);
781 Resolved.reserve(
size());
787 Resolved.push_back(E);
806 std::string Result =
"[";
808 for (
const Init *Element : *
this) {
823 ID.AddInteger(Opcode);
850 if (LHS->isConcrete()) {
855 OS << *Def->getDef();
895 (Anonymous && Name == Anonymous->getNameInit())) {
902 auto PrintFatalErrorHelper = [CurRec](
const Twine &
T) {
911 PrintFatalErrorHelper(
Twine(
"Undefined reference to record: '") +
912 Name->getValue() +
"'\n");
919 PrintFatalErrorHelper(
Twine(
"Expected type '") +
935 if (LHS->isConcrete())
947 assert(!LHSl->empty() &&
"Empty list in head");
948 return LHSl->getElement(0);
954 assert(!LHSl->empty() &&
"Empty list in tail");
958 LHSl->getElementType());
985 if (!TI->getType()->typeIsA(
getType())) {
991 return Dag->getOperator();
998 return Dag->getName();
1005 int64_t LHSv = LHSi->getValue();
1008 "Illegal operation: logtwo is undefined "
1009 "on arguments less than or equal to 0");
1013 "Log of an int64_t must be smaller than INT64_MAX");
1027 [](
const ListInit *
List) -> std::optional<std::vector<const Init *>> {
1028 std::vector<const Init *> Flattened;
1030 for (
const Init *InnerInit :
List->getElements()) {
1033 return std::nullopt;
1039 auto Flattened = Flatten(LHSList);
1041 return ListInit::get(*Flattened, InnerListTy->getElementType());
1053 ->Fold(R.getCurrentRecord(), R.isFinal());
1061 case NOT: Result =
"!not";
break;
1062 case HEAD: Result =
"!head";
break;
1063 case TAIL: Result =
"!tail";
break;
1064 case SIZE: Result =
"!size";
break;
1065 case EMPTY: Result =
"!empty";
break;
1066 case GETDAGOP: Result =
"!getdagop";
break;
1068 Result =
"!getdagopname";
1070 case LOG2 : Result =
"!logtwo";
break;
1072 Result =
"!listflatten";
1078 Result =
"!tolower";
1081 Result =
"!toupper";
1084 Result =
"!initialized";
1087 return Result +
"(" + LHS->getAsString() +
")";
1093 ID.AddInteger(Opcode);
1121 Concat.append(I1->getValue());
1129 if (List->size() == 0)
1137 for (
const Init *Elem : List->getElements().drop_front()) {
1142 Result.append(Element->getValue());
1151 if (List->size() == 0)
1154 List->getElement(0)->convertInitializerTo(
IntRecTy::get(RK)));
1159 for (
const Init *Elem : List->getElements().drop_front()) {
1165 Result.append(Element->getAsString());
1198 const Init *RHS)
const {
1209 Result = LHSi->getValue() == RHSi->getValue();
1212 Result = LHSi->getValue() != RHSi->getValue();
1215 Result = LHSi->getValue() <= RHSi->getValue();
1218 Result = LHSi->getValue() < RHSi->getValue();
1221 Result = LHSi->getValue() >= RHSi->getValue();
1224 Result = LHSi->getValue() > RHSi->getValue();
1240 Result = LHSs->getValue() == RHSs->getValue();
1243 Result = LHSs->getValue() != RHSs->getValue();
1246 Result = LHSs->getValue() <= RHSs->getValue();
1249 Result = LHSs->getValue() < RHSs->getValue();
1252 Result = LHSs->getValue() >= RHSs->getValue();
1255 Result = LHSs->getValue() > RHSs->getValue();
1268 return (
Opc ==
EQ) ? LHSd == RHSd : LHSd != RHSd;
1271 return std::nullopt;
1274static std::optional<unsigned>
1278 int64_t Pos = Idx->getValue();
1282 (
Twine(
"index ") + std::to_string(Pos) +
Twine(
" is negative")).str();
1283 return std::nullopt;
1285 if (Pos >= Dag->getNumArgs()) {
1287 Error = (
Twine(
"index ") + std::to_string(Pos) +
1288 " is out of range (dag has " +
1289 std::to_string(Dag->getNumArgs()) +
" arguments)")
1291 return std::nullopt;
1298 auto ArgNo = Dag->getArgNo(Name->getValue());
1301 Error = (
Twine(
"key '") + Name->getValue() +
Twine(
"' is not found")).str();
1302 return std::nullopt;
1318 if (LOp && ROp && LOp->getDef() != ROp->getDef()) {
1320 LHSs->getAsString() +
"' vs. '" + RHSs->getAsString() +
1323 const Init *
Op = LOp ? LOp : ROp;
1331 const auto *NameInit = LHSs->getName();
1333 NameInit = RHSs->getName();
1347 StringRef RegexStr = RegexInit->getValue();
1353 Matcher.
match(StrInit->getValue()));
1380 for (
const Init *EltLHS : *LHSs) {
1382 for (
const Init *EltRHS : *RHSs) {
1383 if (std::optional<bool> Result =
CompareInit(
EQ, EltLHS, EltRHS)) {
1391 Args.push_back(EltLHS);
1400 if (!TheList || !Idx)
1402 auto i = Idx->getValue();
1403 if (i < 0 || i >= (ssize_t)TheList->size())
1405 return TheList->getElement(i);
1410 if (!TheList || !SliceIdxs)
1413 Args.reserve(SliceIdxs->size());
1414 for (
auto *
I : *SliceIdxs) {
1418 auto i =
II->getValue();
1419 if (i < 0 || i >= (ssize_t)TheList->size())
1421 Args.push_back(TheList->getElement(i));
1431 int64_t Start = LHSi->getValue();
1432 int64_t End = RHSi->getValue();
1438 Args.reserve(End - Start + 1);
1439 for (
auto i = Start; i <= End; ++i)
1443 Args.reserve(Start - End + 1);
1444 for (
auto i = Start; i >= End; --i)
1447 }
else if (Start < End) {
1449 Args.reserve(End - Start);
1450 for (
auto i = Start; i < End; ++i)
1467 if (
List && Delim) {
1496 assert(*ArgNo < Dag->getNumArgs());
1498 const Init *Arg = Dag->getArg(*ArgNo);
1500 if (!TI->getType()->typeIsConvertibleTo(
getType()))
1510 int64_t Pos = Idx->getValue();
1511 if (Pos < 0 || Pos >= Dag->getNumArgs()) {
1514 Twine(
"!getdagname index is out of range 0...") +
1515 std::to_string(Dag->getNumArgs() - 1) +
": " +
1516 std::to_string(Pos));
1518 const Init *ArgName = Dag->getArgName(Pos);
1537 Dag->getArgNames());
1555 int64_t LHSv = LHSi->getValue(), RHSv = RHSi->getValue();
1559 case ADD: Result = LHSv + RHSv;
break;
1560 case SUB: Result = LHSv - RHSv;
break;
1561 case MUL: Result = LHSv * RHSv;
break;
1565 "Illegal operation: division by zero");
1566 else if (LHSv ==
INT64_MIN && RHSv == -1)
1568 "Illegal operation: INT64_MIN / -1");
1570 Result = LHSv / RHSv;
1572 case AND: Result = LHSv & RHSv;
break;
1573 case OR: Result = LHSv | RHSv;
break;
1574 case XOR: Result = LHSv ^ RHSv;
break;
1576 if (RHSv < 0 || RHSv >= 64)
1578 "Illegal operation: out of bounds shift");
1582 if (RHSv < 0 || RHSv >= 64)
1584 "Illegal operation: out of bounds shift");
1588 if (RHSv < 0 || RHSv >= 64)
1590 "Illegal operation: out of bounds shift");
1617 if ((
Opc ==
AND && !LHSi->getValue()) ||
1618 (
Opc ==
OR && LHSi->getValue() == -1))
1625 if (LHS != NewLHS || RHS != NewRHS)
1627 ->Fold(R.getCurrentRecord());
1636 return LHS->getAsString() +
"[" + RHS->getAsString() +
"]";
1638 return LHS->getAsString() +
"..." + RHS->getAsString();
1639 case CONCAT: Result =
"!con";
break;
1643 case ADD: Result =
"!add";
break;
1644 case SUB: Result =
"!sub";
break;
1645 case MUL: Result =
"!mul";
break;
1646 case DIV: Result =
"!div";
break;
1647 case AND: Result =
"!and";
break;
1648 case OR: Result =
"!or";
break;
1649 case XOR: Result =
"!xor";
break;
1650 case SHL: Result =
"!shl";
break;
1651 case SRA: Result =
"!sra";
break;
1652 case SRL: Result =
"!srl";
break;
1653 case EQ: Result =
"!eq";
break;
1654 case NE: Result =
"!ne";
break;
1655 case LE: Result =
"!le";
break;
1656 case LT: Result =
"!lt";
break;
1657 case GE: Result =
"!ge";
break;
1658 case GT: Result =
"!gt";
break;
1659 case LISTCONCAT: Result =
"!listconcat";
break;
1660 case LISTSPLAT: Result =
"!listsplat";
break;
1662 Result =
"!listremove";
1664 case STRCONCAT: Result =
"!strconcat";
break;
1665 case INTERLEAVE: Result =
"!interleave";
break;
1666 case SETDAGOP: Result =
"!setdagop";
break;
1668 Result =
"!setdagopname";
1674 Result =
"!getdagname";
1677 return Result +
"(" + LHS->getAsString() +
", " + RHS->getAsString() +
")";
1683 ID.AddInteger(Opcode);
1714 return RHS->resolveReferences(R);
1719 bool Change =
false;
1753 for (
const Init *&Item : NewList) {
1755 if (NewItem != Item)
1772 for (
const Init *Item : MHSl->getElements()) {
1776 if (
const auto *IncludeInt =
1779 if (IncludeInt->getValue())
1807 if (LHSd && MHSd && RHSd) {
1808 const Record *Val = RHSd->getDef();
1809 if (LHSd->getAsString() == RHSd->getAsString())
1810 Val = MHSd->getDef();
1813 if (LHSv && MHSv && RHSv) {
1814 std::string Val = RHSv->getName().str();
1815 if (LHSv->getAsString() == RHSv->getAsString())
1816 Val = MHSv->getName().str();
1819 if (LHSs && MHSs && RHSs) {
1820 std::string Val = RHSs->getValue().str();
1822 std::string::size_type Idx = 0;
1824 std::string::size_type Found = Val.find(LHSs->getValue(), Idx);
1825 if (Found == std::string::npos)
1827 Val.replace(Found, LHSs->getValue().size(), MHSs->getValue().str());
1828 Idx = Found + MHSs->getValue().size();
1851 if (LHSi->getValue())
1867 if (MHSok && RHSok && (!MHSl || !RHSl || MHSl->size() == RHSl->size())) {
1869 unsigned Size = MHSl ? MHSl->size() : RHSl->size();
1870 for (
unsigned i = 0; i !=
Size; ++i) {
1886 if (!LHSi || !MHSi || !RHSi)
1889 auto Start = LHSi->getValue();
1890 auto End = MHSi->getValue();
1891 auto Step = RHSi->getValue();
1896 if (Start < End && Step > 0) {
1897 Args.reserve((End - Start) / Step);
1898 for (
auto I = Start;
I < End;
I += Step)
1900 }
else if (Start > End && Step < 0) {
1901 Args.reserve((Start - End) / -Step);
1902 for (
auto I = Start;
I > End;
I += Step)
1914 if (LHSs && MHSi && RHSi) {
1915 int64_t StringSize = LHSs->getValue().size();
1916 int64_t Start = MHSi->getValue();
1917 int64_t
Length = RHSi->getValue();
1918 if (Start < 0 || Start > StringSize)
1920 Twine(
"!substr start position is out of range 0...") +
1921 std::to_string(StringSize) +
": " +
1922 std::to_string(Start));
1935 if (LHSs && MHSs && RHSi) {
1936 int64_t SourceSize = LHSs->getValue().size();
1937 int64_t Start = RHSi->getValue();
1938 if (Start < 0 || Start > SourceSize)
1940 Twine(
"!find start position is out of range 0...") +
1941 std::to_string(SourceSize) +
": " +
1942 std::to_string(Start));
1943 auto I = LHSs->getValue().find(MHSs->getValue(), Start);
1944 if (
I == std::string::npos)
1959 assert(*ArgNo < Dag->getNumArgs());
1963 return DagInit::get(Dag->getOperator(), Dag->getName(), Args,
1964 Dag->getArgNames());
1977 assert(*ArgNo < Dag->getNumArgs());
1981 return DagInit::get(Dag->getOperator(), Dag->getName(), Dag->getArgs(),
1998 if (
Value->getValue())
1999 return MHS->resolveReferences(R);
2000 return RHS->resolveReferences(R);
2015 if (LHS != lhs || MHS != mhs || RHS != rhs)
2017 ->Fold(R.getCurrentRecord());
2023 bool UnquotedLHS =
false;
2025 case DAG: Result =
"!dag";
break;
2026 case FILTER: Result =
"!filter"; UnquotedLHS =
true;
break;
2027 case FOREACH: Result =
"!foreach"; UnquotedLHS =
true;
break;
2028 case IF: Result =
"!if";
break;
2032 case SUBST: Result =
"!subst";
break;
2033 case SUBSTR: Result =
"!substr";
break;
2034 case FIND: Result =
"!find";
break;
2036 Result =
"!setdagarg";
2039 Result =
"!setdagname";
2042 return (Result +
"(" +
2043 (UnquotedLHS ? LHS->getAsUnquotedString() : LHS->getAsString()) +
2044 ", " + MHS->getAsString() +
", " + RHS->getAsString() +
")");
2050 ID.AddPointer(Start);
2051 ID.AddPointer(List);
2054 ID.AddPointer(Expr);
2069 FoldOpInit *
I =
new (RK.
Allocator) FoldOpInit(Start, List, A, B, Expr,
Type);
2080 const Init *Accum = Start;
2081 for (
const Init *Elt : *LI) {
2098 const Init *
NewExpr = Expr->resolveReferences(SR);
2100 if (Start == NewStart && List == NewList && Expr ==
NewExpr)
2104 ->
Fold(R.getCurrentRecord());
2112 return (
Twine(
"!foldl(") + Start->getAsString() +
", " + List->getAsString() +
2113 ", " + A->getAsUnquotedString() +
", " + B->getAsUnquotedString() +
2114 ", " + Expr->getAsString() +
")")
2121 ID.AddPointer(Expr);
2134 IsAOpInit *
I =
new (RK.
Allocator) IsAOpInit(CheckType, Expr);
2146 if (TI->getType()->typeIsConvertibleTo(CheckType))
2153 if ((!CheckType->typeIsConvertibleTo(TI->getType()) &&
2154 Expr->isConcrete()) ||
2177 return (
Twine(
"!isa<") + CheckType->getAsString() +
">(" +
2178 Expr->getAsString() +
")")
2185 ID.AddPointer(Expr);
2195 if (
const ExistsOpInit *
I =
2199 ExistsOpInit *
I =
new (RK.
Allocator) ExistsOpInit(CheckType, Expr);
2211 const Record *
D = CheckType->getRecordKeeper().getDef(Name->getValue());
2215 D->getDefInit()->getType()->typeIsA(CheckType));
2223 (Anonymous && Name == Anonymous->getNameInit())) {
2242 if (Expr !=
NewExpr || R.isFinal())
2243 return get(CheckType,
NewExpr)->
Fold(R.getCurrentRecord(), R.isFinal());
2252 return (
Twine(
"!exists<") + CheckType->getAsString() +
">(" +
2253 Expr->getAsString() +
")")
2264 const Init *Regex) {
2270 if (
const InstancesOpInit *
I =
2274 InstancesOpInit *
I =
new (RK.
Allocator) InstancesOpInit(Type, Regex);
2284 if (CurRec && !IsFinal)
2291 StringRef RegexStr = RegexInit->getValue();
2299 if (Matcher.
match(Def->getName()))
2307 if (Regex != NewRegex || R.isFinal())
2308 return get(Type, NewRegex)->
Fold(R.getCurrentRecord(), R.isFinal());
2317 return "!instances<" + Type->getAsString() +
">(" + Regex->getAsString() +
2325 return Field->getType();
2345 if (!
T)
return nullptr;
2346 unsigned NumBits =
T->getNumBits();
2350 for (
unsigned Bit : Bits) {
2370 if (!
getType()->typeIsConvertibleTo(Ty))
2391 return NameString->getValue();
2401 if (
const Init *Val = R.resolve(VarName))
2415 return TI->getAsString() +
"{" +
utostr(Bit) +
"}";
2419 const Init *
I = TI->resolveReferences(R);
2426DefInit::DefInit(
const Record *
D)
2431 if (
getType()->typeIsConvertibleTo(RRT))
2438 return RV->getType();
2446 ID.AddInteger(Args.size());
2447 ID.AddPointer(Class);
2449 for (
const Init *
I : Args)
2472 VarDefInit *
I =
new (Mem) VarDefInit(Loc, Class, Args);
2481const DefInit *VarDefInit::instantiate() {
2486 auto NewRecOwner = std::make_unique<Record>(
2488 Record *NewRec = NewRecOwner.get();
2491 for (
const RecordVal &Val : Class->getValues())
2504 for (
const Init *Arg : TArgs) {
2509 for (
auto *Arg :
args()) {
2510 if (Arg->isPositional())
2511 R.set(TArgs[Arg->getIndex()], Arg->getValue());
2513 R.set(Arg->getName(), Arg->getValue());
2520 Class, SMRange(Class->getLoc().back(), Class->getLoc().back()));
2524 Records.addDef(std::move(NewRecOwner));
2550 return const_cast<VarDefInit *
>(New)->instantiate();
2562 Arg->resolveReferences(R);
2564 if (!R.foundUnresolved())
2565 return const_cast<VarDefInit *
>(
this)->instantiate();
2570 std::string Result = Class->getNameInitAsString() +
"<";
2574 Result += Arg->getAsString();
2576 return Result +
">";
2602 const Record *Def = DI->getDef();
2605 Twine(
"Attempting to access field '") +
2606 FieldName->getAsUnquotedString() +
"' of '" +
2607 Rec->getAsString() +
"' is a forbidden self-reference");
2608 const Init *FieldVal = Def->getValue(FieldName)->getValue();
2617 const Init *FieldVal = DI->getDef()->getValue(FieldName)->getValue();
2626 const RecTy *ValType) {
2628 "Number of conditions and values must match!");
2629 ID.AddPointer(ValType);
2631 for (
const auto &[
Cond, Val] :
zip(Conds, Vals)) {
2653 "Number of conditions and values must match!");
2665 CondOpInit *
I =
new (Mem) CondOpInit(Conds, Values, Ty);
2676 const Init *NewCond =
Cond->resolveReferences(R);
2697 if (CondI->getValue())
2698 return Val->convertInitializerTo(
getValType());
2706 " does not have any true condition in:" +
2707 this->getAsString());
2713 return std::get<0>(Pair)->isConcrete() && std::get<1>(Pair)->isConcrete();
2719 return std::get<0>(Pair)->isComplete() && std::get<1>(Pair)->isComplete();
2724 std::string Result =
"!cond(";
2728 Result +=
Cond->getAsString() +
": ";
2729 Result += Val->getAsString();
2731 return Result +
")";
2744 for (
auto [Arg, Name] :
zip_equal(Args, ArgNames)) {
2746 ID.AddPointer(Name);
2754 ValName(VN), NumArgs(
Args.
size()) {
2763 "Number of DAG args and arg names must match!");
2775 Args.size(), ArgNames.
size()),
2777 DagInit *
I =
new (Mem) DagInit(V, VN, Args, ArgNames);
2784 ArrayRef<std::pair<const Init *, const StringInit *>> ArgAndNames) {
2796 return DefI->getDef();
2804 return ArgName && ArgName->
getValue() == Name;
2806 if (It == ArgNames.
end())
2807 return std::nullopt;
2808 return std::distance(ArgNames.
begin(), It);
2814 bool ArgsChanged =
false;
2818 ArgsChanged |= NewArg != Arg;
2821 const Init *
Op = Val->resolveReferences(R);
2822 if (
Op != Val || ArgsChanged)
2829 if (!Val->isConcrete())
2835 std::string Result =
"(" + Val->getAsString();
2837 Result +=
":$" + ValName->getAsUnquotedString();
2843 Result += Arg->getAsString();
2845 Result +=
":$" + Name->getAsUnquotedString();
2848 return Result +
")";
2856 : Name(
N), TyAndKind(
T, K) {
2858 assert(Value &&
"Cannot create unset value for current type!");
2864 : Name(
N), Loc(Loc), TyAndKind(
T, K) {
2866 assert(Value &&
"Cannot create unset value for current type!");
2876 if (StrInit->hasCodeFormat())
2884 return TyAndKind.getPointer()->getAsString();
2894 Value = V->getCastTo(
getType());
2904 for (
unsigned I = 0, E = BTy->getNumBits();
I < E; ++
I)
2905 Bits[
I] = Value->getBit(
I);
2919#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
2930 if (PrintSem) OS <<
";\n";
2934 assert(Locs.size() == 1);
2935 ForwardDeclarationLocs.push_back(Locs.front());
2938 Locs.push_back(
Loc);
2941void Record::checkName() {
2946 "' is not a string!");
2956 if (!CorrespondingDefInit) {
2957 CorrespondingDefInit =
2958 new (TrackedRecords.getImpl().Allocator)
DefInit(
this);
2960 return CorrespondingDefInit;
2986 if (NewName != OldName) {
2993 if (SkipVal == &
Value)
2997 if (
Value.setValue(VR)) {
3001 (
Twine(
"of type '") + VRT->getType()->getAsString() +
"' ").str();
3004 Twine(
"Invalid value ") +
Type +
"found when setting field '" +
3005 Value.getNameInitAsString() +
"' of type '" +
3015 const Init *
Value = Assertion.Condition->resolveReferences(R);
3016 Assertion.Condition =
Value;
3017 Value = Assertion.Message->resolveReferences(R);
3018 Assertion.Message =
Value;
3022 const Init *
Value = Dump.Message->resolveReferences(R);
3023 Dump.Message =
Value;
3034#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
3039 OS << R.getNameInitAsString();
3042 if (!TArgs.
empty()) {
3045 for (
const Init *TA : TArgs) {
3047 assert(RV &&
"Template argument record not found??");
3049 RV->
print(OS,
false);
3055 std::vector<const Record *> SCs = R.getSuperClasses();
3058 for (
const Record *SC : SCs)
3059 OS <<
" " << SC->getNameInitAsString();
3063 for (
const RecordVal &Val : R.getValues())
3064 if (Val.isNonconcreteOK() && !R.isTemplateArg(Val.getNameInit()))
3066 for (
const RecordVal &Val : R.getValues())
3067 if (!Val.isNonconcreteOK() && !R.isTemplateArg(Val.getNameInit()))
3077 "' does not have a field named `" + FieldName +
"'!\n");
3083 if (!R || !R->getValue())
3085 "' does not have a field named `" + FieldName +
"'!\n");
3086 return R->getValue();
3092 return SI->getValue();
3094 "' exists but does not have a string value");
3097std::optional<StringRef>
3100 if (!R || !R->getValue())
3101 return std::nullopt;
3103 return std::nullopt;
3106 return SI->getValue();
3109 "Record `" +
getName() +
"', ` field `" + FieldName +
3110 "' exists but does not have a string initializer!");
3118 "' exists but does not have a bits value");
3126 "' exists but does not have a list value");
3129std::vector<const Record *>
3132 std::vector<const Record *> Defs;
3133 for (
const Init *
I :
List->getElements()) {
3135 Defs.push_back(DI->getDef());
3139 "' list is not entirely DefInit!");
3147 return II->getValue();
3150 Twine(
"Record `") +
getName() +
"', field `" + FieldName +
3151 "' exists but does not have an int value: " +
I->getAsString());
3157 std::vector<int64_t> Ints;
3158 for (
const Init *
I :
List->getElements()) {
3160 Ints.push_back(
II->getValue());
3163 Twine(
"Record `") +
getName() +
"', field `" + FieldName +
3164 "' exists but does not have a list of ints value: " +
3170std::vector<StringRef>
3173 std::vector<StringRef> Strings;
3174 for (
const Init *
I :
List->getElements()) {
3176 Strings.push_back(
SI->getValue());
3179 Twine(
"Record `") +
getName() +
"', field `" + FieldName +
3180 "' exists but does not have a list of strings value: " +
3189 return DI->getDef();
3191 FieldName +
"' does not have a def initializer!");
3197 return DI->getDef();
3201 FieldName +
"' does not have either a def initializer or '?'!");
3207 return BI->getValue();
3209 FieldName +
"' does not have a bit initializer!");
3220 return BI->getValue();
3222 FieldName +
"' does not have a bit initializer!");
3230 FieldName +
"' does not have a dag initializer!");
3241 bool AnyFailed =
false;
3245 AnyFailed |=
CheckAssert(Assertion.Loc, Condition, Message);
3253 PrintError(
this,
"assertion failed in this record");
3261 const Init *Message = Dump.Message->resolveReferences(R);
3277 : Impl(
std::make_unique<
detail::RecordKeeperImpl>(*this)),
3282#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
3287 OS <<
"------------- Classes -----------------\n";
3289 OS <<
"class " << *
C;
3291 OS <<
"------------- Defs -----------------\n";
3307 auto [Iter, Inserted] = Cache.try_emplace(ClassName.
str());
3310 return Iter->second;
3313std::vector<const Record *>
3316 std::vector<const Record *> Defs;
3318 assert(ClassNames.
size() > 0 &&
"At least one class must be passed.");
3319 for (
StringRef ClassName : ClassNames) {
3326 for (
const auto &OneDef :
getDefs()) {
3328 return OneDef.second->isSubClassOf(Class);
3330 Defs.push_back(OneDef.second.get());
3344 Impl->dumpAllocationStats(OS);
3348 auto It = Map.find(VarName);
3349 if (It == Map.end())
3352 const Init *
I = It->second.V;
3354 if (!It->second.Resolved && Map.size() > 1) {
3358 I =
I->resolveReferences(*
this);
3359 Map[VarName] = {
I,
true};
3366 const Init *Val = Cache.lookup(VarName);
3375 Val = RV->getValue();
3376 Stack.push_back(VarName);
3381 Stack.push_back(VarName);
3386 Cache[VarName] = Val;
3391 const Init *
I =
nullptr;
3394 I = R->resolve(VarName);
3395 if (
I && !FoundUnresolved) {
3400 I->resolveReferences(
Sub);
3401 FoundUnresolved |=
Sub.FoundUnresolved;
3406 FoundUnresolved =
true;
3411 if (VarName == VarNameToTrack)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file defines the StringMap class.
This file defines the BumpPtrAllocator interface.
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
This file defines the DenseMap class.
This file defines a hash set that can be used to remove duplication of nodes in a graph.
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
uint64_t IntrinsicInst * II
OptimizedStructLayoutField Field
const SmallVectorImpl< MachineOperand > & Cond
static void ProfileBitsInit(FoldingSetNodeID &ID, ArrayRef< const Init * > Range)
static bool canFitInBitfield(int64_t Value, unsigned NumBits)
static void ProfileCondOpInit(FoldingSetNodeID &ID, ArrayRef< const Init * > Conds, ArrayRef< const Init * > Vals, const RecTy *ValType)
static void ProfileListInit(FoldingSetNodeID &ID, ArrayRef< const Init * > Elements, const RecTy *EltTy)
static std::optional< unsigned > getDagArgNoByKey(const DagInit *Dag, const Init *Key, std::string &Error)
static void ProfileBinOpInit(FoldingSetNodeID &ID, unsigned Opcode, const Init *LHS, const Init *RHS, const RecTy *Type)
static const StringInit * ConcatStringInits(const StringInit *I0, const StringInit *I1)
static void ProfileTernOpInit(FoldingSetNodeID &ID, unsigned Opcode, const Init *LHS, const Init *MHS, const Init *RHS, const RecTy *Type)
static void ProfileExistsOpInit(FoldingSetNodeID &ID, const RecTy *CheckType, const Init *Expr)
static const ListInit * ConcatListInits(const ListInit *LHS, const ListInit *RHS)
static const StringInit * interleaveStringList(const ListInit *List, const StringInit *Delim)
static void ProfileDagInit(FoldingSetNodeID &ID, const Init *V, const StringInit *VN, ArrayRef< const Init * > Args, ArrayRef< const StringInit * > ArgNames)
static void ProfileFoldOpInit(FoldingSetNodeID &ID, const Init *Start, const Init *List, const Init *A, const Init *B, const Init *Expr, const RecTy *Type)
static void ProfileInstancesOpInit(FoldingSetNodeID &ID, const RecTy *Type, const Init *Regex)
static void ProfileUnOpInit(FoldingSetNodeID &ID, unsigned Opcode, const Init *Op, const RecTy *Type)
static void ProfileArgumentInit(FoldingSetNodeID &ID, const Init *Value, ArgAuxType Aux)
static const Init * ForeachDagApply(const Init *LHS, const DagInit *MHSd, const Init *RHS, const Record *CurRec)
static const Init * FilterHelper(const Init *LHS, const Init *MHS, const Init *RHS, const RecTy *Type, const Record *CurRec)
static const Init * ItemApply(const Init *LHS, const Init *MHSe, const Init *RHS, const Record *CurRec)
static const RecordRecTy * resolveRecordTypes(const RecordRecTy *T1, const RecordRecTy *T2)
static void ProfileRecordRecTy(FoldingSetNodeID &ID, ArrayRef< const Record * > Classes)
static const Init * ForeachHelper(const Init *LHS, const Init *MHS, const Init *RHS, const RecTy *Type, const Record *CurRec)
static void ProfileVarDefInit(FoldingSetNodeID &ID, const Record *Class, ArrayRef< const ArgumentInit * > Args)
static void ProfileIsAOpInit(FoldingSetNodeID &ID, const RecTy *CheckType, const Init *Expr)
static const StringInit * interleaveIntList(const ListInit *List, const StringInit *Delim)
This file defines the SmallString class.
This file defines the SmallVector class.
FunctionLoweringInfo::StatepointRelocationRecord RecordType
static SymbolRef::Type getType(const Symbol *Sym)
static constexpr int Concat[]
static AnonymousNameInit * get(RecordKeeper &RK, unsigned)
const StringInit * getNameInit() const
const Init * resolveReferences(Resolver &R) const override
This function is used by classes that refer to other variables which may not be defined at the time t...
std::string getAsString() const override
Convert this value to a literal form.
const ArgumentInit * cloneWithValue(const Init *Value) const
void Profile(FoldingSetNodeID &ID) const
static const ArgumentInit * get(const Init *Value, ArgAuxType Aux)
ArgumentInit(const Init *Value, ArgAuxType Aux)
const Init * resolveReferences(Resolver &R) const override
This function is used by classes that refer to other variables which may not be defined at the time t...
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - Get the array size.
bool empty() const
empty - Check if the array is empty.
static const BinOpInit * get(BinaryOp opc, const Init *lhs, const Init *rhs, const RecTy *Type)
void Profile(FoldingSetNodeID &ID) const
const Init * resolveReferences(Resolver &R) const override
This function is used by classes that refer to other variables which may not be defined at the time t...
static const Init * getStrConcat(const Init *lhs, const Init *rhs)
std::string getAsString() const override
Convert this value to a literal form.
BinaryOp getOpcode() const
const Init * getRHS() const
std::optional< bool > CompareInit(unsigned Opc, const Init *LHS, const Init *RHS) const
const Init * getLHS() const
static const Init * getListConcat(const TypedInit *lhs, const Init *rhs)
const Init * Fold(const Record *CurRec) const
'true'/'false' - Represent a concrete initializer for a bit.
static BitInit * get(RecordKeeper &RK, bool V)
const Init * convertInitializerTo(const RecTy *Ty) const override
Convert to a value whose type is Ty, or return null if this is not possible.
'bit' - Represent a single bit
static const BitRecTy * get(RecordKeeper &RK)
bool typeIsConvertibleTo(const RecTy *RHS) const override
Return true if all values of 'this' type can be converted to the specified type.
'{ a, b, c }' - Represents an initializer for a BitsRecTy value.
void Profile(FoldingSetNodeID &ID) const
std::string getAsString() const override
Convert this value to a literal form.
bool isComplete() const override
Is this a complete value with no unset (uninitialized) subvalues?
unsigned getNumBits() const
std::optional< int64_t > convertInitializerToInt() const
const Init * getBit(unsigned Bit) const override
Get the Init value of the specified bit.
const Init * convertInitializerBitRange(ArrayRef< unsigned > Bits) const override
This function is used to implement the bit range selection operator.
const Init * resolveReferences(Resolver &R) const override
This function is used by classes that refer to other variables which may not be defined at the time t...
const Init * convertInitializerTo(const RecTy *Ty) const override
Convert to a value whose type is Ty, or return null if this is not possible.
ArrayRef< const Init * > getBits() const
uint64_t convertKnownBitsToInt() const
bool allInComplete() const
static BitsInit * get(RecordKeeper &RK, ArrayRef< const Init * > Range)
bool isConcrete() const override
Is this a concrete and fully resolved value without any references or stuck operations?
'bits<n>' - Represent a fixed number of bits
bool typeIsConvertibleTo(const RecTy *RHS) const override
Return true if all values of 'this' type can be converted to the specified type.
static const BitsRecTy * get(RecordKeeper &RK, unsigned Sz)
std::string getAsString() const override
LLVM_ATTRIBUTE_RETURNS_NONNULL void * Allocate(size_t Size, Align Alignment)
Allocate space at the specified alignment.
const Init * Fold(const Record *CurRec) const
auto getCondAndVals() const
ArrayRef< const Init * > getVals() const
const Init * resolveReferences(Resolver &R) const override
This function is used by classes that refer to other variables which may not be defined at the time t...
const Init * getBit(unsigned Bit) const override
Get the Init value of the specified bit.
bool isConcrete() const override
Is this a concrete and fully resolved value without any references or stuck operations?
void Profile(FoldingSetNodeID &ID) const
std::string getAsString() const override
Convert this value to a literal form.
static const CondOpInit * get(ArrayRef< const Init * > Conds, ArrayRef< const Init * > Values, const RecTy *Type)
const RecTy * getValType() const
bool isComplete() const override
Is this a complete value with no unset (uninitialized) subvalues?
ArrayRef< const Init * > getConds() const
(v a, b) - Represent a DAG tree value.
bool isConcrete() const override
Is this a concrete and fully resolved value without any references or stuck operations?
std::optional< unsigned > getArgNo(StringRef Name) const
This method looks up the specified argument name and returns its argument number or std::nullopt if t...
const StringInit * getName() const
void Profile(FoldingSetNodeID &ID) const
const Init * getOperator() const
const Init * resolveReferences(Resolver &R) const override
This function is used by classes that refer to other variables which may not be defined at the time t...
ArrayRef< const StringInit * > getArgNames() const
static const DagInit * get(const Init *V, const StringInit *VN, ArrayRef< const Init * > Args, ArrayRef< const StringInit * > ArgNames)
const Record * getOperatorAsDef(ArrayRef< SMLoc > Loc) const
auto getArgAndNames() const
ArrayRef< const Init * > getArgs() const
std::string getAsString() const override
Convert this value to a literal form.
'dag' - Represent a dag fragment
std::string getAsString() const override
static const DagRecTy * get(RecordKeeper &RK)
AL - Represent a reference to a 'def' in the description.
std::string getAsString() const override
Convert this value to a literal form.
const RecTy * getFieldType(const StringInit *FieldName) const override
This function is used to implement the FieldInit class.
const Init * convertInitializerTo(const RecTy *Ty) const override
Convert to a value whose type is Ty, or return null if this is not possible.
Lightweight error class with error context and mandatory checking.
void Profile(FoldingSetNodeID &ID) const
static const ExistsOpInit * get(const RecTy *CheckType, const Init *Expr)
std::string getAsString() const override
Convert this value to a literal form.
const Init * resolveReferences(Resolver &R) const override
This function is used by classes that refer to other variables which may not be defined at the time t...
const Init * Fold(const Record *CurRec, bool IsFinal=false) const
const Init * getBit(unsigned Bit) const override
Get the Init value of the specified bit.
X.Y - Represent a reference to a subfield of a variable.
const Init * Fold(const Record *CurRec) const
const Init * getBit(unsigned Bit) const override
Get the Init value of the specified bit.
static const FieldInit * get(const Init *R, const StringInit *FN)
const Init * resolveReferences(Resolver &R) const override
This function is used by classes that refer to other variables which may not be defined at the time t...
bool isConcrete() const override
Is this a concrete and fully resolved value without any references or stuck operations?
const Init * Fold(const Record *CurRec) const
std::string getAsString() const override
Convert this value to a literal form.
static const FoldOpInit * get(const Init *Start, const Init *List, const Init *A, const Init *B, const Init *Expr, const RecTy *Type)
const Init * getBit(unsigned Bit) const override
Get the Init value of the specified bit.
const Init * resolveReferences(Resolver &R) const override
This function is used by classes that refer to other variables which may not be defined at the time t...
void Profile(FoldingSetNodeID &ID) const
void InsertNode(T *N, void *InsertPos)
InsertNode - Insert the specified node into the folding set, knowing that it is not already in the fo...
T * FindNodeOrInsertPos(const FoldingSetNodeID &ID, void *&InsertPos)
FindNodeOrInsertPos - Look up the node specified by ID.
FoldingSetNodeID - This class is used to gather all the unique data bits of a node.
FoldingSet - This template class is used to instantiate a specialized implementation of the folding s...
const Init * resolve(const Init *VarName) override
Return the initializer for the given variable name (should normally be a StringInit),...
virtual const Init * resolveReferences(Resolver &R) const
This function is used by classes that refer to other variables which may not be defined at the time t...
virtual std::string getAsUnquotedString() const
Convert this value to a literal form, without adding quotes around a string.
void dump() const
Debugging method that may be called through a debugger; just invokes print on stderr.
void print(raw_ostream &OS) const
Print this value.
virtual std::string getAsString() const =0
Convert this value to a literal form.
virtual bool isConcrete() const
Is this a concrete and fully resolved value without any references or stuck operations?
virtual bool isComplete() const
Is this a complete value with no unset (uninitialized) subvalues?
virtual const Init * getBit(unsigned Bit) const =0
Get the Init value of the specified bit.
virtual const Init * convertInitializerTo(const RecTy *Ty) const =0
Convert to a value whose type is Ty, or return null if this is not possible.
RecordKeeper & getRecordKeeper() const
Get the record keeper that initialized this Init.
Init(InitKind K, uint8_t Opc=0)
void Profile(FoldingSetNodeID &ID) const
const Init * Fold(const Record *CurRec, bool IsFinal=false) const
const Init * getBit(unsigned Bit) const override
Get the Init value of the specified bit.
const Init * resolveReferences(Resolver &R) const override
This function is used by classes that refer to other variables which may not be defined at the time t...
std::string getAsString() const override
Convert this value to a literal form.
static const InstancesOpInit * get(const RecTy *Type, const Init *Regex)
static IntInit * get(RecordKeeper &RK, int64_t V)
const Init * convertInitializerBitRange(ArrayRef< unsigned > Bits) const override
This function is used to implement the bit range selection operator.
std::string getAsString() const override
Convert this value to a literal form.
const Init * convertInitializerTo(const RecTy *Ty) const override
Convert to a value whose type is Ty, or return null if this is not possible.
'int' - Represent an integer value of no particular size
static const IntRecTy * get(RecordKeeper &RK)
bool typeIsConvertibleTo(const RecTy *RHS) const override
Return true if all values of 'this' type can be converted to the specified type.
static const IsAOpInit * get(const RecTy *CheckType, const Init *Expr)
void Profile(FoldingSetNodeID &ID) const
const Init * resolveReferences(Resolver &R) const override
This function is used by classes that refer to other variables which may not be defined at the time t...
std::string getAsString() const override
Convert this value to a literal form.
const Init * getBit(unsigned Bit) const override
Get the Init value of the specified bit.
const Init * Fold() const
[AL, AH, CL] - Represent a list of defs
std::string getAsString() const override
Convert this value to a literal form.
const RecTy * getElementType() const
static const ListInit * get(ArrayRef< const Init * > Range, const RecTy *EltTy)
bool isConcrete() const override
Is this a concrete and fully resolved value without any references or stuck operations?
bool isComplete() const override
Is this a complete value with no unset (uninitialized) subvalues?
const Init * resolveReferences(Resolver &R) const override
This method is used by classes that refer to other variables which may not be defined at the time the...
const Init * convertInitializerTo(const RecTy *Ty) const override
Convert to a value whose type is Ty, or return null if this is not possible.
void Profile(FoldingSetNodeID &ID) const
const Record * getElementAsRecord(unsigned Idx) const
ArrayRef< const Init * > getElements() const
const Init * getElement(unsigned Idx) const
'list<Ty>' - Represent a list of element values, all of which must be of the specified type.
const RecTy * getElementType() const
bool typeIsA(const RecTy *RHS) const override
Return true if 'this' type is equal to or a subtype of RHS.
std::string getAsString() const override
bool typeIsConvertibleTo(const RecTy *RHS) const override
Return true if all values of 'this' type can be converted to the specified type.
A helper class to return the specified delimiter string after the first invocation of operator String...
Resolve arbitrary mappings.
const Init * resolve(const Init *VarName) override
Return the initializer for the given variable name (should normally be a StringInit),...
const Init * getBit(unsigned Bit) const final
Get the Init value of the specified bit.
RecordKeeper & getRecordKeeper() const
Return the RecordKeeper that uniqued this Type.
virtual bool typeIsA(const RecTy *RHS) const
Return true if 'this' type is equal to or a subtype of RHS.
virtual bool typeIsConvertibleTo(const RecTy *RHS) const
Return true if all values of 'this' type can be converted to the specified type.
RecTyKind
Subclass discriminator (for dyn_cast<> et al.)
RecTy(RecTyKind K, RecordKeeper &RK)
virtual std::string getAsString() const =0
const ListRecTy * getListTy() const
Returns the type representing list<thistype>.
void print(raw_ostream &OS) const
const Record * getClass(StringRef Name) const
Get the class with the specified name.
const RecordMap & getClasses() const
Get the map of classes.
const Init * getNewAnonymousName()
GetNewAnonymousName - Generate a unique anonymous name that can be used as an identifier.
const RecordMap & getDefs() const
Get the map of records (defs).
detail::RecordKeeperImpl & getImpl()
Return the internal implementation of the RecordKeeper.
void dumpAllocationStats(raw_ostream &OS) const
ArrayRef< const Record * > getAllDerivedDefinitionsIfDefined(StringRef ClassName) const
Get all the concrete records that inherit from specified class, if the class is defined.
const Record * getDef(StringRef Name) const
Get the concrete record with the specified name.
ArrayRef< const Record * > getAllDerivedDefinitions(StringRef ClassName) const
Get all the concrete records that inherit from the one specified class.
'[classname]' - Type of record values that have zero or more superclasses.
bool typeIsConvertibleTo(const RecTy *RHS) const override
Return true if all values of 'this' type can be converted to the specified type.
bool isSubClassOf(const Record *Class) const
ArrayRef< const Record * > getClasses() const
void Profile(FoldingSetNodeID &ID) const
std::string getAsString() const override
bool typeIsA(const RecTy *RHS) const override
Return true if 'this' type is equal to or a subtype of RHS.
static const RecordRecTy * get(RecordKeeper &RK, ArrayRef< const Record * > Classes)
Get the record type with the given non-redundant list of superclasses.
Resolve all variables from a record except for unset variables.
const Init * resolve(const Init *VarName) override
Return the initializer for the given variable name (should normally be a StringInit),...
This class represents a field in a record, including its name, type, value, and source location.
std::string getNameInitAsString() const
Get the name of the field as a std::string.
bool isNonconcreteOK() const
Is this a field where nonconcrete values are okay?
bool setValue(const Init *V)
Set the value of the field from an Init.
RecordKeeper & getRecordKeeper() const
Get the record keeper used to unique this value.
const SMLoc & getLoc() const
Get the source location of the point where the field was defined.
const Init * getValue() const
Get the value of the field as an Init.
StringRef getName() const
Get the name of the field as a StringRef.
void print(raw_ostream &OS, bool PrintSem=true) const
Print the value to an output stream, possibly with a semicolon.
RecordVal(const Init *N, const RecTy *T, FieldKind K)
const Init * getNameInit() const
Get the name of the field as an Init.
std::string getPrintType() const
Get the type of the field for printing purposes.
const RecTy * getType() const
Get the type of the field value as a RecTy.
std::vector< int64_t > getValueAsListOfInts(StringRef FieldName) const
This method looks up the specified field and returns its value as a vector of integers,...
const RecordRecTy * getType() const
const Init * getValueInit(StringRef FieldName) const
Return the initializer for a value with the specified name, or throw an exception if the field does n...
bool getValueAsBitOrUnset(StringRef FieldName, bool &Unset) const
This method looks up the specified field and returns its value as a bit.
bool getValueAsBit(StringRef FieldName) const
This method looks up the specified field and returns its value as a bit, throwing an exception if the...
static unsigned getNewUID(RecordKeeper &RK)
ArrayRef< SMLoc > getLoc() const
void checkUnusedTemplateArgs()
ArrayRef< DumpInfo > getDumps() const
std::vector< const Record * > getValueAsListOfDefs(StringRef FieldName) const
This method looks up the specified field and returns its value as a vector of records,...
ArrayRef< AssertionInfo > getAssertions() const
std::string getNameInitAsString() const
const Record * getValueAsDef(StringRef FieldName) const
This method looks up the specified field and returns its value as a Record, throwing an exception if ...
const DagInit * getValueAsDag(StringRef FieldName) const
This method looks up the specified field and returns its value as an Dag, throwing an exception if th...
std::vector< StringRef > getValueAsListOfStrings(StringRef FieldName) const
This method looks up the specified field and returns its value as a vector of strings,...
const RecordVal * getValue(const Init *Name) const
void addValue(const RecordVal &RV)
const Record * getValueAsOptionalDef(StringRef FieldName) const
This method looks up the specified field and returns its value as a Record, returning null if the fie...
ArrayRef< std::pair< const Record *, SMRange > > getDirectSuperClasses() const
Return the direct superclasses of this record.
StringRef getName() const
Record(const Init *N, ArrayRef< SMLoc > locs, RecordKeeper &records, RecordKind Kind=RK_Def)
void setName(const Init *Name)
const ListInit * getValueAsListInit(StringRef FieldName) const
This method looks up the specified field and returns its value as a ListInit, throwing an exception i...
void appendDumps(const Record *Rec)
bool isSubClassOf(const Record *R) const
DefInit * getDefInit() const
get the corresponding DefInit.
SMLoc getFieldLoc(StringRef FieldName) const
Return the source location for the named field.
void resolveReferences(const Init *NewName=nullptr)
If there are any field references that refer to fields that have been filled in, we can propagate the...
std::optional< StringRef > getValueAsOptionalString(StringRef FieldName) const
This method looks up the specified field and returns its value as a string, throwing an exception if ...
void removeValue(const Init *Name)
ArrayRef< const Init * > getTemplateArgs() const
void updateClassLoc(SMLoc Loc)
const BitsInit * getValueAsBitsInit(StringRef FieldName) const
This method looks up the specified field and returns its value as a BitsInit, throwing an exception i...
void addDirectSuperClass(const Record *R, SMRange Range)
void appendAssertions(const Record *Rec)
const Init * getNameInit() const
int64_t getValueAsInt(StringRef FieldName) const
This method looks up the specified field and returns its value as an int64_t, throwing an exception i...
void checkRecordAssertions()
StringRef getValueAsString(StringRef FieldName) const
This method looks up the specified field and returns its value as a string, throwing an exception if ...
LLVM_ABI bool isValid(std::string &Error) const
isValid - returns the error encountered during regex compilation, if any.
LLVM_ABI bool match(StringRef String, SmallVectorImpl< StringRef > *Matches=nullptr, std::string *Error=nullptr) const
matches - Match the regex against a given String.
Interface for looking up the initializer for a variable name, used by Init::resolveReferences.
const Record * getCurrentRecord() const
Represents a location in source code.
Delegate resolving to a sub-resolver, but shadow some variable names.
void addShadow(const Init *Key)
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
reference emplace_back(ArgTypes &&... Args)
void reserve(size_type N)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
"foo" - Represent an initialization by a string value.
static const StringInit * get(RecordKeeper &RK, StringRef, StringFormat Fmt=SF_String)
StringFormat getFormat() const
StringRef getValue() const
static StringFormat determineFormat(StringFormat Fmt1, StringFormat Fmt2)
const Init * convertInitializerTo(const RecTy *Ty) const override
Convert to a value whose type is Ty, or return null if this is not possible.
StringMap - This is an unconventional map that is specialized for handling keys that are "strings",...
'string' - Represent an string value
std::string getAsString() const override
static const StringRecTy * get(RecordKeeper &RK)
bool typeIsConvertibleTo(const RecTy *RHS) const override
Return true if all values of 'this' type can be converted to the specified type.
StringRef - Represent a constant reference to a string, i.e.
std::string str() const
str - Get the contents as an std::string.
const Init * Fold(const Record *CurRec) const
const Init * getLHS() const
void Profile(FoldingSetNodeID &ID) const
const Init * getMHS() const
const Init * getRHS() const
static const TernOpInit * get(TernaryOp opc, const Init *lhs, const Init *mhs, const Init *rhs, const RecTy *Type)
std::string getAsString() const override
Convert this value to a literal form.
const Init * resolveReferences(Resolver &R) const override
This function is used by classes that refer to other variables which may not be defined at the time t...
TernaryOp getOpcode() const
(Optionally) delegate resolving to a sub-resolver, and keep track whether there were unresolved refer...
const Init * resolve(const Init *VarName) override
Return the initializer for the given variable name (should normally be a StringInit),...
bool foundUnresolved() const
TrackUnresolvedResolver(Resolver *R=nullptr)
See the file comment for details on the usage of the TrailingObjects type.
static constexpr std::enable_if_t< std::is_same_v< Foo< TrailingTys... >, Foo< Tys... > >, size_t > totalSizeToAlloc(typename trailing_objects_internal::ExtractSecondType< TrailingTys, size_t >::type... Counts)
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
The instances of the Type class are immutable: once they are created, they are never changed.
This is the common superclass of types that have a specific, explicit type, stored in ValueTy.
const RecTy * getFieldType(const StringInit *FieldName) const override
This method is used to implement the FieldInit class.
TypedInit(InitKind K, const RecTy *T, uint8_t Opc=0)
const Init * convertInitializerBitRange(ArrayRef< unsigned > Bits) const override
This function is used to implement the bit range selection operator.
RecordKeeper & getRecordKeeper() const
Get the record keeper that initialized this Init.
const Init * getCastTo(const RecTy *Ty) const override
If this value is convertible to type Ty, return a value whose type is Ty, generating a !...
const Init * convertInitializerTo(const RecTy *Ty) const override
Convert to a value whose type is Ty, or return null if this is not possible.
const RecTy * getType() const
Get the type of the Init as a RecTy.
const Init * getOperand() const
UnaryOp getOpcode() const
static const UnOpInit * get(UnaryOp opc, const Init *lhs, const RecTy *Type)
void Profile(FoldingSetNodeID &ID) const
const Init * resolveReferences(Resolver &R) const override
This function is used by classes that refer to other variables which may not be defined at the time t...
std::string getAsString() const override
Convert this value to a literal form.
const Init * Fold(const Record *CurRec, bool IsFinal=false) const
'?' - Represents an uninitialized value.
const Init * getCastTo(const RecTy *Ty) const override
If this value is convertible to type Ty, return a value whose type is Ty, generating a !...
const Init * convertInitializerTo(const RecTy *Ty) const override
Convert to a value whose type is Ty, or return null if this is not possible.
static UnsetInit * get(RecordKeeper &RK)
Get the singleton unset Init.
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
Opcode{0} - Represent access to one bit of a variable or field.
static const VarBitInit * get(const TypedInit *T, unsigned B)
unsigned getBitNum() const
std::string getAsString() const override
Convert this value to a literal form.
const Init * resolveReferences(Resolver &R) const override
This function is used by classes that refer to other variables which may not be defined at the time t...
ArrayRef< const ArgumentInit * > args() const
static const VarDefInit * get(SMLoc Loc, const Record *Class, ArrayRef< const ArgumentInit * > Args)
const Init * resolveReferences(Resolver &R) const override
This function is used by classes that refer to other variables which may not be defined at the time t...
const Init * Fold() const
void Profile(FoldingSetNodeID &ID) const
std::string getAsString() const override
Convert this value to a literal form.
'Opcode' - Represent a reference to an entire variable object.
static const VarInit * get(StringRef VN, const RecTy *T)
const Init * getBit(unsigned Bit) const override
Get the Init value of the specified bit.
StringRef getName() const
const Init * getNameInit() const
const Init * resolveReferences(Resolver &R) const override
This method is used by classes that refer to other variables which may not be defined at the time the...
This class implements an extremely fast bulk output stream that can only output to a stream.
A raw_ostream that writes to an std::string.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ C
The default llvm calling convention, compatible with C.
llvm::SmallVector< std::shared_ptr< RecordsSlice >, 4 > Records
This is an optimization pass for GlobalISel generic memory operations.
detail::zippy< detail::zip_shortest, T, U, Args... > zip(T &&t, U &&u, Args &&...args)
zip iterator for two or more iteratable types.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
detail::zippy< detail::zip_first, T, U, Args... > zip_equal(T &&t, U &&u, Args &&...args)
zip iterator that assumes that all iteratees have the same length.
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
void PrintFatalError(const Twine &Msg)
void PrintError(const Twine &Msg)
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
std::string utostr(uint64_t X, bool isNeg=false)
auto uninitialized_copy(R &&Src, IterTy Dst)
unsigned Log2_64(uint64_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
bool CheckAssert(SMLoc Loc, const Init *Condition, const Init *Message)
auto dyn_cast_or_null(const Y &Val)
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
void PrintWarning(const Twine &Msg)
auto reverse(ContainerTy &&C)
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
void sort(IteratorTy Start, IteratorTy End)
auto make_first_range(ContainerTy &&c)
Given a container of pairs, return a range over the first elements.
BumpPtrAllocatorImpl BumpPtrAllocator
The standard BumpPtrAllocator which just uses the default template parameters.
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
@ Sub
Subtraction of integers.
DWARFExpression::Operation Op
raw_ostream & operator<<(raw_ostream &OS, const APFixedPoint &FX)
ArrayRef(const T &OneElt) -> ArrayRef< T >
auto make_second_range(ContainerTy &&c)
Given a container of pairs, return a range over the second elements.
void dumpMessage(SMLoc Loc, const Init *Message)
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
const RecTy * resolveTypes(const RecTy *T1, const RecTy *T2)
Find a common type that T1 and T2 convert to.
std::variant< unsigned, const Init * > ArgAuxType
std::string itostr(int64_t X)
Implement std::hash so that hash_code can be used in STL containers.
Sorting predicate to sort record pointers by name.
This class represents the internal implementation of the RecordKeeper.
FoldingSet< BitsInit > TheBitsInitPool
std::map< int64_t, IntInit * > TheIntInitPool
FoldingSet< FoldOpInit > TheFoldOpInitPool
DenseMap< std::pair< const RecTy *, const Init * >, VarInit * > TheVarInitPool
FoldingSet< IsAOpInit > TheIsAOpInitPool
FoldingSet< DagInit > TheDagInitPool
FoldingSet< CondOpInit > TheCondOpInitPool
FoldingSet< BinOpInit > TheBinOpInitPool
FoldingSet< ArgumentInit > TheArgumentInitPool
StringRecTy SharedStringRecTy
FoldingSet< RecordRecTy > RecordTypePool
FoldingSet< VarDefInit > TheVarDefInitPool
StringMap< const StringInit *, BumpPtrAllocator & > StringInitCodePool
DenseMap< std::pair< const TypedInit *, unsigned >, VarBitInit * > TheVarBitInitPool
FoldingSet< InstancesOpInit > TheInstancesOpInitPool
std::vector< BitsRecTy * > SharedBitsRecTys
FoldingSet< UnOpInit > TheUnOpInitPool
void dumpAllocationStats(raw_ostream &OS) const
DenseMap< std::pair< const Init *, const StringInit * >, FieldInit * > TheFieldInitPool
FoldingSet< TernOpInit > TheTernOpInitPool
BumpPtrAllocator Allocator
FoldingSet< ExistsOpInit > TheExistsOpInitPool
StringMap< const StringInit *, BumpPtrAllocator & > StringInitStringPool
FoldingSet< ListInit > TheListInitPool
RecordKeeperImpl(RecordKeeper &RK)