blob: 9647666935ce6c7b4082c989b04376a24dbcb460 [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
Nate Begeman9e584b32010-06-04 22:53:30 +0000174 if (ret)
175 s += "__neon_";
176
Nate Begeman22237772010-06-02 00:34:55 +0000177 if (usgn)
178 s.push_back('u');
179
180 switch (type) {
181 case 'c':
182 s += poly ? "poly8" : "int8";
183 if (scal)
184 break;
185 s += quad ? "x16" : "x8";
186 break;
187 case 's':
188 s += poly ? "poly16" : "int16";
189 if (scal)
190 break;
191 s += quad ? "x8" : "x4";
192 break;
193 case 'i':
194 s += "int32";
195 if (scal)
196 break;
197 s += quad ? "x4" : "x2";
198 break;
199 case 'l':
200 s += "int64";
201 if (scal)
202 break;
203 s += quad ? "x2" : "x1";
204 break;
205 case 'h':
206 s += "float16";
207 if (scal)
208 break;
209 s += quad ? "x8" : "x4";
210 break;
211 case 'f':
212 s += "float32";
213 if (scal)
214 break;
215 s += quad ? "x4" : "x2";
216 break;
Nate Begeman22237772010-06-02 00:34:55 +0000217 default:
218 throw "unhandled type!";
219 break;
220 }
221
222 if (mod == '2')
223 s += "x2";
224 if (mod == '3')
225 s += "x3";
226 if (mod == '4')
227 s += "x4";
228
229 // Append _t, finishing the type string typedef type.
230 s += "_t";
231
232 if (cnst)
233 s += " const";
234
235 if (pntr)
236 s += " *";
237
238 return s.str();
239}
240
Nate Begeman7c21f742010-06-04 21:36:00 +0000241static std::string BuiltinTypeString(const char mod, StringRef typestr,
242 ClassKind ck, bool ret) {
Nate Begeman92f98af2010-06-04 07:11:25 +0000243 bool quad = false;
244 bool poly = false;
245 bool usgn = false;
246 bool scal = false;
247 bool cnst = false;
248 bool pntr = false;
249
250 if (mod == 'v')
251 return "v";
252 if (mod == 'i')
253 return "i";
254
255 // base type to get the type string for.
256 char type = ClassifyType(typestr, quad, poly, usgn);
257
258 // Based on the modifying character, change the type and width if necessary.
259 switch (mod) {
260 case 't':
261 if (poly) {
262 poly = false;
263 usgn = true;
264 }
265 break;
266 case 'x':
267 usgn = true;
268 poly = false;
269 if (type == 'f')
270 type = 'i';
271 break;
272 case 'f':
273 type = 'f';
274 usgn = false;
275 break;
276 case 'w':
277 type = Widen(type);
278 quad = true;
279 break;
280 case 'n':
281 type = Widen(type);
282 break;
283 case 'l':
284 type = 'l';
285 scal = true;
286 usgn = true;
287 break;
288 case 's':
289 scal = true;
290 break;
291 case 'k':
292 quad = true;
293 break;
294 case 'c':
295 cnst = true;
296 case 'p':
297 type = 'v';
298 usgn = false;
299 poly = false;
300 pntr = true;
301 scal = true;
302 break;
303 case 'h':
304 type = Narrow(type);
305 break;
306 case 'e':
307 type = Narrow(type);
308 usgn = true;
309 break;
310 default:
311 break;
312 }
313 if (type == 'h') {
314 type = 's';
315 usgn = true;
316 }
Nate Begeman7c21f742010-06-04 21:36:00 +0000317 usgn = usgn | poly | ((ck == ClassI || ck == ClassW) && scal && type != 'f');
Nate Begeman92f98af2010-06-04 07:11:25 +0000318
319 if (scal) {
320 SmallString<128> s;
321
322 if (usgn)
323 s.push_back('U');
Nate Begeman7c21f742010-06-04 21:36:00 +0000324
325 if (type == 'l')
326 s += "LLi";
327 else
328 s.push_back(type);
329
Nate Begeman92f98af2010-06-04 07:11:25 +0000330 if (cnst)
331 s.push_back('C');
332 if (pntr)
333 s.push_back('*');
334 return s.str();
335 }
Nate Begeman7c21f742010-06-04 21:36:00 +0000336
337 // Since the return value must be one type, return a vector type of the
338 // appropriate width which we will bitcast.
339 if (ret) {
340 if (mod == '2')
341 return quad ? "V32c" : "V16c";
342 if (mod == '3')
343 return quad ? "V48c" : "V24c";
344 if (mod == '4')
345 return quad ? "V64c" : "V32c";
346
347 return quad ? "V16c" : "V8c";
348 }
349
350 // Non-return array types are passed as individual vectors.
Nate Begeman92f98af2010-06-04 07:11:25 +0000351 if (mod == '2')
352 return quad ? "V16cV16c" : "V8cV8c";
353 if (mod == '3')
354 return quad ? "V16cV16cV16c" : "V8cV8cV8c";
355 if (mod == '4')
356 return quad ? "V16cV16cV16cV16c" : "V8cV8cV8cV8c";
357
358 return quad ? "V16c" : "V8c";
359}
360
Nate Begeman22237772010-06-02 00:34:55 +0000361// Turn "vst2_lane" into "vst2q_lane_f32", etc.
Nate Begemana8979a02010-06-04 00:21:41 +0000362static std::string MangleName(const std::string &name, StringRef typestr,
363 ClassKind ck) {
Nate Begemanaf905ef2010-06-02 06:17:19 +0000364 bool quad = false;
365 bool poly = false;
366 bool usgn = false;
367 char type = ClassifyType(typestr, quad, poly, usgn);
368
369 std::string s = name;
370
371 switch (type) {
Nate Begemana8979a02010-06-04 00:21:41 +0000372 case 'c':
373 switch (ck) {
374 case ClassS: s += poly ? "_p8" : usgn ? "_u8" : "_s8"; break;
375 case ClassI: s += "_i8"; break;
376 case ClassW: s += "_8"; break;
377 default: break;
378 }
379 break;
380 case 's':
381 switch (ck) {
382 case ClassS: s += poly ? "_p16" : usgn ? "_u16" : "_s16"; break;
383 case ClassI: s += "_i16"; break;
384 case ClassW: s += "_16"; break;
385 default: break;
386 }
387 break;
388 case 'i':
389 switch (ck) {
390 case ClassS: s += usgn ? "_u32" : "_s32"; break;
391 case ClassI: s += "_i32"; break;
392 case ClassW: s += "_32"; break;
393 default: break;
394 }
395 break;
396 case 'l':
397 switch (ck) {
398 case ClassS: s += usgn ? "_u64" : "_s64"; break;
399 case ClassI: s += "_i64"; break;
400 case ClassW: s += "_64"; break;
401 default: break;
402 }
403 break;
404 case 'h':
405 switch (ck) {
406 case ClassS:
407 case ClassI: s += "_f16"; break;
408 case ClassW: s += "_16"; break;
409 default: break;
410 }
411 break;
412 case 'f':
413 switch (ck) {
414 case ClassS:
415 case ClassI: s += "_f32"; break;
416 case ClassW: s += "_32"; break;
417 default: break;
418 }
419 break;
420 default:
421 throw "unhandled type!";
422 break;
Nate Begemanaf905ef2010-06-02 06:17:19 +0000423 }
Nate Begemana8979a02010-06-04 00:21:41 +0000424 if (ck == ClassB)
Nate Begeman92f98af2010-06-04 07:11:25 +0000425 s += "_v";
Nate Begemana8979a02010-06-04 00:21:41 +0000426
Nate Begemanaf905ef2010-06-02 06:17:19 +0000427 // Insert a 'q' before the first '_' character so that it ends up before
428 // _lane or _n on vector-scalar operations.
429 if (quad) {
430 size_t pos = s.find('_');
431 s = s.insert(pos, "q");
432 }
433 return s;
Nate Begeman22237772010-06-02 00:34:55 +0000434}
435
Nate Begemanaf905ef2010-06-02 06:17:19 +0000436// Generate the string "(argtype a, argtype b, ...)"
Nate Begeman22237772010-06-02 00:34:55 +0000437static std::string GenArgs(const std::string &proto, StringRef typestr) {
Nate Begemanaf905ef2010-06-02 06:17:19 +0000438 char arg = 'a';
439
440 std::string s;
441 s += "(";
442
443 for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) {
444 s += TypeString(proto[i], typestr);
445 s.push_back(' ');
446 s.push_back(arg);
447 if ((i + 1) < e)
448 s += ", ";
449 }
450
451 s += ")";
452 return s;
Nate Begeman22237772010-06-02 00:34:55 +0000453}
454
Nate Begeman7c8c8832010-06-02 21:53:00 +0000455// Generate the definition for this intrinsic, e.g. "a + b" for OpAdd.
456// If structTypes is true, the NEON types are structs of vector types rather
457// than vector types, and the call becomes "a.val + b.val"
458static std::string GenOpString(OpKind op, const std::string &proto,
Nate Begeman162d3ba2010-06-03 04:04:09 +0000459 StringRef typestr, bool structTypes = true) {
460 std::string s("return ");
Nate Begeman9e584b32010-06-04 22:53:30 +0000461 std::string ts = TypeString(proto[0], typestr);
Nate Begeman162d3ba2010-06-03 04:04:09 +0000462 if (structTypes)
463 s += "(" + ts + "){";
464
Nate Begeman3861e742010-06-03 21:35:22 +0000465 std::string a, b, c;
466 if (proto.size() > 1)
467 a = (structTypes && proto[1] != 'l') ? "a.val" : "a";
468 b = structTypes ? "b.val" : "b";
469 c = structTypes ? "c.val" : "c";
Nate Begeman162d3ba2010-06-03 04:04:09 +0000470
471 switch(op) {
472 case OpAdd:
473 s += a + " + " + b;
474 break;
475 case OpSub:
476 s += a + " - " + b;
477 break;
478 case OpMul:
479 s += a + " * " + b;
480 break;
481 case OpMla:
482 s += a + " + ( " + b + " * " + c + " )";
483 break;
484 case OpMls:
485 s += a + " - ( " + b + " * " + c + " )";
486 break;
487 case OpEq:
488 s += "(__neon_" + ts + ")(" + a + " == " + b + ")";
489 break;
490 case OpGe:
491 s += "(__neon_" + ts + ")(" + a + " >= " + b + ")";
492 break;
493 case OpLe:
494 s += "(__neon_" + ts + ")(" + a + " <= " + b + ")";
495 break;
496 case OpGt:
497 s += "(__neon_" + ts + ")(" + a + " > " + b + ")";
498 break;
499 case OpLt:
500 s += "(__neon_" + ts + ")(" + a + " < " + b + ")";
501 break;
502 case OpNeg:
503 s += " -" + a;
504 break;
505 case OpNot:
506 s += " ~" + a;
507 break;
508 case OpAnd:
509 s += a + " & " + b;
510 break;
511 case OpOr:
512 s += a + " | " + b;
513 break;
514 case OpXor:
515 s += a + " ^ " + b;
516 break;
517 case OpAndNot:
518 s += a + " & ~" + b;
519 break;
520 case OpOrNot:
521 s += a + " | ~" + b;
522 break;
Nate Begeman3861e742010-06-03 21:35:22 +0000523 case OpCast:
524 s += "(__neon_" + ts + ")" + a;
525 break;
Nate Begeman162d3ba2010-06-03 04:04:09 +0000526 default:
527 throw "unknown OpKind!";
528 break;
529 }
530
531 if (structTypes)
532 s += "}";
533 s += ";";
534 return s;
Nate Begemane66aab52010-06-02 07:14:28 +0000535}
536
Nate Begeman7c8c8832010-06-02 21:53:00 +0000537// Generate the definition for this intrinsic, e.g. __builtin_neon_cls(a)
538// If structTypes is true, the NEON types are structs of vector types rather
539// than vector types, and the call becomes __builtin_neon_cls(a.val)
540static std::string GenBuiltin(const std::string &name, const std::string &proto,
Nate Begemana8979a02010-06-04 00:21:41 +0000541 StringRef typestr, ClassKind ck,
542 bool structTypes = true) {
Nate Begeman7c8c8832010-06-02 21:53:00 +0000543 char arg = 'a';
Nate Begeman162d3ba2010-06-03 04:04:09 +0000544 std::string s;
Nate Begeman9e584b32010-06-04 22:53:30 +0000545
546 bool unioning = (proto[0] == '2' || proto[0] == '3' || proto[0] == '4');
547
548 // If all types are the same size, bitcasting the args will take care
549 // of arg checking. The actual signedness etc. will be taken care of with
550 // special enums.
551 if (proto.find('s') == std::string::npos)
552 ck = ClassB;
Nate Begeman7c21f742010-06-04 21:36:00 +0000553
Nate Begeman162d3ba2010-06-03 04:04:09 +0000554 if (proto[0] != 'v') {
Nate Begeman9e584b32010-06-04 22:53:30 +0000555 if (unioning) {
556 s += "union { ";
557 s += TypeString(proto[0], typestr, true) + " val; ";
558 s += TypeString(proto[0], typestr, false) + " s; ";
559 s += "} r;";
560 } else {
561 s += TypeString(proto[0], typestr);
Nate Begeman162d3ba2010-06-03 04:04:09 +0000562 }
Nate Begeman9e584b32010-06-04 22:53:30 +0000563
564 s += " r; r";
565 if (structTypes && proto[0] != 's' && proto[0] != 'i' && proto[0] != 'l')
566 s += ".val";
567
568 s += " = ";
Nate Begeman162d3ba2010-06-03 04:04:09 +0000569 }
Nate Begeman7c8c8832010-06-02 21:53:00 +0000570
571 s += "__builtin_neon_";
Nate Begemana8979a02010-06-04 00:21:41 +0000572 s += MangleName(name, typestr, ck);
Nate Begeman7c8c8832010-06-02 21:53:00 +0000573 s += "(";
574
575 for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) {
Nate Begeman9e584b32010-06-04 22:53:30 +0000576 // Handle multiple-vector values specially, emitting each subvector as an
577 // argument to the __builtin.
578 if (structTypes && (proto[i] == '2' || proto[i] == '3' || proto[i] == '4')){
579 for (unsigned vi = 0, ve = proto[i] - '0'; vi != ve; ++vi) {
580 s.push_back(arg);
581 s += ".val[" + utostr(vi) + "]";
582 if ((vi + 1) < ve)
583 s += ", ";
584 }
585 if ((i + 1) < e)
586 s += ", ";
587
588 continue;
589 }
590
Nate Begeman7c8c8832010-06-02 21:53:00 +0000591 s.push_back(arg);
Nate Begeman9e584b32010-06-04 22:53:30 +0000592
Nate Begeman162d3ba2010-06-03 04:04:09 +0000593 if (structTypes && proto[i] != 's' && proto[i] != 'i' && proto[i] != 'l' &&
594 proto[i] != 'p' && proto[i] != 'c') {
Nate Begeman7c8c8832010-06-02 21:53:00 +0000595 s += ".val";
Nate Begeman162d3ba2010-06-03 04:04:09 +0000596 }
Nate Begeman7c8c8832010-06-02 21:53:00 +0000597 if ((i + 1) < e)
598 s += ", ";
599 }
600
Nate Begeman9e584b32010-06-04 22:53:30 +0000601 // Extra constant integer to hold type class enum for this function, e.g. s8
602 // FIXME: emit actual type num.
603 if (ck == ClassB)
604 s += ", 0";
605
606 s += ");";
607
608 if (proto[0] != 'v') {
609 if (unioning)
610 s += " return r.s;";
611 else
612 s += " return r;";
613 }
Nate Begeman7c8c8832010-06-02 21:53:00 +0000614 return s;
Nate Begemane66aab52010-06-02 07:14:28 +0000615}
616
Nate Begeman73cef3e2010-06-04 01:26:15 +0000617static std::string GenBuiltinDef(const std::string &name,
618 const std::string &proto,
619 StringRef typestr, ClassKind ck) {
620 std::string s("BUILTIN(__builtin_neon_");
Nate Begeman92f98af2010-06-04 07:11:25 +0000621
622 // If all types are the same size, bitcasting the args will take care
623 // of arg checking. The actual signedness etc. will be taken care of with
624 // special enums.
625 if (proto.find('s') == std::string::npos)
626 ck = ClassB;
627
Nate Begeman73cef3e2010-06-04 01:26:15 +0000628 s += MangleName(name, typestr, ck);
629 s += ", \"";
630
Nate Begeman92f98af2010-06-04 07:11:25 +0000631 for (unsigned i = 0, e = proto.size(); i != e; ++i)
Nate Begeman7c21f742010-06-04 21:36:00 +0000632 s += BuiltinTypeString(proto[i], typestr, ck, i == 0);
633
634 // Extra constant integer to hold type class enum for this function, e.g. s8
635 if (ck == ClassB)
636 s += "i";
Nate Begeman73cef3e2010-06-04 01:26:15 +0000637
638 s += "\", \"n\")";
639 return s;
640}
641
Nate Begeman5ddb0872010-05-28 01:08:32 +0000642void NeonEmitter::run(raw_ostream &OS) {
643 EmitSourceFileHeader("ARM NEON Header", OS);
644
645 // FIXME: emit license into file?
646
647 OS << "#ifndef __ARM_NEON_H\n";
648 OS << "#define __ARM_NEON_H\n\n";
649
650 OS << "#ifndef __ARM_NEON__\n";
651 OS << "#error \"NEON support not enabled\"\n";
652 OS << "#endif\n\n";
653
654 OS << "#include <stdint.h>\n\n";
Nate Begeman7c8c8832010-06-02 21:53:00 +0000655
656 // Emit NEON-specific scalar typedefs.
657 // FIXME: probably need to do something better for polynomial types.
Nate Begeman162d3ba2010-06-03 04:04:09 +0000658 // FIXME: is this the correct thing to do for float16?
Nate Begeman7c8c8832010-06-02 21:53:00 +0000659 OS << "typedef float float32_t;\n";
660 OS << "typedef uint8_t poly8_t;\n";
661 OS << "typedef uint16_t poly16_t;\n";
Nate Begeman162d3ba2010-06-03 04:04:09 +0000662 OS << "typedef uint16_t float16_t;\n";
Nate Begeman9e584b32010-06-04 22:53:30 +0000663
Nate Begeman7c8c8832010-06-02 21:53:00 +0000664 // Emit Neon vector typedefs.
665 std::string TypedefTypes("cQcsQsiQilQlUcQUcUsQUsUiQUiUlQUlhQhfQfPcQPcPsQPs");
666 SmallVector<StringRef, 24> TDTypeVec;
667 ParseTypes(0, TypedefTypes, TDTypeVec);
668
669 // Emit vector typedefs.
Nate Begeman9e584b32010-06-04 22:53:30 +0000670 for (unsigned v = 1; v != 5; ++v) {
671 for (unsigned i = 0, e = TDTypeVec.size(); i != e; ++i) {
672 bool dummy, quad = false;
673 (void) ClassifyType(TDTypeVec[i], quad, dummy, dummy);
674 OS << "typedef __attribute__(( __vector_size__(";
675
676 OS << utostr(8*v*(quad ? 2 : 1)) << ") )) ";
677 if (!quad)
678 OS << " ";
679
680 OS << TypeString('s', TDTypeVec[i]);
681 OS << " __neon_";
682
683 char t = (v == 1) ? 'd' : '0' + v;
684 OS << TypeString(t, TDTypeVec[i]) << ";\n";
685 }
Nate Begeman7c8c8832010-06-02 21:53:00 +0000686 }
687 OS << "\n";
688
689 // Emit struct typedefs.
690 for (unsigned vi = 1; vi != 5; ++vi) {
691 for (unsigned i = 0, e = TDTypeVec.size(); i != e; ++i) {
692 std::string ts = TypeString('d', TDTypeVec[i]);
693 std::string vs = (vi > 1) ? TypeString('0' + vi, TDTypeVec[i]) : ts;
694 OS << "typedef struct __" << vs << " {\n";
695 OS << " __neon_" << ts << " val";
696 if (vi > 1)
697 OS << "[" << utostr(vi) << "]";
698 OS << ";\n} " << vs << ";\n\n";
699 }
700 }
Nate Begeman5ddb0872010-05-28 01:08:32 +0000701
Nate Begeman7c8c8832010-06-02 21:53:00 +0000702 OS << "#define __ai static __attribute__((__always_inline__))\n\n";
703
Nate Begeman5ddb0872010-05-28 01:08:32 +0000704 std::vector<Record*> RV = Records.getAllDerivedDefinitions("Inst");
705
Nate Begeman22237772010-06-02 00:34:55 +0000706 // Unique the return+pattern types, and assign them.
Nate Begeman5ddb0872010-05-28 01:08:32 +0000707 for (unsigned i = 0, e = RV.size(); i != e; ++i) {
708 Record *R = RV[i];
Nate Begeman22237772010-06-02 00:34:55 +0000709 std::string name = LowercaseString(R->getName());
710 std::string Proto = R->getValueAsString("Prototype");
Nate Begeman5ddb0872010-05-28 01:08:32 +0000711 std::string Types = R->getValueAsString("Types");
Nate Begeman22237772010-06-02 00:34:55 +0000712
713 SmallVector<StringRef, 16> TypeVec;
714 ParseTypes(R, Types, TypeVec);
715
Nate Begeman162d3ba2010-06-03 04:04:09 +0000716 OpKind k = OpMap[R->getValueAsDef("Operand")->getName()];
Nate Begemane66aab52010-06-02 07:14:28 +0000717
Nate Begeman22237772010-06-02 00:34:55 +0000718 for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) {
719 assert(!Proto.empty() && "");
720
Nate Begeman7c8c8832010-06-02 21:53:00 +0000721 // static always inline + return type
722 OS << "__ai " << TypeString(Proto[0], TypeVec[ti]);
Nate Begeman22237772010-06-02 00:34:55 +0000723
Nate Begemane66aab52010-06-02 07:14:28 +0000724 // Function name with type suffix
Nate Begemana8979a02010-06-04 00:21:41 +0000725 OS << " " << MangleName(name, TypeVec[ti], ClassS);
Nate Begeman22237772010-06-02 00:34:55 +0000726
Nate Begemane66aab52010-06-02 07:14:28 +0000727 // Function arguments
728 OS << GenArgs(Proto, TypeVec[ti]);
Nate Begeman22237772010-06-02 00:34:55 +0000729
Nate Begemane66aab52010-06-02 07:14:28 +0000730 // Definition.
731 OS << " { ";
Nate Begeman22237772010-06-02 00:34:55 +0000732
Nate Begemana8979a02010-06-04 00:21:41 +0000733 if (k != OpNone) {
Nate Begeman162d3ba2010-06-03 04:04:09 +0000734 OS << GenOpString(k, Proto, TypeVec[ti]);
Nate Begemana8979a02010-06-04 00:21:41 +0000735 } else {
736 if (R->getSuperClasses().size() < 2)
737 throw TGError(R->getLoc(), "Builtin has no class kind");
738
739 ClassKind ck = ClassMap[R->getSuperClasses()[1]];
740
741 if (ck == ClassNone)
742 throw TGError(R->getLoc(), "Builtin has no class kind");
743 OS << GenBuiltin(name, Proto, TypeVec[ti], ck);
744 }
Nate Begemane66aab52010-06-02 07:14:28 +0000745
Nate Begeman7c8c8832010-06-02 21:53:00 +0000746 OS << " }\n";
Nate Begeman22237772010-06-02 00:34:55 +0000747 }
748 OS << "\n";
Nate Begeman5ddb0872010-05-28 01:08:32 +0000749 }
Nate Begeman73cef3e2010-06-04 01:26:15 +0000750 OS << "#undef __ai\n\n";
Nate Begeman7c8c8832010-06-02 21:53:00 +0000751 OS << "#endif /* __ARM_NEON_H */\n";
Nate Begeman5ddb0872010-05-28 01:08:32 +0000752}
Nate Begemana8979a02010-06-04 00:21:41 +0000753
754void NeonEmitter::runHeader(raw_ostream &OS) {
Nate Begeman73cef3e2010-06-04 01:26:15 +0000755 std::vector<Record*> RV = Records.getAllDerivedDefinitions("Inst");
756
757 StringMap<OpKind> EmittedMap;
758
759 for (unsigned i = 0, e = RV.size(); i != e; ++i) {
760 Record *R = RV[i];
761
762 OpKind k = OpMap[R->getValueAsDef("Operand")->getName()];
763 if (k != OpNone)
764 continue;
765
766 std::string name = LowercaseString(R->getName());
767 std::string Proto = R->getValueAsString("Prototype");
768 std::string Types = R->getValueAsString("Types");
769
770 SmallVector<StringRef, 16> TypeVec;
771 ParseTypes(R, Types, TypeVec);
772
773 if (R->getSuperClasses().size() < 2)
774 throw TGError(R->getLoc(), "Builtin has no class kind");
775
776 ClassKind ck = ClassMap[R->getSuperClasses()[1]];
777
778 for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) {
779 std::string bd = GenBuiltinDef(name, Proto, TypeVec[ti], ck);
780 if (EmittedMap.count(bd))
781 continue;
782
783 EmittedMap[bd] = OpNone;
784 OS << bd << "\n";
785 }
786 }
Nate Begemana8979a02010-06-04 00:21:41 +0000787}