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 for (const SDTypeConstraint &C : getConstraints(Opcode: N->getOpcode())) {
185 SDNodeValue Val = GetConstraintValue(C.ConstrainedValIdx);
186 EVT VT = Val.getValueType();
187
188 switch (C.Kind) {
189 case SDTCisVT: {
190 EVT ExpectedVT = GetConstraintVT(C);
191
192 bool IsPtr = ExpectedVT == MVT::iPTR;
193 if (IsPtr)
194 ExpectedVT =
195 DAG.getTargetLoweringInfo().getPointerTy(DL: DAG.getDataLayout());
196
197 if (VT != ExpectedVT) {
198 SS << Val << " must have type " << ExpectedVT;
199 if (IsPtr)
200 SS << " (iPTR)";
201 SS << ", but has type " << VT;
202 reportNodeError(DAG, N, Msg: SS.str());
203 }
204 break;
205 }
206 case SDTCisPtrTy:
207 break;
208 case SDTCisInt:
209 break;
210 case SDTCisFP:
211 break;
212 case SDTCisVec:
213 break;
214 case SDTCisSameAs:
215 break;
216 case SDTCisVTSmallerThanOp:
217 break;
218 case SDTCisOpSmallerThanOp:
219 break;
220 case SDTCisEltOfVec:
221 break;
222 case SDTCisSubVecOfVec:
223 break;
224 case SDTCVecEltisVT: {
225 EVT ExpectedVT = GetConstraintVT(C);
226
227 if (!VT.isVector()) {
228 SS << Val << " must have vector type";
229 reportNodeError(DAG, N, Msg: SS.str());
230 }
231 if (VT.getVectorElementType() != ExpectedVT) {
232 SS << Val << " must have " << ExpectedVT << " element type, but has "
233 << VT.getVectorElementType() << " element type";
234 reportNodeError(DAG, N, Msg: SS.str());
235 }
236 break;
237 }
238 case SDTCisSameNumEltsAs:
239 break;
240 case SDTCisSameSizeAs:
241 break;
242 }
243 }
244}
245