1//==------------------------------------------------------------------------==//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "llvm/CodeGen/SDNodeInfo.h"
10#include "llvm/CodeGen/SelectionDAG.h"
11#include "llvm/CodeGen/SelectionDAGNodes.h"
12#include "llvm/CodeGen/TargetLowering.h"
13#include "llvm/CodeGen/TargetSubtargetInfo.h"
14
15using namespace llvm;
16
17static void reportNodeError(const SelectionDAG &DAG, const SDNode *N,
18 const Twine &Msg) {
19 std::string S;
20 raw_string_ostream SS(S);
21 SS << "invalid node: " << Msg << '\n';
22 N->printrWithDepth(O&: SS, G: &DAG, depth: 2);
23 report_fatal_error(reason: StringRef(S));
24}
25
26static void checkResultType(const SelectionDAG &DAG, const SDNode *N,
27 unsigned ResIdx, EVT ExpectedVT) {
28 EVT ActualVT = N->getValueType(ResNo: ResIdx);
29 if (ActualVT != ExpectedVT)
30 reportNodeError(
31 DAG, N,
32 Msg: "result #" + Twine(ResIdx) + " has invalid type; expected " +
33 ExpectedVT.getEVTString() + ", got " + ActualVT.getEVTString());
34}
35
36static void checkOperandType(const SelectionDAG &DAG, const SDNode *N,
37 unsigned OpIdx, EVT ExpectedVT) {
38 EVT ActualVT = N->getOperand(Num: OpIdx).getValueType();
39 if (ActualVT != ExpectedVT)
40 reportNodeError(
41 DAG, N,
42 Msg: "operand #" + Twine(OpIdx) + " has invalid type; expected " +
43 ExpectedVT.getEVTString() + ", got " + ActualVT.getEVTString());
44}
45
46namespace {
47
48/// Similar to SDValue, but also records whether it is a result or an operand
49/// of a node so we can provide more precise diagnostics.
50class SDNodeValue {
51 const SDNode *N;
52 unsigned Idx;
53 bool IsRes;
54
55public:
56 SDNodeValue(const SDNode *N, unsigned Idx, bool IsRes)
57 : N(N), Idx(Idx), IsRes(IsRes) {}
58
59 SDValue getValue() const {
60 return IsRes ? SDValue(const_cast<SDNode *>(N), Idx) : N->getOperand(Num: Idx);
61 }
62
63 EVT getValueType() const { return getValue().getValueType(); }
64
65 friend raw_ostream &operator<<(raw_ostream &OS, const SDNodeValue &Op) {
66 return OS << (Op.IsRes ? "result" : "operand") << " #" << Op.Idx;
67 }
68};
69
70} // namespace
71
72void SDNodeInfo::verifyNode(const SelectionDAG &DAG, const SDNode *N) const {
73 const SDNodeDesc &Desc = getDesc(Opcode: N->getOpcode());
74 bool HasChain = Desc.hasProperty(Property: SDNPHasChain);
75 bool HasOutGlue = Desc.hasProperty(Property: SDNPOutGlue);
76 bool HasInGlue = Desc.hasProperty(Property: SDNPInGlue);
77 bool HasOptInGlue = Desc.hasProperty(Property: SDNPOptInGlue);
78 bool IsVariadic = Desc.hasProperty(Property: SDNPVariadic);
79
80 unsigned ActualNumResults = N->getNumValues();
81 unsigned ExpectedNumResults = Desc.NumResults + HasChain + HasOutGlue;
82
83 if (ActualNumResults != ExpectedNumResults)
84 reportNodeError(DAG, N,
85 Msg: "invalid number of results; expected " +
86 Twine(ExpectedNumResults) + ", got " +
87 Twine(ActualNumResults));
88
89 // Chain result comes after all normal results.
90 if (HasChain) {
91 unsigned ChainResIdx = Desc.NumResults;
92 checkResultType(DAG, N, ResIdx: ChainResIdx, ExpectedVT: MVT::Other);
93 }
94
95 // Glue result comes last.
96 if (HasOutGlue) {
97 unsigned GlueResIdx = Desc.NumResults + HasChain;
98 checkResultType(DAG, N, ResIdx: GlueResIdx, ExpectedVT: MVT::Glue);
99 }
100
101 // In the most general case, the operands of a node go in the following order:
102 // chain, fix#0, ..., fix#M-1, var#0, ... var#N-1, glue
103 // If the number of operands is < 0, M can be any;
104 // If the node has SDNPVariadic property, N can be any.
105 bool HasOptionalOperands = Desc.NumOperands < 0 || IsVariadic;
106
107 unsigned ActualNumOperands = N->getNumOperands();
108 unsigned ExpectedMinNumOperands =
109 (Desc.NumOperands >= 0 ? Desc.NumOperands : 0) + HasChain + HasInGlue;
110
111 // Check the lower bound.
112 if (ActualNumOperands < ExpectedMinNumOperands) {
113 StringRef How = HasOptionalOperands ? "at least " : "";
114 reportNodeError(DAG, N,
115 Msg: "invalid number of operands; expected " + How +
116 Twine(ExpectedMinNumOperands) + ", got " +
117 Twine(ActualNumOperands));
118 }
119
120 // Check the upper bound. We can only do this if the number of fixed operands
121 // is known and there are no variadic operands.
122 if (Desc.NumOperands >= 0 && !IsVariadic) {
123 // Account for optional input glue.
124 unsigned ExpectedMaxNumOperands = ExpectedMinNumOperands + HasOptInGlue;
125 if (ActualNumOperands > ExpectedMaxNumOperands) {
126 StringRef How = HasOptInGlue ? "at most " : "";
127 reportNodeError(DAG, N,
128 Msg: "invalid number of operands; expected " + How +
129 Twine(ExpectedMaxNumOperands) + ", got " +
130 Twine(ActualNumOperands));
131 }
132 }
133
134 // Chain operand comes first.
135 if (HasChain)
136 checkOperandType(DAG, N, OpIdx: 0, ExpectedVT: MVT::Other);
137
138 // Glue operand comes last.
139 if (HasInGlue)
140 checkOperandType(DAG, N, OpIdx: ActualNumOperands - 1, ExpectedVT: MVT::Glue);
141 if (HasOptInGlue && ActualNumOperands >= 1 &&
142 N->getOperand(Num: ActualNumOperands - 1).getValueType() == MVT::Glue)
143 HasInGlue = true;
144
145 // Check variadic operands. These should be Register or RegisterMask.
146 if (IsVariadic && Desc.NumOperands >= 0) {
147 unsigned VarOpStart = HasChain + Desc.NumOperands;
148 unsigned VarOpEnd = ActualNumOperands - HasInGlue;
149 for (unsigned OpIdx = VarOpStart; OpIdx != VarOpEnd; ++OpIdx) {
150 unsigned OpOpcode = N->getOperand(Num: OpIdx).getOpcode();
151 if (OpOpcode != ISD::Register && OpOpcode != ISD::RegisterMask)
152 reportNodeError(DAG, N,
153 Msg: "variadic operand #" + Twine(OpIdx) +
154 " must be Register or RegisterMask");
155 }
156 }
157
158 unsigned VTHwMode =
159 DAG.getSubtarget().getHwMode(type: MCSubtargetInfo::HwMode_ValueType);
160
161 // Returns a constrained or constraining value (result or operand) of a node.
162 // ValIdx is the index of a node's value, as defined by SDTypeConstraint;
163 // that is, it indexes a node's operands after its results and ignores
164 // chain/glue values.
165 auto GetConstraintValue = [&](unsigned ValIdx) {
166 if (ValIdx < Desc.NumResults)
167 return SDNodeValue(N, ValIdx, /*IsRes=*/true);
168 return SDNodeValue(N, HasChain + (ValIdx - Desc.NumResults),
169 /*IsRes=*/false);
170 };
171
172 auto GetConstraintVT = [&](const SDTypeConstraint &C) {
173 if (!C.NumHwModes)
174 return static_cast<MVT::SimpleValueType>(C.VT);
175 for (auto [Mode, VT] : ArrayRef(&VTByHwModeTable[C.VT], C.NumHwModes))
176 if (Mode == VTHwMode)
177 return VT;
178 llvm_unreachable("No value type for this HW mode");
179 };
180
181 SmallString<128> ES;
182 raw_svector_ostream SS(ES);
183
184 // Reports an error unless SmallVT is strictly smaller than the type of
185 // BigVal. SmallVal is only used to describe SmallVT in error messages.
186 auto CheckSmallerThan = [&](const SDNodeValue &SmallVal, EVT SmallVT,
187 const SDNodeValue &BigVal) {
188 EVT BigVT = BigVal.getValueType();
189
190 if (SmallVT.isInteger() != BigVT.isInteger() ||
191 SmallVT.isFloatingPoint() != BigVT.isFloatingPoint()) {
192 SS << SmallVal << " type " << SmallVT
193 << " must be the same kind of type as " << BigVal << " (" << BigVT
194 << ")";
195 reportNodeError(DAG, N, Msg: SS.str());
196 }
197 if (SmallVT.isVector() != BigVT.isVector()) {
198 SS << SmallVal << " type " << SmallVT << " and " << BigVal << " ("
199 << BigVT << ") must both be vectors or both be scalars";
200 reportNodeError(DAG, N, Msg: SS.str());
201 }
202
203 // Compare scalar sizes first; only if they match compare total sizes.
204 uint64_t SmallScalarSize = SmallVT.getScalarSizeInBits();
205 uint64_t BigScalarSize = BigVT.getScalarSizeInBits();
206 bool IsSmaller;
207 if (SmallScalarSize != BigScalarSize) {
208 IsSmaller = SmallScalarSize < BigScalarSize;
209 } else {
210 TypeSize SmallSize = SmallVT.getSizeInBits();
211 TypeSize BigSize = BigVT.getSizeInBits();
212 if (SmallVT.isScalableVector() != BigVT.isScalableVector()) {
213 SS << SmallVal << " type " << SmallVT << " and " << BigVal << " ("
214 << BigVT << ") cannot be compared; one is scalable and the "
215 << "other is fixed";
216 reportNodeError(DAG, N, Msg: SS.str());
217 }
218 IsSmaller = SmallSize.getKnownMinValue() < BigSize.getKnownMinValue();
219 }
220 if (!IsSmaller) {
221 SS << SmallVal << " type " << SmallVT << " must be smaller than "
222 << BigVal << " (" << BigVT << ")";
223 reportNodeError(DAG, N, Msg: SS.str());
224 }
225 };
226
227 for (const SDTypeConstraint &C : getConstraints(Opcode: N->getOpcode())) {
228 SDNodeValue Val = GetConstraintValue(C.ConstrainedValIdx);
229 EVT VT = Val.getValueType();
230
231 switch (C.Kind) {
232 case SDTCisVT: {
233 EVT ExpectedVT = GetConstraintVT(C);
234
235 bool IsPtr = ExpectedVT == MVT::iPTR;
236 if (IsPtr)
237 ExpectedVT =
238 DAG.getTargetLoweringInfo().getPointerTy(DL: DAG.getDataLayout());
239
240 if (VT != ExpectedVT) {
241 SS << Val << " must have type " << ExpectedVT;
242 if (IsPtr)
243 SS << " (iPTR)";
244 SS << ", but has type " << VT;
245 reportNodeError(DAG, N, Msg: SS.str());
246 }
247 break;
248 }
249 case SDTCisPtrTy: {
250 unsigned AS = 0;
251 if (const auto *MemSD = dyn_cast<MemSDNode>(Val: N))
252 AS = MemSD->getAddressSpace();
253 EVT PtrVT =
254 DAG.getTargetLoweringInfo().getPointerTy(DL: DAG.getDataLayout(), AS);
255 if (VT != PtrVT) {
256 SS << Val << " must have pointer type " << PtrVT << ", but has type "
257 << VT;
258 reportNodeError(DAG, N, Msg: SS.str());
259 }
260 break;
261 }
262 case SDTCisInt:
263 if (!VT.isInteger()) {
264 SS << Val << " must have integer type, but has type " << VT;
265 reportNodeError(DAG, N, Msg: SS.str());
266 }
267 break;
268 case SDTCisFP:
269 if (!VT.isFloatingPoint()) {
270 SS << Val << " must have floating-point type, but has type " << VT;
271 reportNodeError(DAG, N, Msg: SS.str());
272 }
273 break;
274 case SDTCisVec:
275 if (!VT.isVector()) {
276 SS << Val << " must have vector type, but has type " << VT;
277 reportNodeError(DAG, N, Msg: SS.str());
278 }
279 break;
280 case SDTCisSameAs:
281 break;
282 case SDTCisVTSmallerThanOp: {
283 const auto *VTNode = dyn_cast<VTSDNode>(Val: Val.getValue().getNode());
284 if (!VTNode) {
285 SS << Val << " must be a VT node";
286 reportNodeError(DAG, N, Msg: SS.str());
287 }
288 EVT SmallVT = VTNode->getVT();
289
290 CheckSmallerThan(Val, SmallVT, GetConstraintValue(C.ConstrainingValIdx));
291 break;
292 }
293 case SDTCisOpSmallerThanOp:
294 CheckSmallerThan(Val, VT, GetConstraintValue(C.ConstrainingValIdx));
295 break;
296 case SDTCisEltOfVec: {
297 SDNodeValue VecVal = GetConstraintValue(C.ConstrainingValIdx);
298 EVT VecVT = VecVal.getValueType();
299
300 if (!VecVT.isVector()) {
301 SS << VecVal << " must have vector type, but has type " << VecVT;
302 reportNodeError(DAG, N, Msg: SS.str());
303 }
304 if (!VecVT.isVectorOf(EltVT: VT)) {
305 SS << Val << " must have " << VecVT.getVectorElementType()
306 << " type (element type of " << VecVal << "), but has type " << VT;
307 reportNodeError(DAG, N, Msg: SS.str());
308 }
309 break;
310 }
311 case SDTCisSubVecOfVec: {
312 SDNodeValue VecVal = GetConstraintValue(C.ConstrainingValIdx);
313 EVT VecVT = VecVal.getValueType();
314
315 if (!VT.isVector()) {
316 SS << Val << " must have vector type, but has type " << VT;
317 reportNodeError(DAG, N, Msg: SS.str());
318 }
319 if (!VecVT.isVector()) {
320 SS << VecVal << " must have vector type, but has type " << VecVT;
321 reportNodeError(DAG, N, Msg: SS.str());
322 }
323 if (VT.getVectorElementType() != VecVT.getVectorElementType()) {
324 SS << Val << " must have the same element type as " << VecVal << " ("
325 << VecVT.getVectorElementType() << "), but has element type "
326 << VT.getVectorElementType();
327 reportNodeError(DAG, N, Msg: SS.str());
328 }
329 if (VT.isScalableVector() && !VecVT.isScalableVector()) {
330 SS << Val << " is a scalable vector, but " << VecVal
331 << " is not; a scalable vector cannot be a sub-vector of a fixed "
332 "length vector";
333 reportNodeError(DAG, N, Msg: SS.str());
334 }
335 // We can't compare elements when the subvector is fixed and the vector
336 // is scalable. We would need to take into account vscale.
337 if (VT.isScalableVector() == VecVT.isScalableVector() &&
338 VT.getVectorMinNumElements() >= VecVT.getVectorMinNumElements()) {
339 SS << Val << " must have fewer elements than " << VecVal;
340 reportNodeError(DAG, N, Msg: SS.str());
341 }
342 break;
343 }
344 case SDTCVecEltisVT: {
345 EVT ExpectedVT = GetConstraintVT(C);
346
347 if (!VT.isVector()) {
348 SS << Val << " must have vector type";
349 reportNodeError(DAG, N, Msg: SS.str());
350 }
351 if (VT.getVectorElementType() != ExpectedVT) {
352 SS << Val << " must have " << ExpectedVT << " element type, but has "
353 << VT.getVectorElementType() << " element type";
354 reportNodeError(DAG, N, Msg: SS.str());
355 }
356 break;
357 }
358 case SDTCisSameNumEltsAs: {
359 SDNodeValue OtherVal = GetConstraintValue(C.ConstrainingValIdx);
360 EVT OtherVT = OtherVal.getValueType();
361
362 // Scalars are treated as having the same "number of elements" as any
363 // other scalar, so this only requires equal element counts when both
364 // are vectors.
365 if (VT.isVector() != OtherVT.isVector() ||
366 (VT.isVector() &&
367 VT.getVectorElementCount() != OtherVT.getVectorElementCount())) {
368 SS << Val << " and " << OtherVal
369 << " must have the same number of elements, but have " << VT
370 << " and " << OtherVT;
371 reportNodeError(DAG, N, Msg: SS.str());
372 }
373 break;
374 }
375 case SDTCisSameSizeAs: {
376 SDNodeValue OtherVal = GetConstraintValue(C.ConstrainingValIdx);
377 EVT OtherVT = OtherVal.getValueType();
378
379 if (VT.getSizeInBits() != OtherVT.getSizeInBits()) {
380 SS << Val << " must have the same size as " << OtherVal << " ("
381 << OtherVT << "), but has type " << VT;
382 reportNodeError(DAG, N, Msg: SS.str());
383 }
384 break;
385 }
386 }
387 }
388}
389