diff options
Diffstat (limited to 'llvm/lib/TableGen')
-rw-r--r-- | llvm/lib/TableGen/JSONBackend.cpp | 2 | ||||
-rw-r--r-- | llvm/lib/TableGen/Parser.cpp | 4 | ||||
-rw-r--r-- | llvm/lib/TableGen/Record.cpp | 207 | ||||
-rw-r--r-- | llvm/lib/TableGen/StringMatcher.cpp | 1 | ||||
-rw-r--r-- | llvm/lib/TableGen/TGLexer.cpp | 11 | ||||
-rw-r--r-- | llvm/lib/TableGen/TGLexer.h | 9 | ||||
-rw-r--r-- | llvm/lib/TableGen/TGParser.cpp | 117 | ||||
-rw-r--r-- | llvm/lib/TableGen/TGParser.h | 14 |
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); |