17#include "llvm/Config/llvm-config.h"
56#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
58 errs() <<
"Multiclass:\n";
62 errs() <<
"Template args:\n";
71 const auto *BV = cast<BitsInit>(RV.
getValue());
72 for (
unsigned i = 0, e = BV->getNumBits(); i != e; ++i) {
73 const Init *Bit = BV->getBit(i);
74 bool IsReference =
false;
75 if (
const auto *VBI = dyn_cast<VarBitInit>(Bit)) {
76 if (
const auto *VI = dyn_cast<VarInit>(VBI->getBitVar())) {
77 if (R.getValue(VI->getName()))
80 }
else if (isa<VarInit>(Bit)) {
83 if (!(IsReference || Bit->isConcrete()))
90 for (
const RecordVal &RV : R.getValues()) {
95 if (RV.isNonconcreteOK())
98 if (
const Init *V = RV.getValue()) {
102 Twine(
"Initializer of '") + RV.getNameInitAsString() +
103 "' in '" + R.getNameInitAsString() +
104 "' could not be fully resolved: " +
105 RV.getValue()->getAsString());
120 if (
const auto *BinOp = dyn_cast<BinOpInit>(NewName))
121 NewName = BinOp->Fold(&CurRec);
141 bool TrackReferenceLocs)
const {
143 auto It = Vars.find(
Name->getValue());
144 if (It != Vars.end())
147 auto FindValueInArgs = [&](
Record *Rec,
154 assert(RV &&
"Template arg doesn't exist??");
156 if (TrackReferenceLocs)
160 return Name->getValue() ==
"NAME"
174 if (TrackReferenceLocs)
175 RV->addReferenceLoc(NameLoc);
181 if (
auto *V = FindValueInArgs(CurRec,
Name))
189 const auto *IterVar = dyn_cast<VarInit>(CurLoop->
IterVar);
190 if (IterVar && IterVar->getNameInit() ==
Name)
198 if (
auto *V = FindValueInArgs(&CurMultiClass->
Rec,
Name))
206 return Parent->getVar(Records, ParsingMultiClass,
Name, NameLoc,
214 CurRec = &CurMultiClass->
Rec;
219 return Error(Loc,
"New definition of '" + RV.
getName() +
"' of type '" +
221 "previous definition of type '" +
222 ERV->getType()->getAsString() +
"'");
233 bool AllowSelfAssignment,
bool OverrideDefLoc) {
234 if (!V)
return false;
236 if (!CurRec) CurRec = &CurMultiClass->
Rec;
246 if (
const auto *VI = dyn_cast<VarInit>(V))
247 if (
VI->getNameInit() == ValName && !AllowSelfAssignment)
248 return Error(Loc,
"Recursion / self-assignment forbidden");
254 if (!BitList.
empty()) {
255 const auto *CurVal = dyn_cast<BitsInit>(RV->
getValue());
258 "' is not a bits type");
263 return Error(Loc,
"Initializer is not compatible with bit range");
268 for (
unsigned i = 0, e = BitList.
size(); i != e; ++i) {
269 unsigned Bit = BitList[i];
271 return Error(Loc,
"Cannot set bit #" +
Twine(Bit) +
" of value '" +
276 for (
unsigned i = 0, e = CurVal->getNumBits(); i != e; ++i)
278 NewBits[i] = CurVal->
getBit(i);
284 std::string InitType;
285 if (
const auto *BI = dyn_cast<BitsInit>(V))
286 InitType = (
Twine(
"' of type bit initializer with length ") +
287 Twine(BI->getNumBits())).str();
288 else if (
const auto *TI = dyn_cast<TypedInit>(V))
290 (
Twine(
"' of type '") + TI->getType()->getAsString() +
"'").str();
294 "' is incompatible with value '" +
V->getAsString() +
309 if (!
Field.isTemplateArg())
313 if (resolveArgumentsOfClass(R, SC, SubClass.
TemplateArgs,
335 for (
const auto &[SC, Loc] :
SC->getSuperClasses()) {
338 "Already subclass of '" +
SC->getName() +
"'!\n");
344 "Already subclass of '" +
SC->getName() +
"'!\n");
351 return AddSubClass(
Entry.Rec.get(), SubClass);
356 for (
auto &E :
Entry.Loop->Entries) {
357 if (AddSubClass(E, SubClass))
367bool TGParser::AddSubMultiClass(
MultiClass *CurMC,
372 if (resolveArgumentsOfMultiClass(
386 "RecordsEntry has invalid number of items");
389 if (!Loops.empty()) {
390 Loops.back()->Entries.push_back(std::move(E));
397 return resolve(*E.
Loop, Stack, CurMultiClass ==
nullptr,
398 CurMultiClass ? &CurMultiClass->
Entries :
nullptr);
403 CurMultiClass->
Entries.push_back(std::move(E));
419 return addDefOne(std::move(E.
Rec));
428 bool Final, std::vector<RecordsEntry> *Dest,
432 for (
const auto &S : Substs)
433 R.set(S.first, S.second);
434 const Init *
List =
Loop.ListValue->resolveReferences(R);
442 if (
const auto *TI = dyn_cast<TernOpInit>(
List);
444 const Init *OldLHS = TI->getLHS();
449 Twine(
"unable to resolve if condition '") +
450 LHS->getAsString() +
"' at end of containing scope");
453 const Init *MHS = TI->getMHS();
454 const Init *
RHS = TI->getRHS();
459 const auto *LI = dyn_cast<ListInit>(
List);
462 Dest->emplace_back(std::make_unique<ForeachLoop>(
Loop.Loc,
Loop.IterVar,
464 return resolve(
Loop.Entries, Substs, Final, &Dest->back().Loop->Entries,
469 List->getAsString() +
"', expected a list");
474 for (
auto *Elt : *LI) {
476 Substs.emplace_back(
Loop.IterVar->getNameInit(), Elt);
477 Error = resolve(
Loop.Entries, Substs, Final, Dest);
491bool TGParser::resolve(
const std::vector<RecordsEntry> &Source,
492 SubstStack &Substs,
bool Final,
493 std::vector<RecordsEntry> *Dest,
SMLoc *Loc) {
495 for (
auto &E : Source) {
497 Error = resolve(*E.
Loop, Substs, Final, Dest);
501 for (
const auto &S : Substs)
502 R.set(S.first, S.second);
503 const Init *Condition = E.
Assertion->Condition->resolveReferences(R);
504 const Init *Message = E.
Assertion->Message->resolveReferences(R);
507 Dest->push_back(std::make_unique<Record::AssertionInfo>(
514 for (
const auto &S : Substs)
515 R.set(S.first, S.second);
516 const Init *Message = E.
Dump->Message->resolveReferences(R);
520 std::make_unique<Record::DumpInfo>(E.
Dump->Loc, Message));
525 auto Rec = std::make_unique<Record>(*E.
Rec);
527 Rec->appendLoc(*Loc);
530 for (
const auto &S : Substs)
531 R.set(S.first, S.second);
532 Rec->resolveReferences(R);
535 Dest->push_back(std::move(Rec));
537 Error = addDefOne(std::move(Rec));
546bool TGParser::addDefOne(std::unique_ptr<Record> Rec) {
547 const Init *NewName =
nullptr;
548 if (
const Record *Prev = Records.
getDef(Rec->getNameInitAsString())) {
549 if (!Rec->isAnonymous()) {
551 "def already exists: " + Rec->getNameInitAsString());
552 PrintNote(Prev->getLoc(),
"location of previous definition");
561 if (!isa<StringInit>(Rec->getNameInit())) {
563 Rec->getNameInit()->getAsString() +
564 "' could not be fully resolved");
569 Rec->checkRecordAssertions();
572 Rec->emitRecordDumps();
575 assert(Rec->getTemplateArgs().empty() &&
"How'd this get template args?");
579 if (!
I->getType()->typeIsA(
Defset->EltTy)) {
580 PrintError(Rec->getLoc(),
Twine(
"adding record of incompatible type '") +
581 I->getType()->getAsString() +
589 Records.
addDef(std::move(Rec));
593bool TGParser::resolveArguments(
const Record *Rec,
595 SMLoc Loc, ArgValueHandler ArgValueHandler) {
598 "Too many template arguments allowed");
602 for (
auto *Arg : ArgValues) {
603 const Init *ArgName =
nullptr;
604 const Init *ArgValue = Arg->getValue();
605 if (Arg->isPositional())
606 ArgName = ArgNames[Arg->getIndex()];
608 ArgName = Arg->getName();
612 return Error(Loc,
"We can only specify the template argument '" +
615 ArgValueHandler(ArgName, ArgValue);
620 for (
auto *UnsolvedArgName : UnsolvedArgNames) {
623 std::string
Name = UnsolvedArgName->getAsUnquotedString();
624 Error(Loc,
"value not specified for template argument '" +
Name +
"'");
629 ArgValueHandler(UnsolvedArgName,
Default);
640 return resolveArguments(
647bool TGParser::resolveArgumentsOfMultiClass(
652 return resolveArguments(&MC->
Rec, ArgValues, Loc,
654 Substs.emplace_back(Name, Value);
691 CurRec = &CurMultiClass->
Rec;
701 Name->resolveReferences(R);
715const Record *TGParser::ParseClassID() {
717 TokError(
"expected name for ClassID");
723 std::string Msg(
"Couldn't find class '" + Lex.
getCurStrVal() +
"'");
725 TokError(Msg +
". Use 'defm' if you meant to use multiclass '" +
729 }
else if (TrackReferenceLocs) {
744 TokError(
"expected name for MultiClassID");
763ParseSubClassReference(
Record *CurRec,
bool isDefm) {
771 Result.Rec = ParseClassID();
782 if (ParseTemplateArgValueList(
Result.TemplateArgs, ArgLocs, CurRec,
788 if (CheckTemplateArgValues(
Result.TemplateArgs, ArgLocs,
Result.Rec)) {
805ParseSubMultiClassReference(
MultiClass *CurMC) {
809 Result.MC = ParseMultiClassID();
819 if (ParseTemplateArgValueList(
Result.TemplateArgs, ArgLocs, &CurMC->
Rec,
841 auto LHSLoc = Lex.
getLoc();
842 auto *CurVal = ParseValue(CurRec);
845 const auto *
LHS = cast<TypedInit>(CurVal);
852 auto RHSLoc = Lex.
getLoc();
853 CurVal = ParseValue(CurRec);
856 RHS = cast<TypedInit>(CurVal);
867 TokError(
"invalid range, cannot be negative");
904const TypedInit *TGParser::ParseSliceElements(
Record *CurRec,
bool Single) {
909 auto FlushElems = [&] {
910 if (!Elems.
empty()) {
917 auto LHSLoc = Lex.
getLoc();
918 CurVal = ParseSliceElement(CurRec);
921 auto *CurValTy = CurVal->
getType();
923 if (
const auto *ListValTy = dyn_cast<ListRecTy>(CurValTy)) {
924 if (!isa<IntRecTy>(ListValTy->getElementType())) {
926 "expected list<int>, got " +
Twine(ListValTy->getAsString()));
934 }
else if (!isa<IntRecTy>(CurValTy)) {
936 "unhandled type " +
Twine(CurValTy->getAsString()) +
" in range");
964 for (
auto *Slice : Slices) {
980 const Init *CurVal = FirstItem;
982 CurVal = ParseValue(
nullptr);
984 const auto *
II = dyn_cast_or_null<IntInit>(CurVal);
986 return TokError(
"expected integer or bitrange");
988 int64_t Start =
II->getValue();
992 return TokError(
"invalid range, cannot be negative");
1003 const Init *I_End = ParseValue(
nullptr);
1004 const auto *II_End = dyn_cast_or_null<IntInit>(I_End);
1006 TokError(
"expected integer value as end of range");
1010 End = II_End->getValue();
1020 return TokError(
"invalid range, cannot be negative");
1024 for (; Start <=
End; ++Start)
1027 for (; Start >=
End; --Start)
1038 if (ParseRangePiece(Result)) {
1044 if (ParseRangePiece(Result)) {
1059 ParseRangeList(Ranges);
1060 if (
Ranges.empty())
return true;
1063 TokError(
"expected '>' at end of range list");
1064 return Error(StartLoc,
"to match this '<'");
1078 ParseRangeList(Ranges);
1079 if (
Ranges.empty())
return true;
1082 TokError(
"expected '}' at end of bit list");
1083 return Error(StartLoc,
"to match this '{'");
1099const RecTy *TGParser::ParseType() {
1101 default:
TokError(
"Unknown token when expecting a type");
return nullptr;
1117 if (
I != TypeAliases.end()) {
1121 if (
const Record *R = ParseClassID())
1128 TokError(
"expected '<' after bits type");
1132 TokError(
"expected integer in bits<n> type");
1137 TokError(
"expected '>' at end of bits<n> type");
1145 TokError(
"expected '<' after list type");
1149 const RecTy *SubType = ParseType();
1150 if (!SubType)
return nullptr;
1153 TokError(
"expected '>' at end of list<ty> type");
1163 SMRange NameLoc, IDParseMode Mode) {
1164 if (
const Init *
I = CurScope->getVar(Records, CurMultiClass,
Name, NameLoc,
1165 TrackReferenceLocs))
1168 if (Mode == ParseNameMode)
1173 if (TrackReferenceLocs) {
1174 if (
const auto *Def = dyn_cast<DefInit>(
I))
1175 Def->getDef()->appendReferenceLoc(NameLoc);
1182 if (CurRec && !CurRec->
isClass() && !CurMultiClass &&
1186 Error(NameLoc.
Start,
"Variable not defined: '" +
Name->getValue() +
"'");
1194const Init *TGParser::ParseOperation(
Record *CurRec,
const RecTy *ItemType) {
1221 Type = ParseOperatorType();
1224 TokError(
"did not get type for unary operator");
1283 Type = ParseOperatorType();
1286 TokError(
"did not get type for unary operator");
1290 if (!isa<RecordRecTy>(
Type)) {
1291 TokError(
"type for !getdagop must be a record type");
1306 TokError(
"expected '(' after unary operator");
1310 const Init *
LHS = ParseValue(CurRec);
1311 if (!LHS)
return nullptr;
1314 const auto *LHSl = dyn_cast<ListInit>(LHS);
1315 const auto *LHSs = dyn_cast<StringInit>(LHS);
1316 const auto *LHSd = dyn_cast<DagInit>(LHS);
1317 const auto *LHSt = dyn_cast<TypedInit>(LHS);
1318 if (!LHSl && !LHSs && !LHSd && !LHSt) {
1319 TokError(
"expected string, list, or dag type argument in unary operator");
1323 if (!isa<ListRecTy, StringRecTy, DagRecTy>(LHSt->getType())) {
1324 TokError(
"expected string, list, or dag type argument in unary operator");
1332 const auto *LHSl = dyn_cast<ListInit>(LHS);
1333 const auto *LHSt = dyn_cast<TypedInit>(LHS);
1334 if (!LHSl && !LHSt) {
1335 TokError(
"expected list type argument in unary operator");
1339 if (!isa<ListRecTy>(LHSt->getType())) {
1340 TokError(
"expected list type argument in unary operator");
1345 if (LHSl && LHSl->empty()) {
1346 TokError(
"empty list argument in unary operator");
1349 bool UseElementType =
1352 const Init *Item = LHSl->getElement(0);
1353 const auto *Itemt = dyn_cast<TypedInit>(Item);
1355 TokError(
"untyped list element in unary operator");
1358 Type = UseElementType ? Itemt->getType()
1361 assert(LHSt &&
"expected list type argument in unary operator");
1362 const auto *LType = dyn_cast<ListRecTy>(LHSt->getType());
1363 Type = UseElementType ? LType->getElementType() : LType;
1369 const auto *InnerListTy = dyn_cast<ListRecTy>(
Type);
1381 TokError(
"expected ')' in unary operator");
1391 const RecTy *
Type = ParseOperatorType();
1396 TokError(
"expected '(' after type of !isa");
1400 const Init *
LHS = ParseValue(CurRec);
1416 const RecTy *
Type = ParseOperatorType();
1421 TokError(
"expected '(' after type of !exists");
1426 const Init *Expr = ParseValue(CurRec);
1430 const auto *ExprType = dyn_cast<TypedInit>(Expr);
1432 Error(ExprLoc,
"expected string type argument in !exists operator");
1436 const auto *RecType = dyn_cast<RecordRecTy>(ExprType->getType());
1439 "expected string type argument in !exists operator, please "
1440 "use !isa instead");
1444 const auto *SType = dyn_cast<StringRecTy>(ExprType->getType());
1446 Error(ExprLoc,
"expected string type argument in !exists operator");
1451 TokError(
"expected ')' in !exists");
1524 const RecTy *ArgType =
nullptr;
1534 Type = ParseOperatorType();
1536 TokError(
"did not get type for !getdagarg operator");
1587 if (
Type && ItemType && !
Type->typeIsConvertibleTo(ItemType)) {
1588 Error(OpLoc,
Twine(
"expected value of type '") +
1590 Type->getAsString() +
"'");
1595 TokError(
"expected '(' after binary operator");
1605 InitList.
push_back(ParseValue(CurRec, ArgType));
1606 if (!InitList.
back())
return nullptr;
1608 const auto *InitListBack = dyn_cast<TypedInit>(InitList.
back());
1609 if (!InitListBack) {
1610 Error(OpLoc,
Twine(
"expected value to be a typed value, got '" +
1611 InitList.
back()->getAsString() +
"'"));
1614 const RecTy *ListType = InitListBack->getType();
1622 if (!isa<ListRecTy>(ArgType)) {
1623 Error(InitLoc,
Twine(
"expected a list, got value of type '") +
1629 if (ItemType && InitList.
size() == 1) {
1630 if (!isa<ListRecTy>(ItemType)) {
1632 Twine(
"expected output type to be a list, got type '") +
1637 Error(OpLoc,
Twine(
"expected first arg type to be '") +
1639 "', got value of type '" +
1640 cast<ListRecTy>(ItemType)
1647 if (InitList.
size() == 2 && !isa<IntRecTy>(ArgType)) {
1648 Error(InitLoc,
Twine(
"expected second parameter to be an int, got "
1649 "value of type '") +
1656 if (!isa<ListRecTy>(ArgType)) {
1657 Error(InitLoc,
Twine(
"expected a list, got value of type '") +
1667 Error(InitLoc,
Twine(
"expected bit, bits, int, string, or record; "
1668 "got value of type '") +
1681 Error(InitLoc,
Twine(
"expected bit, bits, int, or string; "
1682 "got value of type '") +
1688 switch (InitList.
size()) {
1693 Error(InitLoc,
Twine(
"expected list of string, int, bits, or bit; "
1694 "got value of type '") +
1700 if (!isa<StringRecTy>(ArgType)) {
1701 Error(InitLoc,
Twine(
"expected second argument to be a string, "
1702 "got value of type '") +
1718 Error(InitLoc,
Twine(
"expected value of type '") +
1757 TokError(
"expected ')' in operator");
1766 Type = cast<TypedInit>(InitList.
front())->getType()->getListTy();
1777 while (InitList.
size() > 2) {
1784 if (InitList.
size() == 2)
1788 Error(OpLoc,
"expected two operands to operator");
1794 return ParseOperationForEachFilter(CurRec, ItemType);
1802 TokError(
"expected '(' after !range operator");
1807 bool FirstArgIsList =
false;
1809 if (
Args.size() >= 3) {
1810 TokError(
"expected at most three values of integer");
1815 Args.push_back(ParseValue(CurRec));
1819 const auto *ArgBack = dyn_cast<TypedInit>(
Args.back());
1821 Error(OpLoc,
Twine(
"expected value to be a typed value, got '" +
1822 Args.back()->getAsString() +
"'"));
1826 const RecTy *ArgBackType = ArgBack->getType();
1827 if (!FirstArgIsList ||
Args.size() == 1) {
1828 if (
Args.size() == 1 && isa<ListRecTy>(ArgBackType)) {
1829 FirstArgIsList =
true;
1830 }
else if (isa<IntRecTy>(ArgBackType)) {
1833 if (
Args.size() != 1)
1834 Error(InitLoc,
Twine(
"expected value of type 'int', got '" +
1837 Error(InitLoc,
Twine(
"expected list or int, got value of type '") +
1843 assert(isa<ListRecTy>(cast<TypedInit>(Args[0])->
getType()));
1844 Error(InitLoc,
Twine(
"expected one list, got extra value of type '") +
1853 TokError(
"expected ')' in operator");
1858 auto ArgCount =
Args.size();
1860 const auto *Arg0 = cast<TypedInit>(Args[0]);
1861 const auto *Arg0Ty = Arg0->getType();
1862 if (ArgCount == 1) {
1863 if (isa<ListRecTy>(Arg0Ty)) {
1870 assert(isa<IntRecTy>(Arg0Ty));
1877 assert(isa<IntRecTy>(Arg0Ty));
1878 const auto *Arg1 = cast<TypedInit>(Args[1]);
1879 assert(isa<IntRecTy>(Arg1->getType()));
1882 if (ArgCount == 3) {
1884 const auto *Arg2 = cast<TypedInit>(Args[2]);
1885 assert(isa<IntRecTy>(Arg2->getType()));
1931 TokError(
"expected '(' after ternary operator");
1935 const Init *
LHS = ParseValue(CurRec);
1936 if (!LHS)
return nullptr;
1939 TokError(
"expected ',' in ternary operator");
1944 const Init *MHS = ParseValue(CurRec, ItemType);
1949 TokError(
"expected ',' in ternary operator");
1954 const Init *
RHS = ParseValue(CurRec, ItemType);
1959 TokError(
"expected ')' in binary operator");
1966 const auto *MHSt = dyn_cast<TypedInit>(MHS);
1967 if (!MHSt && !isa<UnsetInit>(MHS)) {
1968 Error(MHSLoc,
"could not determine type of the child list in !dag");
1971 if (MHSt && !isa<ListRecTy>(MHSt->getType())) {
1972 Error(MHSLoc,
Twine(
"expected list of children, got type '") +
1973 MHSt->getType()->getAsString() +
"'");
1977 const auto *RHSt = dyn_cast<TypedInit>(RHS);
1978 if (!RHSt && !isa<UnsetInit>(RHS)) {
1979 Error(RHSLoc,
"could not determine type of the name list in !dag");
1983 Error(RHSLoc,
Twine(
"expected list<string>, got type '") +
1984 RHSt->getType()->getAsString() +
"'");
1988 if (!MHSt && !RHSt) {
1990 "cannot have both unset children and unset names in !dag");
1996 const RecTy *MHSTy =
nullptr;
1997 const RecTy *RHSTy =
nullptr;
1999 if (
const auto *MHSt = dyn_cast<TypedInit>(MHS))
2000 MHSTy = MHSt->getType();
2001 if (
const auto *MHSbits = dyn_cast<BitsInit>(MHS))
2003 if (isa<BitInit>(MHS))
2006 if (
const auto *RHSt = dyn_cast<TypedInit>(RHS))
2007 RHSTy = RHSt->getType();
2008 if (
const auto *RHSbits = dyn_cast<BitsInit>(RHS))
2010 if (isa<BitInit>(RHS))
2014 if (isa<UnsetInit>(MHS))
2016 if (isa<UnsetInit>(RHS))
2019 if (!MHSTy || !RHSTy) {
2020 TokError(
"could not get type for !if");
2033 const auto *RHSt = dyn_cast<TypedInit>(RHS);
2035 TokError(
"could not get type for !subst");
2038 Type = RHSt->getType();
2042 const auto *MHSt = dyn_cast<TypedInit>(MHS);
2043 if (!MHSt || !isa<IntRecTy, StringRecTy>(MHSt->getType())) {
2044 Error(MHSLoc,
Twine(
"expected integer index or string name, got ") +
2045 (MHSt ? (
"type '" + MHSt->getType()->getAsString())
2053 const auto *MHSt = dyn_cast<TypedInit>(MHS);
2054 if (!MHSt || !isa<IntRecTy, StringRecTy>(MHSt->getType())) {
2055 Error(MHSLoc,
Twine(
"expected integer index or string name, got ") +
2056 (MHSt ? (
"type '" + MHSt->getType()->getAsString())
2061 const auto *RHSt = dyn_cast<TypedInit>(RHS);
2063 if (RHSt && !isa<StringRecTy>(RHSt->getType())) {
2064 Error(RHSLoc,
Twine(
"expected string or unset name, got type '") +
2065 RHSt->getType()->getAsString() +
"'");
2075 return ParseOperationSubstr(CurRec, ItemType);
2078 return ParseOperationFind(CurRec, ItemType);
2081 return ParseOperationCond(CurRec, ItemType);
2087 TokError(
"expected '(' after !foldl");
2091 const Init *StartUntyped = ParseValue(CurRec);
2095 const auto *Start = dyn_cast<TypedInit>(StartUntyped);
2103 TokError(
"expected ',' in !foldl");
2107 const Init *ListUntyped = ParseValue(CurRec);
2111 const auto *
List = dyn_cast<TypedInit>(ListUntyped);
2118 const auto *ListType = dyn_cast<ListRecTy>(
List->getType());
2120 TokError(
Twine(
"!foldl list must be a list, but is of type '") +
2121 List->getType()->getAsString());
2126 TokError(
"expected ',' in !foldl");
2131 TokError(
"third argument of !foldl must be an identifier");
2138 "' already defined")
2144 TokError(
"expected ',' in !foldl");
2149 TokError(
"fourth argument of !foldl must be an identifier");
2156 "' already defined")
2162 TokError(
"expected ',' in !foldl");
2169 std::unique_ptr<Record> ParseRecTmp;
2170 Record *ParseRec = CurRec;
2172 ParseRecTmp = std::make_unique<Record>(
".parse",
ArrayRef<SMLoc>{}, Records);
2173 ParseRec = ParseRecTmp.get();
2180 const Init *ExprUntyped = ParseValue(ParseRec);
2181 ParseRec->removeValue(
A);
2182 ParseRec->removeValue(
B);
2187 const auto *Expr = dyn_cast<TypedInit>(ExprUntyped);
2189 TokError(
"could not get type of !foldl expression");
2193 if (Expr->getType() != Start->getType()) {
2194 TokError(
Twine(
"!foldl expression must be of same type as start (") +
2195 Start->getType()->getAsString() +
"), but is of type " +
2201 TokError(
"expected ')' in fold operator");
2216const RecTy *TGParser::ParseOperatorType() {
2220 TokError(
"expected type name for operator");
2225 TokError(
"the 'code' type is not allowed in bang operators; use 'string'");
2230 TokError(
"expected type name for operator");
2235 TokError(
"expected type name for operator");
2245const Init *TGParser::ParseOperationSubstr(
Record *CurRec,
2246 const RecTy *ItemType) {
2253 TokError(
"expected '(' after !substr operator");
2257 const Init *
LHS = ParseValue(CurRec);
2262 TokError(
"expected ',' in !substr operator");
2267 const Init *MHS = ParseValue(CurRec);
2275 RHS = ParseValue(CurRec);
2283 TokError(
"expected ')' in !substr operator");
2287 if (ItemType && !
Type->typeIsConvertibleTo(ItemType)) {
2288 Error(RHSLoc,
Twine(
"expected value of type '") +
2290 Type->getAsString() +
"'");
2293 const auto *LHSt = dyn_cast<TypedInit>(LHS);
2294 if (!LHSt && !isa<UnsetInit>(LHS)) {
2295 TokError(
"could not determine type of the string in !substr");
2298 if (LHSt && !isa<StringRecTy>(LHSt->getType())) {
2300 LHSt->getType()->getAsString() +
"'");
2304 const auto *MHSt = dyn_cast<TypedInit>(MHS);
2305 if (!MHSt && !isa<UnsetInit>(MHS)) {
2306 TokError(
"could not determine type of the start position in !substr");
2309 if (MHSt && !isa<IntRecTy>(MHSt->getType())) {
2310 Error(MHSLoc,
Twine(
"expected int, got type '") +
2311 MHSt->getType()->getAsString() +
"'");
2316 const auto *RHSt = dyn_cast<TypedInit>(RHS);
2317 if (!RHSt && !isa<UnsetInit>(RHS)) {
2318 TokError(
"could not determine type of the length in !substr");
2321 if (RHSt && !isa<IntRecTy>(RHSt->getType())) {
2323 RHSt->getType()->getAsString() +
"'");
2334const Init *TGParser::ParseOperationFind(
Record *CurRec,
2335 const RecTy *ItemType) {
2342 TokError(
"expected '(' after !find operator");
2346 const Init *
LHS = ParseValue(CurRec);
2351 TokError(
"expected ',' in !find operator");
2356 const Init *MHS = ParseValue(CurRec);
2364 RHS = ParseValue(CurRec);
2372 TokError(
"expected ')' in !find operator");
2376 if (ItemType && !
Type->typeIsConvertibleTo(ItemType)) {
2377 Error(RHSLoc,
Twine(
"expected value of type '") +
2379 Type->getAsString() +
"'");
2382 const auto *LHSt = dyn_cast<TypedInit>(LHS);
2383 if (!LHSt && !isa<UnsetInit>(LHS)) {
2384 TokError(
"could not determine type of the source string in !find");
2387 if (LHSt && !isa<StringRecTy>(LHSt->getType())) {
2389 LHSt->getType()->getAsString() +
"'");
2393 const auto *MHSt = dyn_cast<TypedInit>(MHS);
2394 if (!MHSt && !isa<UnsetInit>(MHS)) {
2395 TokError(
"could not determine type of the target string in !find");
2398 if (MHSt && !isa<StringRecTy>(MHSt->getType())) {
2399 Error(MHSLoc,
Twine(
"expected string, got type '") +
2400 MHSt->getType()->getAsString() +
"'");
2405 const auto *RHSt = dyn_cast<TypedInit>(RHS);
2406 if (!RHSt && !isa<UnsetInit>(RHS)) {
2407 TokError(
"could not determine type of the start position in !find");
2410 if (RHSt && !isa<IntRecTy>(RHSt->getType())) {
2412 RHSt->getType()->getAsString() +
"'");
2424const Init *TGParser::ParseOperationForEachFilter(
Record *CurRec,
2425 const RecTy *ItemType) {
2430 TokError(
"expected '(' after !foreach/!filter");
2435 TokError(
"first argument of !foreach/!filter must be an identifier");
2442 if (CurRec && CurRec->
getValue(LHS)) {
2444 "' is already defined")
2450 TokError(
"expected ',' in !foreach/!filter");
2454 const Init *MHS = ParseValue(CurRec);
2459 TokError(
"expected ',' in !foreach/!filter");
2463 const auto *MHSt = dyn_cast<TypedInit>(MHS);
2465 TokError(
"could not get type of !foreach/!filter list or dag");
2469 const RecTy *InEltType =
nullptr;
2470 const RecTy *ExprEltType =
nullptr;
2473 if (
const auto *InListTy = dyn_cast<ListRecTy>(MHSt->getType())) {
2474 InEltType = InListTy->getElementType();
2476 if (
const auto *OutListTy = dyn_cast<ListRecTy>(ItemType)) {
2478 ? OutListTy->getElementType()
2482 "expected value of type '" +
2484 "', but got list type");
2488 }
else if (
const auto *InDagTy = dyn_cast<DagRecTy>(MHSt->getType())) {
2490 TokError(
"!filter must have a list argument");
2493 InEltType = InDagTy;
2494 if (ItemType && !isa<DagRecTy>(ItemType)) {
2497 "', but got dag type");
2503 TokError(
"!foreach must have a list or dag argument");
2505 TokError(
"!filter must have a list argument");
2511 std::unique_ptr<Record> ParseRecTmp;
2512 Record *ParseRec = CurRec;
2516 ParseRec = ParseRecTmp.get();
2520 const Init *
RHS = ParseValue(ParseRec, ExprEltType);
2521 ParseRec->removeValue(LHS);
2527 TokError(
"expected ')' in !foreach/!filter");
2531 const RecTy *OutType = InEltType;
2533 const auto *RHSt = dyn_cast<TypedInit>(RHS);
2535 TokError(
"could not get type of !foreach result expression");
2545 LHS, MHS, RHS, OutType))
2549const Init *TGParser::ParseOperationCond(
Record *CurRec,
2550 const RecTy *ItemType) {
2554 TokError(
"expected '(' after !cond operator");
2565 const Init *
V = ParseValue(CurRec);
2571 TokError(
"expected ':' following a condition in !cond operator");
2575 V = ParseValue(CurRec, ItemType);
2584 TokError(
"expected ',' or ')' following a value in !cond operator");
2589 if (Case.
size() < 1) {
2590 TokError(
"there should be at least 1 'condition : value' in the !cond operator");
2596 for (
const Init *V : Val) {
2597 const RecTy *VTy =
nullptr;
2598 if (
const auto *Vt = dyn_cast<TypedInit>(V))
2599 VTy = Vt->getType();
2600 if (
const auto *Vbits = dyn_cast<BitsInit>(V))
2602 if (isa<BitInit>(V))
2605 if (
Type ==
nullptr) {
2606 if (!isa<UnsetInit>(V))
2609 if (!isa<UnsetInit>(V)) {
2622 TokError(
"could not determine type for !cond from its arguments");
2655const Init *TGParser::ParseSimpleValue(
Record *CurRec,
const RecTy *ItemType,
2657 const Init *
R =
nullptr;
2662 return ParseOperation(CurRec, ItemType);
2665 default:
TokError(
"Unknown or reserved token when parsing a value");
break;
2682 for (
unsigned i = 0, e = BinaryVal.second; i != e; ++i)
2716 return ParseIDValue(CurRec,
Name, NameLoc, Mode);
2724 "Expected a class name, got '" +
Name->getValue() +
"'");
2731 if (ParseTemplateArgValueList(Args, ArgLocs, CurRec, Class))
2734 if (CheckTemplateArgValues(Args, ArgLocs, Class))
2737 if (resolveArguments(Class, Args, NameLoc.
Start))
2740 if (TrackReferenceLocs)
2741 Class->appendReferenceLoc(NameLoc);
2750 ParseValueList(Vals, CurRec);
2751 if (Vals.
empty())
return nullptr;
2754 TokError(
"expected '}' at end of bit list value");
2763 for (
unsigned i = 0, e = Vals.
size(); i != e; ++i) {
2768 if (
const auto *BI = dyn_cast<BitsInit>(Vals[i])) {
2769 for (
unsigned i = 0, e = BI->getNumBits(); i != e; ++i)
2774 if (
const auto *VI = dyn_cast<VarInit>(Vals[i])) {
2775 if (
const auto *BitsRec = dyn_cast<BitsRecTy>(
VI->getType())) {
2776 for (
unsigned i = 0, e = BitsRec->getNumBits(); i != e; ++i)
2785 Error(BraceLoc,
"Element #" +
Twine(i) +
" (" + Vals[i]->getAsString() +
2786 ") is not convertable to a bit");
2791 std::reverse(NewBits.
begin(), NewBits.
end());
2798 const RecTy *DeducedEltTy =
nullptr;
2802 const auto *ListType = dyn_cast<ListRecTy>(ItemType);
2808 GivenListTy = ListType;
2812 ParseValueList(Vals, CurRec,
2814 if (Vals.
empty())
return nullptr;
2817 TokError(
"expected ']' at end of list value");
2821 const RecTy *GivenEltTy =
nullptr;
2824 GivenEltTy = ParseType();
2831 TokError(
"expected '>' at end of list element type");
2837 const RecTy *EltTy =
nullptr;
2838 for (
const Init *V : Vals) {
2839 const auto *TArg = dyn_cast<TypedInit>(V);
2844 TokError(
"Incompatible types in list elements");
2848 EltTy = TArg->getType();
2857 TokError(
"Incompatible types in list elements");
2874 TokError(
Twine(
"Element type mismatch for list: element type '") +
2880 DeducedEltTy = EltTy;
2891 TokError(
"expected identifier or list of value types in dag init");
2902 TokError(
"expected variable name in dag operator");
2911 ParseDagArgList(DagArgs, CurRec);
2912 if (DagArgs.
empty())
return nullptr;
2916 TokError(
"expected ')' in dag init");
2934const Init *TGParser::ParseValue(
Record *CurRec,
const RecTy *ItemType,
2937 const Init *
Result = ParseSimpleValue(CurRec, ItemType, Mode);
2938 if (!Result)
return nullptr;
2945 if (Mode == ParseNameMode)
2952 ParseRangeList(Ranges);
2953 if (
Ranges.empty())
return nullptr;
2959 Error(CurlyLoc,
"Invalid bit range for value");
2965 TokError(
"expected '}' at end of bit range list");
2971 const auto *
LHS = dyn_cast<TypedInit>(Result);
2973 Error(LHSLoc,
"Invalid value, list expected");
2977 const auto *LHSTy = dyn_cast<ListRecTy>(
LHS->
getType());
2980 "' is invalid, list expected");
2985 const TypedInit *
RHS = ParseSliceElements(CurRec,
true);
2994 LHSTy->getElementType())
3002 TokError(
"expected ']' at end of list slice");
3009 TokError(
"expected field identifier after '.'");
3015 if (!
Result->getFieldType(FieldName)) {
3017 Result->getAsString() +
"'");
3022 if (TrackReferenceLocs) {
3023 if (
const auto *DI = dyn_cast<DefInit>(Result)) {
3024 const RecordVal *
V = DI->getDef()->getValue(FieldName);
3025 const_cast<RecordVal *
>(
V)->addReferenceLoc(FieldNameLoc);
3026 }
else if (
const auto *TI = dyn_cast<TypedInit>(Result)) {
3027 if (
const auto *
RecTy = dyn_cast<RecordRecTy>(TI->getType())) {
3029 if (
const auto *RV =
R->getValue(FieldName))
3042 const auto *
LHS = dyn_cast<TypedInit>(Result);
3044 Error(PasteLoc,
"LHS of paste is not typed!");
3052 assert(Mode == ParseValueMode &&
"encountered paste of lists in name");
3061 const Init *RHSResult = ParseValue(CurRec, ItemType, ParseValueMode);
3073 auto CastLHS = dyn_cast<TypedInit>(
3078 Twine(
"can't cast '") +
LHS->getAsString() +
"' to string");
3100 const Init *RHSResult = ParseValue(CurRec,
nullptr, ParseNameMode);
3103 RHS = dyn_cast<TypedInit>(RHSResult);
3105 Error(PasteLoc,
"RHS of paste is not typed!");
3110 auto CastRHS = dyn_cast<TypedInit>(
3115 Twine(
"can't cast '") +
RHS->getAsString() +
"' to string");
3136void TGParser::ParseDagArgList(
3149 const Init *Val = ParseValue(CurRec);
3159 TokError(
"expected variable name in dag literal");
3167 Result.emplace_back(Val, VarName);
3182 Result.push_back(ParseValue(CurRec, ItemType));
3192 Result.push_back(ParseValue(CurRec, ItemType));
3208bool TGParser::ParseTemplateArgValueList(
3211 assert(
Result.empty() &&
"Result vector is not empty");
3217 bool HasNamedArg =
false;
3218 unsigned ArgIndex = 0;
3220 if (ArgIndex >= TArgs.
size()) {
3221 TokError(
"Too many template arguments: " + utostr(ArgIndex + 1));
3230 HasNamedArg ?
nullptr : ArgsRec->
getValue(TArgs[ArgIndex])->
getType());
3236 if (!isa<StringInit>(
Value))
3237 return Error(ValueLoc,
3238 "The name of named argument should be a valid identifier");
3244 return Error(ValueLoc,
3245 "Argument " +
Name->getAsString() +
" doesn't exist");
3249 Value = ParseValue(CurRec, NamedArg->getType());
3251 if (isa<UnsetInit>(
Value))
3252 return Error(ValueLoc,
3253 "The value of named argument should be initialized, "
3255 Value->getAsString() +
"'");
3262 return Error(ValueLoc,
3263 "Positional argument should be put before named argument");
3271 return TokError(
"Expected comma before next argument");
3286const Init *TGParser::ParseDeclaration(
Record *CurRec,
3287 bool ParsingTemplateArgs) {
3292 if (!
Type)
return nullptr;
3295 TokError(
"Expected identifier in declaration");
3300 if (Str ==
"NAME") {
3301 TokError(
"'" + Str +
"' is a reserved variable name");
3305 if (!ParsingTemplateArgs && CurScope->varAlreadyDefined(Str)) {
3306 TokError(
"local variable of this name already exists");
3315 if (!ParsingTemplateArgs) {
3316 BadField = AddValue(CurRec, IdLoc,
3320 }
else if (CurRec) {
3323 AddValue(CurRec, IdLoc,
3326 assert(CurMultiClass &&
"invalid context for template argument");
3329 AddValue(CurRec, IdLoc,
3338 const Init *Val = ParseValue(CurRec,
Type);
3340 SetValue(CurRec, ValLoc, DeclName, {}, Val,
3361TGParser::ParseForeachDeclaration(
const Init *&ForeachListValue) {
3363 TokError(
"Expected identifier in foreach declaration");
3372 TokError(
"Expected '=' in foreach declaration");
3376 const RecTy *IterType =
nullptr;
3382 ParseRangeList(Ranges);
3384 TokError(
"expected '}' at end of bit range list");
3392 const Init *
I = ParseValue(
nullptr);
3396 const auto *TI = dyn_cast<TypedInit>(
I);
3397 if (TI && isa<ListRecTy>(TI->getType())) {
3398 ForeachListValue =
I;
3399 IterType = cast<ListRecTy>(TI->getType())->getElementType();
3404 if (ParseRangePiece(Ranges, TI))
3409 Error(ValueLoc,
"expected a list, got '" +
I->getAsString() +
"'");
3410 if (CurMultiClass) {
3411 PrintNote({},
"references to multiclass template arguments cannot be "
3412 "resolved at this time");
3420 assert(!IterType &&
"Type already initialized?");
3422 std::vector<Init *> Values;
3423 for (
unsigned R : Ranges)
3441bool TGParser::ParseTemplateArgList(
Record *CurRec) {
3445 Record *TheRecToAddTo = CurRec ? CurRec : &CurMultiClass->
Rec;
3448 const Init *TemplArg = ParseDeclaration(CurRec,
true );
3457 TemplArg = ParseDeclaration(CurRec,
true);
3462 return Error(Loc,
"template argument with the same name has already been "
3469 return TokError(
"expected '>' at end of template argument list");
3481bool TGParser::ParseBodyItem(
Record *CurRec) {
3483 return ParseAssert(
nullptr, CurRec);
3486 return ParseDefvar(CurRec);
3489 return ParseDump(
nullptr, CurRec);
3492 if (!ParseDeclaration(CurRec,
false))
3496 return TokError(
"expected ';' after declaration");
3502 return TokError(
"expected field identifier after let");
3509 if (ParseOptionalBitList(BitList))
3511 std::reverse(BitList.
begin(), BitList.
end());
3514 return TokError(
"expected '=' in let expression");
3518 return Error(IdLoc,
"Value '" + FieldName->
getValue() +
"' unknown!");
3521 if (!BitList.
empty() && isa<BitsRecTy>(
Type)) {
3527 const Init *Val = ParseValue(CurRec,
Type);
3528 if (!Val)
return true;
3531 return TokError(
"expected ';' after let expression");
3533 return SetValue(CurRec, IdLoc, FieldName, BitList, Val);
3543bool TGParser::ParseBody(
Record *CurRec) {
3549 return TokError(
"Expected '{' to start body or ';' for declaration only");
3552 if (ParseBodyItem(CurRec))
3561 PrintError(SemiLoc,
"A class or def body should not end with a semicolon");
3562 PrintNote(
"Semicolon ignored; remove to eliminate this error");
3570bool TGParser::ApplyLetStack(
Record *CurRec) {
3573 if (SetValue(CurRec, LR.Loc, LR.Name, LR.Bits, LR.Value))
3581 return ApplyLetStack(
Entry.Rec.get());
3584 if (
Entry.Assertion)
3591 for (
auto &E :
Entry.Loop->Entries) {
3592 if (ApplyLetStack(E))
3608bool TGParser::ParseObjectBody(
Record *CurRec) {
3618 if (!SubClass.
Rec)
return true;
3621 if (AddSubClass(CurRec, SubClass))
3626 SubClass = ParseSubClassReference(CurRec,
false);
3630 if (ApplyLetStack(CurRec))
3633 bool Result = ParseBody(CurRec);
3643bool TGParser::ParseDef(
MultiClass *CurMultiClass) {
3654 std::unique_ptr<Record> CurRec;
3655 const Init *
Name = ParseObjectName(CurMultiClass);
3659 if (isa<UnsetInit>(
Name)) {
3663 CurRec = std::make_unique<Record>(
Name, NameLoc, Records);
3666 if (ParseObjectBody(CurRec.get()))
3669 return addEntry(std::move(CurRec));
3676bool TGParser::ParseDefset() {
3685 if (!isa<ListRecTy>(
Type))
3687 Defset.EltTy = cast<ListRecTy>(
Type)->getElementType();
3690 return TokError(
"expected identifier");
3693 return TokError(
"def or global variable of this name already exists");
3702 Defsets.push_back(&Defset);
3703 bool Err = ParseObjectList(
nullptr);
3709 TokError(
"expected '}' at end of defset");
3710 return Error(BraceLoc,
"to match this '{'");
3722bool TGParser::ParseDeftype() {
3727 return TokError(
"expected identifier");
3730 if (TypeAliases.count(TypeName) || Records.
getClass(TypeName))
3731 return TokError(
"type of this name '" + TypeName +
"' already exists");
3743 return Error(Loc,
"cannot define type alias for class type '" +
3744 Type->getAsString() +
"'");
3758bool TGParser::ParseDefvar(
Record *CurRec) {
3763 return TokError(
"expected identifier");
3765 if (CurScope->varAlreadyDefined(DeclName->
getValue()))
3766 return TokError(
"local variable of this name already exists");
3771 if (V && !
V->isTemplateArg())
3772 return TokError(
"field of this name already exists");
3778 return TokError(
"def or global variable of this name already exists");
3791 if (!CurScope->isOutermost())
3805bool TGParser::ParseForeach(
MultiClass *CurMultiClass) {
3812 const Init *ListValue =
nullptr;
3813 const VarInit *IterName = ParseForeachDeclaration(ListValue);
3815 return TokError(
"expected declaration in for");
3821 auto TheLoop = std::make_unique<ForeachLoop>(Loc, IterName, ListValue);
3824 Loops.push_back(std::move(TheLoop));
3828 if (ParseObject(CurMultiClass))
3836 if (ParseObjectList(CurMultiClass))
3840 TokError(
"expected '}' at end of foreach command");
3841 return Error(BraceLoc,
"to match this '{'");
3848 std::unique_ptr<ForeachLoop>
Loop = std::move(Loops.back());
3851 return addEntry(std::move(
Loop));
3859bool TGParser::ParseIf(
MultiClass *CurMultiClass) {
3866 const Init *Condition = ParseValue(
nullptr);
3886 const Init *ThenClauseList =
3890 Loops.push_back(std::make_unique<ForeachLoop>(Loc,
nullptr, ThenClauseList));
3892 if (ParseIfBody(CurMultiClass,
"then"))
3895 std::unique_ptr<ForeachLoop>
Loop = std::move(Loops.back());
3898 if (addEntry(std::move(
Loop)))
3908 const Init *ElseClauseList =
3913 std::make_unique<ForeachLoop>(Loc,
nullptr, ElseClauseList));
3915 if (ParseIfBody(CurMultiClass,
"else"))
3918 Loop = std::move(Loops.back());
3921 if (addEntry(std::move(
Loop)))
3939 if (ParseObject(CurMultiClass))
3947 if (ParseObjectList(CurMultiClass))
3951 TokError(
"expected '}' at end of '" + Kind +
"' clause");
3952 return Error(BraceLoc,
"to match this '{'");
3968 const Init *Condition = ParseValue(CurRec);
3973 TokError(
"expected ',' in assert statement");
3977 const Init *Message = ParseValue(CurRec);
3985 CurRec->
addAssertion(ConditionLoc, Condition, Message);
3987 addEntry(std::make_unique<Record::AssertionInfo>(ConditionLoc, Condition,
3996bool TGParser::ParseClass() {
4001 return TokError(
"expected class name after 'class' keyword");
4011 "' already defined");
4018 CurRec = NewRec.get();
4019 Records.
addClass(std::move(NewRec));
4022 if (TypeAliases.count(
Name))
4023 return TokError(
"there is already a defined type alias '" +
Name +
"'");
4031 if (ParseTemplateArgList(CurRec))
4034 if (ParseObjectBody(CurRec))
4037 if (!NoWarnOnUnusedTemplateArgs)
4053 TokError(
"expected identifier in let definition");
4064 if (ParseOptionalRangeList(Bits)) {
4068 std::reverse(
Bits.begin(),
Bits.end());
4071 TokError(
"expected '=' in let expression");
4076 const Init *Val = ParseValue(
nullptr);
4083 Result.emplace_back(
Name, Bits, Val, NameLoc);
4093bool TGParser::ParseTopLevelLet(
MultiClass *CurMultiClass) {
4099 ParseLetList(LetInfo);
4100 if (LetInfo.
empty())
return true;
4104 return TokError(
"expected 'in' at end of top-level 'let'");
4109 if (ParseObject(CurMultiClass))
4120 if (ParseObjectList(CurMultiClass))
4124 TokError(
"expected '}' at end of top level let command");
4125 return Error(BraceLoc,
"to match this '{'");
4149bool TGParser::ParseMultiClass() {
4154 return TokError(
"expected identifier after multiclass for name");
4157 auto Result = MultiClasses.try_emplace(
4158 Name, std::make_unique<MultiClass>(
Name, Lex.
getLoc(), Records));
4161 return TokError(
"multiclass '" +
Name +
"' already defined");
4163 CurMultiClass =
Result.first->second.get();
4171 if (ParseTemplateArgList(
nullptr))
4174 bool inherits =
false;
4182 ParseSubMultiClassReference(CurMultiClass);
4185 if (!SubMultiClass.
MC)
return true;
4188 if (AddSubMultiClass(CurMultiClass, SubMultiClass))
4193 SubMultiClass = ParseSubMultiClassReference(CurMultiClass);
4199 return TokError(
"expected '{' in multiclass definition");
4201 return TokError(
"expected ';' in multiclass definition");
4204 return TokError(
"multiclass must contain at least one def");
4209 return TokError(
"expected 'assert', 'def', 'defm', 'defvar', 'dump', "
4210 "'foreach', 'if', or 'let' in multiclass body");
4220 if (ParseObject(CurMultiClass))
4230 PrintError(SemiLoc,
"A multiclass body should not end with a semicolon");
4231 PrintNote(
"Semicolon ignored; remove to eliminate this error");
4235 if (!NoWarnOnUnusedTemplateArgs)
4239 CurMultiClass =
nullptr;
4247bool TGParser::ParseDefm(
MultiClass *CurMultiClass) {
4251 const Init *DefmName = ParseObjectName(CurMultiClass);
4254 if (isa<UnsetInit>(DefmName)) {
4264 return TokError(
"expected ':' after defm identifier");
4267 std::vector<RecordsEntry> NewEntries;
4270 bool InheritFromClass =
false;
4279 if (!
Ref.Rec)
return true;
4285 MultiClass *MC = MultiClasses[std::string(
Ref.Rec->getName())].get();
4286 assert(MC &&
"Didn't lookup multiclass correctly?");
4289 if (resolveArgumentsOfMultiClass(Substs, MC,
Ref.TemplateArgs, DefmName,
4293 if (resolve(MC->
Entries, Substs, !CurMultiClass && Loops.empty(),
4294 &NewEntries, &SubClassLoc))
4301 return TokError(
"expected identifier");
4303 SubClassLoc = Lex.
getLoc();
4309 if (InheritFromClass)
4312 Ref = ParseSubClassReference(
nullptr,
true);
4315 if (InheritFromClass) {
4321 if (!SubClass.
Rec)
return true;
4325 for (
auto &E : NewEntries) {
4327 if (AddSubClass(E, SubClass))
4333 SubClass = ParseSubClassReference(
nullptr,
false);
4337 for (
auto &E : NewEntries) {
4338 if (ApplyLetStack(E))
4341 addEntry(std::move(E));
4345 return TokError(
"expected ';' at end of defm");
4366 "Expected assert, class, def, defm, defset, dump, foreach, if, or let");
4371 return ParseDeftype();
4374 return ParseDump(MC);
4377 case tgtok::Let:
return ParseTopLevelLet(MC);
4380 return TokError(
"defset is not allowed inside multiclass");
4381 return ParseDefset();
4384 return TokError(
"class is not allowed inside multiclass");
4386 return TokError(
"class is not allowed inside foreach loop");
4387 return ParseClass();
4390 return TokError(
"multiclass is not allowed inside foreach loop");
4391 return ParseMultiClass();
4397bool TGParser::ParseObjectList(
MultiClass *MC) {
4399 if (ParseObject(MC))
4408 if (ParseObjectList())
4416 return TokError(
"Unexpected token at top level");
4423bool TGParser::CheckTemplateArgValues(
4427 "expected as many values as locations");
4431 bool HasError =
false;
4433 const Init *ArgName =
nullptr;
4434 if (
Value->isPositional())
4435 ArgName = TArgs[
Value->getIndex()];
4436 if (
Value->isNamed())
4442 if (
const auto *ArgValue = dyn_cast<TypedInit>(
Value->getValue())) {
4443 auto *CastValue = ArgValue->
getCastTo(ArgType);
4445 assert((!isa<TypedInit>(CastValue) ||
4446 cast<TypedInit>(CastValue)->
getType()->typeIsA(ArgType)) &&
4447 "result of template arg value cast has wrong type");
4451 Loc,
"Value specified for template argument '" +
4453 ArgValue->getType()->
getAsString() +
"; expected type " +
4462#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
4481 errs() <<
"Record:\n";
4484 errs() <<
"Defs:\n";
4496 const Init *Message = ParseValue(CurRec);
4502 if (isa<DefInit>(Message))
4510 CurRec->
addDump(Loc, Message);
4516 addEntry(std::make_unique<Record::DumpInfo>(Loc, ResolvedMessage));
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
uint64_t IntrinsicInst * II
PowerPC Reduce CR logical Operation
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the SmallVector class.
static bool checkBitsConcrete(Record &R, const RecordVal &RV)
static const Init * QualifyName(const Record &CurRec, const Init *Name)
Return an Init with a qualifier prefix referring to CurRec's name.
static const Init * QualifiedNameOfImplicitName(const Record &Rec)
Return the qualified version of the implicit 'NAME' template argument.
static void checkConcrete(Record &R)
static SymbolRef::Type getType(const Symbol *Sym)
static const ArgumentInit * get(const Init *Value, ArgAuxType Aux)
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)
static const Init * getStrConcat(const Init *lhs, const Init *rhs)
static const Init * getListConcat(const TypedInit *lhs, const Init *rhs)
const Init * Fold(const Record *CurRec) const
static BitInit * get(RecordKeeper &RK, bool V)
static const BitRecTy * get(RecordKeeper &RK)
static BitsInit * get(RecordKeeper &RK, ArrayRef< const Init * > Range)
static const BitsRecTy * get(RecordKeeper &RK, unsigned Sz)
static const CondOpInit * get(ArrayRef< const Init * > C, ArrayRef< const Init * > V, const RecTy *Type)
const Init * Fold(const Record *CurRec) const
static const DagInit * get(const Init *V, const StringInit *VN, ArrayRef< const Init * > ArgRange, ArrayRef< const StringInit * > NameRange)
static const DagRecTy * get(RecordKeeper &RK)
AL - Represent a reference to a 'def' in the description.
Lightweight error class with error context and mandatory checking.
static const ExistsOpInit * get(const RecTy *CheckType, const Init *Expr)
const Init * Fold(const Record *CurRec) const
static const FieldInit * get(const Init *R, const StringInit *FN)
const Init * Fold(const Record *CurRec) const
static const FoldOpInit * get(const Init *Start, const Init *List, const Init *A, const Init *B, const Init *Expr, const RecTy *Type)
Do not resolve anything, but keep track of whether a given variable was referenced.
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.
virtual std::string getAsString() const =0
Convert this value to a literal form.
virtual const Init * getBit(unsigned Bit) const =0
Get the Init value of the specified bit.
virtual const Init * getCastTo(const RecTy *Ty) const =0
If this value is convertible to type Ty, return a value whose type is Ty, generating a !...
static IntInit * get(RecordKeeper &RK, int64_t V)
static const IntRecTy * get(RecordKeeper &RK)
static const IsAOpInit * get(const RecTy *CheckType, const Init *Expr)
const Init * Fold() const
[AL, AH, CL] - Represent a list of defs
static const ListInit * get(ArrayRef< const Init * > Range, const RecTy *EltTy)
'list<Ty>' - Represent a list of element values, all of which must be of the specified type.
const RecTy * getElementType() const
static const ListRecTy * get(const RecTy *T)
bool typeIsConvertibleTo(const RecTy *RHS) const override
Return true if all values of 'this' type can be converted to the specified type.
Represents a single loop in the control flow graph.
Resolve arbitrary mappings.
This is a utility class that provides an abstraction for the common functionality between Instruction...
virtual bool typeIsConvertibleTo(const RecTy *RHS) const
Return true if all values of 'this' type can be converted to the specified type.
virtual std::string getAsString() const =0
const ListRecTy * getListTy() const
Returns the type representing list<thistype>.
void addDef(std::unique_ptr< Record > R)
void addClass(std::unique_ptr< Record > R)
const Record * getClass(StringRef Name) const
Get the class with the specified name.
const Init * getNewAnonymousName()
GetNewAnonymousName - Generate a unique anonymous name that can be used as an identifier.
const Init * getGlobal(StringRef Name) const
Get the Init value of the specified global variable.
void addExtraGlobal(StringRef Name, const Init *I)
const Record * getDef(StringRef Name) const
Get the concrete record with the specified name.
static const RecordRecTy * get(RecordKeeper &RK, ArrayRef< const Record * > Classes)
Get the record type with the given non-redundant list of superclasses.
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.
void setUsed(bool Used)
Whether this value is used.
bool setValue(const Init *V)
Set the value of the field from an Init.
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 addReferenceLoc(SMRange Loc)
Add a reference to this record value.
const Init * getNameInit() const
Get the name of the field as an Init.
const RecTy * getType() const
Get the type of the field value as a RecTy.
const RecordRecTy * getType() const
ArrayRef< std::pair< const Record *, SMRange > > getSuperClasses() const
void addDump(SMLoc Loc, const Init *Message)
void checkUnusedTemplateArgs()
std::string getNameInitAsString() const
RecordKeeper & getRecords() const
const RecordVal * getValue(const Init *Name) const
void addTemplateArg(const Init *Name)
bool isMultiClass() const
void addValue(const RecordVal &RV)
void addAssertion(SMLoc Loc, const Init *Condition, const Init *Message)
bool isTemplateArg(const Init *Name) const
void appendDumps(const Record *Rec)
bool isSubClassOf(const Record *R) const
ArrayRef< RecordVal > getValues() const
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...
ArrayRef< const Init * > getTemplateArgs() const
void updateClassLoc(SMLoc Loc)
void appendAssertions(const Record *Rec)
const Init * getNameInit() const
void addSuperClass(const Record *R, SMRange Range)
void setFinal(bool Final)
Represents a location in source code.
Represents a range in source code.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
reference emplace_back(ArgTypes &&... Args)
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)
StringRef getValue() const
static const StringRecTy * get(RecordKeeper &RK)
StringRef - Represent a constant reference to a string, i.e.
SMRange getLocRange() const
int64_t getCurIntVal() const
std::pair< int64_t, unsigned > getCurBinaryIntVal() const
const std::string & getCurStrVal() const
tgtok::TokKind getCode() const
void PopScope(TGVarScope *ExpectedStackTop)
bool TokError(const Twine &Msg) const
bool ParseFile()
ParseFile - Main entrypoint for parsing a tblgen file.
const Init * getVar(RecordKeeper &Records, MultiClass *ParsingMultiClass, const StringInit *Name, SMRange NameLoc, bool TrackReferenceLocs) const
const Init * Fold(const Record *CurRec) const
static const TernOpInit * get(TernaryOp opc, const Init *lhs, const Init *mhs, const Init *rhs, const RecTy *Type)
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 * getType() const
Get the type of the Init as a RecTy.
static const UnOpInit * get(UnaryOp opc, const Init *lhs, const RecTy *Type)
const Init * Fold(const Record *CurRec, bool IsFinal=false) const
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.
StringRef getName() const
Return a constant reference to the value's name.
static const VarDefInit * get(SMLoc Loc, const Record *Class, ArrayRef< const ArgumentInit * > Args)
const Init * Fold() const
'Opcode' - Represent a reference to an entire variable object.
static const VarInit * get(StringRef VN, const RecTy *T)
std::string getAsString() const override
Convert this value to a literal form.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char TypeName[]
Key for Kernel::Arg::Metadata::mTypeName.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
@ SC
CHAIN = SC CHAIN, Imm128 - System call.
@ Resolved
Queried, materialization begun.
NodeAddr< DefNode * > Def
NodeAddr< CodeNode * > Code
static bool isBangOperator(tgtok::TokKind Kind)
isBangOperator - Return true if this is a bang operator.
static bool isObjectStart(tgtok::TokKind Kind)
isObjectStart - Return true if this is a valid first token for a statement.
This is an optimization pass for GlobalISel generic memory operations.
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.
void PrintError(const Twine &Msg)
bool CheckAssert(SMLoc Loc, const Init *Condition, const Init *Message)
void erase(Container &C, ValueType V)
Wrapper function to remove a value from a container:
void PrintNote(const Twine &Msg)
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
@ Ref
The access may reference the value stored in memory.
void dumpMessage(SMLoc Loc, const Init *Message)
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.
@ Default
The result values are uniform if and only if all operands are uniform.
ForeachLoop - Record the iteration state associated with a for loop.
std::vector< RecordsEntry > Entries
std::vector< RecordsEntry > Entries
RecordsEntry - Holds exactly one of a Record, ForeachLoop, or AssertionInfo.
std::unique_ptr< ForeachLoop > Loop
std::unique_ptr< Record::AssertionInfo > Assertion
std::unique_ptr< Record::DumpInfo > Dump
std::unique_ptr< Record > Rec
SubClassReference()=default
SmallVector< const ArgumentInit *, 4 > TemplateArgs
SubMultiClassReference()=default
SmallVector< const ArgumentInit *, 4 > TemplateArgs