aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/TableGen
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/TableGen')
-rw-r--r--llvm/lib/TableGen/JSONBackend.cpp2
-rw-r--r--llvm/lib/TableGen/Parser.cpp4
-rw-r--r--llvm/lib/TableGen/Record.cpp207
-rw-r--r--llvm/lib/TableGen/StringMatcher.cpp1
-rw-r--r--llvm/lib/TableGen/TGLexer.cpp11
-rw-r--r--llvm/lib/TableGen/TGLexer.h9
-rw-r--r--llvm/lib/TableGen/TGParser.cpp117
-rw-r--r--llvm/lib/TableGen/TGParser.h14
8 files changed, 269 insertions, 96 deletions
diff --git a/llvm/lib/TableGen/JSONBackend.cpp b/llvm/lib/TableGen/JSONBackend.cpp
index 6dc466e29df3..a9dc30d7f59b 100644
--- a/llvm/lib/TableGen/JSONBackend.cpp
+++ b/llvm/lib/TableGen/JSONBackend.cpp
@@ -60,7 +60,7 @@ json::Value JSONEmitter::translateInit(const Init &I) {
return Str->getValue();
} else if (auto *List = dyn_cast<ListInit>(&I)) {
json::Array array;
- for (auto val : *List)
+ for (auto *val : *List)
array.push_back(translateInit(*val));
return std::move(array);
}
diff --git a/llvm/lib/TableGen/Parser.cpp b/llvm/lib/TableGen/Parser.cpp
index 818ded19432b..73a336292412 100644
--- a/llvm/lib/TableGen/Parser.cpp
+++ b/llvm/lib/TableGen/Parser.cpp
@@ -28,7 +28,9 @@ bool llvm::TableGenParseFile(SourceMgr &InputSrcMgr, RecordKeeper &Records) {
auto *MainFileBuffer = SrcMgr.getMemoryBuffer(SrcMgr.getMainFileID());
Records.saveInputFilename(MainFileBuffer->getBufferIdentifier().str());
- TGParser Parser(SrcMgr, /*Macros=*/None, Records);
+ TGParser Parser(SrcMgr, /*Macros=*/std::nullopt, Records,
+ /*NoWarnOnUnusedTemplateArgs=*/false,
+ /*TrackReferenceLocs=*/true);
bool ParseResult = Parser.ParseFile();
// After parsing, reclaim the source manager buffers from TableGen's global
diff --git a/llvm/lib/TableGen/Record.cpp b/llvm/lib/TableGen/Record.cpp
index 6b899a049e6b..9ea68e2eca51 100644
--- a/llvm/lib/TableGen/Record.cpp
+++ b/llvm/lib/TableGen/Record.cpp
@@ -24,6 +24,7 @@
#include "llvm/Support/Casting.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/MathExtras.h"
#include "llvm/Support/SMLoc.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/TableGen/Error.h"
@@ -415,7 +416,7 @@ BitsInit *BitsInit::get(RecordKeeper &RK, ArrayRef<Init *> Range) {
}
void BitsInit::Profile(FoldingSetNodeID &ID) const {
- ProfileBitsInit(ID, makeArrayRef(getTrailingObjects<Init *>(), NumBits));
+ ProfileBitsInit(ID, ArrayRef(getTrailingObjects<Init *>(), NumBits));
}
Init *BitsInit::convertInitializerTo(RecTy *Ty) const {
@@ -885,6 +886,23 @@ Init *UnOpInit::Fold(Record *CurRec, bool IsFinal) const {
}
}
break;
+
+ case LOG2:
+ if (IntInit *LHSi = dyn_cast_or_null<IntInit>(
+ LHS->convertInitializerTo(IntRecTy::get(RK)))) {
+ int64_t LHSv = LHSi->getValue();
+ if (LHSv <= 0) {
+ PrintFatalError(CurRec->getLoc(),
+ "Illegal operation: logtwo is undefined "
+ "on arguments less than or equal to 0");
+ } else {
+ uint64_t Log = Log2_64(LHSv);
+ assert(Log <= INT64_MAX &&
+ "Log of an int64_t must be smaller than INT64_MAX");
+ return IntInit::get(RK, static_cast<int64_t>(Log));
+ }
+ }
+ break;
}
return const_cast<UnOpInit *>(this);
}
@@ -908,6 +926,7 @@ std::string UnOpInit::getAsString() const {
case SIZE: Result = "!size"; break;
case EMPTY: Result = "!empty"; break;
case GETDAGOP: Result = "!getdagop"; break;
+ case LOG2 : Result = "!logtwo"; break;
}
return Result + "(" + LHS->getAsString() + ")";
}
@@ -1018,7 +1037,83 @@ Init *BinOpInit::getListConcat(TypedInit *LHS, Init *RHS) {
return BinOpInit::get(BinOpInit::LISTCONCAT, LHS, RHS, LHS->getType());
}
-Init *BinOpInit::Fold(Record *CurRec) const {
+std::optional<bool> BinOpInit::CompareInit(unsigned Opc, Init *LHS, Init *RHS) const {
+ // First see if we have two bit, bits, or int.
+ IntInit *LHSi = dyn_cast_or_null<IntInit>(
+ LHS->convertInitializerTo(IntRecTy::get(getRecordKeeper())));
+ IntInit *RHSi = dyn_cast_or_null<IntInit>(
+ RHS->convertInitializerTo(IntRecTy::get(getRecordKeeper())));
+
+ if (LHSi && RHSi) {
+ bool Result;
+ switch (Opc) {
+ case EQ:
+ Result = LHSi->getValue() == RHSi->getValue();
+ break;
+ case NE:
+ Result = LHSi->getValue() != RHSi->getValue();
+ break;
+ case LE:
+ Result = LHSi->getValue() <= RHSi->getValue();
+ break;
+ case LT:
+ Result = LHSi->getValue() < RHSi->getValue();
+ break;
+ case GE:
+ Result = LHSi->getValue() >= RHSi->getValue();
+ break;
+ case GT:
+ Result = LHSi->getValue() > RHSi->getValue();
+ break;
+ default:
+ llvm_unreachable("unhandled comparison");
+ }
+ return Result;
+ }
+
+ // Next try strings.
+ StringInit *LHSs = dyn_cast<StringInit>(LHS);
+ StringInit *RHSs = dyn_cast<StringInit>(RHS);
+
+ if (LHSs && RHSs) {
+ bool Result;
+ switch (Opc) {
+ case EQ:
+ Result = LHSs->getValue() == RHSs->getValue();
+ break;
+ case NE:
+ Result = LHSs->getValue() != RHSs->getValue();
+ break;
+ case LE:
+ Result = LHSs->getValue() <= RHSs->getValue();
+ break;
+ case LT:
+ Result = LHSs->getValue() < RHSs->getValue();
+ break;
+ case GE:
+ Result = LHSs->getValue() >= RHSs->getValue();
+ break;
+ case GT:
+ Result = LHSs->getValue() > RHSs->getValue();
+ break;
+ default:
+ llvm_unreachable("unhandled comparison");
+ }
+ return Result;
+ }
+
+ // Finally, !eq and !ne can be used with records.
+ if (Opc == EQ || Opc == NE) {
+ DefInit *LHSd = dyn_cast<DefInit>(LHS);
+ DefInit *RHSd = dyn_cast<DefInit>(RHS);
+ if (LHSd && RHSd)
+ return (Opc == EQ) ? LHSd == RHSd : LHSd != RHSd;
+ }
+
+ return std::nullopt;
+}
+
+ Init *BinOpInit::Fold(Record *CurRec) const {
switch (getOpcode()) {
case CONCAT: {
DagInit *LHSs = dyn_cast<DagInit>(LHS);
@@ -1072,6 +1167,28 @@ Init *BinOpInit::Fold(Record *CurRec) const {
}
break;
}
+ case LISTREMOVE: {
+ ListInit *LHSs = dyn_cast<ListInit>(LHS);
+ ListInit *RHSs = dyn_cast<ListInit>(RHS);
+ if (LHSs && RHSs) {
+ SmallVector<Init *, 8> Args;
+ for (Init *EltLHS : *LHSs) {
+ bool Found = false;
+ for (Init *EltRHS : *RHSs) {
+ if (std::optional<bool> Result = CompareInit(EQ, EltLHS, EltRHS)) {
+ if (*Result) {
+ Found = true;
+ break;
+ }
+ }
+ }
+ if (!Found)
+ Args.push_back(EltLHS);
+ }
+ return ListInit::get(Args, LHSs->getElementType());
+ }
+ break;
+ }
case STRCONCAT: {
StringInit *LHSs = dyn_cast<StringInit>(LHS);
StringInit *RHSs = dyn_cast<StringInit>(RHS);
@@ -1099,53 +1216,8 @@ Init *BinOpInit::Fold(Record *CurRec) const {
case LT:
case GE:
case GT: {
- // First see if we have two bit, bits, or int.
- IntInit *LHSi = dyn_cast_or_null<IntInit>(
- LHS->convertInitializerTo(IntRecTy::get(getRecordKeeper())));
- IntInit *RHSi = dyn_cast_or_null<IntInit>(
- RHS->convertInitializerTo(IntRecTy::get(getRecordKeeper())));
-
- if (LHSi && RHSi) {
- bool Result;
- switch (getOpcode()) {
- case EQ: Result = LHSi->getValue() == RHSi->getValue(); break;
- case NE: Result = LHSi->getValue() != RHSi->getValue(); break;
- case LE: Result = LHSi->getValue() <= RHSi->getValue(); break;
- case LT: Result = LHSi->getValue() < RHSi->getValue(); break;
- case GE: Result = LHSi->getValue() >= RHSi->getValue(); break;
- case GT: Result = LHSi->getValue() > RHSi->getValue(); break;
- default: llvm_unreachable("unhandled comparison");
- }
- return BitInit::get(getRecordKeeper(), Result);
- }
-
- // Next try strings.
- StringInit *LHSs = dyn_cast<StringInit>(LHS);
- StringInit *RHSs = dyn_cast<StringInit>(RHS);
-
- if (LHSs && RHSs) {
- bool Result;
- switch (getOpcode()) {
- case EQ: Result = LHSs->getValue() == RHSs->getValue(); break;
- case NE: Result = LHSs->getValue() != RHSs->getValue(); break;
- case LE: Result = LHSs->getValue() <= RHSs->getValue(); break;
- case LT: Result = LHSs->getValue() < RHSs->getValue(); break;
- case GE: Result = LHSs->getValue() >= RHSs->getValue(); break;
- case GT: Result = LHSs->getValue() > RHSs->getValue(); break;
- default: llvm_unreachable("unhandled comparison");
- }
- return BitInit::get(getRecordKeeper(), Result);
- }
-
- // Finally, !eq and !ne can be used with records.
- if (getOpcode() == EQ || getOpcode() == NE) {
- DefInit *LHSd = dyn_cast<DefInit>(LHS);
- DefInit *RHSd = dyn_cast<DefInit>(RHS);
- if (LHSd && RHSd)
- return BitInit::get(getRecordKeeper(),
- (getOpcode() == EQ) ? LHSd == RHSd : LHSd != RHSd);
- }
-
+ if (std::optional<bool> Result = CompareInit(getOpcode(), LHS, RHS))
+ return BitInit::get(getRecordKeeper(), *Result);
break;
}
case SETDAGOP: {
@@ -1165,6 +1237,7 @@ Init *BinOpInit::Fold(Record *CurRec) const {
case ADD:
case SUB:
case MUL:
+ case DIV:
case AND:
case OR:
case XOR:
@@ -1183,6 +1256,16 @@ Init *BinOpInit::Fold(Record *CurRec) const {
case ADD: Result = LHSv + RHSv; break;
case SUB: Result = LHSv - RHSv; break;
case MUL: Result = LHSv * RHSv; break;
+ case DIV:
+ if (RHSv == 0)
+ PrintFatalError(CurRec->getLoc(),
+ "Illegal operation: division by zero");
+ else if (LHSv == INT64_MIN && RHSv == -1)
+ PrintFatalError(CurRec->getLoc(),
+ "Illegal operation: INT64_MIN / -1");
+ else
+ Result = LHSv / RHSv;
+ break;
case AND: Result = LHSv & RHSv; break;
case OR: Result = LHSv | RHSv; break;
case XOR: Result = LHSv ^ RHSv; break;
@@ -1215,6 +1298,7 @@ std::string BinOpInit::getAsString() const {
case ADD: Result = "!add"; break;
case SUB: Result = "!sub"; break;
case MUL: Result = "!mul"; break;
+ case DIV: Result = "!div"; break;
case AND: Result = "!and"; break;
case OR: Result = "!or"; break;
case XOR: Result = "!xor"; break;
@@ -1229,6 +1313,7 @@ std::string BinOpInit::getAsString() const {
case GT: Result = "!gt"; break;
case LISTCONCAT: Result = "!listconcat"; break;
case LISTSPLAT: Result = "!listsplat"; break;
+ case LISTREMOVE: Result = "!listremove"; break;
case STRCONCAT: Result = "!strconcat"; break;
case INTERLEAVE: Result = "!interleave"; break;
case SETDAGOP: Result = "!setdagop"; break;
@@ -2105,10 +2190,9 @@ static void ProfileCondOpInit(FoldingSetNodeID &ID,
}
void CondOpInit::Profile(FoldingSetNodeID &ID) const {
- ProfileCondOpInit(ID,
- makeArrayRef(getTrailingObjects<Init *>(), NumConds),
- makeArrayRef(getTrailingObjects<Init *>() + NumConds, NumConds),
- ValType);
+ ProfileCondOpInit(ID, ArrayRef(getTrailingObjects<Init *>(), NumConds),
+ ArrayRef(getTrailingObjects<Init *>() + NumConds, NumConds),
+ ValType);
}
CondOpInit *CondOpInit::get(ArrayRef<Init *> CondRange,
@@ -2238,6 +2322,7 @@ static void ProfileDagInit(FoldingSetNodeID &ID, Init *V, StringInit *VN,
DagInit *DagInit::get(Init *V, StringInit *VN, ArrayRef<Init *> ArgRange,
ArrayRef<StringInit *> NameRange) {
+ assert(ArgRange.size() == NameRange.size());
FoldingSetNodeID ID;
ProfileDagInit(ID, V, VN, ArgRange, NameRange);
@@ -2273,7 +2358,9 @@ DagInit::get(Init *V, StringInit *VN,
}
void DagInit::Profile(FoldingSetNodeID &ID) const {
- ProfileDagInit(ID, Val, ValName, makeArrayRef(getTrailingObjects<Init *>(), NumArgs), makeArrayRef(getTrailingObjects<StringInit *>(), NumArgNames));
+ ProfileDagInit(ID, Val, ValName,
+ ArrayRef(getTrailingObjects<Init *>(), NumArgs),
+ ArrayRef(getTrailingObjects<StringInit *>(), NumArgNames));
}
Record *DagInit::getOperatorAsDef(ArrayRef<SMLoc> Loc) const {
@@ -2605,20 +2692,20 @@ Init *Record::getValueInit(StringRef FieldName) const {
}
StringRef Record::getValueAsString(StringRef FieldName) const {
- llvm::Optional<StringRef> S = getValueAsOptionalString(FieldName);
+ std::optional<StringRef> S = getValueAsOptionalString(FieldName);
if (!S)
PrintFatalError(getLoc(), "Record `" + getName() +
"' does not have a field named `" + FieldName + "'!\n");
- return S.value();
+ return *S;
}
-llvm::Optional<StringRef>
+std::optional<StringRef>
Record::getValueAsOptionalString(StringRef FieldName) const {
const RecordVal *R = getValue(FieldName);
if (!R || !R->getValue())
- return llvm::Optional<StringRef>();
+ return std::nullopt;
if (isa<UnsetInit>(R->getValue()))
- return llvm::Optional<StringRef>();
+ return std::nullopt;
if (StringInit *SI = dyn_cast<StringInit>(R->getValue()))
return SI->getValue();
@@ -2877,7 +2964,7 @@ RecordKeeper::getAllDerivedDefinitions(StringRef ClassName) const {
// the same vectors multiple times.
auto Pair = ClassRecordsMap.try_emplace(ClassName);
if (Pair.second)
- Pair.first->second = getAllDerivedDefinitions(makeArrayRef(ClassName));
+ Pair.first->second = getAllDerivedDefinitions(ArrayRef(ClassName));
return Pair.first->second;
}
diff --git a/llvm/lib/TableGen/StringMatcher.cpp b/llvm/lib/TableGen/StringMatcher.cpp
index 7474c5dfe885..c169b4e0a362 100644
--- a/llvm/lib/TableGen/StringMatcher.cpp
+++ b/llvm/lib/TableGen/StringMatcher.cpp
@@ -12,6 +12,7 @@
#include "llvm/TableGen/StringMatcher.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
#include <cassert>
#include <map>
diff --git a/llvm/lib/TableGen/TGLexer.cpp b/llvm/lib/TableGen/TGLexer.cpp
index 2a4ee4473b56..f2148b40a1b5 100644
--- a/llvm/lib/TableGen/TGLexer.cpp
+++ b/llvm/lib/TableGen/TGLexer.cpp
@@ -63,6 +63,10 @@ SMLoc TGLexer::getLoc() const {
return SMLoc::getFromPointer(TokStart);
}
+SMRange TGLexer::getLocRange() const {
+ return {getLoc(), SMLoc::getFromPointer(CurPtr)};
+}
+
/// ReturnError - Set the error to the specified string at the specified
/// location. This is defined to always return tgtok::Error.
tgtok::TokKind TGLexer::ReturnError(SMLoc Loc, const Twine &Msg) {
@@ -239,7 +243,7 @@ tgtok::TokKind TGLexer::LexToken(bool FileOrLineStart) {
case '0': case '1':
if (NextChar == 'b')
return LexNumber();
- LLVM_FALLTHROUGH;
+ [[fallthrough]];
case '2': case '3': case '4': case '5':
case '6': case '7': case '8': case '9':
case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
@@ -306,7 +310,7 @@ tgtok::TokKind TGLexer::LexString() {
case '\0':
if (CurPtr == CurBuf.end())
return ReturnError(StrStart, "End of file in string literal");
- LLVM_FALLTHROUGH;
+ [[fallthrough]];
default:
return ReturnError(CurPtr, "invalid escape in string literal");
}
@@ -563,7 +567,9 @@ tgtok::TokKind TGLexer::LexExclaim() {
.Case("add", tgtok::XADD)
.Case("sub", tgtok::XSUB)
.Case("mul", tgtok::XMUL)
+ .Case("div", tgtok::XDIV)
.Case("not", tgtok::XNOT)
+ .Case("logtwo", tgtok::XLOG2)
.Case("and", tgtok::XAND)
.Case("or", tgtok::XOR)
.Case("xor", tgtok::XXOR)
@@ -578,6 +584,7 @@ tgtok::TokKind TGLexer::LexExclaim() {
.Case("filter", tgtok::XFilter)
.Case("listconcat", tgtok::XListConcat)
.Case("listsplat", tgtok::XListSplat)
+ .Case("listremove", tgtok::XListRemove)
.Case("strconcat", tgtok::XStrConcat)
.Case("interleave", tgtok::XInterleave)
.Case("substr", tgtok::XSubstr)
diff --git a/llvm/lib/TableGen/TGLexer.h b/llvm/lib/TableGen/TGLexer.h
index 459ba0f4af64..284f1bade9de 100644
--- a/llvm/lib/TableGen/TGLexer.h
+++ b/llvm/lib/TableGen/TGLexer.h
@@ -52,11 +52,11 @@ namespace tgtok {
String, Then, TrueKW,
// Bang operators.
- XConcat, XADD, XSUB, XMUL, XNOT, XAND, XOR, XXOR, XSRA, XSRL, XSHL,
- XListConcat, XListSplat, XStrConcat, XInterleave, XSubstr, XFind, XCast,
- XSubst, XForEach, XFilter, XFoldl, XHead, XTail, XSize, XEmpty, XIf,
+ XConcat, XADD, XSUB, XMUL, XDIV, XNOT, XLOG2, XAND, XOR, XXOR, XSRA, XSRL,
+ XSHL, XListConcat, XListSplat, XStrConcat, XInterleave, XSubstr, XFind,
+ XCast, XSubst, XForEach, XFilter, XFoldl, XHead, XTail, XSize, XEmpty, XIf,
XCond, XEq, XIsA, XDag, XNe, XLe, XLt, XGe, XGt, XSetDagOp, XGetDagOp,
- XExists,
+ XExists, XListRemove,
// Boolean literals.
TrueVal, FalseVal,
@@ -131,6 +131,7 @@ public:
}
SMLoc getLoc() const;
+ SMRange getLocRange() const;
private:
/// LexToken - Read the next token and return its code.
diff --git a/llvm/lib/TableGen/TGParser.cpp b/llvm/lib/TableGen/TGParser.cpp
index aab1802c5348..7fc46a8b4a87 100644
--- a/llvm/lib/TableGen/TGParser.cpp
+++ b/llvm/lib/TableGen/TGParser.cpp
@@ -12,7 +12,6 @@
#include "TGParser.h"
#include "llvm/ADT/DenseMapInfo.h"
-#include "llvm/ADT/None.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/Twine.h"
@@ -161,7 +160,7 @@ bool TGParser::AddValue(Record *CurRec, SMLoc Loc, const RecordVal &RV) {
/// Return true on error, false on success.
bool TGParser::SetValue(Record *CurRec, SMLoc Loc, Init *ValName,
ArrayRef<unsigned> BitList, Init *V,
- bool AllowSelfAssignment) {
+ bool AllowSelfAssignment, bool OverrideDefLoc) {
if (!V) return false;
if (!CurRec) CurRec = &CurMultiClass->Rec;
@@ -211,7 +210,7 @@ bool TGParser::SetValue(Record *CurRec, SMLoc Loc, Init *ValName,
V = BitsInit::get(Records, NewBits);
}
- if (RV->setValue(V, Loc)) {
+ if (OverrideDefLoc ? RV->setValue(V, Loc) : RV->setValue(V)) {
std::string InitType;
if (BitsInit *BI = dyn_cast<BitsInit>(V))
InitType = (Twine("' of type bit initializer with length ") +
@@ -404,7 +403,7 @@ bool TGParser::resolve(const ForeachLoop &Loop, SubstStack &Substs,
}
bool Error = false;
- for (auto Elt : *LI) {
+ for (auto *Elt : *LI) {
if (Loop.IterVar)
Substs.emplace_back(Loop.IterVar->getNameInit(), Elt);
Error = resolve(Loop.Entries, Substs, Final, Dest);
@@ -586,6 +585,8 @@ Record *TGParser::ParseClassID() {
Lex.getCurStrVal() + "'");
else
TokError(Msg);
+ } else if (TrackReferenceLocs) {
+ Result->appendReferenceLoc(Lex.getLocRange());
}
Lex.Lex();
@@ -867,11 +868,14 @@ RecTy *TGParser::ParseType() {
}
/// ParseIDValue
-Init *TGParser::ParseIDValue(Record *CurRec, StringInit *Name, SMLoc NameLoc,
+Init *TGParser::ParseIDValue(Record *CurRec, StringInit *Name, SMRange NameLoc,
IDParseMode Mode) {
if (CurRec) {
- if (const RecordVal *RV = CurRec->getValue(Name))
+ if (RecordVal *RV = CurRec->getValue(Name)) {
+ if (TrackReferenceLocs)
+ RV->addReferenceLoc(NameLoc);
return VarInit::get(Name, RV->getType());
+ }
}
if ((CurRec && CurRec->isClass()) || CurMultiClass) {
@@ -887,6 +891,8 @@ Init *TGParser::ParseIDValue(Record *CurRec, StringInit *Name, SMLoc NameLoc,
RecordVal *RV = TemplateRec->getValue(TemplateArgName);
assert(RV && "Template arg doesn't exist??");
RV->setUsed(true);
+ if (TrackReferenceLocs)
+ RV->addReferenceLoc(NameLoc);
return VarInit::get(TemplateArgName, RV->getType());
} else if (Name->getValue() == "NAME") {
return VarInit::get(TemplateArgName, StringRecTy::get(Records));
@@ -909,8 +915,14 @@ Init *TGParser::ParseIDValue(Record *CurRec, StringInit *Name, SMLoc NameLoc,
if (Mode == ParseNameMode)
return Name;
- if (Init *I = Records.getGlobal(Name->getValue()))
+ if (Init *I = Records.getGlobal(Name->getValue())) {
+ // Add a reference to the global if it's a record.
+ if (TrackReferenceLocs) {
+ if (auto *Def = dyn_cast<DefInit>(I))
+ Def->getDef()->appendReferenceLoc(NameLoc);
+ }
return I;
+ }
// Allow self-references of concrete defs, but delay the lookup so that we
// get the correct type.
@@ -918,7 +930,7 @@ Init *TGParser::ParseIDValue(Record *CurRec, StringInit *Name, SMLoc NameLoc,
CurRec->getNameInit() == Name)
return UnOpInit::get(UnOpInit::CAST, Name, CurRec->getType());
- Error(NameLoc, "Variable not defined: '" + Name->getValue() + "'");
+ Error(NameLoc.Start, "Variable not defined: '" + Name->getValue() + "'");
return nullptr;
}
@@ -932,6 +944,7 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) {
TokError("unknown bang operator");
return nullptr;
case tgtok::XNOT:
+ case tgtok::XLOG2:
case tgtok::XHead:
case tgtok::XTail:
case tgtok::XSize:
@@ -960,6 +973,11 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) {
Code = UnOpInit::NOT;
Type = IntRecTy::get(Records);
break;
+ case tgtok::XLOG2:
+ Lex.Lex(); // eat the operation
+ Code = UnOpInit::LOG2;
+ Type = IntRecTy::get(Records);
+ break;
case tgtok::XHead:
Lex.Lex(); // eat the operation
Code = UnOpInit::HEAD;
@@ -1146,6 +1164,7 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) {
case tgtok::XADD:
case tgtok::XSUB:
case tgtok::XMUL:
+ case tgtok::XDIV:
case tgtok::XAND:
case tgtok::XOR:
case tgtok::XXOR:
@@ -1160,6 +1179,7 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) {
case tgtok::XGt:
case tgtok::XListConcat:
case tgtok::XListSplat:
+ case tgtok::XListRemove:
case tgtok::XStrConcat:
case tgtok::XInterleave:
case tgtok::XSetDagOp: { // Value ::= !binop '(' Value ',' Value ')'
@@ -1174,6 +1194,7 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) {
case tgtok::XADD: Code = BinOpInit::ADD; break;
case tgtok::XSUB: Code = BinOpInit::SUB; break;
case tgtok::XMUL: Code = BinOpInit::MUL; break;
+ case tgtok::XDIV: Code = BinOpInit::DIV; break;
case tgtok::XAND: Code = BinOpInit::AND; break;
case tgtok::XOR: Code = BinOpInit::OR; break;
case tgtok::XXOR: Code = BinOpInit::XOR; break;
@@ -1188,6 +1209,7 @@ 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::XStrConcat: Code = BinOpInit::STRCONCAT; break;
case tgtok::XInterleave: Code = BinOpInit::INTERLEAVE; break;
case tgtok::XSetDagOp: Code = BinOpInit::SETDAGOP; break;
@@ -1212,6 +1234,7 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) {
case tgtok::XADD:
case tgtok::XSUB:
case tgtok::XMUL:
+ case tgtok::XDIV:
Type = IntRecTy::get(Records);
ArgType = IntRecTy::get(Records);
break;
@@ -1225,12 +1248,16 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) {
// ArgType for the comparison operators is not yet known.
break;
case tgtok::XListConcat:
- // We don't know the list type until we parse the first argument
+ // We don't know the list type until we parse the first argument.
ArgType = ItemType;
break;
case tgtok::XListSplat:
// Can't do any typechecking until we parse the first argument.
break;
+ case tgtok::XListRemove:
+ // We don't know the list type until we parse the first argument.
+ ArgType = ItemType;
+ break;
case tgtok::XStrConcat:
Type = StringRecTy::get(Records);
ArgType = StringRecTy::get(Records);
@@ -1308,6 +1335,13 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) {
}
ArgType = nullptr; // Broken invariant: types not identical.
break;
+ case BinOpInit::LISTREMOVE:
+ if (!isa<ListRecTy>(ArgType)) {
+ Error(InitLoc, Twine("expected a list, got value of type '") +
+ ArgType->getAsString() + "'");
+ return nullptr;
+ }
+ break;
case BinOpInit::EQ:
case BinOpInit::NE:
if (!ArgType->typeIsConvertibleTo(IntRecTy::get(Records)) &&
@@ -1371,7 +1405,7 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) {
Code != BinOpInit::AND && Code != BinOpInit::OR &&
Code != BinOpInit::XOR && Code != BinOpInit::SRA &&
Code != BinOpInit::SRL && Code != BinOpInit::SHL &&
- Code != BinOpInit::MUL)
+ Code != BinOpInit::MUL && Code != BinOpInit::DIV)
ArgType = Resolved;
}
@@ -1402,6 +1436,9 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) {
// listsplat returns a list of type of the *first* argument.
if (Code == BinOpInit::LISTSPLAT)
Type = cast<TypedInit>(InitList.front())->getType()->getListTy();
+ // listremove returns a list with type of the argument.
+ if (Code == BinOpInit::LISTREMOVE)
+ Type = ArgType;
// We allow multiple operands to associative operators like !strconcat as
// shorthand for nesting them.
@@ -2126,12 +2163,14 @@ Init *TGParser::ParseOperationCond(Record *CurRec, RecTy *ItemType) {
/// SimpleValue ::= '(' IDValue DagArgList ')'
/// SimpleValue ::= CONCATTOK '(' Value ',' Value ')'
/// SimpleValue ::= ADDTOK '(' Value ',' Value ')'
+/// SimpleValue ::= DIVTOK '(' Value ',' Value ')'
/// SimpleValue ::= SUBTOK '(' Value ',' Value ')'
/// SimpleValue ::= SHLTOK '(' Value ',' Value ')'
/// SimpleValue ::= SRATOK '(' Value ',' Value ')'
/// SimpleValue ::= SRLTOK '(' Value ',' Value ')'
/// SimpleValue ::= LISTCONCATTOK '(' Value ',' Value ')'
/// SimpleValue ::= LISTSPLATTOK '(' Value ',' Value ')'
+/// SimpleValue ::= LISTREMOVETOK '(' Value ',' Value ')'
/// SimpleValue ::= STRCONCATTOK '(' Value ',' Value ')'
/// SimpleValue ::= COND '(' [Value ':' Value,]+ ')'
///
@@ -2184,7 +2223,7 @@ Init *TGParser::ParseSimpleValue(Record *CurRec, RecTy *ItemType,
Lex.Lex();
break;
case tgtok::Id: {
- SMLoc NameLoc = Lex.getLoc();
+ SMRange NameLoc = Lex.getLocRange();
StringInit *Name = StringInit::get(Records, Lex.getCurStrVal());
if (Lex.Lex() != tgtok::less) // consume the Id.
return ParseIDValue(CurRec, Name, NameLoc, Mode); // Value ::= IDValue
@@ -2194,7 +2233,8 @@ Init *TGParser::ParseSimpleValue(Record *CurRec, RecTy *ItemType,
// from the class with the template arguments, but no body.
Record *Class = Records.getClass(Name->getValue());
if (!Class) {
- Error(NameLoc, "Expected a class name, got '" + Name->getValue() + "'");
+ Error(NameLoc.Start,
+ "Expected a class name, got '" + Name->getValue() + "'");
return nullptr;
}
@@ -2203,7 +2243,7 @@ Init *TGParser::ParseSimpleValue(Record *CurRec, RecTy *ItemType,
if (ParseTemplateArgValueList(Args, CurRec, Class))
return nullptr; // Error parsing value list.
- if (CheckTemplateArgValues(Args, NameLoc, Class))
+ if (CheckTemplateArgValues(Args, NameLoc.Start, Class))
return nullptr; // Error checking template argument values.
// Loop through the arguments that were not specified and make sure
@@ -2211,14 +2251,16 @@ Init *TGParser::ParseSimpleValue(Record *CurRec, RecTy *ItemType,
ArrayRef<Init *> TArgs = Class->getTemplateArgs();
for (unsigned I = Args.size(), E = TArgs.size(); I < E; ++I) {
RecordVal *Arg = Class->getValue(TArgs[I]);
- if (!Arg->getValue()->isComplete())
- Error(NameLoc, "Value not specified for template argument '" +
- TArgs[I]->getAsUnquotedString() + "' (#" + Twine(I) +
- ") of parent class '" +
- Class->getNameInitAsString() + "'");
-
+ if (!Arg->getValue()->isComplete()) {
+ Error(NameLoc.Start, "Value not specified for template argument '" +
+ TArgs[I]->getAsUnquotedString() + "' (#" +
+ Twine(I) + ") of parent class '" +
+ Class->getNameInitAsString() + "'");
+ }
}
+ if (TrackReferenceLocs)
+ Class->appendReferenceLoc(NameLoc);
return VarDefInit::get(Class, Args)->Fold();
}
case tgtok::l_brace: { // Value ::= '{' ValueList '}'
@@ -2411,7 +2453,9 @@ Init *TGParser::ParseSimpleValue(Record *CurRec, RecTy *ItemType,
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:
@@ -2426,6 +2470,7 @@ Init *TGParser::ParseSimpleValue(Record *CurRec, RecTy *ItemType,
case tgtok::XGt:
case tgtok::XListConcat:
case tgtok::XListSplat:
+ case tgtok::XListRemove:
case tgtok::XStrConcat:
case tgtok::XInterleave:
case tgtok::XSetDagOp: // Value ::= !binop '(' Value ',' Value ')'
@@ -2510,12 +2555,27 @@ Init *TGParser::ParseValue(Record *CurRec, RecTy *ItemType, IDParseMode Mode) {
TokError("expected field identifier after '.'");
return nullptr;
}
+ SMRange FieldNameLoc = Lex.getLocRange();
StringInit *FieldName = StringInit::get(Records, Lex.getCurStrVal());
if (!Result->getFieldType(FieldName)) {
TokError("Cannot access field '" + Lex.getCurStrVal() + "' of value '" +
Result->getAsString() + "'");
return nullptr;
}
+
+ // Add a reference to this field if we know the record class.
+ if (TrackReferenceLocs) {
+ if (auto *DI = dyn_cast<DefInit>(Result)) {
+ DI->getDef()->getValue(FieldName)->addReferenceLoc(FieldNameLoc);
+ } else if (auto *TI = dyn_cast<TypedInit>(Result)) {
+ if (auto *RecTy = dyn_cast<RecordRecTy>(TI->getType())) {
+ for (Record *R : RecTy->getClasses())
+ if (auto *RV = R->getValue(FieldName))
+ RV->addReferenceLoc(FieldNameLoc);
+ }
+ }
+ }
+
Result = FieldInit::get(Result, FieldName)->Fold(CurRec);
Lex.Lex(); // eat field name
break;
@@ -2780,11 +2840,13 @@ Init *TGParser::ParseDeclaration(Record *CurRec,
SMLoc ValLoc = Lex.getLoc();
Init *Val = ParseValue(CurRec, Type);
if (!Val ||
- SetValue(CurRec, ValLoc, DeclName, None, Val))
+ SetValue(CurRec, ValLoc, DeclName, std::nullopt, Val,
+ /*AllowSelfAssignment=*/false, /*OverrideDefLoc=*/false)) {
// Return the name, even if an error is thrown. This is so that we can
// continue to make some progress, even without the value having been
// initialized.
return DeclName;
+ }
}
return DeclName;
@@ -3078,17 +3140,24 @@ bool TGParser::ParseDef(MultiClass *CurMultiClass) {
assert(Lex.getCode() == tgtok::Def && "Unknown tok");
Lex.Lex(); // Eat the 'def' token.
+ // If the name of the def is an Id token, use that for the location.
+ // Otherwise, the name is more complex and we use the location of the 'def'
+ // token.
+ SMLoc NameLoc = Lex.getCode() == tgtok::Id ? Lex.getLoc() : DefLoc;
+
// Parse ObjectName and make a record for it.
std::unique_ptr<Record> CurRec;
Init *Name = ParseObjectName(CurMultiClass);
if (!Name)
return true;
- if (isa<UnsetInit>(Name))
- CurRec = std::make_unique<Record>(Records.getNewAnonymousName(), DefLoc, Records,
+ if (isa<UnsetInit>(Name)) {
+ CurRec =
+ std::make_unique<Record>(Records.getNewAnonymousName(), DefLoc, Records,
/*Anonymous=*/true);
- else
- CurRec = std::make_unique<Record>(Name, DefLoc, Records);
+ } else {
+ CurRec = std::make_unique<Record>(Name, NameLoc, Records);
+ }
if (ParseObjectBody(CurRec.get()))
return true;
diff --git a/llvm/lib/TableGen/TGParser.h b/llvm/lib/TableGen/TGParser.h
index d4b928c62fd7..f7271a5e79c3 100644
--- a/llvm/lib/TableGen/TGParser.h
+++ b/llvm/lib/TableGen/TGParser.h
@@ -161,12 +161,15 @@ class TGParser {
};
bool NoWarnOnUnusedTemplateArgs = false;
+ bool TrackReferenceLocs = false;
public:
TGParser(SourceMgr &SM, ArrayRef<std::string> Macros, RecordKeeper &records,
- const bool NoWarnOnUnusedTemplateArgs = false)
+ const bool NoWarnOnUnusedTemplateArgs = false,
+ const bool TrackReferenceLocs = false)
: Lex(SM, Macros), CurMultiClass(nullptr), Records(records),
- NoWarnOnUnusedTemplateArgs(NoWarnOnUnusedTemplateArgs) {}
+ NoWarnOnUnusedTemplateArgs(NoWarnOnUnusedTemplateArgs),
+ TrackReferenceLocs(TrackReferenceLocs) {}
/// ParseFile - Main entrypoint for parsing a tblgen file. These parser
/// routines return true on error, or false on success.
@@ -198,9 +201,12 @@ public:
private: // Semantic analysis methods.
bool AddValue(Record *TheRec, SMLoc Loc, const RecordVal &RV);
+ /// Set the value of a RecordVal within the given record. If `OverrideDefLoc`
+ /// is set, the provided location overrides any existing location of the
+ /// RecordVal.
bool SetValue(Record *TheRec, SMLoc Loc, Init *ValName,
ArrayRef<unsigned> BitList, Init *V,
- bool AllowSelfAssignment = false);
+ bool AllowSelfAssignment = false, bool OverrideDefLoc = true);
bool AddSubClass(Record *Rec, SubClassReference &SubClass);
bool AddSubClass(RecordsEntry &Entry, SubClassReference &SubClass);
bool AddSubMultiClass(MultiClass *CurMC,
@@ -244,7 +250,7 @@ private: // Parser methods.
SubClassReference ParseSubClassReference(Record *CurRec, bool isDefm);
SubMultiClassReference ParseSubMultiClassReference(MultiClass *CurMC);
- Init *ParseIDValue(Record *CurRec, StringInit *Name, SMLoc NameLoc,
+ Init *ParseIDValue(Record *CurRec, StringInit *Name, SMRange NameLoc,
IDParseMode Mode = ParseValueMode);
Init *ParseSimpleValue(Record *CurRec, RecTy *ItemType = nullptr,
IDParseMode Mode = ParseValueMode);