blob: 34a50211963127ddaff44c4ea238186a1849b424 [file] [log] [blame]
Nate Begeman5ddb0872010-05-28 01:08:32 +00001//===- 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"
Nate Begeman22237772010-06-02 00:34:55 +000017#include "llvm/ADT/SmallString.h"
18#include "llvm/ADT/SmallVector.h"
Nate Begeman5ddb0872010-05-28 01:08:32 +000019#include "llvm/ADT/StringExtras.h"
Nate Begeman5ddb0872010-05-28 01:08:32 +000020#include <string>
21
22using namespace llvm;
23
Nate Begeman22237772010-06-02 00:34:55 +000024static void ParseTypes(Record *r, std::string &s,
25 SmallVectorImpl<StringRef> &TV) {
26 const char *data = s.data();
27 int len = 0;
28
29 for (unsigned i = 0, e = s.size(); i != e; ++i, ++len) {
30 if (data[len] == 'P' || data[len] == 'Q' || data[len] == 'U')
31 continue;
32
33 switch (data[len]) {
34 case 'c':
35 case 's':
36 case 'i':
37 case 'l':
38 case 'h':
39 case 'f':
40 break;
41 default:
42 throw TGError(r->getLoc(),
43 "Unexpected letter: " + std::string(data + len, 1));
44 break;
45 }
46 TV.push_back(StringRef(data, len + 1));
47 data += len + 1;
48 len = -1;
49 }
50}
51
Duncan Sands8dbbace2010-06-02 08:37:30 +000052static char Widen(const char t) {
Nate Begeman22237772010-06-02 00:34:55 +000053 switch (t) {
54 case 'c':
55 return 's';
56 case 's':
57 return 'i';
58 case 'i':
59 return 'l';
60 default: throw "unhandled type in widen!";
61 }
62 return '\0';
63}
64
Nate Begeman3861e742010-06-03 21:35:22 +000065static char Narrow(const char t) {
66 switch (t) {
67 case 's':
68 return 'c';
69 case 'i':
70 return 's';
71 case 'l':
72 return 'i';
73 default: throw "unhandled type in widen!";
74 }
75 return '\0';
76}
77
Nate Begemanaf905ef2010-06-02 06:17:19 +000078static char ClassifyType(StringRef ty, bool &quad, bool &poly, bool &usgn) {
Nate Begeman22237772010-06-02 00:34:55 +000079 unsigned off = 0;
80
Nate Begemanaf905ef2010-06-02 06:17:19 +000081 // remember quad.
82 if (ty[off] == 'Q') {
83 quad = true;
84 ++off;
85 }
86
87 // remember poly.
88 if (ty[off] == 'P') {
89 poly = true;
90 ++off;
91 }
92
93 // remember unsigned.
94 if (ty[off] == 'U') {
95 usgn = true;
96 ++off;
97 }
98
99 // base type to get the type string for.
100 return ty[off];
101}
102
Nate Begeman7c21f742010-06-04 21:36:00 +0000103static std::string TypeString(const char mod, StringRef typestr,
104 bool ret = false) {
Nate Begeman22237772010-06-02 00:34:55 +0000105 bool quad = false;
106 bool poly = false;
107 bool usgn = false;
108 bool scal = false;
109 bool cnst = false;
110 bool pntr = false;
111
Nate Begeman22237772010-06-02 00:34:55 +0000112 // base type to get the type string for.
Nate Begemanaf905ef2010-06-02 06:17:19 +0000113 char type = ClassifyType(typestr, quad, poly, usgn);
Nate Begeman22237772010-06-02 00:34:55 +0000114
115 // Based on the modifying character, change the type and width if necessary.
116 switch (mod) {
117 case 'v':
Nate Begemane66aab52010-06-02 07:14:28 +0000118 return "void";
119 case 'i':
120 return "int";
Nate Begeman22237772010-06-02 00:34:55 +0000121 case 't':
122 if (poly) {
123 poly = false;
124 usgn = true;
125 }
126 break;
127 case 'x':
128 usgn = true;
Nate Begeman162d3ba2010-06-03 04:04:09 +0000129 poly = false;
Nate Begeman22237772010-06-02 00:34:55 +0000130 if (type == 'f')
131 type = 'i';
132 break;
133 case 'f':
134 type = 'f';
Nate Begeman162d3ba2010-06-03 04:04:09 +0000135 usgn = false;
Nate Begeman22237772010-06-02 00:34:55 +0000136 break;
137 case 'w':
138 type = Widen(type);
139 quad = true;
140 break;
141 case 'n':
142 type = Widen(type);
143 break;
Nate Begeman22237772010-06-02 00:34:55 +0000144 case 'l':
145 type = 'l';
146 scal = true;
147 usgn = true;
148 break;
149 case 's':
150 scal = true;
151 break;
152 case 'k':
153 quad = true;
154 break;
155 case 'c':
156 cnst = true;
157 case 'p':
158 pntr = true;
159 scal = true;
160 break;
Nate Begeman3861e742010-06-03 21:35:22 +0000161 case 'h':
162 type = Narrow(type);
163 break;
164 case 'e':
165 type = Narrow(type);
166 usgn = true;
167 break;
Nate Begeman22237772010-06-02 00:34:55 +0000168 default:
169 break;
170 }
171
172 SmallString<128> s;
173
174 if (usgn)
175 s.push_back('u');
176
177 switch (type) {
178 case 'c':
179 s += poly ? "poly8" : "int8";
180 if (scal)
181 break;
182 s += quad ? "x16" : "x8";
183 break;
184 case 's':
185 s += poly ? "poly16" : "int16";
186 if (scal)
187 break;
188 s += quad ? "x8" : "x4";
189 break;
190 case 'i':
191 s += "int32";
192 if (scal)
193 break;
194 s += quad ? "x4" : "x2";
195 break;
196 case 'l':
197 s += "int64";
198 if (scal)
199 break;
200 s += quad ? "x2" : "x1";
201 break;
202 case 'h':
203 s += "float16";
204 if (scal)
205 break;
206 s += quad ? "x8" : "x4";
207 break;
208 case 'f':
209 s += "float32";
210 if (scal)
211 break;
212 s += quad ? "x4" : "x2";
213 break;
Nate Begeman22237772010-06-02 00:34:55 +0000214 default:
215 throw "unhandled type!";
216 break;
217 }
218
219 if (mod == '2')
220 s += "x2";
221 if (mod == '3')
222 s += "x3";
223 if (mod == '4')
224 s += "x4";
225
226 // Append _t, finishing the type string typedef type.
227 s += "_t";
228
229 if (cnst)
230 s += " const";
231
232 if (pntr)
233 s += " *";
234
235 return s.str();
236}
237
Nate Begeman7c21f742010-06-04 21:36:00 +0000238static std::string BuiltinTypeString(const char mod, StringRef typestr,
239 ClassKind ck, bool ret) {
Nate Begeman92f98af2010-06-04 07:11:25 +0000240 bool quad = false;
241 bool poly = false;
242 bool usgn = false;
243 bool scal = false;
244 bool cnst = false;
245 bool pntr = false;
246
247 if (mod == 'v')
248 return "v";
249 if (mod == 'i')
250 return "i";
251
252 // base type to get the type string for.
253 char type = ClassifyType(typestr, quad, poly, usgn);
254
255 // Based on the modifying character, change the type and width if necessary.
256 switch (mod) {
257 case 't':
258 if (poly) {
259 poly = false;
260 usgn = true;
261 }
262 break;
263 case 'x':
264 usgn = true;
265 poly = false;
266 if (type == 'f')
267 type = 'i';
268 break;
269 case 'f':
270 type = 'f';
271 usgn = false;
272 break;
273 case 'w':
274 type = Widen(type);
275 quad = true;
276 break;
277 case 'n':
278 type = Widen(type);
279 break;
280 case 'l':
281 type = 'l';
282 scal = true;
283 usgn = true;
284 break;
285 case 's':
286 scal = true;
287 break;
288 case 'k':
289 quad = true;
290 break;
291 case 'c':
292 cnst = true;
293 case 'p':
294 type = 'v';
295 usgn = false;
296 poly = false;
297 pntr = true;
298 scal = true;
299 break;
300 case 'h':
301 type = Narrow(type);
302 break;
303 case 'e':
304 type = Narrow(type);
305 usgn = true;
306 break;
307 default:
308 break;
309 }
310 if (type == 'h') {
311 type = 's';
312 usgn = true;
313 }
Nate Begeman7c21f742010-06-04 21:36:00 +0000314 usgn = usgn | poly | ((ck == ClassI || ck == ClassW) && scal && type != 'f');
Nate Begeman92f98af2010-06-04 07:11:25 +0000315
316 if (scal) {
317 SmallString<128> s;
318
319 if (usgn)
320 s.push_back('U');
Nate Begeman7c21f742010-06-04 21:36:00 +0000321
322 if (type == 'l')
323 s += "LLi";
324 else
325 s.push_back(type);
326
Nate Begeman92f98af2010-06-04 07:11:25 +0000327 if (cnst)
328 s.push_back('C');
329 if (pntr)
330 s.push_back('*');
331 return s.str();
332 }
Nate Begeman7c21f742010-06-04 21:36:00 +0000333
334 // Since the return value must be one type, return a vector type of the
335 // appropriate width which we will bitcast.
336 if (ret) {
337 if (mod == '2')
338 return quad ? "V32c" : "V16c";
339 if (mod == '3')
340 return quad ? "V48c" : "V24c";
341 if (mod == '4')
342 return quad ? "V64c" : "V32c";
343
344 return quad ? "V16c" : "V8c";
345 }
346
347 // Non-return array types are passed as individual vectors.
Nate Begeman92f98af2010-06-04 07:11:25 +0000348 if (mod == '2')
349 return quad ? "V16cV16c" : "V8cV8c";
350 if (mod == '3')
351 return quad ? "V16cV16cV16c" : "V8cV8cV8c";
352 if (mod == '4')
353 return quad ? "V16cV16cV16cV16c" : "V8cV8cV8cV8c";
354
355 return quad ? "V16c" : "V8c";
356}
357
Nate Begeman22237772010-06-02 00:34:55 +0000358// Turn "vst2_lane" into "vst2q_lane_f32", etc.
Nate Begemana8979a02010-06-04 00:21:41 +0000359static std::string MangleName(const std::string &name, StringRef typestr,
360 ClassKind ck) {
Nate Begemanaf905ef2010-06-02 06:17:19 +0000361 bool quad = false;
362 bool poly = false;
363 bool usgn = false;
364 char type = ClassifyType(typestr, quad, poly, usgn);
365
366 std::string s = name;
367
368 switch (type) {
Nate Begemana8979a02010-06-04 00:21:41 +0000369 case 'c':
370 switch (ck) {
371 case ClassS: s += poly ? "_p8" : usgn ? "_u8" : "_s8"; break;
372 case ClassI: s += "_i8"; break;
373 case ClassW: s += "_8"; break;
374 default: break;
375 }
376 break;
377 case 's':
378 switch (ck) {
379 case ClassS: s += poly ? "_p16" : usgn ? "_u16" : "_s16"; break;
380 case ClassI: s += "_i16"; break;
381 case ClassW: s += "_16"; break;
382 default: break;
383 }
384 break;
385 case 'i':
386 switch (ck) {
387 case ClassS: s += usgn ? "_u32" : "_s32"; break;
388 case ClassI: s += "_i32"; break;
389 case ClassW: s += "_32"; break;
390 default: break;
391 }
392 break;
393 case 'l':
394 switch (ck) {
395 case ClassS: s += usgn ? "_u64" : "_s64"; break;
396 case ClassI: s += "_i64"; break;
397 case ClassW: s += "_64"; break;
398 default: break;
399 }
400 break;
401 case 'h':
402 switch (ck) {
403 case ClassS:
404 case ClassI: s += "_f16"; break;
405 case ClassW: s += "_16"; break;
406 default: break;
407 }
408 break;
409 case 'f':
410 switch (ck) {
411 case ClassS:
412 case ClassI: s += "_f32"; break;
413 case ClassW: s += "_32"; break;
414 default: break;
415 }
416 break;
417 default:
418 throw "unhandled type!";
419 break;
Nate Begemanaf905ef2010-06-02 06:17:19 +0000420 }
Nate Begemana8979a02010-06-04 00:21:41 +0000421 if (ck == ClassB)
Nate Begeman92f98af2010-06-04 07:11:25 +0000422 s += "_v";
Nate Begemana8979a02010-06-04 00:21:41 +0000423
Nate Begemanaf905ef2010-06-02 06:17:19 +0000424 // Insert a 'q' before the first '_' character so that it ends up before
425 // _lane or _n on vector-scalar operations.
426 if (quad) {
427 size_t pos = s.find('_');
428 s = s.insert(pos, "q");
429 }
430 return s;
Nate Begeman22237772010-06-02 00:34:55 +0000431}
432
Nate Begemanaf905ef2010-06-02 06:17:19 +0000433// Generate the string "(argtype a, argtype b, ...)"
Nate Begeman22237772010-06-02 00:34:55 +0000434static std::string GenArgs(const std::string &proto, StringRef typestr) {
Nate Begemanaf905ef2010-06-02 06:17:19 +0000435 char arg = 'a';
436
437 std::string s;
438 s += "(";
439
440 for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) {
441 s += TypeString(proto[i], typestr);
442 s.push_back(' ');
443 s.push_back(arg);
444 if ((i + 1) < e)
445 s += ", ";
446 }
447
448 s += ")";
449 return s;
Nate Begeman22237772010-06-02 00:34:55 +0000450}
451
Nate Begeman7c8c8832010-06-02 21:53:00 +0000452// Generate the definition for this intrinsic, e.g. "a + b" for OpAdd.
453// If structTypes is true, the NEON types are structs of vector types rather
454// than vector types, and the call becomes "a.val + b.val"
455static std::string GenOpString(OpKind op, const std::string &proto,
Nate Begeman162d3ba2010-06-03 04:04:09 +0000456 StringRef typestr, bool structTypes = true) {
457 std::string s("return ");
Nate Begeman7c21f742010-06-04 21:36:00 +0000458 std::string ts = TypeString(proto[0], typestr, true);
Nate Begeman162d3ba2010-06-03 04:04:09 +0000459 if (structTypes)
460 s += "(" + ts + "){";
461
Nate Begeman3861e742010-06-03 21:35:22 +0000462 std::string a, b, c;
463 if (proto.size() > 1)
464 a = (structTypes && proto[1] != 'l') ? "a.val" : "a";
465 b = structTypes ? "b.val" : "b";
466 c = structTypes ? "c.val" : "c";
Nate Begeman162d3ba2010-06-03 04:04:09 +0000467
468 switch(op) {
469 case OpAdd:
470 s += a + " + " + b;
471 break;
472 case OpSub:
473 s += a + " - " + b;
474 break;
475 case OpMul:
476 s += a + " * " + b;
477 break;
478 case OpMla:
479 s += a + " + ( " + b + " * " + c + " )";
480 break;
481 case OpMls:
482 s += a + " - ( " + b + " * " + c + " )";
483 break;
484 case OpEq:
485 s += "(__neon_" + ts + ")(" + a + " == " + b + ")";
486 break;
487 case OpGe:
488 s += "(__neon_" + ts + ")(" + a + " >= " + b + ")";
489 break;
490 case OpLe:
491 s += "(__neon_" + ts + ")(" + a + " <= " + b + ")";
492 break;
493 case OpGt:
494 s += "(__neon_" + ts + ")(" + a + " > " + b + ")";
495 break;
496 case OpLt:
497 s += "(__neon_" + ts + ")(" + a + " < " + b + ")";
498 break;
499 case OpNeg:
500 s += " -" + a;
501 break;
502 case OpNot:
503 s += " ~" + a;
504 break;
505 case OpAnd:
506 s += a + " & " + b;
507 break;
508 case OpOr:
509 s += a + " | " + b;
510 break;
511 case OpXor:
512 s += a + " ^ " + b;
513 break;
514 case OpAndNot:
515 s += a + " & ~" + b;
516 break;
517 case OpOrNot:
518 s += a + " | ~" + b;
519 break;
Nate Begeman3861e742010-06-03 21:35:22 +0000520 case OpCast:
521 s += "(__neon_" + ts + ")" + a;
522 break;
Nate Begeman162d3ba2010-06-03 04:04:09 +0000523 default:
524 throw "unknown OpKind!";
525 break;
526 }
527
528 if (structTypes)
529 s += "}";
530 s += ";";
531 return s;
Nate Begemane66aab52010-06-02 07:14:28 +0000532}
533
Nate Begeman7c8c8832010-06-02 21:53:00 +0000534// Generate the definition for this intrinsic, e.g. __builtin_neon_cls(a)
535// If structTypes is true, the NEON types are structs of vector types rather
536// than vector types, and the call becomes __builtin_neon_cls(a.val)
537static std::string GenBuiltin(const std::string &name, const std::string &proto,
Nate Begemana8979a02010-06-04 00:21:41 +0000538 StringRef typestr, ClassKind ck,
539 bool structTypes = true) {
Nate Begeman7c8c8832010-06-02 21:53:00 +0000540 char arg = 'a';
Nate Begeman162d3ba2010-06-03 04:04:09 +0000541 std::string s;
Nate Begeman7c21f742010-06-04 21:36:00 +0000542 //bool unioning = (proto[0] == '2' || proto[0] == '3' || proto[0] == '4');
543
Nate Begeman162d3ba2010-06-03 04:04:09 +0000544 if (proto[0] != 'v') {
545 // FIXME: if return type is 2/3/4, emit unioning code.
Nate Begeman7c21f742010-06-04 21:36:00 +0000546 //if (unioning)
547 // ;
548
Nate Begeman162d3ba2010-06-03 04:04:09 +0000549 s += "return ";
550 if (structTypes) {
551 s += "(";
Nate Begeman7c21f742010-06-04 21:36:00 +0000552 s += TypeString(proto[0], typestr, true);
Nate Begeman162d3ba2010-06-03 04:04:09 +0000553 s += "){";
554 }
555 }
Nate Begeman7c8c8832010-06-02 21:53:00 +0000556
557 s += "__builtin_neon_";
Nate Begemana8979a02010-06-04 00:21:41 +0000558 s += MangleName(name, typestr, ck);
Nate Begeman7c8c8832010-06-02 21:53:00 +0000559 s += "(";
560
561 for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) {
562 s.push_back(arg);
Nate Begeman162d3ba2010-06-03 04:04:09 +0000563 if (structTypes && proto[i] != 's' && proto[i] != 'i' && proto[i] != 'l' &&
564 proto[i] != 'p' && proto[i] != 'c') {
Nate Begeman7c8c8832010-06-02 21:53:00 +0000565 s += ".val";
Nate Begeman162d3ba2010-06-03 04:04:09 +0000566 }
Nate Begeman7c8c8832010-06-02 21:53:00 +0000567 if ((i + 1) < e)
568 s += ", ";
569 }
570
571 s += ")";
Nate Begeman162d3ba2010-06-03 04:04:09 +0000572 if (proto[0] != 'v' && structTypes)
Nate Begeman7c8c8832010-06-02 21:53:00 +0000573 s += "}";
574 s += ";";
575 return s;
Nate Begemane66aab52010-06-02 07:14:28 +0000576}
577
Nate Begeman73cef3e2010-06-04 01:26:15 +0000578static std::string GenBuiltinDef(const std::string &name,
579 const std::string &proto,
580 StringRef typestr, ClassKind ck) {
581 std::string s("BUILTIN(__builtin_neon_");
Nate Begeman92f98af2010-06-04 07:11:25 +0000582
583 // If all types are the same size, bitcasting the args will take care
584 // of arg checking. The actual signedness etc. will be taken care of with
585 // special enums.
586 if (proto.find('s') == std::string::npos)
587 ck = ClassB;
588
Nate Begeman73cef3e2010-06-04 01:26:15 +0000589 s += MangleName(name, typestr, ck);
590 s += ", \"";
591
Nate Begeman92f98af2010-06-04 07:11:25 +0000592 for (unsigned i = 0, e = proto.size(); i != e; ++i)
Nate Begeman7c21f742010-06-04 21:36:00 +0000593 s += BuiltinTypeString(proto[i], typestr, ck, i == 0);
594
595 // Extra constant integer to hold type class enum for this function, e.g. s8
596 if (ck == ClassB)
597 s += "i";
Nate Begeman73cef3e2010-06-04 01:26:15 +0000598
599 s += "\", \"n\")";
600 return s;
601}
602
Nate Begeman5ddb0872010-05-28 01:08:32 +0000603void NeonEmitter::run(raw_ostream &OS) {
604 EmitSourceFileHeader("ARM NEON Header", OS);
605
606 // FIXME: emit license into file?
607
608 OS << "#ifndef __ARM_NEON_H\n";
609 OS << "#define __ARM_NEON_H\n\n";
610
611 OS << "#ifndef __ARM_NEON__\n";
612 OS << "#error \"NEON support not enabled\"\n";
613 OS << "#endif\n\n";
614
615 OS << "#include <stdint.h>\n\n";
Nate Begeman7c8c8832010-06-02 21:53:00 +0000616
617 // Emit NEON-specific scalar typedefs.
618 // FIXME: probably need to do something better for polynomial types.
Nate Begeman162d3ba2010-06-03 04:04:09 +0000619 // FIXME: is this the correct thing to do for float16?
Nate Begeman7c8c8832010-06-02 21:53:00 +0000620 OS << "typedef float float32_t;\n";
621 OS << "typedef uint8_t poly8_t;\n";
622 OS << "typedef uint16_t poly16_t;\n";
Nate Begeman162d3ba2010-06-03 04:04:09 +0000623 OS << "typedef uint16_t float16_t;\n";
Nate Begeman5ddb0872010-05-28 01:08:32 +0000624
Nate Begeman7c8c8832010-06-02 21:53:00 +0000625 // Emit Neon vector typedefs.
626 std::string TypedefTypes("cQcsQsiQilQlUcQUcUsQUsUiQUiUlQUlhQhfQfPcQPcPsQPs");
627 SmallVector<StringRef, 24> TDTypeVec;
628 ParseTypes(0, TypedefTypes, TDTypeVec);
629
630 // Emit vector typedefs.
631 for (unsigned i = 0, e = TDTypeVec.size(); i != e; ++i) {
632 bool dummy, quad = false;
633 (void) ClassifyType(TDTypeVec[i], quad, dummy, dummy);
634 OS << "typedef __attribute__(( __vector_size__(";
635 OS << (quad ? "16) )) " : "8) )) ");
636 OS << TypeString('s', TDTypeVec[i]);
637 OS << " __neon_";
Nate Begeman162d3ba2010-06-03 04:04:09 +0000638 OS << TypeString('d', TDTypeVec[i]) << ";\n";
Nate Begeman7c8c8832010-06-02 21:53:00 +0000639 }
640 OS << "\n";
641
642 // Emit struct typedefs.
643 for (unsigned vi = 1; vi != 5; ++vi) {
644 for (unsigned i = 0, e = TDTypeVec.size(); i != e; ++i) {
645 std::string ts = TypeString('d', TDTypeVec[i]);
646 std::string vs = (vi > 1) ? TypeString('0' + vi, TDTypeVec[i]) : ts;
647 OS << "typedef struct __" << vs << " {\n";
648 OS << " __neon_" << ts << " val";
649 if (vi > 1)
650 OS << "[" << utostr(vi) << "]";
651 OS << ";\n} " << vs << ";\n\n";
652 }
653 }
Nate Begeman5ddb0872010-05-28 01:08:32 +0000654
Nate Begeman7c8c8832010-06-02 21:53:00 +0000655 OS << "#define __ai static __attribute__((__always_inline__))\n\n";
656
Nate Begeman5ddb0872010-05-28 01:08:32 +0000657 std::vector<Record*> RV = Records.getAllDerivedDefinitions("Inst");
658
Nate Begeman22237772010-06-02 00:34:55 +0000659 // Unique the return+pattern types, and assign them.
Nate Begeman5ddb0872010-05-28 01:08:32 +0000660 for (unsigned i = 0, e = RV.size(); i != e; ++i) {
661 Record *R = RV[i];
Nate Begeman22237772010-06-02 00:34:55 +0000662 std::string name = LowercaseString(R->getName());
663 std::string Proto = R->getValueAsString("Prototype");
Nate Begeman5ddb0872010-05-28 01:08:32 +0000664 std::string Types = R->getValueAsString("Types");
Nate Begeman22237772010-06-02 00:34:55 +0000665
666 SmallVector<StringRef, 16> TypeVec;
667 ParseTypes(R, Types, TypeVec);
668
Nate Begeman162d3ba2010-06-03 04:04:09 +0000669 OpKind k = OpMap[R->getValueAsDef("Operand")->getName()];
Nate Begemane66aab52010-06-02 07:14:28 +0000670
Nate Begeman22237772010-06-02 00:34:55 +0000671 for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) {
672 assert(!Proto.empty() && "");
673
Nate Begeman7c8c8832010-06-02 21:53:00 +0000674 // static always inline + return type
675 OS << "__ai " << TypeString(Proto[0], TypeVec[ti]);
Nate Begeman22237772010-06-02 00:34:55 +0000676
Nate Begemane66aab52010-06-02 07:14:28 +0000677 // Function name with type suffix
Nate Begemana8979a02010-06-04 00:21:41 +0000678 OS << " " << MangleName(name, TypeVec[ti], ClassS);
Nate Begeman22237772010-06-02 00:34:55 +0000679
Nate Begemane66aab52010-06-02 07:14:28 +0000680 // Function arguments
681 OS << GenArgs(Proto, TypeVec[ti]);
Nate Begeman22237772010-06-02 00:34:55 +0000682
Nate Begemane66aab52010-06-02 07:14:28 +0000683 // Definition.
684 OS << " { ";
Nate Begeman22237772010-06-02 00:34:55 +0000685
Nate Begemana8979a02010-06-04 00:21:41 +0000686 if (k != OpNone) {
Nate Begeman162d3ba2010-06-03 04:04:09 +0000687 OS << GenOpString(k, Proto, TypeVec[ti]);
Nate Begemana8979a02010-06-04 00:21:41 +0000688 } else {
689 if (R->getSuperClasses().size() < 2)
690 throw TGError(R->getLoc(), "Builtin has no class kind");
691
692 ClassKind ck = ClassMap[R->getSuperClasses()[1]];
693
694 if (ck == ClassNone)
695 throw TGError(R->getLoc(), "Builtin has no class kind");
696 OS << GenBuiltin(name, Proto, TypeVec[ti], ck);
697 }
Nate Begemane66aab52010-06-02 07:14:28 +0000698
Nate Begeman7c8c8832010-06-02 21:53:00 +0000699 OS << " }\n";
Nate Begeman22237772010-06-02 00:34:55 +0000700 }
701 OS << "\n";
Nate Begeman5ddb0872010-05-28 01:08:32 +0000702 }
Nate Begeman73cef3e2010-06-04 01:26:15 +0000703 OS << "#undef __ai\n\n";
Nate Begeman7c8c8832010-06-02 21:53:00 +0000704 OS << "#endif /* __ARM_NEON_H */\n";
Nate Begeman5ddb0872010-05-28 01:08:32 +0000705}
Nate Begemana8979a02010-06-04 00:21:41 +0000706
707void NeonEmitter::runHeader(raw_ostream &OS) {
Nate Begeman73cef3e2010-06-04 01:26:15 +0000708 std::vector<Record*> RV = Records.getAllDerivedDefinitions("Inst");
709
710 StringMap<OpKind> EmittedMap;
711
712 for (unsigned i = 0, e = RV.size(); i != e; ++i) {
713 Record *R = RV[i];
714
715 OpKind k = OpMap[R->getValueAsDef("Operand")->getName()];
716 if (k != OpNone)
717 continue;
718
719 std::string name = LowercaseString(R->getName());
720 std::string Proto = R->getValueAsString("Prototype");
721 std::string Types = R->getValueAsString("Types");
722
723 SmallVector<StringRef, 16> TypeVec;
724 ParseTypes(R, Types, TypeVec);
725
726 if (R->getSuperClasses().size() < 2)
727 throw TGError(R->getLoc(), "Builtin has no class kind");
728
729 ClassKind ck = ClassMap[R->getSuperClasses()[1]];
730
731 for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) {
732 std::string bd = GenBuiltinDef(name, Proto, TypeVec[ti], ck);
733 if (EmittedMap.count(bd))
734 continue;
735
736 EmittedMap[bd] = OpNone;
737 OS << bd << "\n";
738 }
739 }
Nate Begemana8979a02010-06-04 00:21:41 +0000740}