forked from OSchip/llvm-project
[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
This commit is contained in:
parent
67bce07964
commit
50d96f59d0
|
@ -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
|
||||
|
|
|
@ -1478,6 +1478,9 @@ private:
|
|||
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 @@ public:
|
|||
/// 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 @@ public:
|
|||
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 @@ public:
|
|||
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);
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -131,6 +131,7 @@ public:
|
|||
}
|
||||
|
||||
SMLoc getLoc() const;
|
||||
SMRange getLocRange() const;
|
||||
|
||||
private:
|
||||
/// LexToken - Read the next token and return its code.
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -198,9 +198,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 +247,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);
|
||||
|
|
|
@ -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">;
|
||||
|
|
|
@ -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 ">;
|
||||
|
|
|
@ -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">;
|
||||
|
|
|
@ -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">;
|
||||
|
|
|
@ -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">;
|
||||
|
|
|
@ -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">;
|
||||
|
|
|
@ -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">;
|
||||
|
|
|
@ -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)))]>;
|
||||
|
|
|
@ -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!
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue