22#include "llvm/Config/llvm-config.h"
43#define DEBUG_TYPE "tblgen-records"
125 OS <<
"Bytes allocated = " <<
Allocator.getBytesAllocated() <<
'\n';
126 OS <<
"Total allocator memory = " <<
Allocator.getTotalMemory() <<
"\n\n";
128 OS <<
"Number of records instantiated = " <<
LastRecordID <<
'\n';
129 OS <<
"Number of anonymous records = " <<
AnonCounter <<
'\n';
136#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
142 ListTy =
new (RK.getImpl().Allocator)
ListRecTy(
this);
147 assert(RHS &&
"NULL pointer");
148 return Kind == RHS->getRecTyKind();
154 return &RK.getImpl().SharedBitRecTy;
161 return BitsTy->getNumBits() == 1;
171 Ty =
new (RKImpl.
Allocator) BitsRecTy(RK, Sz);
176 return "bits<" +
utostr(Size) +
">";
187 return &RK.getImpl().SharedIntRecTy;
196 return &RK.getImpl().SharedStringRecTy;
209 return "list<" + ElementTy->getAsString() +
">";
214 return ElementTy->typeIsConvertibleTo(ListTy->getElementType());
225 return &RK.getImpl().SharedDagRecTy;
234 ID.AddInteger(Classes.
size());
235 for (
const Record *R : Classes)
240 :
RecTy(RecordRecTyKind, RK), NumClasses(Classes.
size()) {
247 if (UnsortedClasses.
empty())
254 return LHS->getNameInitAsString() < RHS->getNameInitAsString();
266 for (
unsigned i = 0; i < Classes.
size(); ++i) {
267 for (
unsigned j = 0; j < Classes.
size(); ++j) {
270 assert(&Classes[0]->getRecords() == &Classes[i]->getRecords());
276 RecordRecTy *Ty =
new (Mem) RecordRecTy(RK, Classes);
282 assert(Class &&
"unexpected null class");
283 return get(Class->getRecords(), {Class});
292 return getClasses()[0]->getNameInitAsString();
294 std::string Str =
"{";
298 Str += R->getNameInitAsString();
306 return MySuperClass == Class || MySuperClass->
isSubClassOf(Class);
319 return isSubClassOf(TargetClass);
332 while (!Stack.empty()) {
333 const Record *R = Stack.pop_back_val();
335 if (T2->isSubClassOf(R))
353 assert(T1 !=
nullptr &&
"Invalid record type");
354 if (T1->typeIsConvertibleTo(T2))
357 assert(T2 !=
nullptr &&
"Invalid record type");
358 if (T2->typeIsConvertibleTo(T1))
363 const RecTy *NewType =
364 resolveTypes(ListTy1->getElementType(), ListTy2->getElementType());
377void Init::anchor() {}
379#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
385 return TyInit->getType()->getRecordKeeper();
387 return ArgInit->getRecordKeeper();
392 return &RK.getImpl().TheUnsetInit;
403 auto I = Aux.index();
406 ID.AddInteger(std::get<ArgumentInit::Positional>(Aux));
408 ID.AddPointer(std::get<ArgumentInit::Named>(Aux));
433 const Init *NewValue = Value->resolveReferences(R);
434 if (NewValue != Value)
453 if (BRT->getNumBits() == 1)
485 BitsInit *
I =
new (Mem) BitsInit(RK, Bits);
503 if (
getNumBits() != BRT->getNumBits())
return nullptr;
520 Result |=
static_cast<int64_t
>(Bit->getValue()) << Idx;
530 Result |=
static_cast<int64_t
>(Bit->getValue()) << Idx;
538 for (
auto [Bit, NewBit] :
zip_equal(Bits, NewBits)) {
557 std::string Result =
"{ ";
562 Result += Bit->getAsString();
566 return Result +
" }";
575 const Init *CachedBitVarRef =
nullptr;
576 const Init *CachedBitVarResolved =
nullptr;
582 if (CurBitVar->getBitVar() != CachedBitVarRef) {
583 CachedBitVarRef = CurBitVar->getBitVar();
586 assert(CachedBitVarResolved &&
"Unresolved bitvar reference");
587 NewBit = CachedBitVarResolved->
getBit(CurBitVar->getBitNum());
590 NewBit = CurBit->resolveReferences(R)->getBit(0);
607 I =
new (RK.
getImpl().Allocator) IntInit(RK, V);
617 return (NumBits >=
sizeof(
Value) * 8) ||
618 (
Value >> NumBits == 0) || (
Value >> (NumBits-1) == -1);
627 if (Val != 0 && Val != 1)
return nullptr;
638 for (
unsigned i = 0; i != BRT->getNumBits(); ++i)
651 for (
auto [Bit, NewBit] :
zip_equal(Bits, NewBits)) {
661 return new (RK.
getImpl().Allocator) AnonymousNameInit(RK, V);
669 return "anonymous_" +
utostr(Value);
674 auto *New = R.resolve(Old);
675 New = New ? New : Old;
678 return Anonymous->getNameInit();
687 auto &Entry = *InitMap.try_emplace(V,
nullptr).first;
689 Entry.second =
new (RKImpl.
Allocator) StringInit(RK, Entry.getKey(), Fmt);
702 const RecTy *EltTy) {
703 ID.AddInteger(Elements.size());
704 ID.AddPointer(EltTy);
706 for (
const Init *
E : Elements)
717 const RecTy *EltTy) {
731 ListInit *
I =
new (Mem) ListInit(Elements, EltTy);
747 Elements.reserve(
size());
752 const RecTy *ElementType = LRT->getElementType();
754 if (
const Init *CI =
I->convertInitializerTo(ElementType)) {
755 Elements.push_back(CI);
779 Resolved.reserve(
size());
785 Resolved.push_back(E);
804 std::string Result =
"[";
806 for (
const Init *Element : *
this) {
821 ID.AddInteger(Opcode);
848 if (LHS->isConcrete()) {
853 OS << *Def->getDef();
893 (Anonymous && Name == Anonymous->getNameInit())) {
900 auto PrintFatalErrorHelper = [CurRec](
const Twine &
T) {
909 PrintFatalErrorHelper(
Twine(
"Undefined reference to record: '") +
910 Name->getValue() +
"'\n");
917 PrintFatalErrorHelper(
Twine(
"Expected type '") +
933 if (LHS->isConcrete())
945 assert(!LHSl->empty() &&
"Empty list in head");
946 return LHSl->getElement(0);
952 assert(!LHSl->empty() &&
"Empty list in tail");
956 LHSl->getElementType());
983 if (!TI->getType()->typeIsA(
getType())) {
989 return Dag->getOperator();
996 return Dag->getName();
1003 int64_t LHSv = LHSi->getValue();
1006 "Illegal operation: logtwo is undefined "
1007 "on arguments less than or equal to 0");
1011 "Log of an int64_t must be smaller than INT64_MAX");
1025 [](
const ListInit *
List) -> std::optional<std::vector<const Init *>> {
1026 std::vector<const Init *> Flattened;
1028 for (
const Init *InnerInit :
List->getElements()) {
1031 return std::nullopt;
1037 auto Flattened = Flatten(LHSList);
1039 return ListInit::get(*Flattened, InnerListTy->getElementType());
1051 ->Fold(R.getCurrentRecord(), R.isFinal());
1059 case NOT: Result =
"!not";
break;
1060 case HEAD: Result =
"!head";
break;
1061 case TAIL: Result =
"!tail";
break;
1062 case SIZE: Result =
"!size";
break;
1063 case EMPTY: Result =
"!empty";
break;
1064 case GETDAGOP: Result =
"!getdagop";
break;
1066 Result =
"!getdagopname";
1068 case LOG2 : Result =
"!logtwo";
break;
1070 Result =
"!listflatten";
1076 Result =
"!tolower";
1079 Result =
"!toupper";
1082 Result =
"!initialized";
1085 return Result +
"(" + LHS->getAsString() +
")";
1091 ID.AddInteger(Opcode);
1119 Concat.append(I1->getValue());
1127 if (List->size() == 0)
1135 for (
const Init *Elem : List->getElements().drop_front()) {
1140 Result.append(Element->getValue());
1149 if (List->size() == 0)
1152 List->getElement(0)->convertInitializerTo(
IntRecTy::get(RK)));
1157 for (
const Init *Elem : List->getElements().drop_front()) {
1163 Result.append(Element->getAsString());
1196 const Init *RHS)
const {
1207 Result = LHSi->getValue() == RHSi->getValue();
1210 Result = LHSi->getValue() != RHSi->getValue();
1213 Result = LHSi->getValue() <= RHSi->getValue();
1216 Result = LHSi->getValue() < RHSi->getValue();
1219 Result = LHSi->getValue() >= RHSi->getValue();
1222 Result = LHSi->getValue() > RHSi->getValue();
1238 Result = LHSs->getValue() == RHSs->getValue();
1241 Result = LHSs->getValue() != RHSs->getValue();
1244 Result = LHSs->getValue() <= RHSs->getValue();
1247 Result = LHSs->getValue() < RHSs->getValue();
1250 Result = LHSs->getValue() >= RHSs->getValue();
1253 Result = LHSs->getValue() > RHSs->getValue();
1266 return (
Opc ==
EQ) ? LHSd == RHSd : LHSd != RHSd;
1269 return std::nullopt;
1272static std::optional<unsigned>
1276 int64_t Pos = Idx->getValue();
1280 (
Twine(
"index ") + std::to_string(Pos) +
Twine(
" is negative")).str();
1281 return std::nullopt;
1283 if (Pos >= Dag->getNumArgs()) {
1285 Error = (
Twine(
"index ") + std::to_string(Pos) +
1286 " is out of range (dag has " +
1287 std::to_string(Dag->getNumArgs()) +
" arguments)")
1289 return std::nullopt;
1296 auto ArgNo = Dag->getArgNo(Name->getValue());
1299 Error = (
Twine(
"key '") + Name->getValue() +
Twine(
"' is not found")).str();
1300 return std::nullopt;
1316 if (LOp && ROp && LOp->getDef() != ROp->getDef()) {
1318 LHSs->getAsString() +
"' vs. '" + RHSs->getAsString() +
1321 const Init *
Op = LOp ? LOp : ROp;
1329 const auto *NameInit = LHSs->getName();
1331 NameInit = RHSs->getName();
1345 StringRef RegexStr = RegexInit->getValue();
1351 Matcher.
match(StrInit->getValue()));
1368 if (
Count->getValue() < 0)
1381 for (
const Init *EltLHS : *LHSs) {
1383 for (
const Init *EltRHS : *RHSs) {
1384 if (std::optional<bool> Result =
CompareInit(
EQ, EltLHS, EltRHS)) {
1392 Args.push_back(EltLHS);
1401 if (!TheList || !Idx)
1403 auto i = Idx->getValue();
1404 if (i < 0 || i >= (ssize_t)TheList->size())
1406 return TheList->getElement(i);
1411 if (!TheList || !SliceIdxs)
1414 Args.reserve(SliceIdxs->size());
1415 for (
auto *
I : *SliceIdxs) {
1419 auto i =
II->getValue();
1420 if (i < 0 || i >= (ssize_t)TheList->size())
1422 Args.push_back(TheList->getElement(i));
1432 int64_t Start = LHSi->getValue();
1433 int64_t End = RHSi->getValue();
1439 Args.reserve(End - Start + 1);
1440 for (
auto i = Start; i <= End; ++i)
1444 Args.reserve(Start - End + 1);
1445 for (
auto i = Start; i >= End; --i)
1448 }
else if (Start < End) {
1450 Args.reserve(End - Start);
1451 for (
auto i = Start; i < End; ++i)
1468 if (
List && Delim) {
1497 assert(*ArgNo < Dag->getNumArgs());
1499 const Init *Arg = Dag->getArg(*ArgNo);
1501 if (!TI->getType()->typeIsConvertibleTo(
getType()))
1511 int64_t Pos = Idx->getValue();
1512 if (Pos < 0 || Pos >= Dag->getNumArgs()) {
1515 Twine(
"!getdagname index is out of range 0...") +
1516 std::to_string(Dag->getNumArgs() - 1) +
": " +
1517 std::to_string(Pos));
1519 const Init *ArgName = Dag->getArgName(Pos);
1538 Dag->getArgNames());
1556 int64_t LHSv = LHSi->getValue(), RHSv = RHSi->getValue();
1560 case ADD: Result = LHSv + RHSv;
break;
1561 case SUB: Result = LHSv - RHSv;
break;
1562 case MUL: Result = LHSv * RHSv;
break;
1566 "Illegal operation: division by zero");
1567 else if (LHSv ==
INT64_MIN && RHSv == -1)
1569 "Illegal operation: INT64_MIN / -1");
1571 Result = LHSv / RHSv;
1573 case AND: Result = LHSv & RHSv;
break;
1574 case OR: Result = LHSv | RHSv;
break;
1575 case XOR: Result = LHSv ^ RHSv;
break;
1577 if (RHSv < 0 || RHSv >= 64)
1579 "Illegal operation: out of bounds shift");
1583 if (RHSv < 0 || RHSv >= 64)
1585 "Illegal operation: out of bounds shift");
1589 if (RHSv < 0 || RHSv >= 64)
1591 "Illegal operation: out of bounds shift");
1618 if ((
Opc ==
AND && !LHSi->getValue()) ||
1619 (
Opc ==
OR && LHSi->getValue() == -1))
1626 if (LHS != NewLHS || RHS != NewRHS)
1628 ->Fold(R.getCurrentRecord());
1637 return LHS->getAsString() +
"[" + RHS->getAsString() +
"]";
1639 return LHS->getAsString() +
"..." + RHS->getAsString();
1640 case CONCAT: Result =
"!con";
break;
1644 case ADD: Result =
"!add";
break;
1645 case SUB: Result =
"!sub";
break;
1646 case MUL: Result =
"!mul";
break;
1647 case DIV: Result =
"!div";
break;
1648 case AND: Result =
"!and";
break;
1649 case OR: Result =
"!or";
break;
1650 case XOR: Result =
"!xor";
break;
1651 case SHL: Result =
"!shl";
break;
1652 case SRA: Result =
"!sra";
break;
1653 case SRL: Result =
"!srl";
break;
1654 case EQ: Result =
"!eq";
break;
1655 case NE: Result =
"!ne";
break;
1656 case LE: Result =
"!le";
break;
1657 case LT: Result =
"!lt";
break;
1658 case GE: Result =
"!ge";
break;
1659 case GT: Result =
"!gt";
break;
1660 case LISTCONCAT: Result =
"!listconcat";
break;
1661 case LISTSPLAT: Result =
"!listsplat";
break;
1663 Result =
"!listremove";
1665 case STRCONCAT: Result =
"!strconcat";
break;
1666 case INTERLEAVE: Result =
"!interleave";
break;
1667 case SETDAGOP: Result =
"!setdagop";
break;
1669 Result =
"!setdagopname";
1675 Result =
"!getdagname";
1678 return Result +
"(" + LHS->getAsString() +
", " + RHS->getAsString() +
")";
1684 ID.AddInteger(Opcode);
1715 return RHS->resolveReferences(R);
1720 bool Change =
false;
1754 for (
const Init *&Item : NewList) {
1756 if (NewItem != Item)
1773 for (
const Init *Item : MHSl->getElements()) {
1777 if (
const auto *IncludeInt =
1780 if (IncludeInt->getValue())
1808 if (LHSd && MHSd && RHSd) {
1809 const Record *Val = RHSd->getDef();
1810 if (LHSd->getAsString() == RHSd->getAsString())
1811 Val = MHSd->getDef();
1814 if (LHSv && MHSv && RHSv) {
1815 std::string Val = RHSv->getName().str();
1816 if (LHSv->getAsString() == RHSv->getAsString())
1817 Val = MHSv->getName().str();
1820 if (LHSs && MHSs && RHSs) {
1821 std::string Val = RHSs->getValue().str();
1823 std::string::size_type Idx = 0;
1825 std::string::size_type Found = Val.find(LHSs->getValue(), Idx);
1826 if (Found == std::string::npos)
1828 Val.replace(Found, LHSs->getValue().size(), MHSs->getValue().str());
1829 Idx = Found + MHSs->getValue().size();
1852 if (LHSi->getValue())
1868 if (MHSok && RHSok && (!MHSl || !RHSl || MHSl->size() == RHSl->size())) {
1870 unsigned Size = MHSl ? MHSl->size() : RHSl->size();
1871 for (
unsigned i = 0; i !=
Size; ++i) {
1887 if (!LHSi || !MHSi || !RHSi)
1890 auto Start = LHSi->getValue();
1891 auto End = MHSi->getValue();
1892 auto Step = RHSi->getValue();
1897 if (Start < End && Step > 0) {
1898 Args.reserve((End - Start) / Step);
1899 for (
auto I = Start;
I < End;
I += Step)
1901 }
else if (Start > End && Step < 0) {
1902 Args.reserve((Start - End) / -Step);
1903 for (
auto I = Start;
I > End;
I += Step)
1915 if (LHSs && MHSi && RHSi) {
1916 int64_t StringSize = LHSs->getValue().size();
1917 int64_t Start = MHSi->getValue();
1918 int64_t
Length = RHSi->getValue();
1919 if (Start < 0 || Start > StringSize)
1921 Twine(
"!substr start position is out of range 0...") +
1922 std::to_string(StringSize) +
": " +
1923 std::to_string(Start));
1936 if (LHSs && MHSs && RHSi) {
1937 int64_t SourceSize = LHSs->getValue().size();
1938 int64_t Start = RHSi->getValue();
1939 if (Start < 0 || Start > SourceSize)
1941 Twine(
"!find start position is out of range 0...") +
1942 std::to_string(SourceSize) +
": " +
1943 std::to_string(Start));
1944 auto I = LHSs->getValue().find(MHSs->getValue(), Start);
1945 if (
I == std::string::npos)
1960 assert(*ArgNo < Dag->getNumArgs());
1964 return DagInit::get(Dag->getOperator(), Dag->getName(), Args,
1965 Dag->getArgNames());
1978 assert(*ArgNo < Dag->getNumArgs());
1982 return DagInit::get(Dag->getOperator(), Dag->getName(), Dag->getArgs(),
1999 if (
Value->getValue())
2000 return MHS->resolveReferences(R);
2001 return RHS->resolveReferences(R);
2016 if (LHS != lhs || MHS != mhs || RHS != rhs)
2018 ->Fold(R.getCurrentRecord());
2024 bool UnquotedLHS =
false;
2026 case DAG: Result =
"!dag";
break;
2027 case FILTER: Result =
"!filter"; UnquotedLHS =
true;
break;
2028 case FOREACH: Result =
"!foreach"; UnquotedLHS =
true;
break;
2029 case IF: Result =
"!if";
break;
2033 case SUBST: Result =
"!subst";
break;
2034 case SUBSTR: Result =
"!substr";
break;
2035 case FIND: Result =
"!find";
break;
2037 Result =
"!setdagarg";
2040 Result =
"!setdagname";
2043 return (Result +
"(" +
2044 (UnquotedLHS ? LHS->getAsUnquotedString() : LHS->getAsString()) +
2045 ", " + MHS->getAsString() +
", " + RHS->getAsString() +
")");
2051 ID.AddPointer(Start);
2052 ID.AddPointer(List);
2055 ID.AddPointer(Expr);
2070 FoldOpInit *
I =
new (RK.
Allocator) FoldOpInit(Start, List, A, B, Expr,
Type);
2081 const Init *Accum = Start;
2082 for (
const Init *Elt : *LI) {
2099 const Init *
NewExpr = Expr->resolveReferences(SR);
2101 if (Start == NewStart && List == NewList && Expr ==
NewExpr)
2105 ->
Fold(R.getCurrentRecord());
2113 return (
Twine(
"!foldl(") + Start->getAsString() +
", " + List->getAsString() +
2114 ", " + A->getAsUnquotedString() +
", " + B->getAsUnquotedString() +
2115 ", " + Expr->getAsString() +
")")
2122 ID.AddPointer(Expr);
2135 IsAOpInit *
I =
new (RK.
Allocator) IsAOpInit(CheckType, Expr);
2147 if (TI->getType()->typeIsConvertibleTo(CheckType))
2154 if ((!CheckType->typeIsConvertibleTo(TI->getType()) &&
2155 Expr->isConcrete()) ||
2178 return (
Twine(
"!isa<") + CheckType->getAsString() +
">(" +
2179 Expr->getAsString() +
")")
2186 ID.AddPointer(Expr);
2196 if (
const ExistsOpInit *
I =
2200 ExistsOpInit *
I =
new (RK.
Allocator) ExistsOpInit(CheckType, Expr);
2212 const Record *
D = CheckType->getRecordKeeper().getDef(Name->getValue());
2216 D->getDefInit()->getType()->typeIsA(CheckType));
2224 (Anonymous && Name == Anonymous->getNameInit())) {
2243 if (Expr !=
NewExpr || R.isFinal())
2244 return get(CheckType,
NewExpr)->
Fold(R.getCurrentRecord(), R.isFinal());
2253 return (
Twine(
"!exists<") + CheckType->getAsString() +
">(" +
2254 Expr->getAsString() +
")")
2265 const Init *Regex) {
2271 if (
const InstancesOpInit *
I =
2275 InstancesOpInit *
I =
new (RK.
Allocator) InstancesOpInit(Type, Regex);
2285 if (CurRec && !IsFinal)
2292 StringRef RegexStr = RegexInit->getValue();
2300 if (Matcher.
match(Def->getName()))
2308 if (Regex != NewRegex || R.isFinal())
2309 return get(Type, NewRegex)->
Fold(R.getCurrentRecord(), R.isFinal());
2318 return "!instances<" + Type->getAsString() +
">(" + Regex->getAsString() +
2326 return Field->getType();
2346 if (!
T)
return nullptr;
2347 unsigned NumBits =
T->getNumBits();
2351 for (
unsigned Bit : Bits) {
2371 if (!
getType()->typeIsConvertibleTo(Ty))
2392 return NameString->getValue();
2402 if (
const Init *Val = R.resolve(VarName))
2416 return TI->getAsString() +
"{" +
utostr(Bit) +
"}";
2420 const Init *
I = TI->resolveReferences(R);
2427DefInit::DefInit(
const Record *
D)
2432 if (
getType()->typeIsConvertibleTo(RRT))
2439 return RV->getType();
2447 ID.AddInteger(Args.size());
2448 ID.AddPointer(Class);
2450 for (
const Init *
I : Args)
2473 VarDefInit *
I =
new (Mem) VarDefInit(Loc, Class, Args);
2482const DefInit *VarDefInit::instantiate() {
2487 auto NewRecOwner = std::make_unique<Record>(
2489 Record *NewRec = NewRecOwner.get();
2492 for (
const RecordVal &Val : Class->getValues())
2505 for (
const Init *Arg : TArgs) {
2510 for (
auto *Arg :
args()) {
2511 if (Arg->isPositional())
2512 R.set(TArgs[Arg->getIndex()], Arg->getValue());
2514 R.set(Arg->getName(), Arg->getValue());
2521 Class, SMRange(Class->getLoc().back(), Class->getLoc().back()));
2525 Records.addDef(std::move(NewRecOwner));
2551 return const_cast<VarDefInit *
>(New)->instantiate();
2563 Arg->resolveReferences(R);
2565 if (!R.foundUnresolved())
2566 return const_cast<VarDefInit *
>(
this)->instantiate();
2571 std::string Result = Class->getNameInitAsString() +
"<";
2575 Result += Arg->getAsString();
2577 return Result +
">";
2603 const Record *Def = DI->getDef();
2606 Twine(
"Attempting to access field '") +
2607 FieldName->getAsUnquotedString() +
"' of '" +
2608 Rec->getAsString() +
"' is a forbidden self-reference");
2609 const Init *FieldVal = Def->getValue(FieldName)->getValue();
2618 const Init *FieldVal = DI->getDef()->getValue(FieldName)->getValue();
2627 const RecTy *ValType) {
2629 "Number of conditions and values must match!");
2630 ID.AddPointer(ValType);
2632 for (
const auto &[
Cond, Val] :
zip(Conds, Vals)) {
2654 "Number of conditions and values must match!");
2666 CondOpInit *
I =
new (Mem) CondOpInit(Conds, Values, Ty);
2677 const Init *NewCond =
Cond->resolveReferences(R);
2698 if (CondI->getValue())
2699 return Val->convertInitializerTo(
getValType());
2707 " does not have any true condition in:" +
2708 this->getAsString());
2714 return std::get<0>(Pair)->isConcrete() && std::get<1>(Pair)->isConcrete();
2720 return std::get<0>(Pair)->isComplete() && std::get<1>(Pair)->isComplete();
2725 std::string Result =
"!cond(";
2729 Result +=
Cond->getAsString() +
": ";
2730 Result += Val->getAsString();
2732 return Result +
")";
2745 for (
auto [Arg, Name] :
zip_equal(Args, ArgNames)) {
2747 ID.AddPointer(Name);
2755 ValName(VN), NumArgs(
Args.
size()) {
2764 "Number of DAG args and arg names must match!");
2776 Args.size(), ArgNames.
size()),
2778 DagInit *
I =
new (Mem) DagInit(V, VN, Args, ArgNames);
2785 ArrayRef<std::pair<const Init *, const StringInit *>> ArgAndNames) {
2797 return DefI->getDef();
2805 return ArgName && ArgName->
getValue() == Name;
2807 if (It == ArgNames.
end())
2808 return std::nullopt;
2809 return std::distance(ArgNames.
begin(), It);
2815 bool ArgsChanged =
false;
2819 ArgsChanged |= NewArg != Arg;
2822 const Init *
Op = Val->resolveReferences(R);
2823 if (
Op != Val || ArgsChanged)
2830 if (!Val->isConcrete())
2836 std::string Result =
"(" + Val->getAsString();
2838 Result +=
":$" + ValName->getAsUnquotedString();
2844 Result += Arg->getAsString();
2846 Result +=
":$" + Name->getAsUnquotedString();
2849 return Result +
")";
2857 : Name(
N), TyAndKind(
T, K) {
2859 assert(Value &&
"Cannot create unset value for current type!");
2865 : Name(
N), Loc(Loc), TyAndKind(
T, K) {
2867 assert(Value &&
"Cannot create unset value for current type!");
2877 if (StrInit->hasCodeFormat())
2885 return TyAndKind.getPointer()->getAsString();
2895 Value = V->getCastTo(
getType());
2905 for (
unsigned I = 0, E = BTy->getNumBits();
I < E; ++
I)
2906 Bits[
I] = Value->getBit(
I);
2920#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
2931 if (PrintSem) OS <<
";\n";
2935 assert(Locs.size() == 1);
2936 ForwardDeclarationLocs.push_back(Locs.front());
2939 Locs.push_back(
Loc);
2942void Record::checkName() {
2947 "' is not a string!");
2957 if (!CorrespondingDefInit) {
2958 CorrespondingDefInit =
2959 new (TrackedRecords.getImpl().Allocator)
DefInit(
this);
2961 return CorrespondingDefInit;
2987 if (NewName != OldName) {
2994 if (SkipVal == &
Value)
2998 if (
Value.setValue(VR)) {
3002 (
Twine(
"of type '") + VRT->getType()->getAsString() +
"' ").str();
3005 Twine(
"Invalid value ") +
Type +
"found when setting field '" +
3006 Value.getNameInitAsString() +
"' of type '" +
3016 const Init *
Value = Assertion.Condition->resolveReferences(R);
3017 Assertion.Condition =
Value;
3018 Value = Assertion.Message->resolveReferences(R);
3019 Assertion.Message =
Value;
3023 const Init *
Value = Dump.Message->resolveReferences(R);
3024 Dump.Message =
Value;
3035#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
3040 OS << R.getNameInitAsString();
3043 if (!TArgs.
empty()) {
3046 for (
const Init *TA : TArgs) {
3048 assert(RV &&
"Template argument record not found??");
3050 RV->
print(OS,
false);
3056 std::vector<const Record *> SCs = R.getSuperClasses();
3059 for (
const Record *SC : SCs)
3060 OS <<
" " << SC->getNameInitAsString();
3064 for (
const RecordVal &Val : R.getValues())
3065 if (Val.isNonconcreteOK() && !R.isTemplateArg(Val.getNameInit()))
3067 for (
const RecordVal &Val : R.getValues())
3068 if (!Val.isNonconcreteOK() && !R.isTemplateArg(Val.getNameInit()))
3078 "' does not have a field named `" + FieldName +
"'!\n");
3084 if (!R || !R->getValue())
3086 "' does not have a field named `" + FieldName +
"'!\n");
3087 return R->getValue();
3093 return SI->getValue();
3095 "' exists but does not have a string value");
3098std::optional<StringRef>
3101 if (!R || !R->getValue())
3102 return std::nullopt;
3104 return std::nullopt;
3107 return SI->getValue();
3110 "Record `" +
getName() +
"', ` field `" + FieldName +
3111 "' exists but does not have a string initializer!");
3119 "' exists but does not have a bits value");
3127 "' exists but does not have a list value");
3130std::vector<const Record *>
3133 std::vector<const Record *> Defs;
3134 for (
const Init *
I :
List->getElements()) {
3136 Defs.push_back(DI->getDef());
3140 "' list is not entirely DefInit!");
3148 return II->getValue();
3151 Twine(
"Record `") +
getName() +
"', field `" + FieldName +
3152 "' exists but does not have an int value: " +
I->getAsString());
3158 std::vector<int64_t> Ints;
3159 for (
const Init *
I :
List->getElements()) {
3161 Ints.push_back(
II->getValue());
3164 Twine(
"Record `") +
getName() +
"', field `" + FieldName +
3165 "' exists but does not have a list of ints value: " +
3171std::vector<StringRef>
3174 std::vector<StringRef> Strings;
3175 for (
const Init *
I :
List->getElements()) {
3177 Strings.push_back(
SI->getValue());
3180 Twine(
"Record `") +
getName() +
"', field `" + FieldName +
3181 "' exists but does not have a list of strings value: " +
3190 return DI->getDef();
3192 FieldName +
"' does not have a def initializer!");
3198 return DI->getDef();
3202 FieldName +
"' does not have either a def initializer or '?'!");
3208 return BI->getValue();
3210 FieldName +
"' does not have a bit initializer!");
3221 return BI->getValue();
3223 FieldName +
"' does not have a bit initializer!");
3231 FieldName +
"' does not have a dag initializer!");
3242 bool AnyFailed =
false;
3246 AnyFailed |=
CheckAssert(Assertion.Loc, Condition, Message);
3254 PrintError(
this,
"assertion failed in this record");
3262 const Init *Message = Dump.Message->resolveReferences(R);
3278 : Impl(
std::make_unique<
detail::RecordKeeperImpl>(*this)),
3283#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
3288 OS <<
"------------- Classes -----------------\n";
3290 OS <<
"class " << *
C;
3292 OS <<
"------------- Defs -----------------\n";
3308 auto [Iter, Inserted] = Cache.try_emplace(ClassName.
str());
3311 return Iter->second;
3314std::vector<const Record *>
3317 std::vector<const Record *> Defs;
3319 assert(ClassNames.
size() > 0 &&
"At least one class must be passed.");
3320 for (
StringRef ClassName : ClassNames) {
3327 for (
const auto &OneDef :
getDefs()) {
3329 return OneDef.second->isSubClassOf(Class);
3331 Defs.push_back(OneDef.second.get());
3345 Impl->dumpAllocationStats(OS);
3349 auto It = Map.find(VarName);
3350 if (It == Map.end())
3353 const Init *
I = It->second.V;
3355 if (!It->second.Resolved && Map.size() > 1) {
3359 I =
I->resolveReferences(*
this);
3360 Map[VarName] = {
I,
true};
3367 const Init *Val = Cache.lookup(VarName);
3376 Val = RV->getValue();
3377 Stack.push_back(VarName);
3382 Stack.push_back(VarName);
3387 Cache[VarName] = Val;
3392 const Init *
I =
nullptr;
3395 I = R->resolve(VarName);
3396 if (
I && !FoundUnresolved) {
3401 I->resolveReferences(
Sub);
3402 FoundUnresolved |=
Sub.FoundUnresolved;
3407 FoundUnresolved =
true;
3412 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.
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
A self-contained host- and target-independent arbitrary-precision floating-point software implementat...
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.
FunctionAddr VTableAddr Count
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)