LLVM 24.0.0git
SDNodeInfo.cpp
Go to the documentation of this file.
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
14
15using namespace llvm;
16
17static void reportNodeError(const SelectionDAG &DAG, const SDNode *N,
18 const Twine &Msg) {
19 std::string S;
21 SS << "invalid node: " << Msg << '\n';
22 N->printrWithDepth(SS, &DAG, 2);
24}
25
26static void checkResultType(const SelectionDAG &DAG, const SDNode *N,
27 unsigned ResIdx, EVT ExpectedVT) {
28 EVT ActualVT = N->getValueType(ResIdx);
29 if (ActualVT != ExpectedVT)
31 DAG, N,
32 "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(OpIdx).getValueType();
39 if (ActualVT != ExpectedVT)
41 DAG, N,
42 "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(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(N->getOpcode());
74 bool HasChain = Desc.hasProperty(SDNPHasChain);
75 bool HasOutGlue = Desc.hasProperty(SDNPOutGlue);
76 bool HasInGlue = Desc.hasProperty(SDNPInGlue);
77 bool HasOptInGlue = Desc.hasProperty(SDNPOptInGlue);
78 bool IsVariadic = Desc.hasProperty(SDNPVariadic);
79
80 unsigned ActualNumResults = N->getNumValues();
81 unsigned ExpectedNumResults = Desc.NumResults + HasChain + HasOutGlue;
82
83 if (ActualNumResults != ExpectedNumResults)
84 reportNodeError(DAG, N,
85 "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, ChainResIdx, MVT::Other);
93 }
94
95 // Glue result comes last.
96 if (HasOutGlue) {
97 unsigned GlueResIdx = Desc.NumResults + HasChain;
98 checkResultType(DAG, N, GlueResIdx, 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 "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 "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, 0, MVT::Other);
137
138 // Glue operand comes last.
139 if (HasInGlue)
140 checkOperandType(DAG, N, ActualNumOperands - 1, MVT::Glue);
141 if (HasOptInGlue && ActualNumOperands >= 1 &&
142 N->getOperand(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(OpIdx).getOpcode();
151 if (OpOpcode != ISD::Register && OpOpcode != ISD::RegisterMask)
152 reportNodeError(DAG, N,
153 "variadic operand #" + Twine(OpIdx) +
154 " must be Register or RegisterMask");
155 }
156 }
157
158 unsigned VTHwMode =
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
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, 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, 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, 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, SS.str());
224 }
225 };
226
227 for (const SDTypeConstraint &C : getConstraints(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 =
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, SS.str());
246 }
247 break;
248 }
249 case SDTCisPtrTy: {
250 unsigned AS = 0;
251 if (const auto *MemSD = dyn_cast<MemSDNode>(N))
252 AS = MemSD->getAddressSpace();
253 EVT PtrVT =
255 if (VT != PtrVT) {
256 SS << Val << " must have pointer type " << PtrVT << ", but has type "
257 << VT;
258 reportNodeError(DAG, N, 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, 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, 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, SS.str());
278 }
279 break;
280 case SDTCisSameAs:
281 break;
283 const auto *VTNode = dyn_cast<VTSDNode>(Val.getValue().getNode());
284 if (!VTNode) {
285 SS << Val << " must be a VT node";
286 reportNodeError(DAG, N, SS.str());
287 }
288 EVT SmallVT = VTNode->getVT();
289
290 CheckSmallerThan(Val, SmallVT, GetConstraintValue(C.ConstrainingValIdx));
291 break;
292 }
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, SS.str());
303 }
304 if (!VecVT.isVectorOf(VT)) {
305 SS << Val << " must have " << VecVT.getVectorElementType()
306 << " type (element type of " << VecVal << "), but has type " << VT;
307 reportNodeError(DAG, N, 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, SS.str());
318 }
319 if (!VecVT.isVector()) {
320 SS << VecVal << " must have vector type, but has type " << VecVT;
321 reportNodeError(DAG, N, 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, 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, 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() &&
339 SS << Val << " must have fewer elements than " << VecVal;
340 reportNodeError(DAG, N, 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, 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, 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, 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, SS.str());
383 }
384 break;
385 }
386 }
387 }
388}
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static constexpr Value * getValue(Ty &ValueOrUse)
static void checkOperandType(const SelectionDAG &DAG, const SDNode *N, unsigned OpIdx, EVT ExpectedVT)
static void reportNodeError(const SelectionDAG &DAG, const SDNode *N, const Twine &Msg)
static void checkResultType(const SelectionDAG &DAG, const SDNode *N, unsigned ResIdx, EVT ExpectedVT)
const char * Msg
This file describes how to lower LLVM code to machine code.
virtual unsigned getHwMode(enum HwModeType type=HwMode_Default) const
HwMode ID corresponding to the 'type' parameter is retrieved from the HwMode bit set of the current s...
const SDNodeDesc & getDesc(unsigned Opcode) const
Returns the description of a node with the given opcode.
Definition SDNodeInfo.h:107
LLVM_ABI void verifyNode(const SelectionDAG &DAG, const SDNode *N) const
ArrayRef< SDTypeConstraint > getConstraints(unsigned Opcode) const
Returns operand constraints for a node with the given opcode.
Definition SDNodeInfo.h:113
Represents one node in the SelectionDAG.
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
const TargetSubtargetInfo & getSubtarget() const
const TargetLowering & getTargetLoweringInfo() const
const DataLayout & getDataLayout() const
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
Definition SmallString.h:26
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
virtual MVT getPointerTy(const DataLayout &DL, uint32_t AS=0) const
Return the pointer type for the given address space, defaults to the pointer type from the data layou...
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition Twine.h:82
constexpr ScalarTy getKnownMinValue() const
Returns the minimum value this quantity can represent.
Definition TypeSize.h:165
A raw_ostream that writes to an std::string.
A raw_ostream that writes to an SmallVector or SmallString.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Type * getValueType(Value *V, bool ReVec, bool LookThroughCmp)
Returns the "element type" of the given value/instruction V.
This is an optimization pass for GlobalISel generic memory operations.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
Op::Description Desc
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition Error.cpp:163
@ SDNPOptInGlue
Definition SDNodeInfo.h:26
@ SDNPVariadic
Definition SDNodeInfo.h:28
@ SDNPInGlue
Definition SDNodeInfo.h:25
@ SDNPOutGlue
Definition SDNodeInfo.h:24
@ SDNPHasChain
Definition SDNodeInfo.h:23
DWARFExpression::Operation Op
raw_ostream & operator<<(raw_ostream &OS, const APFixedPoint &FX)
ArrayRef(const T &OneElt) -> ArrayRef< T >
@ SDTCisSameAs
Definition SDNodeInfo.h:37
@ SDTCisPtrTy
Definition SDNodeInfo.h:33
@ SDTCisOpSmallerThanOp
Definition SDNodeInfo.h:39
@ SDTCisSameSizeAs
Definition SDNodeInfo.h:44
@ SDTCisSameNumEltsAs
Definition SDNodeInfo.h:43
@ SDTCisEltOfVec
Definition SDNodeInfo.h:40
@ SDTCisVTSmallerThanOp
Definition SDNodeInfo.h:38
@ SDTCisInt
Definition SDNodeInfo.h:34
@ SDTCisVec
Definition SDNodeInfo.h:36
@ SDTCisVT
Definition SDNodeInfo.h:32
@ SDTCVecEltisVT
Definition SDNodeInfo.h:42
@ SDTCisSubVecOfVec
Definition SDNodeInfo.h:41
@ SDTCisFP
Definition SDNodeInfo.h:35
#define N
Extended Value Type.
Definition ValueTypes.h:35
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
Definition ValueTypes.h:155
ElementCount getVectorElementCount() const
Definition ValueTypes.h:373
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
Definition ValueTypes.h:396
unsigned getVectorMinNumElements() const
Given a vector type, return the minimum number of elements it contains.
Definition ValueTypes.h:382
uint64_t getScalarSizeInBits() const
Definition ValueTypes.h:408
LLVM_ABI std::string getEVTString() const
This function returns value type as a string, e.g. "i32".
bool isVector() const
Return true if this is a vector value type.
Definition ValueTypes.h:176
bool isScalableVector() const
Return true if this is a vector type where the runtime length is machine dependent.
Definition ValueTypes.h:187
EVT getVectorElementType() const
Given a vector type, return the type of each element.
Definition ValueTypes.h:351
bool isVectorOf(EVT EltVT) const
Return true if this is a vector with matching element type.
Definition ValueTypes.h:181
bool isInteger() const
Return true if this is an integer or a vector integer type.
Definition ValueTypes.h:160