1203954Srdivacky//===- DAGISelMatcherEmitter.cpp - Matcher Emitter ------------------------===//
2203954Srdivacky//
3203954Srdivacky//                     The LLVM Compiler Infrastructure
4203954Srdivacky//
5203954Srdivacky// This file is distributed under the University of Illinois Open Source
6203954Srdivacky// License. See LICENSE.TXT for details.
7203954Srdivacky//
8203954Srdivacky//===----------------------------------------------------------------------===//
9203954Srdivacky//
10212904Sdim// This file contains code to generate C++ code for a matcher.
11203954Srdivacky//
12203954Srdivacky//===----------------------------------------------------------------------===//
13203954Srdivacky
14203954Srdivacky#include "DAGISelMatcher.h"
15203954Srdivacky#include "CodeGenDAGPatterns.h"
16204642Srdivacky#include "llvm/ADT/DenseMap.h"
17203954Srdivacky#include "llvm/ADT/SmallString.h"
18203954Srdivacky#include "llvm/ADT/StringMap.h"
19204642Srdivacky#include "llvm/Support/CommandLine.h"
20203954Srdivacky#include "llvm/Support/FormattedStream.h"
21249423Sdim#include "llvm/TableGen/Record.h"
22203954Srdivackyusing namespace llvm;
23203954Srdivacky
24203954Srdivackyenum {
25204642Srdivacky  CommentIndent = 30
26203954Srdivacky};
27203954Srdivacky
28204642Srdivacky// To reduce generated source code size.
29204642Srdivackystatic cl::opt<bool>
30204642SrdivackyOmitComments("omit-comments", cl::desc("Do not generate comments"),
31204642Srdivacky             cl::init(false));
32203954Srdivacky
33203954Srdivackynamespace {
34203954Srdivackyclass MatcherTableEmitter {
35206083Srdivacky  const CodeGenDAGPatterns &CGP;
36221345Sdim
37221345Sdim  DenseMap<TreePattern *, unsigned> NodePredicateMap;
38221345Sdim  std::vector<TreePredicateFn> NodePredicates;
39221345Sdim
40221345Sdim  StringMap<unsigned> PatternPredicateMap;
41221345Sdim  std::vector<std::string> PatternPredicates;
42204642Srdivacky
43204642Srdivacky  DenseMap<const ComplexPattern*, unsigned> ComplexPatternMap;
44204642Srdivacky  std::vector<const ComplexPattern*> ComplexPatterns;
45204642Srdivacky
46204642Srdivacky
47204642Srdivacky  DenseMap<Record*, unsigned> NodeXFormMap;
48204642Srdivacky  std::vector<Record*> NodeXForms;
49204642Srdivacky
50203954Srdivackypublic:
51221345Sdim  MatcherTableEmitter(const CodeGenDAGPatterns &cgp)
52221345Sdim    : CGP(cgp) {}
53203954Srdivacky
54204642Srdivacky  unsigned EmitMatcherList(const Matcher *N, unsigned Indent,
55204642Srdivacky                           unsigned StartIdx, formatted_raw_ostream &OS);
56221345Sdim
57206083Srdivacky  void EmitPredicateFunctions(formatted_raw_ostream &OS);
58221345Sdim
59204792Srdivacky  void EmitHistogram(const Matcher *N, formatted_raw_ostream &OS);
60203954Srdivackyprivate:
61204642Srdivacky  unsigned EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx,
62204642Srdivacky                       formatted_raw_ostream &OS);
63221345Sdim
64221345Sdim  unsigned getNodePredicate(TreePredicateFn Pred) {
65221345Sdim    unsigned &Entry = NodePredicateMap[Pred.getOrigPatFragRecord()];
66203954Srdivacky    if (Entry == 0) {
67221345Sdim      NodePredicates.push_back(Pred);
68203954Srdivacky      Entry = NodePredicates.size();
69203954Srdivacky    }
70203954Srdivacky    return Entry-1;
71203954Srdivacky  }
72221345Sdim
73203954Srdivacky  unsigned getPatternPredicate(StringRef PredName) {
74203954Srdivacky    unsigned &Entry = PatternPredicateMap[PredName];
75203954Srdivacky    if (Entry == 0) {
76203954Srdivacky      PatternPredicates.push_back(PredName.str());
77203954Srdivacky      Entry = PatternPredicates.size();
78203954Srdivacky    }
79203954Srdivacky    return Entry-1;
80203954Srdivacky  }
81204642Srdivacky  unsigned getComplexPat(const ComplexPattern &P) {
82204642Srdivacky    unsigned &Entry = ComplexPatternMap[&P];
83204642Srdivacky    if (Entry == 0) {
84204642Srdivacky      ComplexPatterns.push_back(&P);
85204642Srdivacky      Entry = ComplexPatterns.size();
86204642Srdivacky    }
87204642Srdivacky    return Entry-1;
88204642Srdivacky  }
89221345Sdim
90204642Srdivacky  unsigned getNodeXFormID(Record *Rec) {
91204642Srdivacky    unsigned &Entry = NodeXFormMap[Rec];
92204642Srdivacky    if (Entry == 0) {
93204642Srdivacky      NodeXForms.push_back(Rec);
94204642Srdivacky      Entry = NodeXForms.size();
95204642Srdivacky    }
96204642Srdivacky    return Entry-1;
97204642Srdivacky  }
98221345Sdim
99203954Srdivacky};
100203954Srdivacky} // end anonymous namespace.
101203954Srdivacky
102204642Srdivackystatic unsigned GetVBRSize(unsigned Val) {
103204642Srdivacky  if (Val <= 127) return 1;
104221345Sdim
105204642Srdivacky  unsigned NumBytes = 0;
106204642Srdivacky  while (Val >= 128) {
107204642Srdivacky    Val >>= 7;
108204642Srdivacky    ++NumBytes;
109204642Srdivacky  }
110204642Srdivacky  return NumBytes+1;
111204642Srdivacky}
112204642Srdivacky
113204642Srdivacky/// EmitVBRValue - Emit the specified value as a VBR, returning the number of
114204642Srdivacky/// bytes emitted.
115204642Srdivackystatic uint64_t EmitVBRValue(uint64_t Val, raw_ostream &OS) {
116204642Srdivacky  if (Val <= 127) {
117204642Srdivacky    OS << Val << ", ";
118204642Srdivacky    return 1;
119204642Srdivacky  }
120221345Sdim
121204642Srdivacky  uint64_t InVal = Val;
122204642Srdivacky  unsigned NumBytes = 0;
123204642Srdivacky  while (Val >= 128) {
124204642Srdivacky    OS << (Val&127) << "|128,";
125204642Srdivacky    Val >>= 7;
126204642Srdivacky    ++NumBytes;
127204642Srdivacky  }
128204642Srdivacky  OS << Val;
129204642Srdivacky  if (!OmitComments)
130204642Srdivacky    OS << "/*" << InVal << "*/";
131204642Srdivacky  OS << ", ";
132204642Srdivacky  return NumBytes+1;
133204642Srdivacky}
134204642Srdivacky
135249423Sdim/// EmitMatcher - Emit bytes for the specified matcher and return
136203954Srdivacky/// the number of bytes emitted.
137203954Srdivackyunsigned MatcherTableEmitter::
138204642SrdivackyEmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx,
139204642Srdivacky            formatted_raw_ostream &OS) {
140203954Srdivacky  OS.PadToColumn(Indent*2);
141221345Sdim
142203954Srdivacky  switch (N->getKind()) {
143204642Srdivacky  case Matcher::Scope: {
144204642Srdivacky    const ScopeMatcher *SM = cast<ScopeMatcher>(N);
145204642Srdivacky    assert(SM->getNext() == 0 && "Shouldn't have next after scope");
146221345Sdim
147204642Srdivacky    unsigned StartIdx = CurrentIdx;
148221345Sdim
149204642Srdivacky    // Emit all of the children.
150204642Srdivacky    for (unsigned i = 0, e = SM->getNumChildren(); i != e; ++i) {
151204642Srdivacky      if (i == 0) {
152204642Srdivacky        OS << "OPC_Scope, ";
153204642Srdivacky        ++CurrentIdx;
154204642Srdivacky      } else  {
155204642Srdivacky        if (!OmitComments) {
156204642Srdivacky          OS << "/*" << CurrentIdx << "*/";
157204642Srdivacky          OS.PadToColumn(Indent*2) << "/*Scope*/ ";
158204642Srdivacky        } else
159204642Srdivacky          OS.PadToColumn(Indent*2);
160204642Srdivacky      }
161204642Srdivacky
162204642Srdivacky      // We need to encode the child and the offset of the failure code before
163204642Srdivacky      // emitting either of them.  Handle this by buffering the output into a
164204642Srdivacky      // string while we get the size.  Unfortunately, the offset of the
165204642Srdivacky      // children depends on the VBR size of the child, so for large children we
166204642Srdivacky      // have to iterate a bit.
167204642Srdivacky      SmallString<128> TmpBuf;
168204642Srdivacky      unsigned ChildSize = 0;
169204642Srdivacky      unsigned VBRSize = 0;
170204642Srdivacky      do {
171204642Srdivacky        VBRSize = GetVBRSize(ChildSize);
172221345Sdim
173204642Srdivacky        TmpBuf.clear();
174204642Srdivacky        raw_svector_ostream OS(TmpBuf);
175204642Srdivacky        formatted_raw_ostream FOS(OS);
176204642Srdivacky        ChildSize = EmitMatcherList(SM->getChild(i), Indent+1,
177204642Srdivacky                                    CurrentIdx+VBRSize, FOS);
178204642Srdivacky      } while (GetVBRSize(ChildSize) != VBRSize);
179221345Sdim
180204642Srdivacky      assert(ChildSize != 0 && "Should not have a zero-sized child!");
181221345Sdim
182204642Srdivacky      CurrentIdx += EmitVBRValue(ChildSize, OS);
183204642Srdivacky      if (!OmitComments) {
184204642Srdivacky        OS << "/*->" << CurrentIdx+ChildSize << "*/";
185221345Sdim
186204642Srdivacky        if (i == 0)
187204642Srdivacky          OS.PadToColumn(CommentIndent) << "// " << SM->getNumChildren()
188204642Srdivacky            << " children in Scope";
189204642Srdivacky      }
190221345Sdim
191204642Srdivacky      OS << '\n' << TmpBuf.str();
192204642Srdivacky      CurrentIdx += ChildSize;
193204642Srdivacky    }
194221345Sdim
195204642Srdivacky    // Emit a zero as a sentinel indicating end of 'Scope'.
196204642Srdivacky    if (!OmitComments)
197204642Srdivacky      OS << "/*" << CurrentIdx << "*/";
198204642Srdivacky    OS.PadToColumn(Indent*2) << "0, ";
199204642Srdivacky    if (!OmitComments)
200204642Srdivacky      OS << "/*End of Scope*/";
201204642Srdivacky    OS << '\n';
202204642Srdivacky    return CurrentIdx - StartIdx + 1;
203204642Srdivacky  }
204221345Sdim
205204642Srdivacky  case Matcher::RecordNode:
206204642Srdivacky    OS << "OPC_RecordNode,";
207204642Srdivacky    if (!OmitComments)
208204642Srdivacky      OS.PadToColumn(CommentIndent) << "// #"
209204642Srdivacky        << cast<RecordMatcher>(N)->getResultNo() << " = "
210204642Srdivacky        << cast<RecordMatcher>(N)->getWhatFor();
211204642Srdivacky    OS << '\n';
212203954Srdivacky    return 1;
213204642Srdivacky
214204642Srdivacky  case Matcher::RecordChild:
215204642Srdivacky    OS << "OPC_RecordChild" << cast<RecordChildMatcher>(N)->getChildNo()
216204642Srdivacky       << ',';
217204642Srdivacky    if (!OmitComments)
218204642Srdivacky      OS.PadToColumn(CommentIndent) << "// #"
219204642Srdivacky        << cast<RecordChildMatcher>(N)->getResultNo() << " = "
220204642Srdivacky        << cast<RecordChildMatcher>(N)->getWhatFor();
221204642Srdivacky    OS << '\n';
222203954Srdivacky    return 1;
223221345Sdim
224204642Srdivacky  case Matcher::RecordMemRef:
225204642Srdivacky    OS << "OPC_RecordMemRef,\n";
226204642Srdivacky    return 1;
227221345Sdim
228218893Sdim  case Matcher::CaptureGlueInput:
229218893Sdim    OS << "OPC_CaptureGlueInput,\n";
230204642Srdivacky    return 1;
231221345Sdim
232204642Srdivacky  case Matcher::MoveChild:
233204642Srdivacky    OS << "OPC_MoveChild, " << cast<MoveChildMatcher>(N)->getChildNo() << ",\n";
234203954Srdivacky    return 2;
235221345Sdim
236204642Srdivacky  case Matcher::MoveParent:
237203954Srdivacky    OS << "OPC_MoveParent,\n";
238203954Srdivacky    return 1;
239221345Sdim
240204642Srdivacky  case Matcher::CheckSame:
241203954Srdivacky    OS << "OPC_CheckSame, "
242204642Srdivacky       << cast<CheckSameMatcher>(N)->getMatchNumber() << ",\n";
243203954Srdivacky    return 2;
244203954Srdivacky
245263508Sdim  case Matcher::CheckChildSame:
246263508Sdim    OS << "OPC_CheckChild"
247263508Sdim       << cast<CheckChildSameMatcher>(N)->getChildNo() << "Same, "
248263508Sdim       << cast<CheckChildSameMatcher>(N)->getMatchNumber() << ",\n";
249263508Sdim    return 2;
250263508Sdim
251204642Srdivacky  case Matcher::CheckPatternPredicate: {
252221345Sdim    StringRef Pred =cast<CheckPatternPredicateMatcher>(N)->getPredicate();
253203954Srdivacky    OS << "OPC_CheckPatternPredicate, " << getPatternPredicate(Pred) << ',';
254204642Srdivacky    if (!OmitComments)
255204642Srdivacky      OS.PadToColumn(CommentIndent) << "// " << Pred;
256204642Srdivacky    OS << '\n';
257203954Srdivacky    return 2;
258203954Srdivacky  }
259204642Srdivacky  case Matcher::CheckPredicate: {
260221345Sdim    TreePredicateFn Pred = cast<CheckPredicateMatcher>(N)->getPredicate();
261203954Srdivacky    OS << "OPC_CheckPredicate, " << getNodePredicate(Pred) << ',';
262204642Srdivacky    if (!OmitComments)
263221345Sdim      OS.PadToColumn(CommentIndent) << "// " << Pred.getFnName();
264204642Srdivacky    OS << '\n';
265203954Srdivacky    return 2;
266203954Srdivacky  }
267203954Srdivacky
268204642Srdivacky  case Matcher::CheckOpcode:
269221345Sdim    OS << "OPC_CheckOpcode, TARGET_VAL("
270206083Srdivacky       << cast<CheckOpcodeMatcher>(N)->getOpcode().getEnumName() << "),\n";
271206083Srdivacky    return 3;
272221345Sdim
273204642Srdivacky  case Matcher::SwitchOpcode:
274204642Srdivacky  case Matcher::SwitchType: {
275204642Srdivacky    unsigned StartIdx = CurrentIdx;
276221345Sdim
277204642Srdivacky    unsigned NumCases;
278204642Srdivacky    if (const SwitchOpcodeMatcher *SOM = dyn_cast<SwitchOpcodeMatcher>(N)) {
279204642Srdivacky      OS << "OPC_SwitchOpcode ";
280204642Srdivacky      NumCases = SOM->getNumCases();
281204642Srdivacky    } else {
282204642Srdivacky      OS << "OPC_SwitchType ";
283204642Srdivacky      NumCases = cast<SwitchTypeMatcher>(N)->getNumCases();
284204642Srdivacky    }
285204642Srdivacky
286204642Srdivacky    if (!OmitComments)
287204642Srdivacky      OS << "/*" << NumCases << " cases */";
288204642Srdivacky    OS << ", ";
289204642Srdivacky    ++CurrentIdx;
290221345Sdim
291204642Srdivacky    // For each case we emit the size, then the opcode, then the matcher.
292204642Srdivacky    for (unsigned i = 0, e = NumCases; i != e; ++i) {
293204642Srdivacky      const Matcher *Child;
294206083Srdivacky      unsigned IdxSize;
295206083Srdivacky      if (const SwitchOpcodeMatcher *SOM = dyn_cast<SwitchOpcodeMatcher>(N)) {
296204642Srdivacky        Child = SOM->getCaseMatcher(i);
297206083Srdivacky        IdxSize = 2;  // size of opcode in table is 2 bytes.
298206083Srdivacky      } else {
299204642Srdivacky        Child = cast<SwitchTypeMatcher>(N)->getCaseMatcher(i);
300206083Srdivacky        IdxSize = 1;  // size of type in table is 1 byte.
301206083Srdivacky      }
302221345Sdim
303204642Srdivacky      // We need to encode the opcode and the offset of the case code before
304204642Srdivacky      // emitting the case code.  Handle this by buffering the output into a
305204642Srdivacky      // string while we get the size.  Unfortunately, the offset of the
306204642Srdivacky      // children depends on the VBR size of the child, so for large children we
307204642Srdivacky      // have to iterate a bit.
308204642Srdivacky      SmallString<128> TmpBuf;
309204642Srdivacky      unsigned ChildSize = 0;
310204642Srdivacky      unsigned VBRSize = 0;
311204642Srdivacky      do {
312204642Srdivacky        VBRSize = GetVBRSize(ChildSize);
313221345Sdim
314204642Srdivacky        TmpBuf.clear();
315204642Srdivacky        raw_svector_ostream OS(TmpBuf);
316204642Srdivacky        formatted_raw_ostream FOS(OS);
317206083Srdivacky        ChildSize = EmitMatcherList(Child, Indent+1, CurrentIdx+VBRSize+IdxSize,
318206083Srdivacky                                    FOS);
319204642Srdivacky      } while (GetVBRSize(ChildSize) != VBRSize);
320221345Sdim
321204642Srdivacky      assert(ChildSize != 0 && "Should not have a zero-sized child!");
322221345Sdim
323204642Srdivacky      if (i != 0) {
324263508Sdim        if (!OmitComments)
325263508Sdim          OS << "/*" << CurrentIdx << "*/";
326204642Srdivacky        OS.PadToColumn(Indent*2);
327204642Srdivacky        if (!OmitComments)
328263508Sdim          OS << (isa<SwitchOpcodeMatcher>(N) ?
329263508Sdim                     "/*SwitchOpcode*/ " : "/*SwitchType*/ ");
330204642Srdivacky      }
331221345Sdim
332204642Srdivacky      // Emit the VBR.
333204642Srdivacky      CurrentIdx += EmitVBRValue(ChildSize, OS);
334221345Sdim
335204642Srdivacky      OS << ' ';
336204642Srdivacky      if (const SwitchOpcodeMatcher *SOM = dyn_cast<SwitchOpcodeMatcher>(N))
337221345Sdim        OS << "TARGET_VAL(" << SOM->getCaseOpcode(i).getEnumName() << "),";
338204642Srdivacky      else
339206083Srdivacky        OS << getEnumName(cast<SwitchTypeMatcher>(N)->getCaseType(i)) << ',';
340206083Srdivacky
341206083Srdivacky      CurrentIdx += IdxSize;
342206083Srdivacky
343204642Srdivacky      if (!OmitComments)
344206083Srdivacky        OS << "// ->" << CurrentIdx+ChildSize;
345204642Srdivacky      OS << '\n';
346204642Srdivacky      OS << TmpBuf.str();
347204642Srdivacky      CurrentIdx += ChildSize;
348204642Srdivacky    }
349204642Srdivacky
350204642Srdivacky    // Emit the final zero to terminate the switch.
351263508Sdim    if (!OmitComments)
352263508Sdim      OS << "/*" << CurrentIdx << "*/";
353204642Srdivacky    OS.PadToColumn(Indent*2) << "0, ";
354204642Srdivacky    if (!OmitComments)
355204642Srdivacky      OS << (isa<SwitchOpcodeMatcher>(N) ?
356204642Srdivacky             "// EndSwitchOpcode" : "// EndSwitchType");
357204642Srdivacky
358204642Srdivacky    OS << '\n';
359204642Srdivacky    ++CurrentIdx;
360204642Srdivacky    return CurrentIdx-StartIdx;
361204642Srdivacky  }
362204642Srdivacky
363204642Srdivacky case Matcher::CheckType:
364206083Srdivacky    assert(cast<CheckTypeMatcher>(N)->getResNo() == 0 &&
365206083Srdivacky           "FIXME: Add support for CheckType of resno != 0");
366203954Srdivacky    OS << "OPC_CheckType, "
367204642Srdivacky       << getEnumName(cast<CheckTypeMatcher>(N)->getType()) << ",\n";
368203954Srdivacky    return 2;
369221345Sdim
370204642Srdivacky  case Matcher::CheckChildType:
371204642Srdivacky    OS << "OPC_CheckChild"
372204642Srdivacky       << cast<CheckChildTypeMatcher>(N)->getChildNo() << "Type, "
373204642Srdivacky       << getEnumName(cast<CheckChildTypeMatcher>(N)->getType()) << ",\n";
374204642Srdivacky    return 2;
375221345Sdim
376204642Srdivacky  case Matcher::CheckInteger: {
377204642Srdivacky    OS << "OPC_CheckInteger, ";
378204642Srdivacky    unsigned Bytes=1+EmitVBRValue(cast<CheckIntegerMatcher>(N)->getValue(), OS);
379204642Srdivacky    OS << '\n';
380204642Srdivacky    return Bytes;
381204642Srdivacky  }
382204642Srdivacky  case Matcher::CheckCondCode:
383203954Srdivacky    OS << "OPC_CheckCondCode, ISD::"
384204642Srdivacky       << cast<CheckCondCodeMatcher>(N)->getCondCodeName() << ",\n";
385203954Srdivacky    return 2;
386221345Sdim
387204642Srdivacky  case Matcher::CheckValueType:
388203954Srdivacky    OS << "OPC_CheckValueType, MVT::"
389204642Srdivacky       << cast<CheckValueTypeMatcher>(N)->getTypeName() << ",\n";
390203954Srdivacky    return 2;
391203954Srdivacky
392204642Srdivacky  case Matcher::CheckComplexPat: {
393204792Srdivacky    const CheckComplexPatMatcher *CCPM = cast<CheckComplexPatMatcher>(N);
394204792Srdivacky    const ComplexPattern &Pattern = CCPM->getPattern();
395204792Srdivacky    OS << "OPC_CheckComplexPat, /*CP*/" << getComplexPat(Pattern) << ", /*#*/"
396204792Srdivacky       << CCPM->getMatchNumber() << ',';
397221345Sdim
398204642Srdivacky    if (!OmitComments) {
399204642Srdivacky      OS.PadToColumn(CommentIndent) << "// " << Pattern.getSelectFunc();
400204792Srdivacky      OS << ":$" << CCPM->getName();
401204792Srdivacky      for (unsigned i = 0, e = Pattern.getNumOperands(); i != e; ++i)
402204792Srdivacky        OS << " #" << CCPM->getFirstResult()+i;
403221345Sdim
404204642Srdivacky      if (Pattern.hasProperty(SDNPHasChain))
405204792Srdivacky        OS << " + chain result";
406204642Srdivacky    }
407204642Srdivacky    OS << '\n';
408204792Srdivacky    return 3;
409204642Srdivacky  }
410221345Sdim
411204642Srdivacky  case Matcher::CheckAndImm: {
412204642Srdivacky    OS << "OPC_CheckAndImm, ";
413204642Srdivacky    unsigned Bytes=1+EmitVBRValue(cast<CheckAndImmMatcher>(N)->getValue(), OS);
414204642Srdivacky    OS << '\n';
415204642Srdivacky    return Bytes;
416203954Srdivacky  }
417203954Srdivacky
418204642Srdivacky  case Matcher::CheckOrImm: {
419204642Srdivacky    OS << "OPC_CheckOrImm, ";
420204642Srdivacky    unsigned Bytes = 1+EmitVBRValue(cast<CheckOrImmMatcher>(N)->getValue(), OS);
421204642Srdivacky    OS << '\n';
422204642Srdivacky    return Bytes;
423203954Srdivacky  }
424221345Sdim
425204642Srdivacky  case Matcher::CheckFoldableChainNode:
426204642Srdivacky    OS << "OPC_CheckFoldableChainNode,\n";
427203954Srdivacky    return 1;
428221345Sdim
429204642Srdivacky  case Matcher::EmitInteger: {
430204642Srdivacky    int64_t Val = cast<EmitIntegerMatcher>(N)->getValue();
431204642Srdivacky    OS << "OPC_EmitInteger, "
432204642Srdivacky       << getEnumName(cast<EmitIntegerMatcher>(N)->getVT()) << ", ";
433204642Srdivacky    unsigned Bytes = 2+EmitVBRValue(Val, OS);
434204642Srdivacky    OS << '\n';
435204642Srdivacky    return Bytes;
436203954Srdivacky  }
437204642Srdivacky  case Matcher::EmitStringInteger: {
438204642Srdivacky    const std::string &Val = cast<EmitStringIntegerMatcher>(N)->getValue();
439204642Srdivacky    // These should always fit into one byte.
440204642Srdivacky    OS << "OPC_EmitInteger, "
441204642Srdivacky      << getEnumName(cast<EmitStringIntegerMatcher>(N)->getVT()) << ", "
442204642Srdivacky      << Val << ",\n";
443204642Srdivacky    return 3;
444204642Srdivacky  }
445221345Sdim
446221345Sdim  case Matcher::EmitRegister: {
447221345Sdim    const EmitRegisterMatcher *Matcher = cast<EmitRegisterMatcher>(N);
448221345Sdim    const CodeGenRegister *Reg = Matcher->getReg();
449221345Sdim    // If the enum value of the register is larger than one byte can handle,
450221345Sdim    // use EmitRegister2.
451221345Sdim    if (Reg && Reg->EnumValue > 255) {
452221345Sdim      OS << "OPC_EmitRegister2, " << getEnumName(Matcher->getVT()) << ", ";
453221345Sdim      OS << "TARGET_VAL(" << getQualifiedName(Reg->TheDef) << "),\n";
454221345Sdim      return 4;
455221345Sdim    } else {
456221345Sdim      OS << "OPC_EmitRegister, " << getEnumName(Matcher->getVT()) << ", ";
457221345Sdim      if (Reg) {
458221345Sdim        OS << getQualifiedName(Reg->TheDef) << ",\n";
459221345Sdim      } else {
460221345Sdim        OS << "0 ";
461221345Sdim        if (!OmitComments)
462221345Sdim          OS << "/*zero_reg*/";
463221345Sdim        OS << ",\n";
464221345Sdim      }
465221345Sdim      return 3;
466204642Srdivacky    }
467221345Sdim  }
468221345Sdim
469204642Srdivacky  case Matcher::EmitConvertToTarget:
470204642Srdivacky    OS << "OPC_EmitConvertToTarget, "
471204642Srdivacky       << cast<EmitConvertToTargetMatcher>(N)->getSlot() << ",\n";
472204642Srdivacky    return 2;
473221345Sdim
474204642Srdivacky  case Matcher::EmitMergeInputChains: {
475204642Srdivacky    const EmitMergeInputChainsMatcher *MN =
476204642Srdivacky      cast<EmitMergeInputChainsMatcher>(N);
477221345Sdim
478206083Srdivacky    // Handle the specialized forms OPC_EmitMergeInputChains1_0 and 1_1.
479206083Srdivacky    if (MN->getNumNodes() == 1 && MN->getNode(0) < 2) {
480206083Srdivacky      OS << "OPC_EmitMergeInputChains1_" << MN->getNode(0) << ",\n";
481206083Srdivacky      return 1;
482206083Srdivacky    }
483221345Sdim
484204642Srdivacky    OS << "OPC_EmitMergeInputChains, " << MN->getNumNodes() << ", ";
485204642Srdivacky    for (unsigned i = 0, e = MN->getNumNodes(); i != e; ++i)
486204642Srdivacky      OS << MN->getNode(i) << ", ";
487204642Srdivacky    OS << '\n';
488204642Srdivacky    return 2+MN->getNumNodes();
489204642Srdivacky  }
490204642Srdivacky  case Matcher::EmitCopyToReg:
491204642Srdivacky    OS << "OPC_EmitCopyToReg, "
492204642Srdivacky       << cast<EmitCopyToRegMatcher>(N)->getSrcSlot() << ", "
493204642Srdivacky       << getQualifiedName(cast<EmitCopyToRegMatcher>(N)->getDestPhysReg())
494204642Srdivacky       << ",\n";
495204642Srdivacky    return 3;
496204642Srdivacky  case Matcher::EmitNodeXForm: {
497204642Srdivacky    const EmitNodeXFormMatcher *XF = cast<EmitNodeXFormMatcher>(N);
498204642Srdivacky    OS << "OPC_EmitNodeXForm, " << getNodeXFormID(XF->getNodeXForm()) << ", "
499204642Srdivacky       << XF->getSlot() << ',';
500204642Srdivacky    if (!OmitComments)
501204642Srdivacky      OS.PadToColumn(CommentIndent) << "// "<<XF->getNodeXForm()->getName();
502204642Srdivacky    OS <<'\n';
503204642Srdivacky    return 3;
504204642Srdivacky  }
505221345Sdim
506204642Srdivacky  case Matcher::EmitNode:
507204642Srdivacky  case Matcher::MorphNodeTo: {
508204642Srdivacky    const EmitNodeMatcherCommon *EN = cast<EmitNodeMatcherCommon>(N);
509204642Srdivacky    OS << (isa<EmitNodeMatcher>(EN) ? "OPC_EmitNode" : "OPC_MorphNodeTo");
510221345Sdim    OS << ", TARGET_VAL(" << EN->getOpcodeName() << "), 0";
511221345Sdim
512204642Srdivacky    if (EN->hasChain())   OS << "|OPFL_Chain";
513218893Sdim    if (EN->hasInFlag())  OS << "|OPFL_GlueInput";
514218893Sdim    if (EN->hasOutFlag()) OS << "|OPFL_GlueOutput";
515204642Srdivacky    if (EN->hasMemRefs()) OS << "|OPFL_MemRefs";
516204642Srdivacky    if (EN->getNumFixedArityOperands() != -1)
517204642Srdivacky      OS << "|OPFL_Variadic" << EN->getNumFixedArityOperands();
518204642Srdivacky    OS << ",\n";
519221345Sdim
520204642Srdivacky    OS.PadToColumn(Indent*2+4) << EN->getNumVTs();
521204642Srdivacky    if (!OmitComments)
522204642Srdivacky      OS << "/*#VTs*/";
523204642Srdivacky    OS << ", ";
524204642Srdivacky    for (unsigned i = 0, e = EN->getNumVTs(); i != e; ++i)
525204642Srdivacky      OS << getEnumName(EN->getVT(i)) << ", ";
526204642Srdivacky
527204642Srdivacky    OS << EN->getNumOperands();
528204642Srdivacky    if (!OmitComments)
529204642Srdivacky      OS << "/*#Ops*/";
530204642Srdivacky    OS << ", ";
531204642Srdivacky    unsigned NumOperandBytes = 0;
532204642Srdivacky    for (unsigned i = 0, e = EN->getNumOperands(); i != e; ++i)
533204642Srdivacky      NumOperandBytes += EmitVBRValue(EN->getOperand(i), OS);
534221345Sdim
535204642Srdivacky    if (!OmitComments) {
536204642Srdivacky      // Print the result #'s for EmitNode.
537204642Srdivacky      if (const EmitNodeMatcher *E = dyn_cast<EmitNodeMatcher>(EN)) {
538204642Srdivacky        if (unsigned NumResults = EN->getNumVTs()) {
539239462Sdim          OS.PadToColumn(CommentIndent) << "// Results =";
540204642Srdivacky          unsigned First = E->getFirstResultSlot();
541204642Srdivacky          for (unsigned i = 0; i != NumResults; ++i)
542239462Sdim            OS << " #" << First+i;
543204642Srdivacky        }
544204642Srdivacky      }
545204642Srdivacky      OS << '\n';
546204642Srdivacky
547204642Srdivacky      if (const MorphNodeToMatcher *SNT = dyn_cast<MorphNodeToMatcher>(N)) {
548204642Srdivacky        OS.PadToColumn(Indent*2) << "// Src: "
549221345Sdim          << *SNT->getPattern().getSrcPattern() << " - Complexity = "
550206083Srdivacky          << SNT->getPattern().getPatternComplexity(CGP) << '\n';
551204642Srdivacky        OS.PadToColumn(Indent*2) << "// Dst: "
552204642Srdivacky          << *SNT->getPattern().getDstPattern() << '\n';
553204642Srdivacky      }
554204642Srdivacky    } else
555204642Srdivacky      OS << '\n';
556221345Sdim
557204642Srdivacky    return 6+EN->getNumVTs()+NumOperandBytes;
558204642Srdivacky  }
559218893Sdim  case Matcher::MarkGlueResults: {
560218893Sdim    const MarkGlueResultsMatcher *CFR = cast<MarkGlueResultsMatcher>(N);
561218893Sdim    OS << "OPC_MarkGlueResults, " << CFR->getNumNodes() << ", ";
562204642Srdivacky    unsigned NumOperandBytes = 0;
563204642Srdivacky    for (unsigned i = 0, e = CFR->getNumNodes(); i != e; ++i)
564204642Srdivacky      NumOperandBytes += EmitVBRValue(CFR->getNode(i), OS);
565204642Srdivacky    OS << '\n';
566204642Srdivacky    return 2+NumOperandBytes;
567204642Srdivacky  }
568204642Srdivacky  case Matcher::CompleteMatch: {
569204642Srdivacky    const CompleteMatchMatcher *CM = cast<CompleteMatchMatcher>(N);
570204642Srdivacky    OS << "OPC_CompleteMatch, " << CM->getNumResults() << ", ";
571204642Srdivacky    unsigned NumResultBytes = 0;
572204642Srdivacky    for (unsigned i = 0, e = CM->getNumResults(); i != e; ++i)
573204642Srdivacky      NumResultBytes += EmitVBRValue(CM->getResult(i), OS);
574204642Srdivacky    OS << '\n';
575204642Srdivacky    if (!OmitComments) {
576204642Srdivacky      OS.PadToColumn(Indent*2) << "// Src: "
577221345Sdim        << *CM->getPattern().getSrcPattern() << " - Complexity = "
578206083Srdivacky        << CM->getPattern().getPatternComplexity(CGP) << '\n';
579204642Srdivacky      OS.PadToColumn(Indent*2) << "// Dst: "
580204642Srdivacky        << *CM->getPattern().getDstPattern();
581204642Srdivacky    }
582204642Srdivacky    OS << '\n';
583204642Srdivacky    return 2 + NumResultBytes;
584204642Srdivacky  }
585204642Srdivacky  }
586234353Sdim  llvm_unreachable("Unreachable");
587203954Srdivacky}
588203954Srdivacky
589204642Srdivacky/// EmitMatcherList - Emit the bytes for the specified matcher subtree.
590203954Srdivackyunsigned MatcherTableEmitter::
591204642SrdivackyEmitMatcherList(const Matcher *N, unsigned Indent, unsigned CurrentIdx,
592204642Srdivacky                formatted_raw_ostream &OS) {
593203954Srdivacky  unsigned Size = 0;
594204642Srdivacky  while (N) {
595204642Srdivacky    if (!OmitComments)
596204642Srdivacky      OS << "/*" << CurrentIdx << "*/";
597204642Srdivacky    unsigned MatcherSize = EmitMatcher(N, Indent, CurrentIdx, OS);
598204642Srdivacky    Size += MatcherSize;
599204642Srdivacky    CurrentIdx += MatcherSize;
600221345Sdim
601204642Srdivacky    // If there are other nodes in this list, iterate to them, otherwise we're
602204642Srdivacky    // done.
603204642Srdivacky    N = N->getNext();
604204642Srdivacky  }
605204642Srdivacky  return Size;
606204642Srdivacky}
607204642Srdivacky
608206083Srdivackyvoid MatcherTableEmitter::EmitPredicateFunctions(formatted_raw_ostream &OS) {
609204642Srdivacky  // Emit pattern predicates.
610204642Srdivacky  if (!PatternPredicates.empty()) {
611243830Sdim    OS << "virtual bool CheckPatternPredicate(unsigned PredNo) const {\n";
612204642Srdivacky    OS << "  switch (PredNo) {\n";
613234353Sdim    OS << "  default: llvm_unreachable(\"Invalid predicate in table?\");\n";
614204642Srdivacky    for (unsigned i = 0, e = PatternPredicates.size(); i != e; ++i)
615204642Srdivacky      OS << "  case " << i << ": return "  << PatternPredicates[i] << ";\n";
616204642Srdivacky    OS << "  }\n";
617204642Srdivacky    OS << "}\n\n";
618204642Srdivacky  }
619221345Sdim
620204642Srdivacky  // Emit Node predicates.
621204642Srdivacky  // FIXME: Annoyingly, these are stored by name, which we never even emit. Yay?
622204642Srdivacky  StringMap<TreePattern*> PFsByName;
623221345Sdim
624204642Srdivacky  for (CodeGenDAGPatterns::pf_iterator I = CGP.pf_begin(), E = CGP.pf_end();
625204642Srdivacky       I != E; ++I)
626204642Srdivacky    PFsByName[I->first->getName()] = I->second;
627221345Sdim
628204642Srdivacky  if (!NodePredicates.empty()) {
629243830Sdim    OS << "virtual bool CheckNodePredicate(SDNode *Node,\n";
630243830Sdim    OS << "                                unsigned PredNo) const {\n";
631204642Srdivacky    OS << "  switch (PredNo) {\n";
632234353Sdim    OS << "  default: llvm_unreachable(\"Invalid predicate in table?\");\n";
633204642Srdivacky    for (unsigned i = 0, e = NodePredicates.size(); i != e; ++i) {
634221345Sdim      // Emit the predicate code corresponding to this pattern.
635221345Sdim      TreePredicateFn PredFn = NodePredicates[i];
636203954Srdivacky
637221345Sdim      assert(!PredFn.isAlwaysTrue() && "No code in this predicate");
638221345Sdim      OS << "  case " << i << ": { // " << NodePredicates[i].getFnName() <<'\n';
639221345Sdim
640221345Sdim      OS << PredFn.getCodeToRunOnSDNode() << "\n  }\n";
641204642Srdivacky    }
642204642Srdivacky    OS << "  }\n";
643204642Srdivacky    OS << "}\n\n";
644204642Srdivacky  }
645221345Sdim
646204642Srdivacky  // Emit CompletePattern matchers.
647204642Srdivacky  // FIXME: This should be const.
648204642Srdivacky  if (!ComplexPatterns.empty()) {
649243830Sdim    OS << "virtual bool CheckComplexPattern(SDNode *Root, SDNode *Parent,\n";
650243830Sdim    OS << "                                 SDValue N, unsigned PatternNo,\n";
651218893Sdim    OS << "         SmallVectorImpl<std::pair<SDValue, SDNode*> > &Result) {\n";
652210299Sed    OS << "  unsigned NextRes = Result.size();\n";
653204642Srdivacky    OS << "  switch (PatternNo) {\n";
654234353Sdim    OS << "  default: llvm_unreachable(\"Invalid pattern # in table?\");\n";
655204642Srdivacky    for (unsigned i = 0, e = ComplexPatterns.size(); i != e; ++i) {
656204642Srdivacky      const ComplexPattern &P = *ComplexPatterns[i];
657204642Srdivacky      unsigned NumOps = P.getNumOperands();
658204642Srdivacky
659204642Srdivacky      if (P.hasProperty(SDNPHasChain))
660204642Srdivacky        ++NumOps;  // Get the chained node too.
661221345Sdim
662204642Srdivacky      OS << "  case " << i << ":\n";
663210299Sed      OS << "    Result.resize(NextRes+" << NumOps << ");\n";
664204642Srdivacky      OS << "    return "  << P.getSelectFunc();
665204642Srdivacky
666218893Sdim      OS << "(";
667218893Sdim      // If the complex pattern wants the root of the match, pass it in as the
668218893Sdim      // first argument.
669218893Sdim      if (P.hasProperty(SDNPWantRoot))
670218893Sdim        OS << "Root, ";
671221345Sdim
672218893Sdim      // If the complex pattern wants the parent of the operand being matched,
673218893Sdim      // pass it in as the next argument.
674218893Sdim      if (P.hasProperty(SDNPWantParent))
675218893Sdim        OS << "Parent, ";
676221345Sdim
677218893Sdim      OS << "N";
678204642Srdivacky      for (unsigned i = 0; i != NumOps; ++i)
679218893Sdim        OS << ", Result[NextRes+" << i << "].first";
680204642Srdivacky      OS << ");\n";
681204642Srdivacky    }
682204642Srdivacky    OS << "  }\n";
683204642Srdivacky    OS << "}\n\n";
684204642Srdivacky  }
685221345Sdim
686221345Sdim
687204642Srdivacky  // Emit SDNodeXForm handlers.
688204642Srdivacky  // FIXME: This should be const.
689204642Srdivacky  if (!NodeXForms.empty()) {
690243830Sdim    OS << "virtual SDValue RunSDNodeXForm(SDValue V, unsigned XFormNo) {\n";
691204642Srdivacky    OS << "  switch (XFormNo) {\n";
692234353Sdim    OS << "  default: llvm_unreachable(\"Invalid xform # in table?\");\n";
693221345Sdim
694204642Srdivacky    // FIXME: The node xform could take SDValue's instead of SDNode*'s.
695204642Srdivacky    for (unsigned i = 0, e = NodeXForms.size(); i != e; ++i) {
696204642Srdivacky      const CodeGenDAGPatterns::NodeXForm &Entry =
697204642Srdivacky        CGP.getSDNodeTransform(NodeXForms[i]);
698221345Sdim
699204642Srdivacky      Record *SDNode = Entry.first;
700204642Srdivacky      const std::string &Code = Entry.second;
701221345Sdim
702204642Srdivacky      OS << "  case " << i << ": {  ";
703204642Srdivacky      if (!OmitComments)
704204642Srdivacky        OS << "// " << NodeXForms[i]->getName();
705204642Srdivacky      OS << '\n';
706221345Sdim
707204642Srdivacky      std::string ClassName = CGP.getSDNodeInfo(SDNode).getSDClassName();
708204642Srdivacky      if (ClassName == "SDNode")
709204642Srdivacky        OS << "    SDNode *N = V.getNode();\n";
710204642Srdivacky      else
711204642Srdivacky        OS << "    " << ClassName << " *N = cast<" << ClassName
712204642Srdivacky           << ">(V.getNode());\n";
713204642Srdivacky      OS << Code << "\n  }\n";
714203954Srdivacky    }
715204642Srdivacky    OS << "  }\n";
716204642Srdivacky    OS << "}\n\n";
717203954Srdivacky  }
718203954Srdivacky}
719203954Srdivacky
720204792Srdivackystatic void BuildHistogram(const Matcher *M, std::vector<unsigned> &OpcodeFreq){
721204792Srdivacky  for (; M != 0; M = M->getNext()) {
722204792Srdivacky    // Count this node.
723204792Srdivacky    if (unsigned(M->getKind()) >= OpcodeFreq.size())
724204792Srdivacky      OpcodeFreq.resize(M->getKind()+1);
725204792Srdivacky    OpcodeFreq[M->getKind()]++;
726221345Sdim
727204792Srdivacky    // Handle recursive nodes.
728204792Srdivacky    if (const ScopeMatcher *SM = dyn_cast<ScopeMatcher>(M)) {
729204792Srdivacky      for (unsigned i = 0, e = SM->getNumChildren(); i != e; ++i)
730204792Srdivacky        BuildHistogram(SM->getChild(i), OpcodeFreq);
731221345Sdim    } else if (const SwitchOpcodeMatcher *SOM =
732204792Srdivacky                 dyn_cast<SwitchOpcodeMatcher>(M)) {
733204792Srdivacky      for (unsigned i = 0, e = SOM->getNumCases(); i != e; ++i)
734204792Srdivacky        BuildHistogram(SOM->getCaseMatcher(i), OpcodeFreq);
735204792Srdivacky    } else if (const SwitchTypeMatcher *STM = dyn_cast<SwitchTypeMatcher>(M)) {
736204792Srdivacky      for (unsigned i = 0, e = STM->getNumCases(); i != e; ++i)
737204792Srdivacky        BuildHistogram(STM->getCaseMatcher(i), OpcodeFreq);
738204792Srdivacky    }
739204792Srdivacky  }
740204792Srdivacky}
741204792Srdivacky
742204792Srdivackyvoid MatcherTableEmitter::EmitHistogram(const Matcher *M,
743204792Srdivacky                                        formatted_raw_ostream &OS) {
744204642Srdivacky  if (OmitComments)
745204642Srdivacky    return;
746221345Sdim
747204792Srdivacky  std::vector<unsigned> OpcodeFreq;
748204792Srdivacky  BuildHistogram(M, OpcodeFreq);
749221345Sdim
750204642Srdivacky  OS << "  // Opcode Histogram:\n";
751204792Srdivacky  for (unsigned i = 0, e = OpcodeFreq.size(); i != e; ++i) {
752204642Srdivacky    OS << "  // #";
753204642Srdivacky    switch ((Matcher::KindTy)i) {
754221345Sdim    case Matcher::Scope: OS << "OPC_Scope"; break;
755221345Sdim    case Matcher::RecordNode: OS << "OPC_RecordNode"; break;
756204642Srdivacky    case Matcher::RecordChild: OS << "OPC_RecordChild"; break;
757204642Srdivacky    case Matcher::RecordMemRef: OS << "OPC_RecordMemRef"; break;
758218893Sdim    case Matcher::CaptureGlueInput: OS << "OPC_CaptureGlueInput"; break;
759204642Srdivacky    case Matcher::MoveChild: OS << "OPC_MoveChild"; break;
760204642Srdivacky    case Matcher::MoveParent: OS << "OPC_MoveParent"; break;
761204642Srdivacky    case Matcher::CheckSame: OS << "OPC_CheckSame"; break;
762263508Sdim    case Matcher::CheckChildSame: OS << "OPC_CheckChildSame"; break;
763204642Srdivacky    case Matcher::CheckPatternPredicate:
764204642Srdivacky      OS << "OPC_CheckPatternPredicate"; break;
765204642Srdivacky    case Matcher::CheckPredicate: OS << "OPC_CheckPredicate"; break;
766204642Srdivacky    case Matcher::CheckOpcode: OS << "OPC_CheckOpcode"; break;
767204642Srdivacky    case Matcher::SwitchOpcode: OS << "OPC_SwitchOpcode"; break;
768204642Srdivacky    case Matcher::CheckType: OS << "OPC_CheckType"; break;
769204642Srdivacky    case Matcher::SwitchType: OS << "OPC_SwitchType"; break;
770204642Srdivacky    case Matcher::CheckChildType: OS << "OPC_CheckChildType"; break;
771204642Srdivacky    case Matcher::CheckInteger: OS << "OPC_CheckInteger"; break;
772204642Srdivacky    case Matcher::CheckCondCode: OS << "OPC_CheckCondCode"; break;
773204642Srdivacky    case Matcher::CheckValueType: OS << "OPC_CheckValueType"; break;
774204642Srdivacky    case Matcher::CheckComplexPat: OS << "OPC_CheckComplexPat"; break;
775204642Srdivacky    case Matcher::CheckAndImm: OS << "OPC_CheckAndImm"; break;
776204642Srdivacky    case Matcher::CheckOrImm: OS << "OPC_CheckOrImm"; break;
777204642Srdivacky    case Matcher::CheckFoldableChainNode:
778204642Srdivacky      OS << "OPC_CheckFoldableChainNode"; break;
779204642Srdivacky    case Matcher::EmitInteger: OS << "OPC_EmitInteger"; break;
780204642Srdivacky    case Matcher::EmitStringInteger: OS << "OPC_EmitStringInteger"; break;
781204642Srdivacky    case Matcher::EmitRegister: OS << "OPC_EmitRegister"; break;
782204642Srdivacky    case Matcher::EmitConvertToTarget: OS << "OPC_EmitConvertToTarget"; break;
783204642Srdivacky    case Matcher::EmitMergeInputChains: OS << "OPC_EmitMergeInputChains"; break;
784204642Srdivacky    case Matcher::EmitCopyToReg: OS << "OPC_EmitCopyToReg"; break;
785204642Srdivacky    case Matcher::EmitNode: OS << "OPC_EmitNode"; break;
786204642Srdivacky    case Matcher::MorphNodeTo: OS << "OPC_MorphNodeTo"; break;
787204642Srdivacky    case Matcher::EmitNodeXForm: OS << "OPC_EmitNodeXForm"; break;
788218893Sdim    case Matcher::MarkGlueResults: OS << "OPC_MarkGlueResults"; break;
789221345Sdim    case Matcher::CompleteMatch: OS << "OPC_CompleteMatch"; break;
790204642Srdivacky    }
791221345Sdim
792204792Srdivacky    OS.PadToColumn(40) << " = " << OpcodeFreq[i] << '\n';
793204642Srdivacky  }
794204642Srdivacky  OS << '\n';
795203954Srdivacky}
796203954Srdivacky
797203954Srdivacky
798204642Srdivackyvoid llvm::EmitMatcherTable(const Matcher *TheMatcher,
799221345Sdim                            const CodeGenDAGPatterns &CGP,
800221345Sdim                            raw_ostream &O) {
801203954Srdivacky  formatted_raw_ostream OS(O);
802221345Sdim
803203954Srdivacky  OS << "// The main instruction selector code.\n";
804204642Srdivacky  OS << "SDNode *SelectCode(SDNode *N) {\n";
805203954Srdivacky
806206083Srdivacky  MatcherTableEmitter MatcherEmitter(CGP);
807203954Srdivacky
808221345Sdim  OS << "  // Some target values are emitted as 2 bytes, TARGET_VAL handles\n";
809221345Sdim  OS << "  // this.\n";
810221345Sdim  OS << "  #define TARGET_VAL(X) X & 255, unsigned(X) >> 8\n";
811203954Srdivacky  OS << "  static const unsigned char MatcherTable[] = {\n";
812204642Srdivacky  unsigned TotalSize = MatcherEmitter.EmitMatcherList(TheMatcher, 5, 0, OS);
813203954Srdivacky  OS << "    0\n  }; // Total Array size is " << (TotalSize+1) << " bytes\n\n";
814221345Sdim
815204792Srdivacky  MatcherEmitter.EmitHistogram(TheMatcher, OS);
816221345Sdim
817221345Sdim  OS << "  #undef TARGET_VAL\n";
818203954Srdivacky  OS << "  return SelectCodeCommon(N, MatcherTable,sizeof(MatcherTable));\n}\n";
819204642Srdivacky  OS << '\n';
820221345Sdim
821203954Srdivacky  // Next up, emit the function for node and pattern predicates:
822206083Srdivacky  MatcherEmitter.EmitPredicateFunctions(OS);
823203954Srdivacky}
824