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(O&: SS, G: &DAG, depth: 2); |
20 | report_fatal_error(reason: StringRef(S)); |
21 | } |
22 | |
23 | static void checkResultType(const SelectionDAG &DAG, const SDNode *N, |
24 | unsigned ResIdx, EVT ExpectedVT) { |
25 | EVT ActualVT = N->getValueType(ResNo: ResIdx); |
26 | if (ActualVT != ExpectedVT) |
27 | reportNodeError( |
28 | DAG, N, |
29 | Msg: "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(Num: OpIdx).getValueType(); |
36 | if (ActualVT != ExpectedVT) |
37 | reportNodeError( |
38 | DAG, N, |
39 | Msg: "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(Opcode: N->getOpcode()); |
45 | bool HasChain = Desc.hasProperty(Property: SDNPHasChain); |
46 | bool HasOutGlue = Desc.hasProperty(Property: SDNPOutGlue); |
47 | bool HasInGlue = Desc.hasProperty(Property: SDNPInGlue); |
48 | bool HasOptInGlue = Desc.hasProperty(Property: SDNPOptInGlue); |
49 | bool IsVariadic = Desc.hasProperty(Property: SDNPVariadic); |
50 | |
51 | unsigned ActualNumResults = N->getNumValues(); |
52 | unsigned ExpectedNumResults = Desc.NumResults + HasChain + HasOutGlue; |
53 | |
54 | if (ActualNumResults != ExpectedNumResults) |
55 | reportNodeError(DAG, N, |
56 | Msg: "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, ResIdx: ChainResIdx, ExpectedVT: MVT::Other); |
64 | } |
65 | |
66 | // Glue result comes last. |
67 | if (HasOutGlue) { |
68 | unsigned GlueResIdx = Desc.NumResults + HasChain; |
69 | checkResultType(DAG, N, ResIdx: GlueResIdx, ExpectedVT: 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 | Msg: "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 | Msg: "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, OpIdx: 0, ExpectedVT: MVT::Other); |
108 | |
109 | // Glue operand comes last. |
110 | if (HasInGlue) |
111 | checkOperandType(DAG, N, OpIdx: ActualNumOperands - 1, ExpectedVT: MVT::Glue); |
112 | if (HasOptInGlue && ActualNumOperands >= 1 && |
113 | N->getOperand(Num: 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(Num: OpIdx).getOpcode(); |
122 | if (OpOpcode != ISD::Register && OpOpcode != ISD::RegisterMask) |
123 | reportNodeError(DAG, N, |
124 | Msg: "variadic operand #" + Twine(OpIdx) + |
125 | " must be Register or RegisterMask" ); |
126 | } |
127 | } |
128 | } |
129 | |