[clang] 50d96f5 - [TableGen] Track reference locations of Records/RecordVals
River Riddle via cfe-commits
cfe-commits at lists.llvm.org
Tue Sep 27 23:48:51 PDT 2022
Author: River Riddle
Date: 2022-09-27T23:48:16-07:00
New Revision: 50d96f59d0966bdda6b3ac4f8964ed572435b847
URL: https://github.com/llvm/llvm-project/commit/50d96f59d0966bdda6b3ac4f8964ed572435b847
DIFF: https://github.com/llvm/llvm-project/commit/50d96f59d0966bdda6b3ac4f8964ed572435b847.diff
LOG: [TableGen] Track reference locations of Records/RecordVals
This is extremely useful for language tooling as it allows
for providing go-to-def/find-references/etc. for many
more situations than what is currently possible.
Differential Revision: https://reviews.llvm.org/D134087
Added:
Modified:
clang/test/TableGen/redefined-group.td
llvm/include/llvm/TableGen/Record.h
llvm/lib/TableGen/TGLexer.cpp
llvm/lib/TableGen/TGLexer.h
llvm/lib/TableGen/TGParser.cpp
llvm/lib/TableGen/TGParser.h
llvm/test/TableGen/ConstraintChecking1.td
llvm/test/TableGen/ConstraintChecking2.td
llvm/test/TableGen/ConstraintChecking3.td
llvm/test/TableGen/ConstraintChecking4.td
llvm/test/TableGen/ConstraintChecking5.td
llvm/test/TableGen/ConstraintChecking6.td
llvm/test/TableGen/ConstraintChecking7.td
llvm/test/TableGen/GlobalISelEmitter-setcc.td
llvm/test/TableGen/RegisterClass.td
llvm/test/TableGen/SchedModelError.td
llvm/test/TableGen/generic-tables.td
mlir/lib/Tools/tblgen-lsp-server/TableGenServer.cpp
Removed:
################################################################################
diff --git a/clang/test/TableGen/redefined-group.td b/clang/test/TableGen/redefined-group.td
index 5ffeb3011978..558c6775ef4b 100644
--- a/clang/test/TableGen/redefined-group.td
+++ b/clang/test/TableGen/redefined-group.td
@@ -4,31 +4,31 @@ include "DiagnosticBase.inc"
def NamedGroup : DiagGroup<"a">;
def InNamedGroup1 : Warning<"">, InGroup<DiagGroup<"a">>;
def InNamedGroup2 : Warning<"">, InGroup < DiagGroup<"a"> >;
-// CHECK: redefined-group.td:[[@LINE-3]]:1: error: group 'a' is defined more than once
-// CHECK: redefined-group.td:[[@LINE-3]]:1: note: also implicitly defined here
-// CHECK: redefined-group.td:[[@LINE-3]]:1: note: also implicitly defined here
+// CHECK: redefined-group.td:[[@LINE-3]]:5: error: group 'a' is defined more than once
+// CHECK: redefined-group.td:[[@LINE-3]]:5: note: also implicitly defined here
+// CHECK: redefined-group.td:[[@LINE-3]]:5: note: also implicitly defined here
def : DiagGroup<"b">;
def InUnnamedGroup : Warning<"">, InGroup<DiagGroup<"b">>;
// CHECK: redefined-group.td:[[@LINE-2]]:1: error: group 'b' is defined more than once
-// CHECK: redefined-group.td:[[@LINE-2]]:1: note: also implicitly defined here
+// CHECK: redefined-group.td:[[@LINE-2]]:5: note: also implicitly defined here
def ImplicitGroup1 : Warning<"">, InGroup<DiagGroup<"c">>;
def ImplicitGroup2 : Warning<"">, InGroup<DiagGroup<"c">>;
def ImplicitGroup3 : Warning<"">,
InGroup<DiagGroup<"c">>;
-// CHECK: redefined-group.td:[[@LINE-4]]:1: error: group 'c' is implicitly defined more than once
-// CHECK: redefined-group.td:[[@LINE-4]]:1: note: also implicitly defined here
-// CHECK: redefined-group.td:[[@LINE-4]]:1: note: also implicitly defined here
+// CHECK: redefined-group.td:[[@LINE-4]]:5: error: group 'c' is implicitly defined more than once
+// CHECK: redefined-group.td:[[@LINE-4]]:5: note: also implicitly defined here
+// CHECK: redefined-group.td:[[@LINE-4]]:5: note: also implicitly defined here
def NamedAndUnnamed : DiagGroup<"d">;
def : DiagGroup<"d">;
-// CHECK: redefined-group.td:[[@LINE-2]]:1: error: group 'd' is defined more than once
+// CHECK: redefined-group.td:[[@LINE-2]]:5: error: group 'd' is defined more than once
// CHECK: redefined-group.td:[[@LINE-2]]:1: note: also defined here
def : DiagGroup<"e">;
def NamedAndUnnamed2 : DiagGroup<"e">;
-// CHECK: redefined-group.td:[[@LINE-1]]:1: error: group 'e' is defined more than once
+// CHECK: redefined-group.td:[[@LINE-1]]:5: error: group 'e' is defined more than once
// CHECK: redefined-group.td:[[@LINE-3]]:1: note: also defined here
def InGroupF1 : Warning<"">, InGroup<DiagGroup<"f">>;
@@ -38,6 +38,6 @@ def GroupF : DiagGroup<"f">;
def InGroupF3 : Warning<"">, InGroup<GroupF>;
def InGroupF4 : Warning<"">, InGroup<DiagGroup<"f">>;
// CHECK: redefined-group.td:[[@LINE-5]]:1: error: group 'f' is defined more than once
-// CHECK: redefined-group.td:[[@LINE-7]]:1: note: also implicitly defined here
-// CHECK: redefined-group.td:[[@LINE-6]]:1: note: also implicitly defined here
-// CHECK: redefined-group.td:[[@LINE-4]]:1: note: also implicitly defined here
+// CHECK: redefined-group.td:[[@LINE-7]]:5: note: also implicitly defined here
+// CHECK: redefined-group.td:[[@LINE-6]]:5: note: also implicitly defined here
+// CHECK: redefined-group.td:[[@LINE-4]]:5: note: also implicitly defined here
diff --git a/llvm/include/llvm/TableGen/Record.h b/llvm/include/llvm/TableGen/Record.h
index 50df38e695d7..2d44f39973e2 100644
--- a/llvm/include/llvm/TableGen/Record.h
+++ b/llvm/include/llvm/TableGen/Record.h
@@ -1478,6 +1478,9 @@ class RecordVal {
Init *Value;
bool IsUsed = false;
+ /// Reference locations to this record value.
+ SmallVector<SMRange> ReferenceLocs;
+
public:
RecordVal(Init *N, RecTy *T, FieldKind K);
RecordVal(Init *N, SMLoc Loc, RecTy *T, FieldKind K);
@@ -1524,6 +1527,12 @@ class RecordVal {
/// Set the value and source location of the field.
bool setValue(Init *V, SMLoc NewLoc);
+ /// Add a reference to this record value.
+ void addReferenceLoc(SMRange Loc) { ReferenceLocs.push_back(Loc); }
+
+ /// Return the references of this record value.
+ ArrayRef<SMRange> getReferenceLocs() const { return ReferenceLocs; }
+
/// Whether this value is used. Useful for reporting warnings, for example
/// when a template argument is unused.
void setUsed(bool Used) { IsUsed = Used; }
@@ -1556,9 +1565,11 @@ class Record {
private:
Init *Name;
// Location where record was instantiated, followed by the location of
- // multiclass prototypes used.
+ // multiclass prototypes used, and finally by the locations of references to
+ // this record.
SmallVector<SMLoc, 4> Locs;
SmallVector<SMLoc, 0> ForwardDeclarationLocs;
+ SmallVector<SMRange, 0> ReferenceLocs;
SmallVector<Init *, 0> TemplateArgs;
SmallVector<RecordVal, 0> Values;
SmallVector<AssertionInfo, 0> Assertions;
@@ -1628,6 +1639,12 @@ class Record {
return ForwardDeclarationLocs;
}
+ /// Add a reference to this record value.
+ void appendReferenceLoc(SMRange Loc) { ReferenceLocs.push_back(Loc); }
+
+ /// Return the references of this record value.
+ ArrayRef<SMRange> getReferenceLocs() const { return ReferenceLocs; }
+
// Update a class location when encountering a (re-)definition.
void updateClassLoc(SMLoc Loc);
diff --git a/llvm/lib/TableGen/TGLexer.cpp b/llvm/lib/TableGen/TGLexer.cpp
index a33ed81dcf29..65959b2c0a0c 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) {
diff --git a/llvm/lib/TableGen/TGLexer.h b/llvm/lib/TableGen/TGLexer.h
index 459ba0f4af64..9ba66b7a5622 100644
--- a/llvm/lib/TableGen/TGLexer.h
+++ b/llvm/lib/TableGen/TGLexer.h
@@ -131,6 +131,7 @@ class TGLexer {
}
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 325d43760aa0..82a589a7a77e 100644
--- a/llvm/lib/TableGen/TGParser.cpp
+++ b/llvm/lib/TableGen/TGParser.cpp
@@ -161,7 +161,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 +211,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 ") +
@@ -586,6 +586,8 @@ Record *TGParser::ParseClassID() {
Lex.getCurStrVal() + "'");
else
TokError(Msg);
+ } else {
+ Result->appendReferenceLoc(Lex.getLocRange());
}
Lex.Lex();
@@ -867,11 +869,13 @@ 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)) {
+ RV->addReferenceLoc(NameLoc);
return VarInit::get(Name, RV->getType());
+ }
}
if ((CurRec && CurRec->isClass()) || CurMultiClass) {
@@ -887,6 +891,7 @@ Init *TGParser::ParseIDValue(Record *CurRec, StringInit *Name, SMLoc NameLoc,
RecordVal *RV = TemplateRec->getValue(TemplateArgName);
assert(RV && "Template arg doesn't exist??");
RV->setUsed(true);
+ RV->addReferenceLoc(NameLoc);
return VarInit::get(TemplateArgName, RV->getType());
} else if (Name->getValue() == "NAME") {
return VarInit::get(TemplateArgName, StringRecTy::get(Records));
@@ -909,8 +914,12 @@ 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 (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 +927,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;
}
@@ -2184,7 +2193,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 +2203,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 +2213,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 +2221,15 @@ 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() + "'");
+ }
}
+ Class->appendReferenceLoc(NameLoc);
return VarDefInit::get(Class, Args)->Fold();
}
case tgtok::l_brace: { // Value ::= '{' ValueList '}'
@@ -2510,12 +2521,25 @@ 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 (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 +2804,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, None, 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 +3104,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..0e630dc99186 100644
--- a/llvm/lib/TableGen/TGParser.h
+++ b/llvm/lib/TableGen/TGParser.h
@@ -198,9 +198,12 @@ class TGParser {
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 +247,7 @@ class TGParser {
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);
diff --git a/llvm/test/TableGen/ConstraintChecking1.td b/llvm/test/TableGen/ConstraintChecking1.td
index 2c0c3d9bfabb..f885974ba7a7 100644
--- a/llvm/test/TableGen/ConstraintChecking1.td
+++ b/llvm/test/TableGen/ConstraintChecking1.td
@@ -2,5 +2,5 @@
include "ConstraintChecking.inc"
-// CHECK: [[FILE]]:[[@LINE+1]]:1: error: Unrecognized constraint '$dest1 ~ $src2' in 'Foo'
+// CHECK: [[FILE]]:[[@LINE+1]]:5: error: Unrecognized constraint '$dest1 ~ $src2' in 'Foo'
def Foo : TestInstructionWithConstraints<"$dest1 ~ $src2">;
diff --git a/llvm/test/TableGen/ConstraintChecking2.td b/llvm/test/TableGen/ConstraintChecking2.td
index 65ec882b18f8..ae9fbe379569 100644
--- a/llvm/test/TableGen/ConstraintChecking2.td
+++ b/llvm/test/TableGen/ConstraintChecking2.td
@@ -2,5 +2,5 @@
include "ConstraintChecking.inc"
-// CHECK: [[FILE]]:[[@LINE+1]]:1: error: Illegal format for @earlyclobber constraint in 'Foo'
+// CHECK: [[FILE]]:[[@LINE+1]]:5: error: Illegal format for @earlyclobber constraint in 'Foo'
def Foo : TestInstructionWithConstraints<"@earlyclobber ">;
diff --git a/llvm/test/TableGen/ConstraintChecking3.td b/llvm/test/TableGen/ConstraintChecking3.td
index 835ec2e035f7..2d5fe6b7ef96 100644
--- a/llvm/test/TableGen/ConstraintChecking3.td
+++ b/llvm/test/TableGen/ConstraintChecking3.td
@@ -4,5 +4,5 @@ include "ConstraintChecking.inc"
// (This is illegal because the '=' has to be surrounded by whitespace)
-// CHECK: [[FILE]]:[[@LINE+1]]:1: error: Illegal format for tied-to constraint in 'Foo'
+// CHECK: [[FILE]]:[[@LINE+1]]:5: error: Illegal format for tied-to constraint in 'Foo'
def Foo : TestInstructionWithConstraints<"$dest1=$dest2">;
diff --git a/llvm/test/TableGen/ConstraintChecking4.td b/llvm/test/TableGen/ConstraintChecking4.td
index bd511eb1132d..ae11c47d3d00 100644
--- a/llvm/test/TableGen/ConstraintChecking4.td
+++ b/llvm/test/TableGen/ConstraintChecking4.td
@@ -2,5 +2,5 @@
include "ConstraintChecking.inc"
-// CHECK: [[FILE]]:[[@LINE+1]]:1: error: Output operands '$dest1' and '$dest2' of 'Foo' cannot be tied!
+// CHECK: [[FILE]]:[[@LINE+1]]:5: error: Output operands '$dest1' and '$dest2' of 'Foo' cannot be tied!
def Foo : TestInstructionWithConstraints<"$dest1 = $dest2">;
diff --git a/llvm/test/TableGen/ConstraintChecking5.td b/llvm/test/TableGen/ConstraintChecking5.td
index 7db354637fa1..0773e650302d 100644
--- a/llvm/test/TableGen/ConstraintChecking5.td
+++ b/llvm/test/TableGen/ConstraintChecking5.td
@@ -2,5 +2,5 @@
include "ConstraintChecking.inc"
-// CHECK: [[FILE]]:[[@LINE+1]]:1: error: Input operands '$src1' and '$src2' of 'Foo' cannot be tied!
+// CHECK: [[FILE]]:[[@LINE+1]]:5: error: Input operands '$src1' and '$src2' of 'Foo' cannot be tied!
def Foo : TestInstructionWithConstraints<"$src1 = $src2">;
diff --git a/llvm/test/TableGen/ConstraintChecking6.td b/llvm/test/TableGen/ConstraintChecking6.td
index 2d3bdd2adabe..676eb7a49941 100644
--- a/llvm/test/TableGen/ConstraintChecking6.td
+++ b/llvm/test/TableGen/ConstraintChecking6.td
@@ -2,5 +2,5 @@
include "ConstraintChecking.inc"
-// CHECK: [[FILE]]:[[@LINE+1]]:1: error: Operand '$dest1' of 'Foo' cannot have multiple operands tied to it!
+// CHECK: [[FILE]]:[[@LINE+1]]:5: error: Operand '$dest1' of 'Foo' cannot have multiple operands tied to it!
def Foo : TestInstructionWithConstraints<"$dest1 = $src1, $dest1 = $src2">;
diff --git a/llvm/test/TableGen/ConstraintChecking7.td b/llvm/test/TableGen/ConstraintChecking7.td
index 5a44ee4f1d8a..d884ac60744a 100644
--- a/llvm/test/TableGen/ConstraintChecking7.td
+++ b/llvm/test/TableGen/ConstraintChecking7.td
@@ -2,5 +2,5 @@
include "ConstraintChecking.inc"
-// CHECK: [[FILE]]:[[@LINE+1]]:1: error: Operand '$src1' of 'Foo' cannot have multiple constraints!
+// CHECK: [[FILE]]:[[@LINE+1]]:5: error: Operand '$src1' of 'Foo' cannot have multiple constraints!
def Foo : TestInstructionWithConstraints<"$dest1 = $src1, $dest2 = $src1">;
diff --git a/llvm/test/TableGen/GlobalISelEmitter-setcc.td b/llvm/test/TableGen/GlobalISelEmitter-setcc.td
index 1bad1754f64d..933489b31bc3 100644
--- a/llvm/test/TableGen/GlobalISelEmitter-setcc.td
+++ b/llvm/test/TableGen/GlobalISelEmitter-setcc.td
@@ -19,6 +19,6 @@ def ICMPEQ : I<(outs GPR32:$dst), (ins GPR32Op:$src0, GPR32:$src1),
[(set GPR32:$dst, (i32 (setcc i32:$src0, i32:$src1, SETEQ)))]>;
// Check there is an error if not a CondCode operand.
-// ERR: [[FILE]]:[[@LINE+1]]:1: warning: Skipped pattern: Unable to handle CondCode
+// ERR: [[FILE]]:[[@LINE+1]]:5: warning: Skipped pattern: Unable to handle CondCode
def FCMP_NOTCC : I<(outs GPR32:$dst), (ins FPR32Op:$src0, FPR32:$src1),
[(set GPR32:$dst, (i32 (setcc f32:$src0, f32:$src1, i32)))]>;
diff --git a/llvm/test/TableGen/RegisterClass.td b/llvm/test/TableGen/RegisterClass.td
index d81c2df45309..b7520bc76972 100644
--- a/llvm/test/TableGen/RegisterClass.td
+++ b/llvm/test/TableGen/RegisterClass.td
@@ -4,4 +4,4 @@ include "llvm/Target/Target.td"
def MyTarget : Target;
def R0 : Register<"r0">;
-def ClassA : RegisterClass<"MyTarget", [], 32, (add R0)>; // CHECK: [[@LINE]]:1: error: RegTypes list must not be empty!
+def ClassA : RegisterClass<"MyTarget", [], 32, (add R0)>; // CHECK: [[@LINE]]:5: error: RegTypes list must not be empty!
diff --git a/llvm/test/TableGen/SchedModelError.td b/llvm/test/TableGen/SchedModelError.td
index 237bc459c45d..d846d279ee75 100644
--- a/llvm/test/TableGen/SchedModelError.td
+++ b/llvm/test/TableGen/SchedModelError.td
@@ -4,7 +4,7 @@ include "llvm/Target/Target.td"
def TestTarget : Target;
-// CHECK: [[FILE]]:[[@LINE+1]]:1: error: No schedule information for instruction 'TestInst' in SchedMachineModel 'TestSchedModel'
+// CHECK: [[FILE]]:[[@LINE+1]]:5: error: No schedule information for instruction 'TestInst' in SchedMachineModel 'TestSchedModel'
def TestInst : Instruction {
let OutOperandList = (outs);
let InOperandList = (ins);
diff --git a/llvm/test/TableGen/generic-tables.td b/llvm/test/TableGen/generic-tables.td
index e410159e6dfb..4bf3918c01a1 100644
--- a/llvm/test/TableGen/generic-tables.td
+++ b/llvm/test/TableGen/generic-tables.td
@@ -154,7 +154,7 @@ class DEntry<string str, int val1> {
}
def DFoo : DEntry<"foo", 1>;
-// ERROR1: [[@LINE+1]]:1: error: Record 'DBar' for table 'DTable' is missing field 'Val1'
+// ERROR1: [[@LINE+1]]:5: error: Record 'DBar' for table 'DTable' is missing field 'Val1'
def DBar : DEntry<"bar", ?>;
def DTable : GenericTable {
diff --git a/mlir/lib/Tools/tblgen-lsp-server/TableGenServer.cpp b/mlir/lib/Tools/tblgen-lsp-server/TableGenServer.cpp
index 7d4404787da5..faa9a55c4677 100644
--- a/mlir/lib/Tools/tblgen-lsp-server/TableGenServer.cpp
+++ b/mlir/lib/Tools/tblgen-lsp-server/TableGenServer.cpp
@@ -202,16 +202,15 @@ void TableGenIndex::initialize(const llvm::RecordKeeper &records) {
// Add references to the definition.
for (SMLoc loc : def.getLoc().drop_front())
insertRef(sym, lsp::convertTokenLocToRange(loc));
-
- // Add references to any super classes.
- for (auto &it : def.getSuperClasses())
- insertRef(getOrInsertDef(it.first),
- lsp::convertTokenLocToRange(it.second.Start));
+ for (SMRange loc : def.getReferenceLocs())
+ insertRef(sym, loc);
// Add definitions for any values.
for (const llvm::RecordVal &value : def.getValues()) {
auto *sym = getOrInsertDef(&value);
insertRef(sym, sym->defLoc, /*isDef=*/true);
+ for (SMRange refLoc : value.getReferenceLocs())
+ insertRef(sym, refLoc);
}
}
}
More information about the cfe-commits
mailing list