refactor some code into a local class.
[oota-llvm.git] / utils / TableGen / DAGISelMatcherEmitter.cpp
1 //===- DAGISelMatcherEmitter.cpp - Matcher Emitter ------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file contains code to generate C++ code a matcher.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "DAGISelMatcher.h"
15 #include "CodeGenDAGPatterns.h"
16 #include "llvm/ADT/SmallString.h"
17 #include "llvm/Support/Casting.h"
18 #include "llvm/Support/FormattedStream.h"
19 using namespace llvm;
20
21 namespace {
22 enum {
23   CommentIndent = 25
24 };
25 }
26
27 /// ClassifyInt - Classify an integer by size, return '1','2','4','8' if this
28 /// fits in 1, 2, 4, or 8 sign extended bytes.
29 static char ClassifyInt(int64_t Val) {
30   if (Val == int8_t(Val))  return '1';
31   if (Val == int16_t(Val)) return '2';
32   if (Val == int32_t(Val)) return '4';
33   return '8';
34 }
35
36 /// EmitInt - Emit the specified integer, returning the number of bytes emitted.
37 static unsigned EmitInt(int64_t Val, formatted_raw_ostream &OS) {
38   unsigned BytesEmitted = 1;
39   OS << (int)(unsigned char)Val << ", ";
40   if (Val == int8_t(Val)) {
41     OS << "\n";
42     return BytesEmitted;
43   }
44   
45   OS << (int)(unsigned char)(Val >> 8) << ", ";
46   ++BytesEmitted;
47   
48   if (Val != int16_t(Val)) {
49     OS << (int)(unsigned char)(Val >> 16) << ','
50        << (int)(unsigned char)(Val >> 24) << ',';
51     BytesEmitted += 2;
52     
53     if (Val != int32_t(Val)) {
54       OS << (int)(unsigned char)(Val >> 32) << ','
55          << (int)(unsigned char)(Val >> 40) << ','
56          << (int)(unsigned char)(Val >> 48) << ','
57          << (int)(unsigned char)(Val >> 56) << ',';
58       BytesEmitted += 4;
59     }   
60   }
61   
62   OS.PadToColumn(CommentIndent) << "// " << Val << '\n';
63   return BytesEmitted;
64 }
65
66 namespace {
67 class MatcherTableEmitter {
68   formatted_raw_ostream &OS;
69 public:
70   MatcherTableEmitter(formatted_raw_ostream &os) : OS(os) {}
71
72   unsigned EmitMatcherAndChildren(const MatcherNode *N, unsigned Indent);
73 private:
74   unsigned EmitMatcher(const MatcherNode *N, unsigned Indent);
75 };
76 } // end anonymous namespace.
77
78 /// EmitMatcherOpcodes - Emit bytes for the specified matcher and return
79 /// the number of bytes emitted.
80 unsigned MatcherTableEmitter::
81 EmitMatcher(const MatcherNode *N, unsigned Indent) {
82   OS.PadToColumn(Indent*2);
83   
84   switch (N->getKind()) {
85   case MatcherNode::Push: assert(0 && "Should be handled by caller");
86   case MatcherNode::EmitNode:
87     OS << "OPC_Emit, /*XXX*/";
88     OS.PadToColumn(CommentIndent) << "// Src: "
89       << *cast<EmitNodeMatcherNode>(N)->getPattern().getSrcPattern() << '\n';
90     OS.PadToColumn(CommentIndent) << "// Dst: "
91       << *cast<EmitNodeMatcherNode>(N)->getPattern().getDstPattern() << '\n';
92     return 1;
93   case MatcherNode::Record:
94     OS << "OPC_Record,\n";
95     return 1;
96   case MatcherNode::MoveChild:
97     OS << "OPC_MoveChild, "
98        << cast<MoveChildMatcherNode>(N)->getChildNo() << ",\n";
99     return 2;
100       
101   case MatcherNode::MoveParent:
102     OS << "OPC_MoveParent,\n";
103     return 1;
104       
105   case MatcherNode::CheckSame:
106     OS << "OPC_CheckSame, "
107        << cast<CheckSameMatcherNode>(N)->getMatchNumber() << ",\n";
108     return 2;
109
110   case MatcherNode::CheckPatternPredicate:
111     OS << "OPC_CheckPatternPredicate, /*XXX*/0,";
112     OS.PadToColumn(CommentIndent) << "// "
113       << cast<CheckPatternPredicateMatcherNode>(N)->getPredicate() << '\n';
114     return 2;
115     
116   case MatcherNode::CheckPredicate:
117     OS << "OPC_CheckPredicate, /*XXX*/0,";
118     OS.PadToColumn(CommentIndent) << "// "
119       << cast<CheckPredicateMatcherNode>(N)->getPredicateName() << '\n';
120     return 2;
121       
122   case MatcherNode::CheckOpcode:
123     OS << "OPC_CheckOpcode, "
124        << cast<CheckOpcodeMatcherNode>(N)->getOpcodeName() << ",\n";
125     return 2;
126       
127   case MatcherNode::CheckType:
128     OS << "OPC_CheckType, "
129        << getEnumName(cast<CheckTypeMatcherNode>(N)->getType()) << ",\n";
130     return 2;
131
132   case MatcherNode::CheckInteger: {
133     int64_t Val = cast<CheckIntegerMatcherNode>(N)->getValue();
134     OS << "OPC_CheckInteger" << ClassifyInt(Val) << ", ";
135     return EmitInt(Val, OS)+1;
136   }   
137   case MatcherNode::CheckCondCode:
138     OS << "OPC_CheckCondCode, ISD::"
139        << cast<CheckCondCodeMatcherNode>(N)->getCondCodeName() << ",\n";
140     return 2;
141       
142   case MatcherNode::CheckValueType:
143     OS << "OPC_CheckValueType, MVT::"
144        << cast<CheckValueTypeMatcherNode>(N)->getTypeName() << ",\n";
145     return 2;
146
147   case MatcherNode::CheckComplexPat:
148     OS << "OPC_CheckComplexPat, 0/*XXX*/,\n";
149     return 2;
150       
151   case MatcherNode::CheckAndImm: {
152     int64_t Val = cast<CheckAndImmMatcherNode>(N)->getValue();
153     OS << "OPC_CheckAndImm" << ClassifyInt(Val) << ", ";
154     return EmitInt(Val, OS)+1;
155   }
156
157   case MatcherNode::CheckOrImm: {
158     int64_t Val = cast<CheckOrImmMatcherNode>(N)->getValue();
159     OS << "OPC_CheckOrImm" << ClassifyInt(Val) << ", ";
160     return EmitInt(Val, OS)+1;
161   }
162   case MatcherNode::CheckProfitableToFold:
163     OS << "OPC_IsProfitableToFold,\n";
164     return 1;
165   case MatcherNode::CheckLegalToFold:
166     OS << "OPC_IsLegalToFold,\n";
167     return 1;
168   }
169   assert(0 && "Unreachable");
170   return 0;
171 }
172
173 /// EmitMatcherAndChildren - Emit the bytes for the specified matcher subtree.
174 unsigned MatcherTableEmitter::
175 EmitMatcherAndChildren(const MatcherNode *N, unsigned Indent) {
176   unsigned Size = 0;
177   while (1) {
178     // Push is a special case since it is binary.
179     if (const PushMatcherNode *PMN = dyn_cast<PushMatcherNode>(N)) {
180       // We need to encode the child and the offset of the failure code before
181       // emitting either of them.  Handle this by buffering the output into a
182       // string while we get the size.
183       SmallString<128> TmpBuf;
184       unsigned ChildSize;
185       {
186         raw_svector_ostream OS(TmpBuf);
187         formatted_raw_ostream FOS(OS);
188         ChildSize = 
189           EmitMatcherAndChildren(cast<PushMatcherNode>(N)->getChild(),Indent+1);
190       }
191       
192       if (ChildSize > 255) {
193         errs() <<
194           "Tblgen internal error: can't handle predicate this complex yet\n";
195         exit(1);
196       }
197       
198       OS.PadToColumn(Indent*2);
199       OS << "OPC_Push, " << ChildSize << ",\n";
200       OS << TmpBuf.str();
201       
202       Size += 2 + ChildSize;
203       
204       N = PMN->getFailure();
205       continue;
206     }
207   
208     Size += EmitMatcher(N, Indent);
209     
210     // If there are children of this node, iterate to them, otherwise we're
211     // done.
212     if (const MatcherNodeWithChild *MNWC = dyn_cast<MatcherNodeWithChild>(N))
213       N = MNWC->getChild();
214     else
215       return Size;
216   }
217 }
218
219 void llvm::EmitMatcherTable(const MatcherNode *Matcher, raw_ostream &O) {
220   formatted_raw_ostream OS(O);
221   
222   OS << "// The main instruction selector code.\n";
223   OS << "SDNode *SelectCode2(SDNode *N) {\n";
224
225   MatcherTableEmitter MatcherEmitter(OS);
226
227   OS << "  static const unsigned char MatcherTable[] = {\n";
228   unsigned TotalSize = MatcherEmitter.EmitMatcherAndChildren(Matcher, 2);
229   OS << "    0\n  }; // Total Array size is " << (TotalSize+1) << " bytes\n\n";
230   OS << "  return SelectCodeCommon(N, MatcherTable,sizeof(MatcherTable));\n}\n";
231 }