6c5f86290da01199d45fe280c79bbe8f05cac6c9
[oota-llvm.git] / utils / TableGen / NeonEmitter.cpp
1 //===- NeonEmitter.cpp - Generate arm_neon.h for use with clang -*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This tablegen backend is responsible for emitting arm_neon.h, which includes
11 // a declaration and definition of each function specified by the ARM NEON 
12 // compiler interface.  See ARM document DUI0348B.
13 //
14 //===----------------------------------------------------------------------===//
15
16 #include "NeonEmitter.h"
17 #include "llvm/ADT/SmallString.h"
18 #include "llvm/ADT/SmallVector.h"
19 #include "llvm/ADT/StringExtras.h"
20 #include <string>
21
22 using namespace llvm;
23
24 static 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
52 static char Widen(const char t) {
53   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
65 static 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     case 'f':
74       return 'h';
75     default: throw "unhandled type in widen!";
76   }
77   return '\0';
78 }
79
80 static char ClassifyType(StringRef ty, bool &quad, bool &poly, bool &usgn) {
81   unsigned off = 0;
82   
83   // remember quad.
84   if (ty[off] == 'Q') {
85     quad = true;
86     ++off;
87   }
88   
89   // remember poly.
90   if (ty[off] == 'P') {
91     poly = true;
92     ++off;
93   }
94   
95   // remember unsigned.
96   if (ty[off] == 'U') {
97     usgn = true;
98     ++off;
99   }
100   
101   // base type to get the type string for.
102   return ty[off];
103 }
104
105 static char ModType(const char mod, char type, bool &quad, bool &poly,
106                     bool &usgn, bool &scal, bool &cnst, bool &pntr) {
107   switch (mod) {
108     case 't':
109       if (poly) {
110         poly = false;
111         usgn = true;
112       }
113       break;
114     case 'u':
115       usgn = true;
116     case 'x':
117       poly = false;
118       if (type == 'f')
119         type = 'i';
120       break;
121     case 'f':
122       if (type == 'h')
123         quad = true;
124       type = 'f';
125       usgn = false;
126       break;
127     case 'w':
128       type = Widen(type);
129       quad = true;
130       break;
131     case 'n':
132       type = Widen(type);
133       break;
134     case 'l':
135       type = 'l';
136       scal = true;
137       usgn = true;
138       break;
139     case 's':
140     case 'a':
141       scal = true;
142       break;
143     case 'k':
144       quad = true;
145       break;
146     case 'c':
147       cnst = true;
148     case 'p':
149       usgn = false;
150       poly = false;
151       pntr = true;
152       scal = true;
153       break;
154     case 'h':
155       type = Narrow(type);
156       if (type == 'h')
157         quad = false;
158       break;
159     case 'e':
160       type = Narrow(type);
161       usgn = true;
162       break;
163     default:
164       break;
165   }
166   return type;
167 }
168
169 static std::string TypeString(const char mod, StringRef typestr,
170                               bool ret = false) {
171   bool quad = false;
172   bool poly = false;
173   bool usgn = false;
174   bool scal = false;
175   bool cnst = false;
176   bool pntr = false;
177   
178   if (mod == 'v')
179     return "void";
180   if (mod == 'i')
181     return "int";
182   
183   // base type to get the type string for.
184   char type = ClassifyType(typestr, quad, poly, usgn);
185   
186   // Based on the modifying character, change the type and width if necessary.
187   type = ModType(mod, type, quad, poly, usgn, scal, cnst, pntr);
188   
189   SmallString<128> s;
190   
191   if (ret)
192     s += "__neon_";
193   
194   if (usgn)
195     s.push_back('u');
196   
197   switch (type) {
198     case 'c':
199       s += poly ? "poly8" : "int8";
200       if (scal)
201         break;
202       s += quad ? "x16" : "x8";
203       break;
204     case 's':
205       s += poly ? "poly16" : "int16";
206       if (scal)
207         break;
208       s += quad ? "x8" : "x4";
209       break;
210     case 'i':
211       s += "int32";
212       if (scal)
213         break;
214       s += quad ? "x4" : "x2";
215       break;
216     case 'l':
217       s += "int64";
218       if (scal)
219         break;
220       s += quad ? "x2" : "x1";
221       break;
222     case 'h':
223       s += "float16";
224       if (scal)
225         break;
226       s += quad ? "x8" : "x4";
227       break;
228     case 'f':
229       s += "float32";
230       if (scal)
231         break;
232       s += quad ? "x4" : "x2";
233       break;
234     default:
235       throw "unhandled type!";
236       break;
237   }
238
239   if (mod == '2')
240     s += "x2";
241   if (mod == '3')
242     s += "x3";
243   if (mod == '4')
244     s += "x4";
245   
246   // Append _t, finishing the type string typedef type.
247   s += "_t";
248   
249   if (cnst)
250     s += " const";
251   
252   if (pntr)
253     s += " *";
254   
255   return s.str();
256 }
257
258 static std::string BuiltinTypeString(const char mod, StringRef typestr,
259                                      ClassKind ck, bool ret) {
260   bool quad = false;
261   bool poly = false;
262   bool usgn = false;
263   bool scal = false;
264   bool cnst = false;
265   bool pntr = false;
266   
267   if (mod == 'v')
268     return "v";
269   if (mod == 'i')
270     return "i";
271   
272   // base type to get the type string for.
273   char type = ClassifyType(typestr, quad, poly, usgn);
274   
275   // Based on the modifying character, change the type and width if necessary.
276   type = ModType(mod, type, quad, poly, usgn, scal, cnst, pntr);
277
278   if (pntr)
279     type = 'v';
280   
281   if (type == 'h') {
282     type = 's';
283     usgn = true;
284   }
285   usgn = usgn | poly | ((ck == ClassI || ck == ClassW) && scal && type != 'f');
286
287   if (scal) {
288     SmallString<128> s;
289
290     if (usgn)
291       s.push_back('U');
292     
293     if (type == 'l')
294       s += "LLi";
295     else
296       s.push_back(type);
297  
298     if (cnst)
299       s.push_back('C');
300     if (pntr)
301       s.push_back('*');
302     return s.str();
303   }
304
305   // Since the return value must be one type, return a vector type of the
306   // appropriate width which we will bitcast.
307   if (ret) {
308     if (mod == '2')
309       return quad ? "V32c" : "V16c";
310     if (mod == '3')
311       return quad ? "V48c" : "V24c";
312     if (mod == '4')
313       return quad ? "V64c" : "V32c";
314     if (mod == 'f' || (ck != ClassB && type == 'f'))
315       return quad ? "V4f" : "V2f";
316     if (ck != ClassB && type == 's')
317       return quad ? "V8s" : "V4s";
318     if (ck != ClassB && type == 'i')
319       return quad ? "V4i" : "V2i";
320     if (ck != ClassB && type == 'l')
321       return quad ? "V2LLi" : "V1LLi";
322     
323     return quad ? "V16c" : "V8c";
324   }    
325
326   // Non-return array types are passed as individual vectors.
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   if (mod == 'f' || (ck != ClassB && type == 'f'))
335     return quad ? "V4f" : "V2f";
336   if (ck != ClassB && type == 's')
337     return quad ? "V8s" : "V4s";
338   if (ck != ClassB && type == 'i')
339     return quad ? "V4i" : "V2i";
340   if (ck != ClassB && type == 'l')
341     return quad ? "V2LLi" : "V1LLi";
342   
343   return quad ? "V16c" : "V8c";
344 }
345
346 // Turn "vst2_lane" into "vst2q_lane_f32", etc.
347 static std::string MangleName(const std::string &name, StringRef typestr,
348                               ClassKind ck) {
349   if (name == "vcvt_f32_f16")
350     return name;
351   
352   bool quad = false;
353   bool poly = false;
354   bool usgn = false;
355   char type = ClassifyType(typestr, quad, poly, usgn);
356
357   std::string s = name;
358   
359   switch (type) {
360   case 'c':
361     switch (ck) {
362     case ClassS: s += poly ? "_p8" : usgn ? "_u8" : "_s8"; break;
363     case ClassI: s += "_i8"; break;
364     case ClassW: s += "_8"; break;
365     default: break;
366     }
367     break;
368   case 's':
369     switch (ck) {
370     case ClassS: s += poly ? "_p16" : usgn ? "_u16" : "_s16"; break;
371     case ClassI: s += "_i16"; break;
372     case ClassW: s += "_16"; break;
373     default: break;
374     }
375     break;
376   case 'i':
377     switch (ck) {
378     case ClassS: s += usgn ? "_u32" : "_s32"; break;
379     case ClassI: s += "_i32"; break;
380     case ClassW: s += "_32"; break;
381     default: break;
382     }
383     break;
384   case 'l':
385     switch (ck) {
386     case ClassS: s += usgn ? "_u64" : "_s64"; break;
387     case ClassI: s += "_i64"; break;
388     case ClassW: s += "_64"; break;
389     default: break;
390     }
391     break;
392   case 'h':
393     switch (ck) {
394     case ClassS:
395     case ClassI: s += "_f16"; break;
396     case ClassW: s += "_16"; break;
397     default: break;
398     }
399     break;
400   case 'f':
401     switch (ck) {
402     case ClassS:
403     case ClassI: s += "_f32"; break;
404     case ClassW: s += "_32"; break;
405     default: break;
406     }
407     break;
408   default:
409     throw "unhandled type!";
410     break;
411   }
412   if (ck == ClassB)
413     s += "_v";
414     
415   // Insert a 'q' before the first '_' character so that it ends up before 
416   // _lane or _n on vector-scalar operations.
417   if (quad) {
418     size_t pos = s.find('_');
419     s = s.insert(pos, "q");
420   }
421   return s;
422 }
423
424 // Generate the string "(argtype a, argtype b, ...)"
425 static std::string GenArgs(const std::string &proto, StringRef typestr) {
426   bool define = proto.find('i') != std::string::npos;
427   char arg = 'a';
428   
429   std::string s;
430   s += "(";
431   
432   for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) {
433     if (!define) {
434       s += TypeString(proto[i], typestr);
435       s.push_back(' ');
436     }
437     s.push_back(arg);
438     if ((i + 1) < e)
439       s += ", ";
440   }
441   
442   s += ")";
443   return s;
444 }
445
446 static std::string Duplicate(unsigned nElts, StringRef typestr, 
447                              const std::string &a) {
448   std::string s;
449   
450   s = "(__neon_" + TypeString('d', typestr) + "){ ";
451   for (unsigned i = 0; i != nElts; ++i) {
452     s += a;
453     if ((i + 1) < nElts)
454       s += ", ";
455   }
456   s += " }";
457   
458   return s;
459 }
460
461 // Generate the definition for this intrinsic, e.g. "a + b" for OpAdd.
462 // If structTypes is true, the NEON types are structs of vector types rather
463 // than vector types, and the call becomes "a.val + b.val"
464 static std::string GenOpString(OpKind op, const std::string &proto,
465                                StringRef typestr, bool structTypes = true) {
466   bool dummy, quad = false;
467   char type = ClassifyType(typestr, quad, dummy, dummy);
468   unsigned nElts = 0;
469   switch (type) {
470     case 'c': nElts = 8; break;
471     case 's': nElts = 4; break;
472     case 'i': nElts = 2; break;
473     case 'l': nElts = 1; break;
474     case 'h': nElts = 4; break;
475     case 'f': nElts = 2; break;
476   }
477   
478   std::string ts = TypeString(proto[0], typestr);
479   std::string s = ts + " r; r";
480   
481   if (structTypes)
482     s += ".val";
483   
484   s += " = ";
485
486   std::string a, b, c;
487   if (proto.size() > 1)
488     a = (structTypes && proto[1] != 'l' && proto[1] != 's') ? "a.val" : "a";
489   b = structTypes ? "b.val" : "b";
490   c = structTypes ? "c.val" : "c";
491   
492   switch(op) {
493   case OpAdd:
494     s += a + " + " + b;
495     break;
496   case OpSub:
497     s += a + " - " + b;
498     break;
499   case OpMulN:
500     b = Duplicate(nElts << quad, typestr, "b");
501   case OpMul:
502     s += a + " * " + b;
503     break;
504   case OpMlaN:
505     c = Duplicate(nElts << quad, typestr, "c");
506   case OpMla:
507     s += a + " + ( " + b + " * " + c + " )";
508     break;
509   case OpMlsN:
510     c = Duplicate(nElts << quad, typestr, "c");
511   case OpMls:
512     s += a + " - ( " + b + " * " + c + " )";
513     break;
514   case OpEq:
515     s += "(__neon_" + ts + ")(" + a + " == " + b + ")";
516     break;
517   case OpGe:
518     s += "(__neon_" + ts + ")(" + a + " >= " + b + ")";
519     break;
520   case OpLe:
521     s += "(__neon_" + ts + ")(" + a + " <= " + b + ")";
522     break;
523   case OpGt:
524     s += "(__neon_" + ts + ")(" + a + " > " + b + ")";
525     break;
526   case OpLt:
527     s += "(__neon_" + ts + ")(" + a + " < " + b + ")";
528     break;
529   case OpNeg:
530     s += " -" + a;
531     break;
532   case OpNot:
533     s += " ~" + a;
534     break;
535   case OpAnd:
536     s += a + " & " + b;
537     break;
538   case OpOr:
539     s += a + " | " + b;
540     break;
541   case OpXor:
542     s += a + " ^ " + b;
543     break;
544   case OpAndNot:
545     s += a + " & ~" + b;
546     break;
547   case OpOrNot:
548     s += a + " | ~" + b;
549     break;
550   case OpCast:
551     s += "(__neon_" + ts + ")" + a;
552     break;
553   case OpConcat:
554     s += "__builtin_shufflevector((__neon_int64x1_t)" + a;
555     s += ", (__neon_int64x1_t)" + b + ", 0, 1)";
556     break;
557   case OpHi:
558     s += "(__neon_int64x1_t)(((__neon_int64x2_t)" + a + ")[1])";
559     break;
560   case OpLo:
561     s += "(__neon_int64x1_t)(((__neon_int64x2_t)" + a + ")[0])";
562     break;
563   case OpDup:
564     s += Duplicate(nElts << quad, typestr, a);
565     break;
566   case OpSelect:
567     // ((0 & 1) | (~0 & 2))
568     ts = TypeString(proto[1], typestr);
569     s += "( " + a + " & (__neon_" + ts + ")" + b + ") | ";
570     s += "(~" + a + " & (__neon_" + ts + ")" + c + ")";
571     break;
572   case OpRev16:
573     s += "__builtin_shufflevector(" + a + ", " + a;
574     for (unsigned i = 2; i <= nElts << quad; i += 2)
575       for (unsigned j = 0; j != 2; ++j)
576         s += ", " + utostr(i - j - 1);
577     s += ")";
578     break;
579   case OpRev32:
580     nElts >>= 1;
581     s += "__builtin_shufflevector(" + a + ", " + a;
582     for (unsigned i = nElts; i <= nElts << (1 + quad); i += nElts)
583       for (unsigned j = 0; j != nElts; ++j)
584         s += ", " + utostr(i - j - 1);
585     s += ")";
586     break;
587   case OpRev64:
588     s += "__builtin_shufflevector(" + a + ", " + a;
589     for (unsigned i = nElts; i <= nElts << quad; i += nElts)
590       for (unsigned j = 0; j != nElts; ++j)
591         s += ", " + utostr(i - j - 1);
592     s += ")";
593     break;
594   default:
595     throw "unknown OpKind!";
596     break;
597   }
598   s += "; return r;";
599   return s;
600 }
601
602 static unsigned GetNeonEnum(const std::string &proto, StringRef typestr) {
603   unsigned mod = proto[0];
604   unsigned ret = 0;
605
606   if (mod == 'v' || mod == 'f')
607     mod = proto[1];
608
609   bool quad = false;
610   bool poly = false;
611   bool usgn = false;
612   bool scal = false;
613   bool cnst = false;
614   bool pntr = false;
615   
616   // base type to get the type string for.
617   char type = ClassifyType(typestr, quad, poly, usgn);
618   
619   // Based on the modifying character, change the type and width if necessary.
620   type = ModType(mod, type, quad, poly, usgn, scal, cnst, pntr);
621   
622   if (usgn)
623     ret |= 0x08;
624   if (quad)
625     ret |= 0x10;
626   if (poly)
627     ret |= 0x20;
628   
629   switch (type) {
630     case 'c': 
631       ret |= poly ? 5 : 0;
632       break;
633     case 's':
634       ret |= poly ? 6 : 1;
635       break;
636     case 'i':
637       ret |= 2;
638       break;
639     case 'l':
640       ret |= 3;
641       break;
642     case 'h':
643       ret |= 7;
644       break;
645     case 'f':
646       ret |= 4;
647       break;
648     default:
649       throw "unhandled type!";
650       break;
651   }
652   return ret;
653 }
654
655 // Generate the definition for this intrinsic, e.g. __builtin_neon_cls(a)
656 // If structTypes is true, the NEON types are structs of vector types rather
657 // than vector types, and the call becomes __builtin_neon_cls(a.val)
658 static std::string GenBuiltin(const std::string &name, const std::string &proto,
659                               StringRef typestr, ClassKind ck,
660                               bool structTypes = true) {
661   bool dummy, quad = false;
662   char type = ClassifyType(typestr, quad, dummy, dummy);
663   unsigned nElts = 0;
664   switch (type) {
665     case 'c': nElts = 8; break;
666     case 's': nElts = 4; break;
667     case 'i': nElts = 2; break;
668     case 'l': nElts = 1; break;
669     case 'h': nElts = 4; break;
670     case 'f': nElts = 2; break;
671   }
672   if (quad) nElts <<= 1;
673
674   char arg = 'a';
675   std::string s;
676
677   bool unioning = (proto[0] == '2' || proto[0] == '3' || proto[0] == '4');
678   bool define = proto.find('i') != std::string::npos;
679
680   // If all types are the same size, bitcasting the args will take care 
681   // of arg checking.  The actual signedness etc. will be taken care of with
682   // special enums.
683   if (proto.find('s') == std::string::npos)
684     ck = ClassB;
685
686   if (proto[0] != 'v') {
687     std::string ts = TypeString(proto[0], typestr);
688     
689     if (define) {
690       if (proto[0] != 's')
691         s += "(" + ts + "){(__neon_" + ts + ")";
692     } else {
693       if (unioning) {
694         s += "union { ";
695         s += TypeString(proto[0], typestr, true) + " val; ";
696         s += TypeString(proto[0], typestr, false) + " s; ";
697         s += "} r;";
698       } else {
699         s += ts;
700       }
701       
702       s += " r; r";
703       if (structTypes && proto[0] != 's' && proto[0] != 'i' && proto[0] != 'l')
704         s += ".val";
705       
706       s += " = ";
707     }
708   }
709   
710   bool splat = proto.find('a') != std::string::npos;
711   
712   s += "__builtin_neon_";
713   if (splat) {
714     std::string vname(name, 0, name.size()-2);
715     s += MangleName(vname, typestr, ck);
716   } else {
717     s += MangleName(name, typestr, ck);
718   }
719   s += "(";
720   
721   for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) {
722     std::string args = std::string(&arg, 1);
723     if (define)
724       args = "(" + args + ")";
725     
726     // Handle multiple-vector values specially, emitting each subvector as an
727     // argument to the __builtin.
728     if (structTypes && (proto[i] == '2' || proto[i] == '3' || proto[i] == '4')){
729       for (unsigned vi = 0, ve = proto[i] - '0'; vi != ve; ++vi) {
730         s += args + ".val[" + utostr(vi) + "]";
731         if ((vi + 1) < ve)
732           s += ", ";
733       }
734       if ((i + 1) < e)
735         s += ", ";
736
737       continue;
738     }
739     
740     if (splat && (i + 1) == e) 
741       s += Duplicate(nElts, typestr, args);
742     else
743       s += args;
744     
745     if (structTypes && proto[i] != 's' && proto[i] != 'i' && proto[i] != 'l' &&
746         proto[i] != 'p' && proto[i] != 'c' && proto[i] != 'a') {
747       s += ".val";
748     }
749     if ((i + 1) < e)
750       s += ", ";
751   }
752   
753   // Extra constant integer to hold type class enum for this function, e.g. s8
754   if (ck == ClassB)
755     s += ", " + utostr(GetNeonEnum(proto, typestr));
756   
757   if (define)
758     s += ")";
759   else
760     s += ");";
761
762   if (proto[0] != 'v') {
763     if (define) {
764       if (proto[0] != 's')
765         s += "}";
766     } else {
767       if (unioning)
768         s += " return r.s;";
769       else
770         s += " return r;";
771     }
772   }
773   return s;
774 }
775
776 static std::string GenBuiltinDef(const std::string &name, 
777                                  const std::string &proto,
778                                  StringRef typestr, ClassKind ck) {
779   std::string s("BUILTIN(__builtin_neon_");
780
781   // If all types are the same size, bitcasting the args will take care 
782   // of arg checking.  The actual signedness etc. will be taken care of with
783   // special enums.
784   if (proto.find('s') == std::string::npos)
785     ck = ClassB;
786   
787   s += MangleName(name, typestr, ck);
788   s += ", \"";
789   
790   for (unsigned i = 0, e = proto.size(); i != e; ++i)
791     s += BuiltinTypeString(proto[i], typestr, ck, i == 0);
792
793   // Extra constant integer to hold type class enum for this function, e.g. s8
794   if (ck == ClassB)
795     s += "i";
796   
797   s += "\", \"n\")";
798   return s;
799 }
800
801 void NeonEmitter::run(raw_ostream &OS) {
802   EmitSourceFileHeader("ARM NEON Header", OS);
803   
804   // FIXME: emit license into file?
805   
806   OS << "#ifndef __ARM_NEON_H\n";
807   OS << "#define __ARM_NEON_H\n\n";
808   
809   OS << "#ifndef __ARM_NEON__\n";
810   OS << "#error \"NEON support not enabled\"\n";
811   OS << "#endif\n\n";
812
813   OS << "#include <stdint.h>\n\n";
814
815   // Emit NEON-specific scalar typedefs.
816   // FIXME: probably need to do something better for polynomial types.
817   OS << "typedef float float32_t;\n";
818   OS << "typedef uint8_t poly8_t;\n";
819   OS << "typedef uint16_t poly16_t;\n";
820   OS << "typedef uint16_t float16_t;\n";
821
822   // Emit Neon vector typedefs.
823   std::string TypedefTypes("cQcsQsiQilQlUcQUcUsQUsUiQUiUlQUlhQhfQfPcQPcPsQPs");
824   SmallVector<StringRef, 24> TDTypeVec;
825   ParseTypes(0, TypedefTypes, TDTypeVec);
826
827   // Emit vector typedefs.
828   for (unsigned v = 1; v != 5; ++v) {
829     for (unsigned i = 0, e = TDTypeVec.size(); i != e; ++i) {
830       bool dummy, quad = false;
831       (void) ClassifyType(TDTypeVec[i], quad, dummy, dummy);
832       OS << "typedef __attribute__(( __vector_size__(";
833       
834       OS << utostr(8*v*(quad ? 2 : 1)) << ") )) ";
835       if (!quad)
836         OS << " ";
837       
838       OS << TypeString('s', TDTypeVec[i]);
839       OS << " __neon_";
840       
841       char t = (v == 1) ? 'd' : '0' + v;
842       OS << TypeString(t, TDTypeVec[i]) << ";\n";
843     }
844   }
845   OS << "\n";
846
847   // Emit struct typedefs.
848   for (unsigned vi = 1; vi != 5; ++vi) {
849     for (unsigned i = 0, e = TDTypeVec.size(); i != e; ++i) {
850       std::string ts = TypeString('d', TDTypeVec[i]);
851       std::string vs = (vi > 1) ? TypeString('0' + vi, TDTypeVec[i]) : ts;
852       OS << "typedef struct __" << vs << " {\n";
853       OS << "  __neon_" << ts << " val";
854       if (vi > 1)
855         OS << "[" << utostr(vi) << "]";
856       OS << ";\n} " << vs << ";\n\n";
857     }
858   }
859   
860   OS << "#define __ai static __attribute__((__always_inline__))\n\n";
861
862   std::vector<Record*> RV = Records.getAllDerivedDefinitions("Inst");
863   
864   // Unique the return+pattern types, and assign them.
865   for (unsigned i = 0, e = RV.size(); i != e; ++i) {
866     Record *R = RV[i];
867     std::string name = LowercaseString(R->getName());
868     std::string Proto = R->getValueAsString("Prototype");
869     std::string Types = R->getValueAsString("Types");
870     
871     SmallVector<StringRef, 16> TypeVec;
872     ParseTypes(R, Types, TypeVec);
873     
874     OpKind k = OpMap[R->getValueAsDef("Operand")->getName()];
875     
876     bool define = Proto.find('i') != std::string::npos;
877     
878     for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) {
879       assert(!Proto.empty() && "");
880       
881       // static always inline + return type
882       if (define)
883         OS << "#define";
884       else
885         OS << "__ai " << TypeString(Proto[0], TypeVec[ti]);
886       
887       // Function name with type suffix
888       OS << " " << MangleName(name, TypeVec[ti], ClassS);
889       
890       // Function arguments
891       OS << GenArgs(Proto, TypeVec[ti]);
892       
893       // Definition.
894       if (define)
895         OS << " ";
896       else
897         OS << " { ";
898       
899       if (k != OpNone) {
900         OS << GenOpString(k, Proto, TypeVec[ti]);
901       } else {
902         if (R->getSuperClasses().size() < 2)
903           throw TGError(R->getLoc(), "Builtin has no class kind");
904         
905         ClassKind ck = ClassMap[R->getSuperClasses()[1]];
906
907         if (ck == ClassNone)
908           throw TGError(R->getLoc(), "Builtin has no class kind");
909         OS << GenBuiltin(name, Proto, TypeVec[ti], ck);
910       }
911       if (!define)
912         OS << " }";
913       OS << "\n";
914     }
915     OS << "\n";
916   }
917   OS << "#undef __ai\n\n";
918   OS << "#endif /* __ARM_NEON_H */\n";
919 }
920
921 void NeonEmitter::runHeader(raw_ostream &OS) {
922   std::vector<Record*> RV = Records.getAllDerivedDefinitions("Inst");
923
924   StringMap<OpKind> EmittedMap;
925   
926   for (unsigned i = 0, e = RV.size(); i != e; ++i) {
927     Record *R = RV[i];
928
929     OpKind k = OpMap[R->getValueAsDef("Operand")->getName()];
930     if (k != OpNone)
931       continue;
932     
933     std::string name = LowercaseString(R->getName());
934     std::string Proto = R->getValueAsString("Prototype");
935     std::string Types = R->getValueAsString("Types");
936
937     if (Proto.find('a') != std::string::npos)
938       continue;
939       
940     SmallVector<StringRef, 16> TypeVec;
941     ParseTypes(R, Types, TypeVec);
942
943     if (R->getSuperClasses().size() < 2)
944       throw TGError(R->getLoc(), "Builtin has no class kind");
945     
946     ClassKind ck = ClassMap[R->getSuperClasses()[1]];
947     
948     for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) {
949       std::string bd = GenBuiltinDef(name, Proto, TypeVec[ti], ck);
950       if (EmittedMap.count(bd))
951         continue;
952       
953       EmittedMap[bd] = OpNone;
954       OS << bd << "\n";
955     }
956   }
957 }