|
7 | 7 | //===----------------------------------------------------------------------===// |
8 | 8 |
|
9 | 9 | #include "llvm/CodeGen/SDNodeInfo.h" |
| 10 | +#include "llvm/CodeGen/SelectionDAG.h" |
10 | 11 | #include "llvm/CodeGen/SelectionDAGNodes.h" |
| 12 | +#include "llvm/CodeGen/TargetLowering.h" |
| 13 | +#include "llvm/CodeGen/TargetSubtargetInfo.h" |
11 | 14 |
|
12 | 15 | using namespace llvm; |
13 | 16 |
|
@@ -40,6 +43,32 @@ static void checkOperandType(const SelectionDAG &DAG, const SDNode *N, |
40 | 43 | ExpectedVT.getEVTString() + ", got " + ActualVT.getEVTString()); |
41 | 44 | } |
42 | 45 |
|
| 46 | +namespace { |
| 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. |
| 50 | +class SDNodeValue { |
| 51 | + const SDNode *N; |
| 52 | + unsigned Idx; |
| 53 | + bool IsRes; |
| 54 | + |
| 55 | +public: |
| 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 | + |
43 | 72 | void SDNodeInfo::verifyNode(const SelectionDAG &DAG, const SDNode *N) const { |
44 | 73 | const SDNodeDesc &Desc = getDesc(N->getOpcode()); |
45 | 74 | bool HasChain = Desc.hasProperty(SDNPHasChain); |
@@ -125,4 +154,91 @@ void SDNodeInfo::verifyNode(const SelectionDAG &DAG, const SDNode *N) const { |
125 | 154 | " must be Register or RegisterMask"); |
126 | 155 | } |
127 | 156 | } |
| 157 | + |
| 158 | + unsigned VTHwMode = |
| 159 | + DAG.getSubtarget().getHwMode(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(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(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, 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, 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, SS.str()); |
| 235 | + } |
| 236 | + break; |
| 237 | + } |
| 238 | + case SDTCisSameNumEltsAs: |
| 239 | + break; |
| 240 | + case SDTCisSameSizeAs: |
| 241 | + break; |
| 242 | + } |
| 243 | + } |
128 | 244 | } |
0 commit comments