summaryrefslogtreecommitdiff
path: root/support/tools/TableGen/InstrSelectorEmitter.cpp
blob: a2bd08c7948c996ff9e734861aa42746769ad0b4 (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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
//===- InstrInfoEmitter.cpp - Generate a Instruction Set Desc. ------------===//
//
// This tablegen backend is responsible for emitting a description of the target
// instruction set for the code generator.
//
//===----------------------------------------------------------------------===//

#include "InstrSelectorEmitter.h"
#include "CodeGenWrappers.h"
#include "Record.h"
#include "Support/Debug.h"

NodeType::ArgResultTypes NodeType::Translate(Record *R) {
  const std::string &Name = R->getName();
  if (Name == "DNVT_void") return Void;
  if (Name == "DNVT_val" ) return Val;
  if (Name == "DNVT_arg0") return Arg0;
  if (Name == "DNVT_ptr" ) return Ptr;
  throw "Unknown DagNodeValType '" + Name + "'!";
}

std::ostream &operator<<(std::ostream &OS, const TreePatternNode &N) {
  if (N.isLeaf())
    return OS << N.getType() << ":" << *N.getValue();
  OS << "(" << N.getType() << ":";
  OS << N.getOperator()->getName();
  
  const std::vector<TreePatternNode*> &Children = N.getChildren();
  if (!Children.empty()) {
    OS << " " << *Children[0];
    for (unsigned i = 1, e = Children.size(); i != e; ++i)
      OS << ", " << *Children[i];
  }  
  return OS << ")";
}
void TreePatternNode::dump() const { std::cerr << *this; }


/// ProcessNodeTypes - Process all of the node types in the current
/// RecordKeeper, turning them into the more accessible NodeTypes data
/// structure.
///
void InstrSelectorEmitter::ProcessNodeTypes() {
  std::vector<Record*> Nodes = Records.getAllDerivedDefinitions("DagNode");
  for (unsigned i = 0, e = Nodes.size(); i != e; ++i) {
    Record *Node = Nodes[i];
    
    // Translate the return type...
    NodeType::ArgResultTypes RetTy =
      NodeType::Translate(Node->getValueAsDef("RetType"));

    // Translate the arguments...
    ListInit *Args = Node->getValueAsListInit("ArgTypes");
    std::vector<NodeType::ArgResultTypes> ArgTypes;

    for (unsigned a = 0, e = Args->getSize(); a != e; ++a) {
      if (DefInit *DI = dynamic_cast<DefInit*>(Args->getElement(a)))
        ArgTypes.push_back(NodeType::Translate(DI->getDef()));
      else
        throw "In node " + Node->getName() + ", argument is not a Def!";

      if (a == 0 && ArgTypes.back() == NodeType::Arg0)
        throw "In node " + Node->getName() + ", arg 0 cannot have type 'arg0'!";
      if (ArgTypes.back() == NodeType::Void)
        throw "In node " + Node->getName() + ", args cannot be void type!";
    }
    if (RetTy == NodeType::Arg0 && Args->getSize() == 0)
      throw "In node " + Node->getName() +
            ", invalid return type for nullary node!";

    // Add the node type mapping now...
    NodeTypes[Node] = NodeType(RetTy, ArgTypes);
    DEBUG(std::cerr << "Got node type '" << Node->getName() << "'\n");
  }
}

static MVT::ValueType getIntrinsicType(Record *R) {
  // Check to see if this is a register or a register class...
  const std::vector<Record*> &SuperClasses = R->getSuperClasses();
  for (unsigned i = 0, e = SuperClasses.size(); i != e; ++i)
    if (SuperClasses[i]->getName() == "RegisterClass") {
      return getValueType(R->getValueAsDef("RegType"));
    } else if (SuperClasses[i]->getName() == "Register") {
      std::cerr << "WARNING: Explicit registers not handled yet!\n";
    } else if (SuperClasses[i]->getName() == "Nonterminal") {
    }
  //throw "Error: Unknown value used: " + R->getName();

  return MVT::Other;
}

// Parse the specified DagInit into a TreePattern which we can use.
//
TreePatternNode *InstrSelectorEmitter::ParseTreePattern(DagInit *DI,
                                                   const std::string &RecName) {
  Record *Operator = DI->getNodeType();

  if (!NodeTypes.count(Operator))
    throw "Illegal node for instruction pattern: '" + Operator->getName() +"'!";

  const std::vector<Init*> &Args = DI->getArgs();
  std::vector<TreePatternNode*> Children;
  
  for (unsigned i = 0, e = Args.size(); i != e; ++i) {
    Init *Arg = Args[i];
    if (DagInit *DI = dynamic_cast<DagInit*>(Arg)) {
      Children.push_back(ParseTreePattern(DI, RecName));
    } else if (DefInit *DI = dynamic_cast<DefInit*>(Arg)) {
      Children.push_back(new TreePatternNode(DI));
      // If it's a regclass or something else known, set the type.
      Children.back()->setType(getIntrinsicType(DI->getDef()));
    } else {
      Arg->dump();
      throw "Unknown value for tree pattern in '" + RecName + "'!";
    }
  }

  return new TreePatternNode(Operator, Children);
}

// UpdateNodeType - Set the node type of N to VT if VT contains information.  If
// N already contains a conflicting type, then throw an exception
//
static bool UpdateNodeType(TreePatternNode *N, MVT::ValueType VT,
                           const std::string &RecName) {
  if (VT == MVT::Other || N->getType() == VT) return false;

  if (N->getType() == MVT::Other) {
    N->setType(VT);
    return true;
  }

  throw "Type inferfence contradiction found for pattern " + RecName;
}

// InferTypes - Perform type inference on the tree, returning true if there
// are any remaining untyped nodes and setting MadeChange if any changes were
// made.
bool InstrSelectorEmitter::InferTypes(TreePatternNode *N,
                                      const std::string &RecName,
                                      bool &MadeChange) {
  if (N->isLeaf()) return N->getType() == MVT::Other;

  bool AnyUnset = false;
  Record *Operator = N->getOperator();
  assert(NodeTypes.count(Operator) && "No node info for node!");
  const NodeType &NT = NodeTypes[Operator];

  // Check to see if we can infer anything about the argument types from the
  // return types...
  const std::vector<TreePatternNode*> &Children = N->getChildren();
  if (Children.size() != NT.ArgTypes.size())
    throw "In record " + RecName + " incorrect number of children for " +
          Operator->getName() + " node!";

  for (unsigned i = 0, e = Children.size(); i != e; ++i) {
    AnyUnset |= InferTypes(Children[i], RecName, MadeChange);


    switch (NT.ArgTypes[i]) {
    case NodeType::Arg0:
      MadeChange |=UpdateNodeType(Children[i], Children[0]->getType(), RecName);
      break;
    case NodeType::Val:
      if (Children[i]->getType() == MVT::isVoid)
        throw "In pattern for " + RecName + " should not get a void node!";
      break;
    case NodeType::Ptr: // FIXME
    default: assert(0 && "Invalid argument ArgType!");
    }
  }

  // See if we can infer anything about the return type now...
  switch (NT.ResultType) {
  case NodeType::Void:
    MadeChange |= UpdateNodeType(N, MVT::isVoid, RecName);
    break;
  case NodeType::Arg0:
    MadeChange |= UpdateNodeType(N, Children[0]->getType(), RecName);
    break;

  case NodeType::Ptr:   // FIXME: get from target
  case NodeType::Val:
    assert(0 && "Unhandled type constraint!");
    break;
  }

  return AnyUnset | N->getType() == MVT::Other;
}


// ReadAndCheckPattern - Parse the specified DagInit into a pattern and then
// perform full type inference.
//
TreePatternNode *InstrSelectorEmitter::ReadAndCheckPattern(DagInit *DI,
                                                  const std::string &RecName) {
  // First, parse the pattern...
  TreePatternNode *Pattern = ParseTreePattern(DI, RecName);
  
  bool MadeChange, AnyUnset;
  do {
    MadeChange = false;
    AnyUnset = InferTypes(Pattern, RecName, MadeChange);
    if (AnyUnset && !MadeChange) {
      std::cerr << "In pattern: " << *Pattern << "\n";
      throw "Cannot infer types for " + RecName;
    }
  } while (AnyUnset || MadeChange);

  return Pattern;
}



/// ProcessInstructionPatterns - Read in all subclasses of Instruction, and
/// process those with a useful Pattern field.
///
void InstrSelectorEmitter::ProcessInstructionPatterns() {
  std::vector<Record*> Insts = Records.getAllDerivedDefinitions("Instruction");
  for (unsigned i = 0, e = Insts.size(); i != e; ++i) {
    Record *Inst = Insts[i];
    if (DagInit *DI = dynamic_cast<DagInit*>(Inst->getValueInit("Pattern"))) {
      TreePatternNode *Pattern = ReadAndCheckPattern(DI, Inst->getName());


      DEBUG(std::cerr << "Parsed inst pattern " << Inst->getName() << "\t= "
                      << *Pattern << "\n");
    }
  }
}


void InstrSelectorEmitter::run(std::ostream &OS) {
  // Type-check all of the node types to ensure we "understand" them.
  ProcessNodeTypes();
  
  // Read in all of the nonterminals...

  // Read all of the instruction patterns in...
  ProcessInstructionPatterns();

  // Read all of the Expander patterns in...
  
}