aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/llvm/lib/TableGen/TGParser.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/llvm/lib/TableGen/TGParser.cpp')
-rw-r--r--contrib/llvm-project/llvm/lib/TableGen/TGParser.cpp385
1 files changed, 219 insertions, 166 deletions
diff --git a/contrib/llvm-project/llvm/lib/TableGen/TGParser.cpp b/contrib/llvm-project/llvm/lib/TableGen/TGParser.cpp
index a371bd21f026..e7dcb91ba20a 100644
--- a/contrib/llvm-project/llvm/lib/TableGen/TGParser.cpp
+++ b/contrib/llvm-project/llvm/lib/TableGen/TGParser.cpp
@@ -11,7 +11,6 @@
//===----------------------------------------------------------------------===//
#include "TGParser.h"
-#include "llvm/ADT/DenseMapInfo.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/Twine.h"
@@ -35,20 +34,20 @@ namespace llvm {
struct SubClassReference {
SMRange RefRange;
- Record *Rec;
+ Record *Rec = nullptr;
SmallVector<ArgumentInit *, 4> TemplateArgs;
- SubClassReference() : Rec(nullptr) {}
+ SubClassReference() = default;
bool isInvalid() const { return Rec == nullptr; }
};
struct SubMultiClassReference {
SMRange RefRange;
- MultiClass *MC;
+ MultiClass *MC = nullptr;
SmallVector<ArgumentInit *, 4> TemplateArgs;
- SubMultiClassReference() : MC(nullptr) {}
+ SubMultiClassReference() = default;
bool isInvalid() const { return MC == nullptr; }
void dump() const;
@@ -111,11 +110,11 @@ static void checkConcrete(Record &R) {
/// Return an Init with a qualifier prefix referring
/// to CurRec's name.
-static Init *QualifyName(Record &CurRec, MultiClass *CurMultiClass, Init *Name,
- StringRef Scoper) {
+static Init *QualifyName(Record &CurRec, Init *Name) {
RecordKeeper &RK = CurRec.getRecords();
- Init *NewName = BinOpInit::getStrConcat(CurRec.getNameInit(),
- StringInit::get(RK, Scoper));
+ Init *NewName = BinOpInit::getStrConcat(
+ CurRec.getNameInit(),
+ StringInit::get(RK, CurRec.isMultiClass() ? "::" : ":"));
NewName = BinOpInit::getStrConcat(NewName, Name);
if (BinOpInit *BinOp = dyn_cast<BinOpInit>(NewName))
@@ -123,18 +122,20 @@ static Init *QualifyName(Record &CurRec, MultiClass *CurMultiClass, Init *Name,
return NewName;
}
+static Init *QualifyName(MultiClass *MC, Init *Name) {
+ return QualifyName(MC->Rec, Name);
+}
+
/// Return the qualified version of the implicit 'NAME' template argument.
-static Init *QualifiedNameOfImplicitName(Record &Rec,
- MultiClass *MC = nullptr) {
- return QualifyName(Rec, MC, StringInit::get(Rec.getRecords(), "NAME"),
- MC ? "::" : ":");
+static Init *QualifiedNameOfImplicitName(Record &Rec) {
+ return QualifyName(Rec, StringInit::get(Rec.getRecords(), "NAME"));
}
static Init *QualifiedNameOfImplicitName(MultiClass *MC) {
- return QualifiedNameOfImplicitName(MC->Rec, MC);
+ return QualifiedNameOfImplicitName(MC->Rec);
}
-Init *TGVarScope::getVar(RecordKeeper &Records, MultiClass* ParsingMultiClass,
+Init *TGVarScope::getVar(RecordKeeper &Records, MultiClass *ParsingMultiClass,
StringInit *Name, SMRange NameLoc,
bool TrackReferenceLocs) const {
// First, we search in local variables.
@@ -142,11 +143,10 @@ Init *TGVarScope::getVar(RecordKeeper &Records, MultiClass* ParsingMultiClass,
if (It != Vars.end())
return It->second;
- std::function<Init *(Record *, StringInit *, StringRef)> FindValueInArgs =
- [&](Record *Rec, StringInit *Name, StringRef Scoper) -> Init * {
+ auto FindValueInArgs = [&](Record *Rec, StringInit *Name) -> Init * {
if (!Rec)
return nullptr;
- Init *ArgName = QualifyName(*Rec, ParsingMultiClass, Name, Scoper);
+ Init *ArgName = QualifyName(*Rec, Name);
if (Rec->isTemplateArg(ArgName)) {
RecordVal *RV = Rec->getValue(ArgName);
assert(RV && "Template arg doesn't exist??");
@@ -176,7 +176,7 @@ Init *TGVarScope::getVar(RecordKeeper &Records, MultiClass* ParsingMultiClass,
// The variable is a class template argument?
if (CurRec->isClass())
- if (auto *V = FindValueInArgs(CurRec, Name, ":"))
+ if (auto *V = FindValueInArgs(CurRec, Name))
return V;
}
break;
@@ -193,7 +193,7 @@ Init *TGVarScope::getVar(RecordKeeper &Records, MultiClass* ParsingMultiClass,
case SK_MultiClass: {
// The variable is a multiclass template argument?
if (CurMultiClass)
- if (auto *V = FindValueInArgs(&CurMultiClass->Rec, Name, "::"))
+ if (auto *V = FindValueInArgs(&CurMultiClass->Rec, Name))
return V;
break;
}
@@ -313,6 +313,9 @@ bool TGParser::AddSubClass(Record *CurRec, SubClassReference &SubClass) {
// Copy the subclass record's assertions to the new record.
CurRec->appendAssertions(SC);
+ // Copy the subclass record's dumps to the new record.
+ CurRec->appendDumps(SC);
+
Init *Name;
if (CurRec->isClass())
Name = VarInit::get(QualifiedNameOfImplicitName(*CurRec),
@@ -376,7 +379,7 @@ bool TGParser::AddSubMultiClass(MultiClass *CurMC,
/// Add a record, foreach loop, or assertion to the current context.
bool TGParser::addEntry(RecordsEntry E) {
- assert((!!E.Rec + !!E.Loop + !!E.Assertion) == 1 &&
+ assert((!!E.Rec + !!E.Loop + !!E.Assertion + !!E.Dump) == 1 &&
"RecordsEntry has invalid number of items");
// If we are parsing a loop, add it to the loop's entries.
@@ -404,6 +407,11 @@ bool TGParser::addEntry(RecordsEntry E) {
return false;
}
+ if (E.Dump) {
+ dumpMessage(E.Dump->Loc, E.Dump->Message);
+ return false;
+ }
+
// It must be a record, so finish it off.
return addDefOne(std::move(E.Rec));
}
@@ -498,6 +506,18 @@ bool TGParser::resolve(const std::vector<RecordsEntry> &Source,
else
CheckAssert(E.Assertion->Loc, Condition, Message);
+ } else if (E.Dump) {
+ MapResolver R;
+ for (const auto &S : Substs)
+ R.set(S.first, S.second);
+ Init *Message = E.Dump->Message->resolveReferences(R);
+
+ if (Dest)
+ Dest->push_back(
+ std::make_unique<Record::DumpInfo>(E.Dump->Loc, Message));
+ else
+ dumpMessage(E.Dump->Loc, Message);
+
} else {
auto Rec = std::make_unique<Record>(*E.Rec);
if (Loc)
@@ -545,6 +565,9 @@ bool TGParser::addDefOne(std::unique_ptr<Record> Rec) {
// Check the assertions.
Rec->checkRecordAssertions();
+ // Run the dumps.
+ Rec->emitRecordDumps();
+
// If ObjectBody has template arguments, it's an error.
assert(Rec->getTemplateArgs().empty() && "How'd this get template args?");
@@ -586,7 +609,7 @@ bool TGParser::resolveArguments(Record *Rec, ArrayRef<ArgumentInit *> ArgValues,
ArgName->getAsUnquotedString() + "' once");
ArgValueHandler(ArgName, ArgValue);
- llvm::erase_value(UnsolvedArgNames, ArgName);
+ llvm::erase(UnsolvedArgNames, ArgName);
}
// For unsolved arguments, if there is no default value, complain.
@@ -630,14 +653,6 @@ bool TGParser::resolveArgumentsOfMultiClass(SubstStack &Substs, MultiClass *MC,
// Parser Code
//===----------------------------------------------------------------------===//
-/// isObjectStart - Return true if this is a valid first token for a statement.
-static bool isObjectStart(tgtok::TokKind K) {
- return K == tgtok::Assert || K == tgtok::Class || K == tgtok::Def ||
- K == tgtok::Defm || K == tgtok::Defset || K == tgtok::Defvar ||
- K == tgtok::Foreach || K == tgtok::If || K == tgtok::Let ||
- K == tgtok::MultiClass;
-}
-
bool TGParser::consume(tgtok::TokKind K) {
if (Lex.getCode() == K) {
Lex.Lex();
@@ -756,8 +771,7 @@ ParseSubClassReference(Record *CurRec, bool isDefm) {
return Result;
}
- if (ParseTemplateArgValueList(Result.TemplateArgs, CurRec, Result.Rec,
- isDefm)) {
+ if (ParseTemplateArgValueList(Result.TemplateArgs, CurRec, Result.Rec)) {
Result.Rec = nullptr; // Error parsing value list.
return Result;
}
@@ -794,7 +808,7 @@ ParseSubMultiClassReference(MultiClass *CurMC) {
}
if (ParseTemplateArgValueList(Result.TemplateArgs, &CurMC->Rec,
- &Result.MC->Rec, true)) {
+ &Result.MC->Rec)) {
Result.MC = nullptr; // Error parsing value list.
return Result;
}
@@ -1176,6 +1190,7 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) {
case tgtok::XSize:
case tgtok::XEmpty:
case tgtok::XCast:
+ case tgtok::XRepr:
case tgtok::XGetDagOp: { // Value ::= !unop '(' Value ')'
UnOpInit::UnaryOp Code;
RecTy *Type = nullptr;
@@ -1194,6 +1209,11 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) {
}
break;
+ case tgtok::XRepr:
+ Lex.Lex(); // eat the operation
+ Code = UnOpInit::REPR;
+ Type = StringRecTy::get(Records);
+ break;
case tgtok::XToLower:
Lex.Lex(); // eat the operation
Code = UnOpInit::TOLOWER;
@@ -1416,7 +1436,6 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) {
case tgtok::XListConcat:
case tgtok::XListSplat:
case tgtok::XListRemove:
- case tgtok::XRange:
case tgtok::XStrConcat:
case tgtok::XInterleave:
case tgtok::XGetDagArg:
@@ -1448,8 +1467,9 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) {
case tgtok::XGt: Code = BinOpInit::GT; break;
case tgtok::XListConcat: Code = BinOpInit::LISTCONCAT; break;
case tgtok::XListSplat: Code = BinOpInit::LISTSPLAT; break;
- case tgtok::XListRemove: Code = BinOpInit::LISTREMOVE; break;
- case tgtok::XRange: Code = BinOpInit::RANGE; break;
+ case tgtok::XListRemove:
+ Code = BinOpInit::LISTREMOVE;
+ break;
case tgtok::XStrConcat: Code = BinOpInit::STRCONCAT; break;
case tgtok::XInterleave: Code = BinOpInit::INTERLEAVE; break;
case tgtok::XSetDagOp: Code = BinOpInit::SETDAGOP; break;
@@ -1516,10 +1536,6 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) {
// We don't know the list type until we parse the first argument.
ArgType = ItemType;
break;
- case tgtok::XRange:
- Type = IntRecTy::get(Records)->getListTy();
- // ArgType may be either Int or List.
- break;
case tgtok::XStrConcat:
Type = StringRecTy::get(Records);
ArgType = StringRecTy::get(Records);
@@ -1604,27 +1620,6 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) {
return nullptr;
}
break;
- case BinOpInit::RANGE:
- if (InitList.size() == 1) {
- if (isa<ListRecTy>(ArgType)) {
- ArgType = nullptr; // Detect error if 2nd arg were present.
- } else if (isa<IntRecTy>(ArgType)) {
- // Assume 2nd arg should be IntRecTy
- } else {
- Error(InitLoc,
- Twine("expected list or int, got value of type '") +
- ArgType->getAsString() + "'");
- return nullptr;
- }
- } else {
- // Don't come here unless 1st arg is ListRecTy.
- assert(isa<ListRecTy>(cast<TypedInit>(InitList[0])->getType()));
- Error(InitLoc,
- Twine("expected one list, got extra value of type '") +
- ArgType->getAsString() + "'");
- return nullptr;
- }
- break;
case BinOpInit::EQ:
case BinOpInit::NE:
if (!ArgType->typeIsConvertibleTo(IntRecTy::get(Records)) &&
@@ -1734,37 +1729,6 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) {
if (Code == BinOpInit::LISTREMOVE)
Type = ArgType;
- if (Code == BinOpInit::RANGE) {
- Init *LHS, *RHS;
- auto ArgCount = InitList.size();
- assert(ArgCount >= 1);
- auto *Arg0 = cast<TypedInit>(InitList[0]);
- auto *Arg0Ty = Arg0->getType();
- if (ArgCount == 1) {
- if (isa<ListRecTy>(Arg0Ty)) {
- // (0, !size(arg))
- LHS = IntInit::get(Records, 0);
- RHS = UnOpInit::get(UnOpInit::SIZE, Arg0, IntRecTy::get(Records))
- ->Fold(CurRec);
- } else {
- assert(isa<IntRecTy>(Arg0Ty));
- // (0, arg)
- LHS = IntInit::get(Records, 0);
- RHS = Arg0;
- }
- } else if (ArgCount == 2) {
- assert(isa<IntRecTy>(Arg0Ty));
- auto *Arg1 = cast<TypedInit>(InitList[1]);
- assert(isa<IntRecTy>(Arg1->getType()));
- LHS = Arg0;
- RHS = Arg1;
- } else {
- Error(OpLoc, "expected at most two values of integer");
- return nullptr;
- }
- return BinOpInit::get(Code, LHS, RHS, Type)->Fold(CurRec);
- }
-
// We allow multiple operands to associative operators like !strconcat as
// shorthand for nesting them.
if (Code == BinOpInit::STRCONCAT || Code == BinOpInit::LISTCONCAT ||
@@ -1791,6 +1755,105 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) {
return ParseOperationForEachFilter(CurRec, ItemType);
}
+ case tgtok::XRange: {
+ SMLoc OpLoc = Lex.getLoc();
+ Lex.Lex(); // eat the operation
+
+ if (!consume(tgtok::l_paren)) {
+ TokError("expected '(' after !range operator");
+ return nullptr;
+ }
+
+ SmallVector<Init *, 2> Args;
+ bool FirstArgIsList = false;
+ for (;;) {
+ if (Args.size() >= 3) {
+ TokError("expected at most three values of integer");
+ return nullptr;
+ }
+
+ SMLoc InitLoc = Lex.getLoc();
+ Args.push_back(ParseValue(CurRec));
+ if (!Args.back())
+ return nullptr;
+
+ TypedInit *ArgBack = dyn_cast<TypedInit>(Args.back());
+ if (!ArgBack) {
+ Error(OpLoc, Twine("expected value to be a typed value, got '" +
+ Args.back()->getAsString() + "'"));
+ return nullptr;
+ }
+
+ RecTy *ArgBackType = ArgBack->getType();
+ if (!FirstArgIsList || Args.size() == 1) {
+ if (Args.size() == 1 && isa<ListRecTy>(ArgBackType)) {
+ FirstArgIsList = true; // Detect error if 2nd arg were present.
+ } else if (isa<IntRecTy>(ArgBackType)) {
+ // Assume 2nd arg should be IntRecTy
+ } else {
+ if (Args.size() != 1)
+ Error(InitLoc, Twine("expected value of type 'int', got '" +
+ ArgBackType->getAsString() + "'"));
+ else
+ Error(InitLoc, Twine("expected list or int, got value of type '") +
+ ArgBackType->getAsString() + "'");
+ return nullptr;
+ }
+ } else {
+ // Don't come here unless 1st arg is ListRecTy.
+ assert(isa<ListRecTy>(cast<TypedInit>(Args[0])->getType()));
+ Error(InitLoc, Twine("expected one list, got extra value of type '") +
+ ArgBackType->getAsString() + "'");
+ return nullptr;
+ }
+ if (!consume(tgtok::comma))
+ break;
+ }
+
+ if (!consume(tgtok::r_paren)) {
+ TokError("expected ')' in operator");
+ return nullptr;
+ }
+
+ Init *LHS, *MHS, *RHS;
+ auto ArgCount = Args.size();
+ assert(ArgCount >= 1);
+ auto *Arg0 = cast<TypedInit>(Args[0]);
+ auto *Arg0Ty = Arg0->getType();
+ if (ArgCount == 1) {
+ if (isa<ListRecTy>(Arg0Ty)) {
+ // (0, !size(arg), 1)
+ LHS = IntInit::get(Records, 0);
+ MHS = UnOpInit::get(UnOpInit::SIZE, Arg0, IntRecTy::get(Records))
+ ->Fold(CurRec);
+ RHS = IntInit::get(Records, 1);
+ } else {
+ assert(isa<IntRecTy>(Arg0Ty));
+ // (0, arg, 1)
+ LHS = IntInit::get(Records, 0);
+ MHS = Arg0;
+ RHS = IntInit::get(Records, 1);
+ }
+ } else {
+ assert(isa<IntRecTy>(Arg0Ty));
+ auto *Arg1 = cast<TypedInit>(Args[1]);
+ assert(isa<IntRecTy>(Arg1->getType()));
+ LHS = Arg0;
+ MHS = Arg1;
+ if (ArgCount == 3) {
+ // (start, end, step)
+ auto *Arg2 = cast<TypedInit>(Args[2]);
+ assert(isa<IntRecTy>(Arg2->getType()));
+ RHS = Arg2;
+ } else
+ // (start, end, 1)
+ RHS = IntInit::get(Records, 1);
+ }
+ return TernOpInit::get(TernOpInit::RANGE, LHS, MHS, RHS,
+ IntRecTy::get(Records)->getListTy())
+ ->Fold(CurRec);
+ }
+
case tgtok::XSetDagArg:
case tgtok::XSetDagName:
case tgtok::XDag:
@@ -2542,13 +2605,20 @@ Init *TGParser::ParseOperationCond(Record *CurRec, RecTy *ItemType) {
/// SimpleValue ::= LISTREMOVETOK '(' Value ',' Value ')'
/// SimpleValue ::= RANGE '(' Value ')'
/// SimpleValue ::= RANGE '(' Value ',' Value ')'
+/// SimpleValue ::= RANGE '(' Value ',' Value ',' Value ')'
/// SimpleValue ::= STRCONCATTOK '(' Value ',' Value ')'
/// SimpleValue ::= COND '(' [Value ':' Value,]+ ')'
///
Init *TGParser::ParseSimpleValue(Record *CurRec, RecTy *ItemType,
IDParseMode Mode) {
Init *R = nullptr;
- switch (Lex.getCode()) {
+ tgtok::TokKind Code = Lex.getCode();
+
+ // Parse bang operators.
+ if (tgtok::isBangOperator(Code))
+ return ParseOperation(CurRec, ItemType);
+
+ switch (Code) {
default: TokError("Unknown or reserved token when parsing a value"); break;
case tgtok::TrueVal:
@@ -2803,58 +2873,6 @@ Init *TGParser::ParseSimpleValue(Record *CurRec, RecTy *ItemType,
return DagInit::get(Operator, OperatorName, DagArgs);
}
-
- case tgtok::XHead:
- case tgtok::XTail:
- case tgtok::XSize:
- case tgtok::XEmpty:
- case tgtok::XCast:
- case tgtok::XToLower:
- case tgtok::XToUpper:
- case tgtok::XGetDagOp: // Value ::= !unop '(' Value ')'
- case tgtok::XExists:
- case tgtok::XIsA:
- case tgtok::XConcat:
- case tgtok::XDag:
- case tgtok::XADD:
- case tgtok::XSUB:
- case tgtok::XMUL:
- case tgtok::XDIV:
- case tgtok::XNOT:
- case tgtok::XLOG2:
- case tgtok::XAND:
- case tgtok::XOR:
- case tgtok::XXOR:
- case tgtok::XSRA:
- case tgtok::XSRL:
- case tgtok::XSHL:
- case tgtok::XEq:
- case tgtok::XNe:
- case tgtok::XLe:
- case tgtok::XLt:
- case tgtok::XGe:
- case tgtok::XGt:
- case tgtok::XListConcat:
- case tgtok::XListSplat:
- case tgtok::XListRemove:
- case tgtok::XRange:
- case tgtok::XStrConcat:
- case tgtok::XInterleave:
- case tgtok::XGetDagArg:
- case tgtok::XGetDagName:
- case tgtok::XSetDagOp: // Value ::= !binop '(' Value ',' Value ')'
- case tgtok::XSetDagArg:
- case tgtok::XSetDagName:
- case tgtok::XIf:
- case tgtok::XCond:
- case tgtok::XFoldl:
- case tgtok::XForEach:
- case tgtok::XFilter:
- case tgtok::XSubst:
- case tgtok::XSubstr:
- case tgtok::XFind: { // Value ::= !ternop '(' Value ',' Value ',' Value ')'
- return ParseOperation(CurRec, ItemType);
- }
}
return R;
@@ -3140,8 +3158,7 @@ void TGParser::ParseValueList(SmallVectorImpl<Init *> &Result, Record *CurRec,
// PostionalArgValueList ::= [Value {',' Value}*]
// NamedArgValueList ::= [NameValue '=' Value {',' NameValue '=' Value}*]
bool TGParser::ParseTemplateArgValueList(
- SmallVectorImpl<ArgumentInit *> &Result, Record *CurRec, Record *ArgsRec,
- bool IsDefm) {
+ SmallVectorImpl<ArgumentInit *> &Result, Record *CurRec, Record *ArgsRec) {
assert(Result.empty() && "Result vector is not empty");
ArrayRef<Init *> TArgs = ArgsRec->getTemplateArgs();
@@ -3172,8 +3189,7 @@ bool TGParser::ParseTemplateArgValueList(
"The name of named argument should be a valid identifier");
auto *Name = cast<StringInit>(Value);
- Init *QualifiedName =
- QualifyName(*ArgsRec, CurMultiClass, Name, IsDefm ? "::" : ":");
+ Init *QualifiedName = QualifyName(*ArgsRec, Name);
auto *NamedArg = ArgsRec->getValue(QualifiedName);
if (!NamedArg)
return Error(ValueLoc,
@@ -3252,17 +3268,17 @@ Init *TGParser::ParseDeclaration(Record *CurRec,
RecordVal(DeclName, IdLoc, Type,
HasField ? RecordVal::FK_NonconcreteOK
: RecordVal::FK_Normal));
-
} else if (CurRec) { // class template argument
- DeclName = QualifyName(*CurRec, CurMultiClass, DeclName, ":");
- BadField = AddValue(CurRec, IdLoc, RecordVal(DeclName, IdLoc, Type,
- RecordVal::FK_TemplateArg));
-
+ DeclName = QualifyName(*CurRec, DeclName);
+ BadField =
+ AddValue(CurRec, IdLoc,
+ RecordVal(DeclName, IdLoc, Type, RecordVal::FK_TemplateArg));
} else { // multiclass template argument
assert(CurMultiClass && "invalid context for template argument");
- DeclName = QualifyName(CurMultiClass->Rec, CurMultiClass, DeclName, "::");
- BadField = AddValue(CurRec, IdLoc, RecordVal(DeclName, IdLoc, Type,
- RecordVal::FK_TemplateArg));
+ DeclName = QualifyName(CurMultiClass, DeclName);
+ BadField =
+ AddValue(CurRec, IdLoc,
+ RecordVal(DeclName, IdLoc, Type, RecordVal::FK_TemplateArg));
}
if (BadField)
return nullptr;
@@ -3409,6 +3425,7 @@ bool TGParser::ParseTemplateArgList(Record *CurRec) {
/// BodyItem ::= Declaration ';'
/// BodyItem ::= LET ID OptionalBitList '=' Value ';'
/// BodyItem ::= Defvar
+/// BodyItem ::= Dump
/// BodyItem ::= Assert
///
bool TGParser::ParseBodyItem(Record *CurRec) {
@@ -3418,6 +3435,9 @@ bool TGParser::ParseBodyItem(Record *CurRec) {
if (Lex.getCode() == tgtok::Defvar)
return ParseDefvar(CurRec);
+ if (Lex.getCode() == tgtok::Dump)
+ return ParseDump(nullptr, CurRec);
+
if (Lex.getCode() != tgtok::Let) {
if (!ParseDeclaration(CurRec, false))
return true;
@@ -3514,6 +3534,10 @@ bool TGParser::ApplyLetStack(RecordsEntry &Entry) {
if (Entry.Assertion)
return false;
+ // Let bindings are not applied to dumps.
+ if (Entry.Dump)
+ return false;
+
for (auto &E : Entry.Loop->Entries) {
if (ApplyLetStack(E))
return true;
@@ -3583,9 +3607,8 @@ bool TGParser::ParseDef(MultiClass *CurMultiClass) {
return true;
if (isa<UnsetInit>(Name)) {
- CurRec =
- std::make_unique<Record>(Records.getNewAnonymousName(), DefLoc, Records,
- /*Anonymous=*/true);
+ CurRec = std::make_unique<Record>(Records.getNewAnonymousName(), DefLoc,
+ Records, Record::RK_AnonymousDef);
} else {
CurRec = std::make_unique<Record>(Name, NameLoc, Records);
}
@@ -3903,9 +3926,8 @@ bool TGParser::ParseClass() {
CurRec->updateClassLoc(Lex.getLoc());
} else {
// If this is the first reference to this class, create and add it.
- auto NewRec =
- std::make_unique<Record>(Lex.getCurStrVal(), Lex.getLoc(), Records,
- /*Class=*/true);
+ auto NewRec = std::make_unique<Record>(Lex.getCurStrVal(), Lex.getLoc(),
+ Records, Record::RK_Class);
CurRec = NewRec.get();
Records.addClass(std::move(NewRec));
}
@@ -4094,13 +4116,14 @@ bool TGParser::ParseMultiClass() {
while (Lex.getCode() != tgtok::r_brace) {
switch (Lex.getCode()) {
default:
- return TokError("expected 'assert', 'def', 'defm', 'defvar', "
+ return TokError("expected 'assert', 'def', 'defm', 'defvar', 'dump', "
"'foreach', 'if', or 'let' in multiclass body");
case tgtok::Assert:
case tgtok::Def:
case tgtok::Defm:
case tgtok::Defvar:
+ case tgtok::Dump:
case tgtok::Foreach:
case tgtok::If:
case tgtok::Let:
@@ -4244,15 +4267,18 @@ bool TGParser::ParseDefm(MultiClass *CurMultiClass) {
/// Object ::= Defset
/// Object ::= Defvar
/// Object ::= Assert
+/// Object ::= Dump
bool TGParser::ParseObject(MultiClass *MC) {
switch (Lex.getCode()) {
default:
return TokError(
- "Expected assert, class, def, defm, defset, foreach, if, or let");
+ "Expected assert, class, def, defm, defset, dump, foreach, if, or let");
case tgtok::Assert: return ParseAssert(MC);
case tgtok::Def: return ParseDef(MC);
case tgtok::Defm: return ParseDefm(MC);
case tgtok::Defvar: return ParseDefvar();
+ case tgtok::Dump:
+ return ParseDump(MC);
case tgtok::Foreach: return ParseForeach(MC);
case tgtok::If: return ParseIf(MC);
case tgtok::Let: return ParseTopLevelLet(MC);
@@ -4276,7 +4302,7 @@ bool TGParser::ParseObject(MultiClass *MC) {
/// ParseObjectList
/// ObjectList :== Object*
bool TGParser::ParseObjectList(MultiClass *MC) {
- while (isObjectStart(Lex.getCode())) {
+ while (tgtok::isObjectStart(Lex.getCode())) {
if (ParseObject(MC))
return true;
}
@@ -4363,3 +4389,30 @@ LLVM_DUMP_METHOD void MultiClass::dump() const {
E.dump();
}
#endif
+
+bool TGParser::ParseDump(MultiClass *CurMultiClass, Record *CurRec) {
+ // Location of the `dump` statement.
+ SMLoc Loc = Lex.getLoc();
+ assert(Lex.getCode() == tgtok::Dump && "Unknown tok");
+ Lex.Lex(); // eat the operation
+
+ Init *Message = ParseValue(CurRec);
+ if (!Message)
+ return true;
+
+ // Allow to use dump directly on `defvar` and `def`, by wrapping
+ // them with a `!repl`.
+ if (isa<DefInit>(Message))
+ Message = UnOpInit::get(UnOpInit::REPR, Message, StringRecTy::get(Records))
+ ->Fold(CurRec);
+
+ if (!consume(tgtok::semi))
+ return TokError("expected ';'");
+
+ if (CurRec)
+ CurRec->addDump(Loc, Message);
+ else
+ addEntry(std::make_unique<Record::DumpInfo>(Loc, Message));
+
+ return false;
+}