xref: /freebsd/contrib/llvm-project/llvm/lib/CodeGen/SelectionDAG/SDNodeInfo.cpp (revision 770cf0a5f02dc8983a89c6568d741fbc25baa999)
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/SelectionDAGNodes.h"
11 
12 using namespace llvm;
13 
14 static void reportNodeError(const SelectionDAG &DAG, const SDNode *N,
15                             const Twine &Msg) {
16   std::string S;
17   raw_string_ostream SS(S);
18   SS << "invalid node: " << Msg << '\n';
19   N->printrWithDepth(SS, &DAG, 2);
20   report_fatal_error(StringRef(S));
21 }
22 
23 static void checkResultType(const SelectionDAG &DAG, const SDNode *N,
24                             unsigned ResIdx, EVT ExpectedVT) {
25   EVT ActualVT = N->getValueType(ResIdx);
26   if (ActualVT != ExpectedVT)
27     reportNodeError(
28         DAG, N,
29         "result #" + Twine(ResIdx) + " has invalid type; expected " +
30             ExpectedVT.getEVTString() + ", got " + ActualVT.getEVTString());
31 }
32 
33 static void checkOperandType(const SelectionDAG &DAG, const SDNode *N,
34                              unsigned OpIdx, EVT ExpectedVT) {
35   EVT ActualVT = N->getOperand(OpIdx).getValueType();
36   if (ActualVT != ExpectedVT)
37     reportNodeError(
38         DAG, N,
39         "operand #" + Twine(OpIdx) + " has invalid type; expected " +
40             ExpectedVT.getEVTString() + ", got " + ActualVT.getEVTString());
41 }
42 
43 void SDNodeInfo::verifyNode(const SelectionDAG &DAG, const SDNode *N) const {
44   const SDNodeDesc &Desc = getDesc(N->getOpcode());
45   bool HasChain = Desc.hasProperty(SDNPHasChain);
46   bool HasOutGlue = Desc.hasProperty(SDNPOutGlue);
47   bool HasInGlue = Desc.hasProperty(SDNPInGlue);
48   bool HasOptInGlue = Desc.hasProperty(SDNPOptInGlue);
49   bool IsVariadic = Desc.hasProperty(SDNPVariadic);
50 
51   unsigned ActualNumResults = N->getNumValues();
52   unsigned ExpectedNumResults = Desc.NumResults + HasChain + HasOutGlue;
53 
54   if (ActualNumResults != ExpectedNumResults)
55     reportNodeError(DAG, N,
56                     "invalid number of results; expected " +
57                         Twine(ExpectedNumResults) + ", got " +
58                         Twine(ActualNumResults));
59 
60   // Chain result comes after all normal results.
61   if (HasChain) {
62     unsigned ChainResIdx = Desc.NumResults;
63     checkResultType(DAG, N, ChainResIdx, MVT::Other);
64   }
65 
66   // Glue result comes last.
67   if (HasOutGlue) {
68     unsigned GlueResIdx = Desc.NumResults + HasChain;
69     checkResultType(DAG, N, GlueResIdx, MVT::Glue);
70   }
71 
72   // In the most general case, the operands of a node go in the following order:
73   //   chain, fix#0, ..., fix#M-1, var#0, ... var#N-1, glue
74   // If the number of operands is < 0, M can be any;
75   // If the node has SDNPVariadic property, N can be any.
76   bool HasOptionalOperands = Desc.NumOperands < 0 || IsVariadic;
77 
78   unsigned ActualNumOperands = N->getNumOperands();
79   unsigned ExpectedMinNumOperands =
80       (Desc.NumOperands >= 0 ? Desc.NumOperands : 0) + HasChain + HasInGlue;
81 
82   // Check the lower bound.
83   if (ActualNumOperands < ExpectedMinNumOperands) {
84     StringRef How = HasOptionalOperands ? "at least " : "";
85     reportNodeError(DAG, N,
86                     "invalid number of operands; expected " + How +
87                         Twine(ExpectedMinNumOperands) + ", got " +
88                         Twine(ActualNumOperands));
89   }
90 
91   // Check the upper bound. We can only do this if the number of fixed operands
92   // is known and there are no variadic operands.
93   if (Desc.NumOperands >= 0 && !IsVariadic) {
94     // Account for optional input glue.
95     unsigned ExpectedMaxNumOperands = ExpectedMinNumOperands + HasOptInGlue;
96     if (ActualNumOperands > ExpectedMaxNumOperands) {
97       StringRef How = HasOptInGlue ? "at most " : "";
98       reportNodeError(DAG, N,
99                       "invalid number of operands; expected " + How +
100                           Twine(ExpectedMaxNumOperands) + ", got " +
101                           Twine(ActualNumOperands));
102     }
103   }
104 
105   // Chain operand comes first.
106   if (HasChain)
107     checkOperandType(DAG, N, 0, MVT::Other);
108 
109   // Glue operand comes last.
110   if (HasInGlue)
111     checkOperandType(DAG, N, ActualNumOperands - 1, MVT::Glue);
112   if (HasOptInGlue && ActualNumOperands >= 1 &&
113       N->getOperand(ActualNumOperands - 1).getValueType() == MVT::Glue)
114     HasInGlue = true;
115 
116   // Check variadic operands. These should be Register or RegisterMask.
117   if (IsVariadic && Desc.NumOperands >= 0) {
118     unsigned VarOpStart = HasChain + Desc.NumOperands;
119     unsigned VarOpEnd = ActualNumOperands - HasInGlue;
120     for (unsigned OpIdx = VarOpStart; OpIdx != VarOpEnd; ++OpIdx) {
121       unsigned OpOpcode = N->getOperand(OpIdx).getOpcode();
122       if (OpOpcode != ISD::Register && OpOpcode != ISD::RegisterMask)
123         reportNodeError(DAG, N,
124                         "variadic operand #" + Twine(OpIdx) +
125                             " must be Register or RegisterMask");
126     }
127   }
128 }
129