Skip to content

Commit dff673b

Browse files
committed
[tablegen] Add locations to many PrintFatalError() calls
Summary: While working on the GISel Combiner, I noticed I was producing location-less error messages fairly often and set about fixing this. In the process, I noticed quite a few places elsewhere in TableGen that also neglected to include a relevant location. This patch adds locations to errors that relate to a specific record (or a field within it) and also have easy access to the relevant location. This is particularly useful when multiclasses are involved as many of these errors refer to the full name of a record and it's difficult to guess which substring is grep-able. Unfortunately, tablegen currently only supports Record granularity so it's not currently possible to point at a specific Init so these sometimes point at the record that caused the error rather than the precise origin of the error. Reviewers: bogner, aditya_nandakumar, volkan, aemerson, paquette, nhaehnle Reviewed By: nhaehnle Subscribers: jdoerfert, nhaehnle, asb, rbar, johnrusso, simoncook, apazos, sabuasal, niosHD, jrtc27, zzheng, edward-jones, rogfer01, MartinMosbeck, brucehoult, the_o, PkmX, jocewei, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D58077 llvm-svn: 353862
1 parent 0e71e73 commit dff673b

13 files changed

+140
-80
lines changed

llvm/utils/TableGen/AsmMatcherEmitter.cpp

+3-2
Original file line numberDiff line numberDiff line change
@@ -1159,8 +1159,9 @@ AsmMatcherInfo::getOperandClass(Record *Rec, int SubOpIdx) {
11591159
// use it, else just fall back to the underlying register class.
11601160
const RecordVal *R = Rec->getValue("ParserMatchClass");
11611161
if (!R || !R->getValue())
1162-
PrintFatalError("Record `" + Rec->getName() +
1163-
"' does not have a ParserMatchClass!\n");
1162+
PrintFatalError(Rec->getLoc(),
1163+
"Record `" + Rec->getName() +
1164+
"' does not have a ParserMatchClass!\n");
11641165

11651166
if (DefInit *DI= dyn_cast<DefInit>(R->getValue())) {
11661167
Record *MatchClass = DI->getDef();

llvm/utils/TableGen/AsmWriterInst.cpp

+22-11
Original file line numberDiff line numberDiff line change
@@ -93,8 +93,10 @@ AsmWriterInst::AsmWriterInst(const CodeGenInstruction &CGI, unsigned CGIIndex,
9393
!= std::string::npos) {
9494
AddLiteralString(std::string(1, AsmString[DollarPos+1]));
9595
} else {
96-
PrintFatalError("Non-supported escaped character found in instruction '" +
97-
CGI.TheDef->getName() + "'!");
96+
PrintFatalError(
97+
CGI.TheDef->getLoc(),
98+
"Non-supported escaped character found in instruction '" +
99+
CGI.TheDef->getName() + "'!");
98100
}
99101
LastEmitted = DollarPos+2;
100102
continue;
@@ -131,33 +133,42 @@ AsmWriterInst::AsmWriterInst(const CodeGenInstruction &CGI, unsigned CGIIndex,
131133
// brace.
132134
if (hasCurlyBraces) {
133135
if (VarEnd >= AsmString.size())
134-
PrintFatalError("Reached end of string before terminating curly brace in '"
135-
+ CGI.TheDef->getName() + "'");
136+
PrintFatalError(
137+
CGI.TheDef->getLoc(),
138+
"Reached end of string before terminating curly brace in '" +
139+
CGI.TheDef->getName() + "'");
136140

137141
// Look for a modifier string.
138142
if (AsmString[VarEnd] == ':') {
139143
++VarEnd;
140144
if (VarEnd >= AsmString.size())
141-
PrintFatalError("Reached end of string before terminating curly brace in '"
142-
+ CGI.TheDef->getName() + "'");
145+
PrintFatalError(
146+
CGI.TheDef->getLoc(),
147+
"Reached end of string before terminating curly brace in '" +
148+
CGI.TheDef->getName() + "'");
143149

144150
std::string::size_type ModifierStart = VarEnd;
145151
while (VarEnd < AsmString.size() && isIdentChar(AsmString[VarEnd]))
146152
++VarEnd;
147153
Modifier = std::string(AsmString.begin()+ModifierStart,
148154
AsmString.begin()+VarEnd);
149155
if (Modifier.empty())
150-
PrintFatalError("Bad operand modifier name in '"+ CGI.TheDef->getName() + "'");
156+
PrintFatalError(CGI.TheDef->getLoc(),
157+
"Bad operand modifier name in '" +
158+
CGI.TheDef->getName() + "'");
151159
}
152160

153161
if (AsmString[VarEnd] != '}')
154-
PrintFatalError("Variable name beginning with '{' did not end with '}' in '"
155-
+ CGI.TheDef->getName() + "'");
162+
PrintFatalError(
163+
CGI.TheDef->getLoc(),
164+
"Variable name beginning with '{' did not end with '}' in '" +
165+
CGI.TheDef->getName() + "'");
156166
++VarEnd;
157167
}
158168
if (VarName.empty() && Modifier.empty())
159-
PrintFatalError("Stray '$' in '" + CGI.TheDef->getName() +
160-
"' asm string, maybe you want $$?");
169+
PrintFatalError(CGI.TheDef->getLoc(),
170+
"Stray '$' in '" + CGI.TheDef->getName() +
171+
"' asm string, maybe you want $$?");
161172

162173
if (VarName.empty()) {
163174
// Just a modifier, pass this into PrintSpecial.

llvm/utils/TableGen/CallingConvEmitter.cpp

+6-4
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ void CallingConvEmitter::EmitAction(Record *Action,
108108
O << Action->getValueAsString("Predicate");
109109
} else {
110110
errs() << *Action;
111-
PrintFatalError("Unknown CCPredicateAction!");
111+
PrintFatalError(Action->getLoc(), "Unknown CCPredicateAction!");
112112
}
113113

114114
O << ") {\n";
@@ -145,7 +145,8 @@ void CallingConvEmitter::EmitAction(Record *Action,
145145
ListInit *RegList = Action->getValueAsListInit("RegList");
146146
ListInit *ShadowRegList = Action->getValueAsListInit("ShadowRegList");
147147
if (!ShadowRegList->empty() && ShadowRegList->size() != RegList->size())
148-
PrintFatalError("Invalid length of list of shadowed registers");
148+
PrintFatalError(Action->getLoc(),
149+
"Invalid length of list of shadowed registers");
149150

150151
if (RegList->size() == 1) {
151152
O << IndentStr << "if (unsigned Reg = State.AllocateReg(";
@@ -248,7 +249,8 @@ void CallingConvEmitter::EmitAction(Record *Action,
248249
MVT::SimpleValueType DestVT = getValueType(DestTy);
249250
O << IndentStr << "LocVT = " << getEnumName(DestVT) << ";\n";
250251
if (MVT(DestVT).isFloatingPoint()) {
251-
PrintFatalError("CCPromoteToUpperBitsInType does not handle floating "
252+
PrintFatalError(Action->getLoc(),
253+
"CCPromoteToUpperBitsInType does not handle floating "
252254
"point");
253255
} else {
254256
O << IndentStr << "if (ArgFlags.isSExt())\n"
@@ -280,7 +282,7 @@ void CallingConvEmitter::EmitAction(Record *Action,
280282
O << IndentStr << IndentStr << "return false;\n";
281283
} else {
282284
errs() << *Action;
283-
PrintFatalError("Unknown CCAction!");
285+
PrintFatalError(Action->getLoc(), "Unknown CCAction!");
284286
}
285287
}
286288
}

llvm/utils/TableGen/CodeGenDAGPatterns.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -1407,7 +1407,8 @@ SDTypeConstraint::SDTypeConstraint(Record *R, const CodeGenHwModes &CGH) {
14071407
x.SDTCisSameSizeAs_Info.OtherOperandNum =
14081408
R->getValueAsInt("OtherOperandNum");
14091409
} else {
1410-
PrintFatalError("Unrecognized SDTypeConstraint '" + R->getName() + "'!\n");
1410+
PrintFatalError(R->getLoc(),
1411+
"Unrecognized SDTypeConstraint '" + R->getName() + "'!\n");
14111412
}
14121413
}
14131414

llvm/utils/TableGen/CodeGenInstruction.cpp

+46-22
Original file line numberDiff line numberDiff line change
@@ -33,18 +33,24 @@ CGIOperandList::CGIOperandList(Record *R) : TheDef(R) {
3333

3434
if (DefInit *Init = dyn_cast<DefInit>(OutDI->getOperator())) {
3535
if (Init->getDef()->getName() != "outs")
36-
PrintFatalError(R->getName() + ": invalid def name for output list: use 'outs'");
36+
PrintFatalError(R->getLoc(),
37+
R->getName() +
38+
": invalid def name for output list: use 'outs'");
3739
} else
38-
PrintFatalError(R->getName() + ": invalid output list: use 'outs'");
40+
PrintFatalError(R->getLoc(),
41+
R->getName() + ": invalid output list: use 'outs'");
3942

4043
NumDefs = OutDI->getNumArgs();
4144

4245
DagInit *InDI = R->getValueAsDag("InOperandList");
4346
if (DefInit *Init = dyn_cast<DefInit>(InDI->getOperator())) {
4447
if (Init->getDef()->getName() != "ins")
45-
PrintFatalError(R->getName() + ": invalid def name for input list: use 'ins'");
48+
PrintFatalError(R->getLoc(),
49+
R->getName() +
50+
": invalid def name for input list: use 'ins'");
4651
} else
47-
PrintFatalError(R->getName() + ": invalid input list: use 'ins'");
52+
PrintFatalError(R->getLoc(),
53+
R->getName() + ": invalid input list: use 'ins'");
4854

4955
unsigned MIOperandNo = 0;
5056
std::set<std::string> OperandNames;
@@ -63,7 +69,8 @@ CGIOperandList::CGIOperandList(Record *R) : TheDef(R) {
6369

6470
DefInit *Arg = dyn_cast<DefInit>(ArgInit);
6571
if (!Arg)
66-
PrintFatalError("Illegal operand for the '" + R->getName() + "' instruction!");
72+
PrintFatalError(R->getLoc(), "Illegal operand for the '" + R->getName() +
73+
"' instruction!");
6774

6875
Record *Rec = Arg->getDef();
6976
std::string PrintMethod = "printOperand";
@@ -88,8 +95,9 @@ CGIOperandList::CGIOperandList(Record *R) : TheDef(R) {
8895
// Verify that MIOpInfo has an 'ops' root value.
8996
if (!isa<DefInit>(MIOpInfo->getOperator()) ||
9097
cast<DefInit>(MIOpInfo->getOperator())->getDef()->getName() != "ops")
91-
PrintFatalError("Bad value for MIOperandInfo in operand '" + Rec->getName() +
92-
"'\n");
98+
PrintFatalError(R->getLoc(),
99+
"Bad value for MIOperandInfo in operand '" +
100+
Rec->getName() + "'\n");
93101

94102
// If we have MIOpInfo, then we have #operands equal to number of entries
95103
// in MIOperandInfo.
@@ -107,16 +115,20 @@ CGIOperandList::CGIOperandList(Record *R) : TheDef(R) {
107115
OperandType = "OPERAND_REGISTER";
108116
} else if (!Rec->isSubClassOf("PointerLikeRegClass") &&
109117
!Rec->isSubClassOf("unknown_class"))
110-
PrintFatalError("Unknown operand class '" + Rec->getName() +
111-
"' in '" + R->getName() + "' instruction!");
118+
PrintFatalError(R->getLoc(), "Unknown operand class '" + Rec->getName() +
119+
"' in '" + R->getName() +
120+
"' instruction!");
112121

113122
// Check that the operand has a name and that it's unique.
114123
if (ArgName.empty())
115-
PrintFatalError("In instruction '" + R->getName() + "', operand #" +
116-
Twine(i) + " has no name!");
124+
PrintFatalError(R->getLoc(), "In instruction '" + R->getName() +
125+
"', operand #" + Twine(i) +
126+
" has no name!");
117127
if (!OperandNames.insert(ArgName).second)
118-
PrintFatalError("In instruction '" + R->getName() + "', operand #" +
119-
Twine(i) + " has the same name as a previous operand!");
128+
PrintFatalError(R->getLoc(),
129+
"In instruction '" + R->getName() + "', operand #" +
130+
Twine(i) +
131+
" has the same name as a previous operand!");
120132

121133
OperandList.emplace_back(Rec, ArgName, PrintMethod, EncoderMethod,
122134
OperandNamespace + "::" + OperandType, MIOperandNo,
@@ -138,9 +150,11 @@ CGIOperandList::CGIOperandList(Record *R) : TheDef(R) {
138150
///
139151
unsigned CGIOperandList::getOperandNamed(StringRef Name) const {
140152
unsigned OpIdx;
141-
if (hasOperandNamed(Name, OpIdx)) return OpIdx;
142-
PrintFatalError("'" + TheDef->getName() +
143-
"' does not have an operand named '$" + Name + "'!");
153+
if (hasOperandNamed(Name, OpIdx))
154+
return OpIdx;
155+
PrintFatalError(TheDef->getLoc(), "'" + TheDef->getName() +
156+
"' does not have an operand named '$" +
157+
Name + "'!");
144158
}
145159

146160
/// hasOperandNamed - Query whether the instruction has an operand of the
@@ -159,7 +173,8 @@ bool CGIOperandList::hasOperandNamed(StringRef Name, unsigned &OpIdx) const {
159173
std::pair<unsigned,unsigned>
160174
CGIOperandList::ParseOperandName(const std::string &Op, bool AllowWholeOp) {
161175
if (Op.empty() || Op[0] != '$')
162-
PrintFatalError(TheDef->getName() + ": Illegal operand name: '" + Op + "'");
176+
PrintFatalError(TheDef->getLoc(),
177+
TheDef->getName() + ": Illegal operand name: '" + Op + "'");
163178

164179
std::string OpName = Op.substr(1);
165180
std::string SubOpName;
@@ -169,7 +184,9 @@ CGIOperandList::ParseOperandName(const std::string &Op, bool AllowWholeOp) {
169184
if (DotIdx != std::string::npos) {
170185
SubOpName = OpName.substr(DotIdx+1);
171186
if (SubOpName.empty())
172-
PrintFatalError(TheDef->getName() + ": illegal empty suboperand name in '" +Op +"'");
187+
PrintFatalError(TheDef->getLoc(),
188+
TheDef->getName() +
189+
": illegal empty suboperand name in '" + Op + "'");
173190
OpName = OpName.substr(0, DotIdx);
174191
}
175192

@@ -179,8 +196,11 @@ CGIOperandList::ParseOperandName(const std::string &Op, bool AllowWholeOp) {
179196
// If one was needed, throw.
180197
if (OperandList[OpIdx].MINumOperands > 1 && !AllowWholeOp &&
181198
SubOpName.empty())
182-
PrintFatalError(TheDef->getName() + ": Illegal to refer to"
183-
" whole operand part of complex operand '" + Op + "'");
199+
PrintFatalError(TheDef->getLoc(),
200+
TheDef->getName() +
201+
": Illegal to refer to"
202+
" whole operand part of complex operand '" +
203+
Op + "'");
184204

185205
// Otherwise, return the operand.
186206
return std::make_pair(OpIdx, 0U);
@@ -189,15 +209,19 @@ CGIOperandList::ParseOperandName(const std::string &Op, bool AllowWholeOp) {
189209
// Find the suboperand number involved.
190210
DagInit *MIOpInfo = OperandList[OpIdx].MIOperandInfo;
191211
if (!MIOpInfo)
192-
PrintFatalError(TheDef->getName() + ": unknown suboperand name in '" + Op + "'");
212+
PrintFatalError(TheDef->getLoc(), TheDef->getName() +
213+
": unknown suboperand name in '" +
214+
Op + "'");
193215

194216
// Find the operand with the right name.
195217
for (unsigned i = 0, e = MIOpInfo->getNumArgs(); i != e; ++i)
196218
if (MIOpInfo->getArgNameStr(i) == SubOpName)
197219
return std::make_pair(OpIdx, i);
198220

199221
// Otherwise, didn't find it!
200-
PrintFatalError(TheDef->getName() + ": unknown suboperand name in '" + Op + "'");
222+
PrintFatalError(TheDef->getLoc(), TheDef->getName() +
223+
": unknown suboperand name in '" + Op +
224+
"'");
201225
return std::make_pair(0U, 0U);
202226
}
203227

llvm/utils/TableGen/CodeGenRegisters.cpp

+3-2
Original file line numberDiff line numberDiff line change
@@ -739,8 +739,9 @@ CodeGenRegisterClass::CodeGenRegisterClass(CodeGenRegBank &RegBank, Record *R)
739739
for (unsigned i = 0, e = TypeList.size(); i != e; ++i) {
740740
Record *Type = TypeList[i];
741741
if (!Type->isSubClassOf("ValueType"))
742-
PrintFatalError("RegTypes list member '" + Type->getName() +
743-
"' does not derive from the ValueType class!");
742+
PrintFatalError(R->getLoc(),
743+
"RegTypes list member '" + Type->getName() +
744+
"' does not derive from the ValueType class!");
744745
VTs.push_back(getValueTypeByHwMode(Type, RegBank.getHwModes()));
745746
}
746747
assert(!VTs.empty() && "RegisterClass must contain at least one ValueType!");

llvm/utils/TableGen/CodeGenSchedule.cpp

+6-4
Original file line numberDiff line numberDiff line change
@@ -1935,8 +1935,9 @@ void CodeGenSchedModels::checkCompleteness() {
19351935
unsigned SCIdx = getSchedClassIdx(*Inst);
19361936
if (!SCIdx) {
19371937
if (Inst->TheDef->isValueUnset("SchedRW") && !HadCompleteModel) {
1938-
PrintError("No schedule information for instruction '"
1939-
+ Inst->TheDef->getName() + "'");
1938+
PrintError(Inst->TheDef->getLoc(),
1939+
"No schedule information for instruction '" +
1940+
Inst->TheDef->getName() + "'");
19401941
Complete = false;
19411942
}
19421943
continue;
@@ -1954,8 +1955,9 @@ void CodeGenSchedModels::checkCompleteness() {
19541955
return R->getValueAsDef("SchedModel") == ProcModel.ModelDef;
19551956
});
19561957
if (I == InstRWs.end()) {
1957-
PrintError("'" + ProcModel.ModelName + "' lacks information for '" +
1958-
Inst->TheDef->getName() + "'");
1958+
PrintError(Inst->TheDef->getLoc(), "'" + ProcModel.ModelName +
1959+
"' lacks information for '" +
1960+
Inst->TheDef->getName() + "'");
19591961
Complete = false;
19601962
}
19611963
}

llvm/utils/TableGen/CodeGenTarget.cpp

+18-10
Original file line numberDiff line numberDiff line change
@@ -495,9 +495,10 @@ ComplexPattern::ComplexPattern(Record *R) {
495495
} else if (PropList[i]->getName() == "SDNPWantParent") {
496496
Properties |= 1 << SDNPWantParent;
497497
} else {
498-
PrintFatalError("Unsupported SD Node property '" +
499-
PropList[i]->getName() + "' on ComplexPattern '" +
500-
R->getName() + "'!");
498+
PrintFatalError(R->getLoc(), "Unsupported SD Node property '" +
499+
PropList[i]->getName() +
500+
"' on ComplexPattern '" + R->getName() +
501+
"'!");
501502
}
502503
}
503504

@@ -533,6 +534,7 @@ CodeGenIntrinsicTable::CodeGenIntrinsicTable(const RecordKeeper &RC,
533534
CodeGenIntrinsic::CodeGenIntrinsic(Record *R) {
534535
TheDef = R;
535536
std::string DefName = R->getName();
537+
ArrayRef<SMLoc> DefLoc = R->getLoc();
536538
ModRef = ReadWriteMem;
537539
Properties = 0;
538540
isOverloaded = false;
@@ -547,7 +549,8 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) {
547549

548550
if (DefName.size() <= 4 ||
549551
std::string(DefName.begin(), DefName.begin() + 4) != "int_")
550-
PrintFatalError("Intrinsic '" + DefName + "' does not start with 'int_'!");
552+
PrintFatalError(DefLoc,
553+
"Intrinsic '" + DefName + "' does not start with 'int_'!");
551554

552555
EnumName = std::string(DefName.begin()+4, DefName.end());
553556

@@ -569,7 +572,8 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) {
569572
// Verify it starts with "llvm.".
570573
if (Name.size() <= 5 ||
571574
std::string(Name.begin(), Name.begin() + 5) != "llvm.")
572-
PrintFatalError("Intrinsic '" + DefName + "'s name does not start with 'llvm.'!");
575+
PrintFatalError(DefLoc, "Intrinsic '" + DefName +
576+
"'s name does not start with 'llvm.'!");
573577
}
574578

575579
// If TargetPrefix is specified, make sure that Name starts with
@@ -578,8 +582,9 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) {
578582
if (Name.size() < 6+TargetPrefix.size() ||
579583
std::string(Name.begin() + 5, Name.begin() + 6 + TargetPrefix.size())
580584
!= (TargetPrefix + "."))
581-
PrintFatalError("Intrinsic '" + DefName + "' does not start with 'llvm." +
582-
TargetPrefix + ".'!");
585+
PrintFatalError(DefLoc, "Intrinsic '" + DefName +
586+
"' does not start with 'llvm." +
587+
TargetPrefix + ".'!");
583588
}
584589

585590
// Parse the list of return types.
@@ -611,7 +616,8 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) {
611616

612617
// Reject invalid types.
613618
if (VT == MVT::isVoid)
614-
PrintFatalError("Intrinsic '" + DefName + " has void in result type list!");
619+
PrintFatalError(DefLoc, "Intrinsic '" + DefName +
620+
" has void in result type list!");
615621

616622
IS.RetVTs.push_back(VT);
617623
IS.RetTypeDefs.push_back(TyEl);
@@ -629,7 +635,8 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) {
629635
PrintError(R->getLoc(),
630636
"Parameter #" + Twine(i) + " has out of bounds matching "
631637
"number " + Twine(MatchTy));
632-
PrintFatalError(Twine("ParamTypes is ") + TypeList->getAsString());
638+
PrintFatalError(DefLoc,
639+
Twine("ParamTypes is ") + TypeList->getAsString());
633640
}
634641
VT = OverloadedVTs[MatchTy];
635642
// It only makes sense to use the extended and truncated vector element
@@ -650,7 +657,8 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) {
650657

651658
// Reject invalid types.
652659
if (VT == MVT::isVoid && i != e-1 /*void at end means varargs*/)
653-
PrintFatalError("Intrinsic '" + DefName + " has void in result type list!");
660+
PrintFatalError(DefLoc, "Intrinsic '" + DefName +
661+
" has void in result type list!");
654662

655663
IS.ParamVTs.push_back(VT);
656664
IS.ParamTypeDefs.push_back(TyEl);

0 commit comments

Comments
 (0)