blob: 7b96de821933bf404a5dd0934a04922ff9f089f1 [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
103static std::string TypeString(const char mod, StringRef typestr) {
Nate Begeman22237772010-06-02 00:34:55 +0000104 bool quad = false;
105 bool poly = false;
106 bool usgn = false;
107 bool scal = false;
108 bool cnst = false;
109 bool pntr = false;
110
Nate Begeman22237772010-06-02 00:34:55 +0000111 // base type to get the type string for.
Nate Begemanaf905ef2010-06-02 06:17:19 +0000112 char type = ClassifyType(typestr, quad, poly, usgn);
Nate Begeman22237772010-06-02 00:34:55 +0000113
114 // Based on the modifying character, change the type and width if necessary.
115 switch (mod) {
116 case 'v':
Nate Begemane66aab52010-06-02 07:14:28 +0000117 return "void";
118 case 'i':
119 return "int";
Nate Begeman22237772010-06-02 00:34:55 +0000120 case 't':
121 if (poly) {
122 poly = false;
123 usgn = true;
124 }
125 break;
126 case 'x':
127 usgn = true;
Nate Begeman162d3ba2010-06-03 04:04:09 +0000128 poly = false;
Nate Begeman22237772010-06-02 00:34:55 +0000129 if (type == 'f')
130 type = 'i';
131 break;
132 case 'f':
133 type = 'f';
Nate Begeman162d3ba2010-06-03 04:04:09 +0000134 usgn = false;
Nate Begeman22237772010-06-02 00:34:55 +0000135 break;
136 case 'w':
137 type = Widen(type);
138 quad = true;
139 break;
140 case 'n':
141 type = Widen(type);
142 break;
Nate Begeman22237772010-06-02 00:34:55 +0000143 case 'l':
144 type = 'l';
145 scal = true;
146 usgn = true;
147 break;
148 case 's':
149 scal = true;
150 break;
151 case 'k':
152 quad = true;
153 break;
154 case 'c':
155 cnst = true;
156 case 'p':
157 pntr = true;
158 scal = true;
159 break;
Nate Begeman3861e742010-06-03 21:35:22 +0000160 case 'h':
161 type = Narrow(type);
162 break;
163 case 'e':
164 type = Narrow(type);
165 usgn = true;
166 break;
Nate Begeman22237772010-06-02 00:34:55 +0000167 default:
168 break;
169 }
170
171 SmallString<128> s;
172
173 if (usgn)
174 s.push_back('u');
175
176 switch (type) {
177 case 'c':
178 s += poly ? "poly8" : "int8";
179 if (scal)
180 break;
181 s += quad ? "x16" : "x8";
182 break;
183 case 's':
184 s += poly ? "poly16" : "int16";
185 if (scal)
186 break;
187 s += quad ? "x8" : "x4";
188 break;
189 case 'i':
190 s += "int32";
191 if (scal)
192 break;
193 s += quad ? "x4" : "x2";
194 break;
195 case 'l':
196 s += "int64";
197 if (scal)
198 break;
199 s += quad ? "x2" : "x1";
200 break;
201 case 'h':
202 s += "float16";
203 if (scal)
204 break;
205 s += quad ? "x8" : "x4";
206 break;
207 case 'f':
208 s += "float32";
209 if (scal)
210 break;
211 s += quad ? "x4" : "x2";
212 break;
Nate Begeman22237772010-06-02 00:34:55 +0000213 default:
214 throw "unhandled type!";
215 break;
216 }
217
218 if (mod == '2')
219 s += "x2";
220 if (mod == '3')
221 s += "x3";
222 if (mod == '4')
223 s += "x4";
224
225 // Append _t, finishing the type string typedef type.
226 s += "_t";
227
228 if (cnst)
229 s += " const";
230
231 if (pntr)
232 s += " *";
233
234 return s.str();
235}
236
Nate Begeman92f98af2010-06-04 07:11:25 +0000237static std::string BuiltinTypeString(const char mod, StringRef typestr) {
238 bool quad = false;
239 bool poly = false;
240 bool usgn = false;
241 bool scal = false;
242 bool cnst = false;
243 bool pntr = false;
244
245 if (mod == 'v')
246 return "v";
247 if (mod == 'i')
248 return "i";
249
250 // base type to get the type string for.
251 char type = ClassifyType(typestr, quad, poly, usgn);
252
253 // Based on the modifying character, change the type and width if necessary.
254 switch (mod) {
255 case 't':
256 if (poly) {
257 poly = false;
258 usgn = true;
259 }
260 break;
261 case 'x':
262 usgn = true;
263 poly = false;
264 if (type == 'f')
265 type = 'i';
266 break;
267 case 'f':
268 type = 'f';
269 usgn = false;
270 break;
271 case 'w':
272 type = Widen(type);
273 quad = true;
274 break;
275 case 'n':
276 type = Widen(type);
277 break;
278 case 'l':
279 type = 'l';
280 scal = true;
281 usgn = true;
282 break;
283 case 's':
284 scal = true;
285 break;
286 case 'k':
287 quad = true;
288 break;
289 case 'c':
290 cnst = true;
291 case 'p':
292 type = 'v';
293 usgn = false;
294 poly = false;
295 pntr = true;
296 scal = true;
297 break;
298 case 'h':
299 type = Narrow(type);
300 break;
301 case 'e':
302 type = Narrow(type);
303 usgn = true;
304 break;
305 default:
306 break;
307 }
308 if (type == 'h') {
309 type = 's';
310 usgn = true;
311 }
312 usgn = usgn | poly;
313
314 if (scal) {
315 SmallString<128> s;
316
317 if (usgn)
318 s.push_back('U');
319 s.push_back(type);
320 if (cnst)
321 s.push_back('C');
322 if (pntr)
323 s.push_back('*');
324 return s.str();
325 }
326
327 if (mod == '2')
328 return quad ? "V16cV16c" : "V8cV8c";
329 if (mod == '3')
330 return quad ? "V16cV16cV16c" : "V8cV8cV8c";
331 if (mod == '4')
332 return quad ? "V16cV16cV16cV16c" : "V8cV8cV8cV8c";
333
334 return quad ? "V16c" : "V8c";
335}
336
Nate Begeman22237772010-06-02 00:34:55 +0000337// Turn "vst2_lane" into "vst2q_lane_f32", etc.
Nate Begemana8979a02010-06-04 00:21:41 +0000338static std::string MangleName(const std::string &name, StringRef typestr,
339 ClassKind ck) {
Nate Begemanaf905ef2010-06-02 06:17:19 +0000340 bool quad = false;
341 bool poly = false;
342 bool usgn = false;
343 char type = ClassifyType(typestr, quad, poly, usgn);
344
345 std::string s = name;
346
347 switch (type) {
Nate Begemana8979a02010-06-04 00:21:41 +0000348 case 'c':
349 switch (ck) {
350 case ClassS: s += poly ? "_p8" : usgn ? "_u8" : "_s8"; break;
351 case ClassI: s += "_i8"; break;
352 case ClassW: s += "_8"; break;
353 default: break;
354 }
355 break;
356 case 's':
357 switch (ck) {
358 case ClassS: s += poly ? "_p16" : usgn ? "_u16" : "_s16"; break;
359 case ClassI: s += "_i16"; break;
360 case ClassW: s += "_16"; break;
361 default: break;
362 }
363 break;
364 case 'i':
365 switch (ck) {
366 case ClassS: s += usgn ? "_u32" : "_s32"; break;
367 case ClassI: s += "_i32"; break;
368 case ClassW: s += "_32"; break;
369 default: break;
370 }
371 break;
372 case 'l':
373 switch (ck) {
374 case ClassS: s += usgn ? "_u64" : "_s64"; break;
375 case ClassI: s += "_i64"; break;
376 case ClassW: s += "_64"; break;
377 default: break;
378 }
379 break;
380 case 'h':
381 switch (ck) {
382 case ClassS:
383 case ClassI: s += "_f16"; break;
384 case ClassW: s += "_16"; break;
385 default: break;
386 }
387 break;
388 case 'f':
389 switch (ck) {
390 case ClassS:
391 case ClassI: s += "_f32"; break;
392 case ClassW: s += "_32"; break;
393 default: break;
394 }
395 break;
396 default:
397 throw "unhandled type!";
398 break;
Nate Begemanaf905ef2010-06-02 06:17:19 +0000399 }
Nate Begemana8979a02010-06-04 00:21:41 +0000400 if (ck == ClassB)
Nate Begeman92f98af2010-06-04 07:11:25 +0000401 s += "_v";
Nate Begemana8979a02010-06-04 00:21:41 +0000402
Nate Begemanaf905ef2010-06-02 06:17:19 +0000403 // Insert a 'q' before the first '_' character so that it ends up before
404 // _lane or _n on vector-scalar operations.
405 if (quad) {
406 size_t pos = s.find('_');
407 s = s.insert(pos, "q");
408 }
409 return s;
Nate Begeman22237772010-06-02 00:34:55 +0000410}
411
Nate Begemanaf905ef2010-06-02 06:17:19 +0000412// Generate the string "(argtype a, argtype b, ...)"
Nate Begeman22237772010-06-02 00:34:55 +0000413static std::string GenArgs(const std::string &proto, StringRef typestr) {
Nate Begemanaf905ef2010-06-02 06:17:19 +0000414 char arg = 'a';
415
416 std::string s;
417 s += "(";
418
419 for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) {
420 s += TypeString(proto[i], typestr);
421 s.push_back(' ');
422 s.push_back(arg);
423 if ((i + 1) < e)
424 s += ", ";
425 }
426
427 s += ")";
428 return s;
Nate Begeman22237772010-06-02 00:34:55 +0000429}
430
Nate Begeman7c8c8832010-06-02 21:53:00 +0000431// Generate the definition for this intrinsic, e.g. "a + b" for OpAdd.
432// If structTypes is true, the NEON types are structs of vector types rather
433// than vector types, and the call becomes "a.val + b.val"
434static std::string GenOpString(OpKind op, const std::string &proto,
Nate Begeman162d3ba2010-06-03 04:04:09 +0000435 StringRef typestr, bool structTypes = true) {
436 std::string s("return ");
437 std::string ts = TypeString(proto[0], typestr);
438 if (structTypes)
439 s += "(" + ts + "){";
440
Nate Begeman3861e742010-06-03 21:35:22 +0000441 std::string a, b, c;
442 if (proto.size() > 1)
443 a = (structTypes && proto[1] != 'l') ? "a.val" : "a";
444 b = structTypes ? "b.val" : "b";
445 c = structTypes ? "c.val" : "c";
Nate Begeman162d3ba2010-06-03 04:04:09 +0000446
447 switch(op) {
448 case OpAdd:
449 s += a + " + " + b;
450 break;
451 case OpSub:
452 s += a + " - " + b;
453 break;
454 case OpMul:
455 s += a + " * " + b;
456 break;
457 case OpMla:
458 s += a + " + ( " + b + " * " + c + " )";
459 break;
460 case OpMls:
461 s += a + " - ( " + b + " * " + c + " )";
462 break;
463 case OpEq:
464 s += "(__neon_" + ts + ")(" + a + " == " + b + ")";
465 break;
466 case OpGe:
467 s += "(__neon_" + ts + ")(" + a + " >= " + b + ")";
468 break;
469 case OpLe:
470 s += "(__neon_" + ts + ")(" + a + " <= " + b + ")";
471 break;
472 case OpGt:
473 s += "(__neon_" + ts + ")(" + a + " > " + b + ")";
474 break;
475 case OpLt:
476 s += "(__neon_" + ts + ")(" + a + " < " + b + ")";
477 break;
478 case OpNeg:
479 s += " -" + a;
480 break;
481 case OpNot:
482 s += " ~" + a;
483 break;
484 case OpAnd:
485 s += a + " & " + b;
486 break;
487 case OpOr:
488 s += a + " | " + b;
489 break;
490 case OpXor:
491 s += a + " ^ " + b;
492 break;
493 case OpAndNot:
494 s += a + " & ~" + b;
495 break;
496 case OpOrNot:
497 s += a + " | ~" + b;
498 break;
Nate Begeman3861e742010-06-03 21:35:22 +0000499 case OpCast:
500 s += "(__neon_" + ts + ")" + a;
501 break;
Nate Begeman162d3ba2010-06-03 04:04:09 +0000502 default:
503 throw "unknown OpKind!";
504 break;
505 }
506
507 if (structTypes)
508 s += "}";
509 s += ";";
510 return s;
Nate Begemane66aab52010-06-02 07:14:28 +0000511}
512
Nate Begeman7c8c8832010-06-02 21:53:00 +0000513// Generate the definition for this intrinsic, e.g. __builtin_neon_cls(a)
514// If structTypes is true, the NEON types are structs of vector types rather
515// than vector types, and the call becomes __builtin_neon_cls(a.val)
516static std::string GenBuiltin(const std::string &name, const std::string &proto,
Nate Begemana8979a02010-06-04 00:21:41 +0000517 StringRef typestr, ClassKind ck,
518 bool structTypes = true) {
Nate Begeman7c8c8832010-06-02 21:53:00 +0000519 char arg = 'a';
Nate Begeman162d3ba2010-06-03 04:04:09 +0000520 std::string s;
Nate Begeman7c8c8832010-06-02 21:53:00 +0000521
Nate Begeman162d3ba2010-06-03 04:04:09 +0000522 if (proto[0] != 'v') {
523 // FIXME: if return type is 2/3/4, emit unioning code.
524 s += "return ";
525 if (structTypes) {
526 s += "(";
527 s += TypeString(proto[0], typestr);
528 s += "){";
529 }
530 }
Nate Begeman7c8c8832010-06-02 21:53:00 +0000531
532 s += "__builtin_neon_";
Nate Begemana8979a02010-06-04 00:21:41 +0000533 s += MangleName(name, typestr, ck);
Nate Begeman7c8c8832010-06-02 21:53:00 +0000534 s += "(";
535
536 for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) {
537 s.push_back(arg);
Nate Begeman162d3ba2010-06-03 04:04:09 +0000538 if (structTypes && proto[i] != 's' && proto[i] != 'i' && proto[i] != 'l' &&
539 proto[i] != 'p' && proto[i] != 'c') {
Nate Begeman7c8c8832010-06-02 21:53:00 +0000540 s += ".val";
Nate Begeman162d3ba2010-06-03 04:04:09 +0000541 }
Nate Begeman7c8c8832010-06-02 21:53:00 +0000542 if ((i + 1) < e)
543 s += ", ";
544 }
545
546 s += ")";
Nate Begeman162d3ba2010-06-03 04:04:09 +0000547 if (proto[0] != 'v' && structTypes)
Nate Begeman7c8c8832010-06-02 21:53:00 +0000548 s += "}";
549 s += ";";
550 return s;
Nate Begemane66aab52010-06-02 07:14:28 +0000551}
552
Nate Begeman73cef3e2010-06-04 01:26:15 +0000553static std::string GenBuiltinDef(const std::string &name,
554 const std::string &proto,
555 StringRef typestr, ClassKind ck) {
556 std::string s("BUILTIN(__builtin_neon_");
Nate Begeman92f98af2010-06-04 07:11:25 +0000557
558 // If all types are the same size, bitcasting the args will take care
559 // of arg checking. The actual signedness etc. will be taken care of with
560 // special enums.
561 if (proto.find('s') == std::string::npos)
562 ck = ClassB;
563
Nate Begeman73cef3e2010-06-04 01:26:15 +0000564 s += MangleName(name, typestr, ck);
565 s += ", \"";
566
Nate Begeman92f98af2010-06-04 07:11:25 +0000567 for (unsigned i = 0, e = proto.size(); i != e; ++i)
568 s += BuiltinTypeString(proto[i], typestr);
Nate Begeman73cef3e2010-06-04 01:26:15 +0000569
570 s += "\", \"n\")";
571 return s;
572}
573
Nate Begeman5ddb0872010-05-28 01:08:32 +0000574void NeonEmitter::run(raw_ostream &OS) {
575 EmitSourceFileHeader("ARM NEON Header", OS);
576
577 // FIXME: emit license into file?
578
579 OS << "#ifndef __ARM_NEON_H\n";
580 OS << "#define __ARM_NEON_H\n\n";
581
582 OS << "#ifndef __ARM_NEON__\n";
583 OS << "#error \"NEON support not enabled\"\n";
584 OS << "#endif\n\n";
585
586 OS << "#include <stdint.h>\n\n";
Nate Begeman7c8c8832010-06-02 21:53:00 +0000587
588 // Emit NEON-specific scalar typedefs.
589 // FIXME: probably need to do something better for polynomial types.
Nate Begeman162d3ba2010-06-03 04:04:09 +0000590 // FIXME: is this the correct thing to do for float16?
Nate Begeman7c8c8832010-06-02 21:53:00 +0000591 OS << "typedef float float32_t;\n";
592 OS << "typedef uint8_t poly8_t;\n";
593 OS << "typedef uint16_t poly16_t;\n";
Nate Begeman162d3ba2010-06-03 04:04:09 +0000594 OS << "typedef uint16_t float16_t;\n";
Nate Begeman5ddb0872010-05-28 01:08:32 +0000595
Nate Begeman7c8c8832010-06-02 21:53:00 +0000596 // Emit Neon vector typedefs.
597 std::string TypedefTypes("cQcsQsiQilQlUcQUcUsQUsUiQUiUlQUlhQhfQfPcQPcPsQPs");
598 SmallVector<StringRef, 24> TDTypeVec;
599 ParseTypes(0, TypedefTypes, TDTypeVec);
600
601 // Emit vector typedefs.
602 for (unsigned i = 0, e = TDTypeVec.size(); i != e; ++i) {
603 bool dummy, quad = false;
604 (void) ClassifyType(TDTypeVec[i], quad, dummy, dummy);
605 OS << "typedef __attribute__(( __vector_size__(";
606 OS << (quad ? "16) )) " : "8) )) ");
607 OS << TypeString('s', TDTypeVec[i]);
608 OS << " __neon_";
Nate Begeman162d3ba2010-06-03 04:04:09 +0000609 OS << TypeString('d', TDTypeVec[i]) << ";\n";
Nate Begeman7c8c8832010-06-02 21:53:00 +0000610 }
611 OS << "\n";
612
613 // Emit struct typedefs.
614 for (unsigned vi = 1; vi != 5; ++vi) {
615 for (unsigned i = 0, e = TDTypeVec.size(); i != e; ++i) {
616 std::string ts = TypeString('d', TDTypeVec[i]);
617 std::string vs = (vi > 1) ? TypeString('0' + vi, TDTypeVec[i]) : ts;
618 OS << "typedef struct __" << vs << " {\n";
619 OS << " __neon_" << ts << " val";
620 if (vi > 1)
621 OS << "[" << utostr(vi) << "]";
622 OS << ";\n} " << vs << ";\n\n";
623 }
624 }
Nate Begeman5ddb0872010-05-28 01:08:32 +0000625
Nate Begeman7c8c8832010-06-02 21:53:00 +0000626 OS << "#define __ai static __attribute__((__always_inline__))\n\n";
627
Nate Begeman5ddb0872010-05-28 01:08:32 +0000628 std::vector<Record*> RV = Records.getAllDerivedDefinitions("Inst");
629
Nate Begeman22237772010-06-02 00:34:55 +0000630 // Unique the return+pattern types, and assign them.
Nate Begeman5ddb0872010-05-28 01:08:32 +0000631 for (unsigned i = 0, e = RV.size(); i != e; ++i) {
632 Record *R = RV[i];
Nate Begeman22237772010-06-02 00:34:55 +0000633 std::string name = LowercaseString(R->getName());
634 std::string Proto = R->getValueAsString("Prototype");
Nate Begeman5ddb0872010-05-28 01:08:32 +0000635 std::string Types = R->getValueAsString("Types");
Nate Begeman22237772010-06-02 00:34:55 +0000636
637 SmallVector<StringRef, 16> TypeVec;
638 ParseTypes(R, Types, TypeVec);
639
Nate Begeman162d3ba2010-06-03 04:04:09 +0000640 OpKind k = OpMap[R->getValueAsDef("Operand")->getName()];
Nate Begemane66aab52010-06-02 07:14:28 +0000641
Nate Begeman22237772010-06-02 00:34:55 +0000642 for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) {
643 assert(!Proto.empty() && "");
644
Nate Begeman7c8c8832010-06-02 21:53:00 +0000645 // static always inline + return type
646 OS << "__ai " << TypeString(Proto[0], TypeVec[ti]);
Nate Begeman22237772010-06-02 00:34:55 +0000647
Nate Begemane66aab52010-06-02 07:14:28 +0000648 // Function name with type suffix
Nate Begemana8979a02010-06-04 00:21:41 +0000649 OS << " " << MangleName(name, TypeVec[ti], ClassS);
Nate Begeman22237772010-06-02 00:34:55 +0000650
Nate Begemane66aab52010-06-02 07:14:28 +0000651 // Function arguments
652 OS << GenArgs(Proto, TypeVec[ti]);
Nate Begeman22237772010-06-02 00:34:55 +0000653
Nate Begemane66aab52010-06-02 07:14:28 +0000654 // Definition.
655 OS << " { ";
Nate Begeman22237772010-06-02 00:34:55 +0000656
Nate Begemana8979a02010-06-04 00:21:41 +0000657 if (k != OpNone) {
Nate Begeman162d3ba2010-06-03 04:04:09 +0000658 OS << GenOpString(k, Proto, TypeVec[ti]);
Nate Begemana8979a02010-06-04 00:21:41 +0000659 } else {
660 if (R->getSuperClasses().size() < 2)
661 throw TGError(R->getLoc(), "Builtin has no class kind");
662
663 ClassKind ck = ClassMap[R->getSuperClasses()[1]];
664
665 if (ck == ClassNone)
666 throw TGError(R->getLoc(), "Builtin has no class kind");
667 OS << GenBuiltin(name, Proto, TypeVec[ti], ck);
668 }
Nate Begemane66aab52010-06-02 07:14:28 +0000669
Nate Begeman7c8c8832010-06-02 21:53:00 +0000670 OS << " }\n";
Nate Begeman22237772010-06-02 00:34:55 +0000671 }
672 OS << "\n";
Nate Begeman5ddb0872010-05-28 01:08:32 +0000673 }
Nate Begeman73cef3e2010-06-04 01:26:15 +0000674 OS << "#undef __ai\n\n";
Nate Begeman7c8c8832010-06-02 21:53:00 +0000675 OS << "#endif /* __ARM_NEON_H */\n";
Nate Begeman5ddb0872010-05-28 01:08:32 +0000676}
Nate Begemana8979a02010-06-04 00:21:41 +0000677
678void NeonEmitter::runHeader(raw_ostream &OS) {
Nate Begeman73cef3e2010-06-04 01:26:15 +0000679 std::vector<Record*> RV = Records.getAllDerivedDefinitions("Inst");
680
681 StringMap<OpKind> EmittedMap;
682
683 for (unsigned i = 0, e = RV.size(); i != e; ++i) {
684 Record *R = RV[i];
685
686 OpKind k = OpMap[R->getValueAsDef("Operand")->getName()];
687 if (k != OpNone)
688 continue;
689
690 std::string name = LowercaseString(R->getName());
691 std::string Proto = R->getValueAsString("Prototype");
692 std::string Types = R->getValueAsString("Types");
693
694 SmallVector<StringRef, 16> TypeVec;
695 ParseTypes(R, Types, TypeVec);
696
697 if (R->getSuperClasses().size() < 2)
698 throw TGError(R->getLoc(), "Builtin has no class kind");
699
700 ClassKind ck = ClassMap[R->getSuperClasses()[1]];
701
702 for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) {
703 std::string bd = GenBuiltinDef(name, Proto, TypeVec[ti], ck);
704 if (EmittedMap.count(bd))
705 continue;
706
707 EmittedMap[bd] = OpNone;
708 OS << bd << "\n";
709 }
710 }
Nate Begemana8979a02010-06-04 00:21:41 +0000711}