eeb0bcc15047be51d4f38c3d87daaa9bff417ced
[oota-llvm.git] / utils / TableGen / NeonEmitter.cpp
1 //===- NeonEmitter.cpp - Generate arm_neon.h for use with clang -*- C++ -*-===//
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 tablegen backend is responsible for emitting arm_neon.h, which includes
11 // a declaration and definition of each function specified by the ARM NEON 
12 // compiler interface.  See ARM document DUI0348B.
13 //
14 //===----------------------------------------------------------------------===//
15
16 #include "NeonEmitter.h"
17 #include "Record.h"
18 #include "llvm/ADT/SmallString.h"
19 #include "llvm/ADT/SmallVector.h"
20 #include "llvm/ADT/StringExtras.h"
21 #include "llvm/ADT/StringMap.h"
22 #include <string>
23
24 using namespace llvm;
25
26 static void ParseTypes(Record *r, std::string &s,
27                        SmallVectorImpl<StringRef> &TV) {
28   const char *data = s.data();
29   int len = 0;
30   
31   for (unsigned i = 0, e = s.size(); i != e; ++i, ++len) {
32     if (data[len] == 'P' || data[len] == 'Q' || data[len] == 'U')
33       continue;
34     
35     switch (data[len]) {
36       case 'c':
37       case 's':
38       case 'i':
39       case 'l':
40       case 'h':
41       case 'f':
42         break;
43       default:
44         throw TGError(r->getLoc(),
45                       "Unexpected letter: " + std::string(data + len, 1));
46         break;
47     }
48     TV.push_back(StringRef(data, len + 1));
49     data += len + 1;
50     len = -1;
51   }
52 }
53
54 static const char Widen(const char t) {
55   switch (t) {
56     case 'c':
57       return 's';
58     case 's':
59       return 'i';
60     case 'i':
61       return 'l';
62     default: throw "unhandled type in widen!";
63   }
64   return '\0';
65 }
66
67 static std::string TypeString(const char mod, StringRef typestr) {
68   unsigned off = 0;
69   
70   bool quad = false;
71   bool poly = false;
72   bool usgn = false;
73   bool scal = false;
74   bool cnst = false;
75   bool pntr = false;
76   
77   // remember quad.
78   if (typestr[off] == 'Q') {
79     quad = true;
80     ++off;
81   }
82     
83   // remember poly.
84   if (typestr[off] == 'P') {
85     poly = true;
86     ++off;
87   }
88   
89   // remember unsigned.
90   if (typestr[off] == 'U') {
91     usgn = true;
92     ++off;
93   }
94   
95   // base type to get the type string for.
96   char type = typestr[off];
97   
98   // Based on the modifying character, change the type and width if necessary.
99   switch (mod) {
100     case 'v':
101       type = 'v';
102       scal = true;
103       usgn = false;
104       break;
105     case 't':
106       if (poly) {
107         poly = false;
108         usgn = true;
109       }
110       break;
111     case 'x':
112       usgn = true;
113       if (type == 'f')
114         type = 'i';
115       break;
116     case 'f':
117       type = 'f';
118       break;
119     case 'w':
120       type = Widen(type);
121       quad = true;
122       break;
123     case 'n':
124       type = Widen(type);
125       break;
126     case 'i':
127       type = 'i';
128       scal = true;
129       usgn = false;
130       break;
131     case 'l':
132       type = 'l';
133       scal = true;
134       usgn = true;
135       break;
136     case 's':
137       scal = true;
138       break;
139     case 'k':
140       quad = true;
141       break;
142     case 'c':
143       cnst = true;
144     case 'p':
145       pntr = true;
146       scal = true;
147       break;
148     default:
149       break;
150   }
151   
152   SmallString<128> s;
153   
154   if (usgn)
155     s.push_back('u');
156   
157   switch (type) {
158     case 'c':
159       s += poly ? "poly8" : "int8";
160       if (scal)
161         break;
162       s += quad ? "x16" : "x8";
163       break;
164     case 's':
165       s += poly ? "poly16" : "int16";
166       if (scal)
167         break;
168       s += quad ? "x8" : "x4";
169       break;
170     case 'i':
171       s += "int32";
172       if (scal)
173         break;
174       s += quad ? "x4" : "x2";
175       break;
176     case 'l':
177       s += "int64";
178       if (scal)
179         break;
180       s += quad ? "x2" : "x1";
181       break;
182     case 'h':
183       s += "float16";
184       if (scal)
185         break;
186       s += quad ? "x8" : "x4";
187       break;
188     case 'f':
189       s += "float32";
190       if (scal)
191         break;
192       s += quad ? "x4" : "x2";
193       break;
194     case 'v':
195       s += "void";
196       break;
197     default:
198       throw "unhandled type!";
199       break;
200   }
201
202   if (mod == '2')
203     s += "x2";
204   if (mod == '3')
205     s += "x3";
206   if (mod == '4')
207     s += "x4";
208   
209   // Append _t, finishing the type string typedef type.
210   s += "_t";
211   
212   if (cnst)
213     s += " const";
214   
215   if (pntr)
216     s += " *";
217   
218   return s.str();
219 }
220
221 // Turn "vst2_lane" into "vst2q_lane_f32", etc.
222 static std::string MangleName(const std::string &name, StringRef typestr) {
223   return "";
224 }
225
226 // 
227 static std::string GenArgs(const std::string &proto, StringRef typestr) {
228   return "";
229 }
230
231 void NeonEmitter::run(raw_ostream &OS) {
232   EmitSourceFileHeader("ARM NEON Header", OS);
233   
234   // FIXME: emit license into file?
235   
236   OS << "#ifndef __ARM_NEON_H\n";
237   OS << "#define __ARM_NEON_H\n\n";
238   
239   OS << "#ifndef __ARM_NEON__\n";
240   OS << "#error \"NEON support not enabled\"\n";
241   OS << "#endif\n\n";
242
243   OS << "#include <stdint.h>\n\n";
244   
245   // EmitTypedefs(OS);
246   
247   std::vector<Record*> RV = Records.getAllDerivedDefinitions("Inst");
248   
249   // Initialize Type Map
250   
251   // Unique the return+pattern types, and assign them.
252   for (unsigned i = 0, e = RV.size(); i != e; ++i) {
253     Record *R = RV[i];
254     std::string name = LowercaseString(R->getName());
255     std::string Proto = R->getValueAsString("Prototype");
256     std::string Types = R->getValueAsString("Types");
257     
258     SmallVector<StringRef, 16> TypeVec;
259     ParseTypes(R, Types, TypeVec);
260     
261     for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) {
262       assert(!Proto.empty() && "");
263       
264       SmallString<128> Prototype;
265       Prototype += TypeString(Proto[0], TypeVec[ti]);
266       Prototype += " ";
267       Prototype += MangleName(name, TypeVec[ti]);
268       Prototype += GenArgs(Proto, TypeVec[ti]);
269       
270       OS << Prototype << ";\n";
271       
272       // gen definition
273     
274         // if (opcode)
275       
276           // gen opstring
277       
278         // gen builtin (args)
279     }
280     OS << "\n";
281   }
282
283   // TODO: 
284   // Unique the return+pattern types, and assign them to each record
285   // Emit a #define for each unique "type" of intrinsic declaring all variants.
286   // Emit a #define for each intrinsic mapping it to a particular type.
287   
288   OS << "\n#endif /* __ARM_NEON_H */\n";
289 }