blob: 2697348c0551344e78b428c15dbed3c50c554111 [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 Begemanb0a4e452010-06-07 16:00:37 +0000103static char ModType(const char mod, char type, bool &quad, bool &poly,
104 bool &usgn, bool &scal, bool &cnst, bool &pntr) {
Nate Begeman22237772010-06-02 00:34:55 +0000105 switch (mod) {
Nate Begeman22237772010-06-02 00:34:55 +0000106 case 't':
107 if (poly) {
108 poly = false;
109 usgn = true;
110 }
111 break;
112 case 'x':
113 usgn = true;
Nate Begeman162d3ba2010-06-03 04:04:09 +0000114 poly = false;
Nate Begeman22237772010-06-02 00:34:55 +0000115 if (type == 'f')
116 type = 'i';
117 break;
118 case 'f':
119 type = 'f';
Nate Begeman162d3ba2010-06-03 04:04:09 +0000120 usgn = false;
Nate Begeman22237772010-06-02 00:34:55 +0000121 break;
122 case 'w':
123 type = Widen(type);
124 quad = true;
125 break;
126 case 'n':
127 type = Widen(type);
128 break;
Nate Begeman22237772010-06-02 00:34:55 +0000129 case 'l':
130 type = 'l';
131 scal = true;
132 usgn = true;
133 break;
134 case 's':
135 scal = true;
136 break;
137 case 'k':
138 quad = true;
139 break;
140 case 'c':
141 cnst = true;
142 case 'p':
Nate Begemanb0a4e452010-06-07 16:00:37 +0000143 usgn = false;
144 poly = false;
Nate Begeman22237772010-06-02 00:34:55 +0000145 pntr = true;
146 scal = true;
147 break;
Nate Begeman3861e742010-06-03 21:35:22 +0000148 case 'h':
149 type = Narrow(type);
150 break;
151 case 'e':
152 type = Narrow(type);
153 usgn = true;
154 break;
Nate Begeman22237772010-06-02 00:34:55 +0000155 default:
156 break;
157 }
Nate Begemanb0a4e452010-06-07 16:00:37 +0000158 return type;
159}
160
161static std::string TypeString(const char mod, StringRef typestr,
162 bool ret = false) {
163 bool quad = false;
164 bool poly = false;
165 bool usgn = false;
166 bool scal = false;
167 bool cnst = false;
168 bool pntr = false;
169
170 if (mod == 'v')
171 return "void";
172 if (mod == 'i')
173 return "int";
174
175 // base type to get the type string for.
176 char type = ClassifyType(typestr, quad, poly, usgn);
177
178 // Based on the modifying character, change the type and width if necessary.
179 type = ModType(mod, type, quad, poly, usgn, scal, cnst, pntr);
Nate Begeman22237772010-06-02 00:34:55 +0000180
181 SmallString<128> s;
182
Nate Begeman9e584b32010-06-04 22:53:30 +0000183 if (ret)
184 s += "__neon_";
185
Nate Begeman22237772010-06-02 00:34:55 +0000186 if (usgn)
187 s.push_back('u');
188
189 switch (type) {
190 case 'c':
191 s += poly ? "poly8" : "int8";
192 if (scal)
193 break;
194 s += quad ? "x16" : "x8";
195 break;
196 case 's':
197 s += poly ? "poly16" : "int16";
198 if (scal)
199 break;
200 s += quad ? "x8" : "x4";
201 break;
202 case 'i':
203 s += "int32";
204 if (scal)
205 break;
206 s += quad ? "x4" : "x2";
207 break;
208 case 'l':
209 s += "int64";
210 if (scal)
211 break;
212 s += quad ? "x2" : "x1";
213 break;
214 case 'h':
215 s += "float16";
216 if (scal)
217 break;
218 s += quad ? "x8" : "x4";
219 break;
220 case 'f':
221 s += "float32";
222 if (scal)
223 break;
224 s += quad ? "x4" : "x2";
225 break;
Nate Begeman22237772010-06-02 00:34:55 +0000226 default:
227 throw "unhandled type!";
228 break;
229 }
230
231 if (mod == '2')
232 s += "x2";
233 if (mod == '3')
234 s += "x3";
235 if (mod == '4')
236 s += "x4";
237
238 // Append _t, finishing the type string typedef type.
239 s += "_t";
240
241 if (cnst)
242 s += " const";
243
244 if (pntr)
245 s += " *";
246
247 return s.str();
248}
249
Nate Begeman7c21f742010-06-04 21:36:00 +0000250static std::string BuiltinTypeString(const char mod, StringRef typestr,
251 ClassKind ck, bool ret) {
Nate Begeman92f98af2010-06-04 07:11:25 +0000252 bool quad = false;
253 bool poly = false;
254 bool usgn = false;
255 bool scal = false;
256 bool cnst = false;
257 bool pntr = false;
258
259 if (mod == 'v')
260 return "v";
261 if (mod == 'i')
262 return "i";
263
264 // base type to get the type string for.
265 char type = ClassifyType(typestr, quad, poly, usgn);
266
267 // Based on the modifying character, change the type and width if necessary.
Nate Begemanb0a4e452010-06-07 16:00:37 +0000268 type = ModType(mod, type, quad, poly, usgn, scal, cnst, pntr);
269
270 if (pntr)
271 type = 'v';
272
Nate Begeman92f98af2010-06-04 07:11:25 +0000273 if (type == 'h') {
274 type = 's';
275 usgn = true;
276 }
Nate Begeman7c21f742010-06-04 21:36:00 +0000277 usgn = usgn | poly | ((ck == ClassI || ck == ClassW) && scal && type != 'f');
Nate Begeman92f98af2010-06-04 07:11:25 +0000278
279 if (scal) {
280 SmallString<128> s;
281
282 if (usgn)
283 s.push_back('U');
Nate Begeman7c21f742010-06-04 21:36:00 +0000284
285 if (type == 'l')
286 s += "LLi";
287 else
288 s.push_back(type);
289
Nate Begeman92f98af2010-06-04 07:11:25 +0000290 if (cnst)
291 s.push_back('C');
292 if (pntr)
293 s.push_back('*');
294 return s.str();
295 }
Nate Begeman7c21f742010-06-04 21:36:00 +0000296
297 // Since the return value must be one type, return a vector type of the
298 // appropriate width which we will bitcast.
299 if (ret) {
300 if (mod == '2')
301 return quad ? "V32c" : "V16c";
302 if (mod == '3')
303 return quad ? "V48c" : "V24c";
304 if (mod == '4')
305 return quad ? "V64c" : "V32c";
306
307 return quad ? "V16c" : "V8c";
308 }
309
310 // Non-return array types are passed as individual vectors.
Nate Begeman92f98af2010-06-04 07:11:25 +0000311 if (mod == '2')
312 return quad ? "V16cV16c" : "V8cV8c";
313 if (mod == '3')
314 return quad ? "V16cV16cV16c" : "V8cV8cV8c";
315 if (mod == '4')
316 return quad ? "V16cV16cV16cV16c" : "V8cV8cV8cV8c";
317
318 return quad ? "V16c" : "V8c";
319}
320
Nate Begeman22237772010-06-02 00:34:55 +0000321// Turn "vst2_lane" into "vst2q_lane_f32", etc.
Nate Begemana8979a02010-06-04 00:21:41 +0000322static std::string MangleName(const std::string &name, StringRef typestr,
323 ClassKind ck) {
Nate Begemanaf905ef2010-06-02 06:17:19 +0000324 bool quad = false;
325 bool poly = false;
326 bool usgn = false;
327 char type = ClassifyType(typestr, quad, poly, usgn);
328
329 std::string s = name;
330
331 switch (type) {
Nate Begemana8979a02010-06-04 00:21:41 +0000332 case 'c':
333 switch (ck) {
334 case ClassS: s += poly ? "_p8" : usgn ? "_u8" : "_s8"; break;
335 case ClassI: s += "_i8"; break;
336 case ClassW: s += "_8"; break;
337 default: break;
338 }
339 break;
340 case 's':
341 switch (ck) {
342 case ClassS: s += poly ? "_p16" : usgn ? "_u16" : "_s16"; break;
343 case ClassI: s += "_i16"; break;
344 case ClassW: s += "_16"; break;
345 default: break;
346 }
347 break;
348 case 'i':
349 switch (ck) {
350 case ClassS: s += usgn ? "_u32" : "_s32"; break;
351 case ClassI: s += "_i32"; break;
352 case ClassW: s += "_32"; break;
353 default: break;
354 }
355 break;
356 case 'l':
357 switch (ck) {
358 case ClassS: s += usgn ? "_u64" : "_s64"; break;
359 case ClassI: s += "_i64"; break;
360 case ClassW: s += "_64"; break;
361 default: break;
362 }
363 break;
364 case 'h':
365 switch (ck) {
366 case ClassS:
367 case ClassI: s += "_f16"; break;
368 case ClassW: s += "_16"; break;
369 default: break;
370 }
371 break;
372 case 'f':
373 switch (ck) {
374 case ClassS:
375 case ClassI: s += "_f32"; break;
376 case ClassW: s += "_32"; break;
377 default: break;
378 }
379 break;
380 default:
381 throw "unhandled type!";
382 break;
Nate Begemanaf905ef2010-06-02 06:17:19 +0000383 }
Nate Begemana8979a02010-06-04 00:21:41 +0000384 if (ck == ClassB)
Nate Begeman92f98af2010-06-04 07:11:25 +0000385 s += "_v";
Nate Begemana8979a02010-06-04 00:21:41 +0000386
Nate Begemanaf905ef2010-06-02 06:17:19 +0000387 // Insert a 'q' before the first '_' character so that it ends up before
388 // _lane or _n on vector-scalar operations.
389 if (quad) {
390 size_t pos = s.find('_');
391 s = s.insert(pos, "q");
392 }
393 return s;
Nate Begeman22237772010-06-02 00:34:55 +0000394}
395
Nate Begemanaf905ef2010-06-02 06:17:19 +0000396// Generate the string "(argtype a, argtype b, ...)"
Nate Begeman22237772010-06-02 00:34:55 +0000397static std::string GenArgs(const std::string &proto, StringRef typestr) {
Nate Begemanaf905ef2010-06-02 06:17:19 +0000398 char arg = 'a';
399
400 std::string s;
401 s += "(";
402
403 for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) {
404 s += TypeString(proto[i], typestr);
405 s.push_back(' ');
406 s.push_back(arg);
407 if ((i + 1) < e)
408 s += ", ";
409 }
410
411 s += ")";
412 return s;
Nate Begeman22237772010-06-02 00:34:55 +0000413}
414
Nate Begeman7c8c8832010-06-02 21:53:00 +0000415// Generate the definition for this intrinsic, e.g. "a + b" for OpAdd.
416// If structTypes is true, the NEON types are structs of vector types rather
417// than vector types, and the call becomes "a.val + b.val"
418static std::string GenOpString(OpKind op, const std::string &proto,
Nate Begeman162d3ba2010-06-03 04:04:09 +0000419 StringRef typestr, bool structTypes = true) {
420 std::string s("return ");
Nate Begeman9e584b32010-06-04 22:53:30 +0000421 std::string ts = TypeString(proto[0], typestr);
Nate Begeman162d3ba2010-06-03 04:04:09 +0000422 if (structTypes)
423 s += "(" + ts + "){";
424
Nate Begeman3861e742010-06-03 21:35:22 +0000425 std::string a, b, c;
426 if (proto.size() > 1)
427 a = (structTypes && proto[1] != 'l') ? "a.val" : "a";
428 b = structTypes ? "b.val" : "b";
429 c = structTypes ? "c.val" : "c";
Nate Begeman162d3ba2010-06-03 04:04:09 +0000430
431 switch(op) {
432 case OpAdd:
433 s += a + " + " + b;
434 break;
435 case OpSub:
436 s += a + " - " + b;
437 break;
438 case OpMul:
439 s += a + " * " + b;
440 break;
441 case OpMla:
442 s += a + " + ( " + b + " * " + c + " )";
443 break;
444 case OpMls:
445 s += a + " - ( " + b + " * " + c + " )";
446 break;
447 case OpEq:
448 s += "(__neon_" + ts + ")(" + a + " == " + b + ")";
449 break;
450 case OpGe:
451 s += "(__neon_" + ts + ")(" + a + " >= " + b + ")";
452 break;
453 case OpLe:
454 s += "(__neon_" + ts + ")(" + a + " <= " + b + ")";
455 break;
456 case OpGt:
457 s += "(__neon_" + ts + ")(" + a + " > " + b + ")";
458 break;
459 case OpLt:
460 s += "(__neon_" + ts + ")(" + a + " < " + b + ")";
461 break;
462 case OpNeg:
463 s += " -" + a;
464 break;
465 case OpNot:
466 s += " ~" + a;
467 break;
468 case OpAnd:
469 s += a + " & " + b;
470 break;
471 case OpOr:
472 s += a + " | " + b;
473 break;
474 case OpXor:
475 s += a + " ^ " + b;
476 break;
477 case OpAndNot:
478 s += a + " & ~" + b;
479 break;
480 case OpOrNot:
481 s += a + " | ~" + b;
482 break;
Nate Begeman3861e742010-06-03 21:35:22 +0000483 case OpCast:
484 s += "(__neon_" + ts + ")" + a;
485 break;
Nate Begeman162d3ba2010-06-03 04:04:09 +0000486 default:
487 throw "unknown OpKind!";
488 break;
489 }
490
491 if (structTypes)
492 s += "}";
493 s += ";";
494 return s;
Nate Begemane66aab52010-06-02 07:14:28 +0000495}
496
Nate Begemanb0a4e452010-06-07 16:00:37 +0000497static unsigned GetNeonEnum(const std::string &proto, StringRef typestr) {
498 unsigned mod = proto[0];
499 unsigned ret = 0;
500
501 if (mod == 'v')
502 mod = proto[1];
503
504 bool quad = false;
505 bool poly = false;
506 bool usgn = false;
507 bool scal = false;
508 bool cnst = false;
509 bool pntr = false;
510
511 // base type to get the type string for.
512 char type = ClassifyType(typestr, quad, poly, usgn);
513
514 // Based on the modifying character, change the type and width if necessary.
515 type = ModType(mod, type, quad, poly, usgn, scal, cnst, pntr);
516
517 if (usgn)
518 ret |= 0x08;
519 if (quad)
520 ret |= 0x10;
521
522 switch (type) {
523 case 'c':
524 ret |= poly ? 5 : 0;
525 break;
526 case 's':
527 ret |= poly ? 6 : 1;
528 break;
529 case 'i':
530 ret |= 2;
531 break;
532 case 'l':
533 ret |= 3;
534 break;
535 case 'h':
536 ret |= 7;
537 break;
538 case 'f':
539 ret |= 4;
540 break;
541 default:
542 throw "unhandled type!";
543 break;
544 }
545 return ret;
546}
547
Nate Begeman7c8c8832010-06-02 21:53:00 +0000548// Generate the definition for this intrinsic, e.g. __builtin_neon_cls(a)
549// If structTypes is true, the NEON types are structs of vector types rather
550// than vector types, and the call becomes __builtin_neon_cls(a.val)
551static std::string GenBuiltin(const std::string &name, const std::string &proto,
Nate Begemana8979a02010-06-04 00:21:41 +0000552 StringRef typestr, ClassKind ck,
553 bool structTypes = true) {
Nate Begeman7c8c8832010-06-02 21:53:00 +0000554 char arg = 'a';
Nate Begeman162d3ba2010-06-03 04:04:09 +0000555 std::string s;
Nate Begeman9e584b32010-06-04 22:53:30 +0000556
557 bool unioning = (proto[0] == '2' || proto[0] == '3' || proto[0] == '4');
558
559 // If all types are the same size, bitcasting the args will take care
560 // of arg checking. The actual signedness etc. will be taken care of with
561 // special enums.
562 if (proto.find('s') == std::string::npos)
563 ck = ClassB;
Nate Begeman7c21f742010-06-04 21:36:00 +0000564
Nate Begeman162d3ba2010-06-03 04:04:09 +0000565 if (proto[0] != 'v') {
Nate Begeman9e584b32010-06-04 22:53:30 +0000566 if (unioning) {
567 s += "union { ";
568 s += TypeString(proto[0], typestr, true) + " val; ";
569 s += TypeString(proto[0], typestr, false) + " s; ";
570 s += "} r;";
571 } else {
572 s += TypeString(proto[0], typestr);
Nate Begeman162d3ba2010-06-03 04:04:09 +0000573 }
Nate Begeman9e584b32010-06-04 22:53:30 +0000574
575 s += " r; r";
576 if (structTypes && proto[0] != 's' && proto[0] != 'i' && proto[0] != 'l')
577 s += ".val";
578
579 s += " = ";
Nate Begeman162d3ba2010-06-03 04:04:09 +0000580 }
Nate Begeman7c8c8832010-06-02 21:53:00 +0000581
582 s += "__builtin_neon_";
Nate Begemana8979a02010-06-04 00:21:41 +0000583 s += MangleName(name, typestr, ck);
Nate Begeman7c8c8832010-06-02 21:53:00 +0000584 s += "(";
585
586 for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) {
Nate Begeman9e584b32010-06-04 22:53:30 +0000587 // Handle multiple-vector values specially, emitting each subvector as an
588 // argument to the __builtin.
589 if (structTypes && (proto[i] == '2' || proto[i] == '3' || proto[i] == '4')){
590 for (unsigned vi = 0, ve = proto[i] - '0'; vi != ve; ++vi) {
591 s.push_back(arg);
592 s += ".val[" + utostr(vi) + "]";
593 if ((vi + 1) < ve)
594 s += ", ";
595 }
596 if ((i + 1) < e)
597 s += ", ";
598
599 continue;
600 }
601
Nate Begeman7c8c8832010-06-02 21:53:00 +0000602 s.push_back(arg);
Nate Begeman9e584b32010-06-04 22:53:30 +0000603
Nate Begeman162d3ba2010-06-03 04:04:09 +0000604 if (structTypes && proto[i] != 's' && proto[i] != 'i' && proto[i] != 'l' &&
605 proto[i] != 'p' && proto[i] != 'c') {
Nate Begeman7c8c8832010-06-02 21:53:00 +0000606 s += ".val";
Nate Begeman162d3ba2010-06-03 04:04:09 +0000607 }
Nate Begeman7c8c8832010-06-02 21:53:00 +0000608 if ((i + 1) < e)
609 s += ", ";
610 }
611
Nate Begeman9e584b32010-06-04 22:53:30 +0000612 // Extra constant integer to hold type class enum for this function, e.g. s8
Nate Begeman9e584b32010-06-04 22:53:30 +0000613 if (ck == ClassB)
Nate Begemanb0a4e452010-06-07 16:00:37 +0000614 s += ", " + utostr(GetNeonEnum(proto, typestr));
Nate Begeman9e584b32010-06-04 22:53:30 +0000615
616 s += ");";
617
618 if (proto[0] != 'v') {
619 if (unioning)
620 s += " return r.s;";
621 else
622 s += " return r;";
623 }
Nate Begeman7c8c8832010-06-02 21:53:00 +0000624 return s;
Nate Begemane66aab52010-06-02 07:14:28 +0000625}
626
Nate Begeman73cef3e2010-06-04 01:26:15 +0000627static std::string GenBuiltinDef(const std::string &name,
628 const std::string &proto,
629 StringRef typestr, ClassKind ck) {
630 std::string s("BUILTIN(__builtin_neon_");
Nate Begeman92f98af2010-06-04 07:11:25 +0000631
632 // If all types are the same size, bitcasting the args will take care
633 // of arg checking. The actual signedness etc. will be taken care of with
634 // special enums.
635 if (proto.find('s') == std::string::npos)
636 ck = ClassB;
637
Nate Begeman73cef3e2010-06-04 01:26:15 +0000638 s += MangleName(name, typestr, ck);
639 s += ", \"";
640
Nate Begeman92f98af2010-06-04 07:11:25 +0000641 for (unsigned i = 0, e = proto.size(); i != e; ++i)
Nate Begeman7c21f742010-06-04 21:36:00 +0000642 s += BuiltinTypeString(proto[i], typestr, ck, i == 0);
643
644 // Extra constant integer to hold type class enum for this function, e.g. s8
645 if (ck == ClassB)
646 s += "i";
Nate Begeman73cef3e2010-06-04 01:26:15 +0000647
648 s += "\", \"n\")";
649 return s;
650}
651
Nate Begeman5ddb0872010-05-28 01:08:32 +0000652void NeonEmitter::run(raw_ostream &OS) {
653 EmitSourceFileHeader("ARM NEON Header", OS);
654
655 // FIXME: emit license into file?
656
657 OS << "#ifndef __ARM_NEON_H\n";
658 OS << "#define __ARM_NEON_H\n\n";
659
660 OS << "#ifndef __ARM_NEON__\n";
661 OS << "#error \"NEON support not enabled\"\n";
662 OS << "#endif\n\n";
663
664 OS << "#include <stdint.h>\n\n";
Nate Begeman7c8c8832010-06-02 21:53:00 +0000665
666 // Emit NEON-specific scalar typedefs.
667 // FIXME: probably need to do something better for polynomial types.
Nate Begeman162d3ba2010-06-03 04:04:09 +0000668 // FIXME: is this the correct thing to do for float16?
Nate Begeman7c8c8832010-06-02 21:53:00 +0000669 OS << "typedef float float32_t;\n";
670 OS << "typedef uint8_t poly8_t;\n";
671 OS << "typedef uint16_t poly16_t;\n";
Nate Begeman162d3ba2010-06-03 04:04:09 +0000672 OS << "typedef uint16_t float16_t;\n";
Nate Begeman9e584b32010-06-04 22:53:30 +0000673
Nate Begeman7c8c8832010-06-02 21:53:00 +0000674 // Emit Neon vector typedefs.
675 std::string TypedefTypes("cQcsQsiQilQlUcQUcUsQUsUiQUiUlQUlhQhfQfPcQPcPsQPs");
676 SmallVector<StringRef, 24> TDTypeVec;
677 ParseTypes(0, TypedefTypes, TDTypeVec);
678
679 // Emit vector typedefs.
Nate Begeman9e584b32010-06-04 22:53:30 +0000680 for (unsigned v = 1; v != 5; ++v) {
681 for (unsigned i = 0, e = TDTypeVec.size(); i != e; ++i) {
682 bool dummy, quad = false;
683 (void) ClassifyType(TDTypeVec[i], quad, dummy, dummy);
684 OS << "typedef __attribute__(( __vector_size__(";
685
686 OS << utostr(8*v*(quad ? 2 : 1)) << ") )) ";
687 if (!quad)
688 OS << " ";
689
690 OS << TypeString('s', TDTypeVec[i]);
691 OS << " __neon_";
692
693 char t = (v == 1) ? 'd' : '0' + v;
694 OS << TypeString(t, TDTypeVec[i]) << ";\n";
695 }
Nate Begeman7c8c8832010-06-02 21:53:00 +0000696 }
697 OS << "\n";
698
699 // Emit struct typedefs.
700 for (unsigned vi = 1; vi != 5; ++vi) {
701 for (unsigned i = 0, e = TDTypeVec.size(); i != e; ++i) {
702 std::string ts = TypeString('d', TDTypeVec[i]);
703 std::string vs = (vi > 1) ? TypeString('0' + vi, TDTypeVec[i]) : ts;
704 OS << "typedef struct __" << vs << " {\n";
705 OS << " __neon_" << ts << " val";
706 if (vi > 1)
707 OS << "[" << utostr(vi) << "]";
708 OS << ";\n} " << vs << ";\n\n";
709 }
710 }
Nate Begeman5ddb0872010-05-28 01:08:32 +0000711
Nate Begeman7c8c8832010-06-02 21:53:00 +0000712 OS << "#define __ai static __attribute__((__always_inline__))\n\n";
713
Nate Begeman5ddb0872010-05-28 01:08:32 +0000714 std::vector<Record*> RV = Records.getAllDerivedDefinitions("Inst");
715
Nate Begeman22237772010-06-02 00:34:55 +0000716 // Unique the return+pattern types, and assign them.
Nate Begeman5ddb0872010-05-28 01:08:32 +0000717 for (unsigned i = 0, e = RV.size(); i != e; ++i) {
718 Record *R = RV[i];
Nate Begeman22237772010-06-02 00:34:55 +0000719 std::string name = LowercaseString(R->getName());
720 std::string Proto = R->getValueAsString("Prototype");
Nate Begeman5ddb0872010-05-28 01:08:32 +0000721 std::string Types = R->getValueAsString("Types");
Nate Begeman22237772010-06-02 00:34:55 +0000722
723 SmallVector<StringRef, 16> TypeVec;
724 ParseTypes(R, Types, TypeVec);
725
Nate Begeman162d3ba2010-06-03 04:04:09 +0000726 OpKind k = OpMap[R->getValueAsDef("Operand")->getName()];
Nate Begemane66aab52010-06-02 07:14:28 +0000727
Nate Begeman22237772010-06-02 00:34:55 +0000728 for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) {
729 assert(!Proto.empty() && "");
730
Nate Begeman7c8c8832010-06-02 21:53:00 +0000731 // static always inline + return type
732 OS << "__ai " << TypeString(Proto[0], TypeVec[ti]);
Nate Begeman22237772010-06-02 00:34:55 +0000733
Nate Begemane66aab52010-06-02 07:14:28 +0000734 // Function name with type suffix
Nate Begemana8979a02010-06-04 00:21:41 +0000735 OS << " " << MangleName(name, TypeVec[ti], ClassS);
Nate Begeman22237772010-06-02 00:34:55 +0000736
Nate Begemane66aab52010-06-02 07:14:28 +0000737 // Function arguments
738 OS << GenArgs(Proto, TypeVec[ti]);
Nate Begeman22237772010-06-02 00:34:55 +0000739
Nate Begemane66aab52010-06-02 07:14:28 +0000740 // Definition.
741 OS << " { ";
Nate Begeman22237772010-06-02 00:34:55 +0000742
Nate Begemana8979a02010-06-04 00:21:41 +0000743 if (k != OpNone) {
Nate Begeman162d3ba2010-06-03 04:04:09 +0000744 OS << GenOpString(k, Proto, TypeVec[ti]);
Nate Begemana8979a02010-06-04 00:21:41 +0000745 } else {
746 if (R->getSuperClasses().size() < 2)
747 throw TGError(R->getLoc(), "Builtin has no class kind");
748
749 ClassKind ck = ClassMap[R->getSuperClasses()[1]];
750
751 if (ck == ClassNone)
752 throw TGError(R->getLoc(), "Builtin has no class kind");
753 OS << GenBuiltin(name, Proto, TypeVec[ti], ck);
754 }
Nate Begemane66aab52010-06-02 07:14:28 +0000755
Nate Begeman7c8c8832010-06-02 21:53:00 +0000756 OS << " }\n";
Nate Begeman22237772010-06-02 00:34:55 +0000757 }
758 OS << "\n";
Nate Begeman5ddb0872010-05-28 01:08:32 +0000759 }
Nate Begeman73cef3e2010-06-04 01:26:15 +0000760 OS << "#undef __ai\n\n";
Nate Begeman7c8c8832010-06-02 21:53:00 +0000761 OS << "#endif /* __ARM_NEON_H */\n";
Nate Begeman5ddb0872010-05-28 01:08:32 +0000762}
Nate Begemana8979a02010-06-04 00:21:41 +0000763
764void NeonEmitter::runHeader(raw_ostream &OS) {
Nate Begeman73cef3e2010-06-04 01:26:15 +0000765 std::vector<Record*> RV = Records.getAllDerivedDefinitions("Inst");
766
767 StringMap<OpKind> EmittedMap;
768
769 for (unsigned i = 0, e = RV.size(); i != e; ++i) {
770 Record *R = RV[i];
771
772 OpKind k = OpMap[R->getValueAsDef("Operand")->getName()];
773 if (k != OpNone)
774 continue;
775
776 std::string name = LowercaseString(R->getName());
777 std::string Proto = R->getValueAsString("Prototype");
778 std::string Types = R->getValueAsString("Types");
779
780 SmallVector<StringRef, 16> TypeVec;
781 ParseTypes(R, Types, TypeVec);
782
783 if (R->getSuperClasses().size() < 2)
784 throw TGError(R->getLoc(), "Builtin has no class kind");
785
786 ClassKind ck = ClassMap[R->getSuperClasses()[1]];
787
788 for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) {
789 std::string bd = GenBuiltinDef(name, Proto, TypeVec[ti], ck);
790 if (EmittedMap.count(bd))
791 continue;
792
793 EmittedMap[bd] = OpNone;
794 OS << bd << "\n";
795 }
796 }
Nate Begemana8979a02010-06-04 00:21:41 +0000797}