aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/CodeGen/SelectionDAG/SDNodeInfo.cpp
blob: e3f6c98a9a90a0747f703fbc741a81bdbab99236 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
//==------------------------------------------------------------------------==//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "llvm/CodeGen/SDNodeInfo.h"
#include "llvm/CodeGen/SelectionDAGNodes.h"

using namespace llvm;

static void reportNodeError(const SelectionDAG &DAG, const SDNode *N,
                            const Twine &Msg) {
  std::string S;
  raw_string_ostream SS(S);
  SS << "invalid node: " << Msg << '\n';
  N->printrWithDepth(SS, &DAG, 2);
  report_fatal_error(StringRef(S));
}

static void checkResultType(const SelectionDAG &DAG, const SDNode *N,
                            unsigned ResIdx, EVT ExpectedVT) {
  EVT ActualVT = N->getValueType(ResIdx);
  if (ActualVT != ExpectedVT)
    reportNodeError(
        DAG, N,
        "result #" + Twine(ResIdx) + " has invalid type; expected " +
            ExpectedVT.getEVTString() + ", got " + ActualVT.getEVTString());
}

static void checkOperandType(const SelectionDAG &DAG, const SDNode *N,
                             unsigned OpIdx, EVT ExpectedVT) {
  EVT ActualVT = N->getOperand(OpIdx).getValueType();
  if (ActualVT != ExpectedVT)
    reportNodeError(
        DAG, N,
        "operand #" + Twine(OpIdx) + " has invalid type; expected " +
            ExpectedVT.getEVTString() + ", got " + ActualVT.getEVTString());
}

void SDNodeInfo::verifyNode(const SelectionDAG &DAG, const SDNode *N) const {
  const SDNodeDesc &Desc = getDesc(N->getOpcode());
  bool HasChain = Desc.hasProperty(SDNPHasChain);
  bool HasOutGlue = Desc.hasProperty(SDNPOutGlue);
  bool HasInGlue = Desc.hasProperty(SDNPInGlue);
  bool HasOptInGlue = Desc.hasProperty(SDNPOptInGlue);
  bool IsVariadic = Desc.hasProperty(SDNPVariadic);

  unsigned ActualNumResults = N->getNumValues();
  unsigned ExpectedNumResults = Desc.NumResults + HasChain + HasOutGlue;

  if (ActualNumResults != ExpectedNumResults)
    reportNodeError(DAG, N,
                    "invalid number of results; expected " +
                        Twine(ExpectedNumResults) + ", got " +
                        Twine(ActualNumResults));

  // Chain result comes after all normal results.
  if (HasChain) {
    unsigned ChainResIdx = Desc.NumResults;
    checkResultType(DAG, N, ChainResIdx, MVT::Other);
  }

  // Glue result comes last.
  if (HasOutGlue) {
    unsigned GlueResIdx = Desc.NumResults + HasChain;
    checkResultType(DAG, N, GlueResIdx, MVT::Glue);
  }

  // In the most general case, the operands of a node go in the following order:
  //   chain, fix#0, ..., fix#M-1, var#0, ... var#N-1, glue
  // If the number of operands is < 0, M can be any;
  // If the node has SDNPVariadic property, N can be any.
  bool HasOptionalOperands = Desc.NumOperands < 0 || IsVariadic;

  unsigned ActualNumOperands = N->getNumOperands();
  unsigned ExpectedMinNumOperands =
      (Desc.NumOperands >= 0 ? Desc.NumOperands : 0) + HasChain + HasInGlue;

  // Check the lower bound.
  if (ActualNumOperands < ExpectedMinNumOperands) {
    StringRef How = HasOptionalOperands ? "at least " : "";
    reportNodeError(DAG, N,
                    "invalid number of operands; expected " + How +
                        Twine(ExpectedMinNumOperands) + ", got " +
                        Twine(ActualNumOperands));
  }

  // Check the upper bound. We can only do this if the number of fixed operands
  // is known and there are no variadic operands.
  if (Desc.NumOperands >= 0 && !IsVariadic) {
    // Account for optional input glue.
    unsigned ExpectedMaxNumOperands = ExpectedMinNumOperands + HasOptInGlue;
    if (ActualNumOperands > ExpectedMaxNumOperands) {
      StringRef How = HasOptInGlue ? "at most " : "";
      reportNodeError(DAG, N,
                      "invalid number of operands; expected " + How +
                          Twine(ExpectedMaxNumOperands) + ", got " +
                          Twine(ActualNumOperands));
    }
  }

  // Chain operand comes first.
  if (HasChain)
    checkOperandType(DAG, N, 0, MVT::Other);

  // Glue operand comes last.
  if (HasInGlue)
    checkOperandType(DAG, N, ActualNumOperands - 1, MVT::Glue);
  if (HasOptInGlue && ActualNumOperands >= 1 &&
      N->getOperand(ActualNumOperands - 1).getValueType() == MVT::Glue)
    HasInGlue = true;

  // Check variadic operands. These should be Register or RegisterMask.
  if (IsVariadic && Desc.NumOperands >= 0) {
    unsigned VarOpStart = HasChain + Desc.NumOperands;
    unsigned VarOpEnd = ActualNumOperands - HasInGlue;
    for (unsigned OpIdx = VarOpStart; OpIdx != VarOpEnd; ++OpIdx) {
      unsigned OpOpcode = N->getOperand(OpIdx).getOpcode();
      if (OpOpcode != ISD::Register && OpOpcode != ISD::RegisterMask)
        reportNodeError(DAG, N,
                        "variadic operand #" + Twine(OpIdx) +
                            " must be Register or RegisterMask");
    }
  }
}