245 lines · cpp
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-exception6//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(SS, &DAG, 2);23 report_fatal_error(StringRef(S));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)30 reportNodeError(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)40 reportNodeError(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 operand49/// 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} // namespace71 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, glue103 // 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 operands121 // 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 =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 ignores164 // 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 }244}245