Additional fixes to BuiltinsARM.def generator, on to clang codegen.
[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     default: throw "unhandled type in widen!";
74   }
75   return '\0';
76 }
77
78 static char ClassifyType(StringRef ty, bool &quad, bool &poly, bool &usgn) {
79   unsigned off = 0;
80   
81   // 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
103 static std::string TypeString(const char mod, StringRef typestr,
104                               bool ret = false) {
105   bool quad = false;
106   bool poly = false;
107   bool usgn = false;
108   bool scal = false;
109   bool cnst = false;
110   bool pntr = false;
111   
112   // base type to get the type string for.
113   char type = ClassifyType(typestr, quad, poly, usgn);
114   
115   // Based on the modifying character, change the type and width if necessary.
116   switch (mod) {
117     case 'v':
118       return "void";
119     case 'i':
120       return "int";
121     case 't':
122       if (poly) {
123         poly = false;
124         usgn = true;
125       }
126       break;
127     case 'x':
128       usgn = true;
129       poly = false;
130       if (type == 'f')
131         type = 'i';
132       break;
133     case 'f':
134       type = 'f';
135       usgn = false;
136       break;
137     case 'w':
138       type = Widen(type);
139       quad = true;
140       break;
141     case 'n':
142       type = Widen(type);
143       break;
144     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;
161     case 'h':
162       type = Narrow(type);
163       break;
164     case 'e':
165       type = Narrow(type);
166       usgn = true;
167       break;
168     default:
169       break;
170   }
171   
172   SmallString<128> s;
173   
174   if (usgn)
175     s.push_back('u');
176   
177   switch (type) {
178     case 'c':
179       s += poly ? "poly8" : "int8";
180       if (scal)
181         break;
182       s += quad ? "x16" : "x8";
183       break;
184     case 's':
185       s += poly ? "poly16" : "int16";
186       if (scal)
187         break;
188       s += quad ? "x8" : "x4";
189       break;
190     case 'i':
191       s += "int32";
192       if (scal)
193         break;
194       s += quad ? "x4" : "x2";
195       break;
196     case 'l':
197       s += "int64";
198       if (scal)
199         break;
200       s += quad ? "x2" : "x1";
201       break;
202     case 'h':
203       s += "float16";
204       if (scal)
205         break;
206       s += quad ? "x8" : "x4";
207       break;
208     case 'f':
209       s += "float32";
210       if (scal)
211         break;
212       s += quad ? "x4" : "x2";
213       break;
214     default:
215       throw "unhandled type!";
216       break;
217   }
218
219   if (mod == '2')
220     s += "x2";
221   if (mod == '3')
222     s += "x3";
223   if (mod == '4')
224     s += "x4";
225   
226   // Append _t, finishing the type string typedef type.
227   s += "_t";
228   
229   if (cnst)
230     s += " const";
231   
232   if (pntr)
233     s += " *";
234   
235   return s.str();
236 }
237
238 static std::string BuiltinTypeString(const char mod, StringRef typestr,
239                                      ClassKind ck, bool ret) {
240   bool quad = false;
241   bool poly = false;
242   bool usgn = false;
243   bool scal = false;
244   bool cnst = false;
245   bool pntr = false;
246   
247   if (mod == 'v')
248     return "v";
249   if (mod == 'i')
250     return "i";
251   
252   // base type to get the type string for.
253   char type = ClassifyType(typestr, quad, poly, usgn);
254   
255   // Based on the modifying character, change the type and width if necessary.
256   switch (mod) {
257     case 't':
258       if (poly) {
259         poly = false;
260         usgn = true;
261       }
262       break;
263     case 'x':
264       usgn = true;
265       poly = false;
266       if (type == 'f')
267         type = 'i';
268       break;
269     case 'f':
270       type = 'f';
271       usgn = false;
272       break;
273     case 'w':
274       type = Widen(type);
275       quad = true;
276       break;
277     case 'n':
278       type = Widen(type);
279       break;
280     case 'l':
281       type = 'l';
282       scal = true;
283       usgn = true;
284       break;
285     case 's':
286       scal = true;
287       break;
288     case 'k':
289       quad = true;
290       break;
291     case 'c':
292       cnst = true;
293     case 'p':
294       type = 'v';
295       usgn = false;
296       poly = false;
297       pntr = true;
298       scal = true;
299       break;
300     case 'h':
301       type = Narrow(type);
302       break;
303     case 'e':
304       type = Narrow(type);
305       usgn = true;
306       break;
307     default:
308       break;
309   }
310   if (type == 'h') {
311     type = 's';
312     usgn = true;
313   }
314   usgn = usgn | poly | ((ck == ClassI || ck == ClassW) && scal && type != 'f');
315
316   if (scal) {
317     SmallString<128> s;
318
319     if (usgn)
320       s.push_back('U');
321     
322     if (type == 'l')
323       s += "LLi";
324     else
325       s.push_back(type);
326  
327     if (cnst)
328       s.push_back('C');
329     if (pntr)
330       s.push_back('*');
331     return s.str();
332   }
333
334   // Since the return value must be one type, return a vector type of the
335   // appropriate width which we will bitcast.
336   if (ret) {
337     if (mod == '2')
338       return quad ? "V32c" : "V16c";
339     if (mod == '3')
340       return quad ? "V48c" : "V24c";
341     if (mod == '4')
342       return quad ? "V64c" : "V32c";
343
344     return quad ? "V16c" : "V8c";
345   }    
346
347   // Non-return array types are passed as individual vectors.
348   if (mod == '2')
349     return quad ? "V16cV16c" : "V8cV8c";
350   if (mod == '3')
351     return quad ? "V16cV16cV16c" : "V8cV8cV8c";
352   if (mod == '4')
353     return quad ? "V16cV16cV16cV16c" : "V8cV8cV8cV8c";
354
355   return quad ? "V16c" : "V8c";
356 }
357
358 // Turn "vst2_lane" into "vst2q_lane_f32", etc.
359 static std::string MangleName(const std::string &name, StringRef typestr,
360                               ClassKind ck) {
361   bool quad = false;
362   bool poly = false;
363   bool usgn = false;
364   char type = ClassifyType(typestr, quad, poly, usgn);
365
366   std::string s = name;
367   
368   switch (type) {
369   case 'c':
370     switch (ck) {
371     case ClassS: s += poly ? "_p8" : usgn ? "_u8" : "_s8"; break;
372     case ClassI: s += "_i8"; break;
373     case ClassW: s += "_8"; break;
374     default: break;
375     }
376     break;
377   case 's':
378     switch (ck) {
379     case ClassS: s += poly ? "_p16" : usgn ? "_u16" : "_s16"; break;
380     case ClassI: s += "_i16"; break;
381     case ClassW: s += "_16"; break;
382     default: break;
383     }
384     break;
385   case 'i':
386     switch (ck) {
387     case ClassS: s += usgn ? "_u32" : "_s32"; break;
388     case ClassI: s += "_i32"; break;
389     case ClassW: s += "_32"; break;
390     default: break;
391     }
392     break;
393   case 'l':
394     switch (ck) {
395     case ClassS: s += usgn ? "_u64" : "_s64"; break;
396     case ClassI: s += "_i64"; break;
397     case ClassW: s += "_64"; break;
398     default: break;
399     }
400     break;
401   case 'h':
402     switch (ck) {
403     case ClassS:
404     case ClassI: s += "_f16"; break;
405     case ClassW: s += "_16"; break;
406     default: break;
407     }
408     break;
409   case 'f':
410     switch (ck) {
411     case ClassS:
412     case ClassI: s += "_f32"; break;
413     case ClassW: s += "_32"; break;
414     default: break;
415     }
416     break;
417   default:
418     throw "unhandled type!";
419     break;
420   }
421   if (ck == ClassB)
422     s += "_v";
423     
424   // Insert a 'q' before the first '_' character so that it ends up before 
425   // _lane or _n on vector-scalar operations.
426   if (quad) {
427     size_t pos = s.find('_');
428     s = s.insert(pos, "q");
429   }
430   return s;
431 }
432
433 // Generate the string "(argtype a, argtype b, ...)"
434 static std::string GenArgs(const std::string &proto, StringRef typestr) {
435   char arg = 'a';
436   
437   std::string s;
438   s += "(";
439   
440   for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) {
441     s += TypeString(proto[i], typestr);
442     s.push_back(' ');
443     s.push_back(arg);
444     if ((i + 1) < e)
445       s += ", ";
446   }
447   
448   s += ")";
449   return s;
450 }
451
452 // Generate the definition for this intrinsic, e.g. "a + b" for OpAdd.
453 // If structTypes is true, the NEON types are structs of vector types rather
454 // than vector types, and the call becomes "a.val + b.val"
455 static std::string GenOpString(OpKind op, const std::string &proto,
456                                StringRef typestr, bool structTypes = true) {
457   std::string s("return ");
458   std::string ts = TypeString(proto[0], typestr, true);
459   if (structTypes)
460     s += "(" + ts + "){";
461   
462   std::string a, b, c;
463   if (proto.size() > 1)
464     a = (structTypes && proto[1] != 'l') ? "a.val" : "a";
465   b = structTypes ? "b.val" : "b";
466   c = structTypes ? "c.val" : "c";
467   
468   switch(op) {
469   case OpAdd:
470     s += a + " + " + b;
471     break;
472   case OpSub:
473     s += a + " - " + b;
474     break;
475   case OpMul:
476     s += a + " * " + b;
477     break;
478   case OpMla:
479     s += a + " + ( " + b + " * " + c + " )";
480     break;
481   case OpMls:
482     s += a + " - ( " + b + " * " + c + " )";
483     break;
484   case OpEq:
485     s += "(__neon_" + ts + ")(" + a + " == " + b + ")";
486     break;
487   case OpGe:
488     s += "(__neon_" + ts + ")(" + a + " >= " + b + ")";
489     break;
490   case OpLe:
491     s += "(__neon_" + ts + ")(" + a + " <= " + b + ")";
492     break;
493   case OpGt:
494     s += "(__neon_" + ts + ")(" + a + " > " + b + ")";
495     break;
496   case OpLt:
497     s += "(__neon_" + ts + ")(" + a + " < " + b + ")";
498     break;
499   case OpNeg:
500     s += " -" + a;
501     break;
502   case OpNot:
503     s += " ~" + a;
504     break;
505   case OpAnd:
506     s += a + " & " + b;
507     break;
508   case OpOr:
509     s += a + " | " + b;
510     break;
511   case OpXor:
512     s += a + " ^ " + b;
513     break;
514   case OpAndNot:
515     s += a + " & ~" + b;
516     break;
517   case OpOrNot:
518     s += a + " | ~" + b;
519     break;
520   case OpCast:
521     s += "(__neon_" + ts + ")" + a;
522     break;
523   default:
524     throw "unknown OpKind!";
525     break;
526   }
527   
528   if (structTypes)
529     s += "}";
530   s += ";";
531   return s;
532 }
533
534 // Generate the definition for this intrinsic, e.g. __builtin_neon_cls(a)
535 // If structTypes is true, the NEON types are structs of vector types rather
536 // than vector types, and the call becomes __builtin_neon_cls(a.val)
537 static std::string GenBuiltin(const std::string &name, const std::string &proto,
538                               StringRef typestr, ClassKind ck,
539                               bool structTypes = true) {
540   char arg = 'a';
541   std::string s;
542   //bool unioning = (proto[0] == '2' || proto[0] == '3' || proto[0] == '4');
543
544   if (proto[0] != 'v') {
545     // FIXME: if return type is 2/3/4, emit unioning code.
546     //if (unioning)
547     //  ;
548       
549     s += "return ";
550     if (structTypes) {
551       s += "(";
552       s += TypeString(proto[0], typestr, true);
553       s += "){";
554     }
555   }    
556   
557   s += "__builtin_neon_";
558   s += MangleName(name, typestr, ck);
559   s += "(";
560   
561   for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) {
562     s.push_back(arg);
563     if (structTypes && proto[i] != 's' && proto[i] != 'i' && proto[i] != 'l' &&
564         proto[i] != 'p' && proto[i] != 'c') {
565       s += ".val";
566     }
567     if ((i + 1) < e)
568       s += ", ";
569   }
570   
571   s += ")";
572   if (proto[0] != 'v' && structTypes)
573     s += "}";
574   s += ";";
575   return s;
576 }
577
578 static std::string GenBuiltinDef(const std::string &name, 
579                                  const std::string &proto,
580                                  StringRef typestr, ClassKind ck) {
581   std::string s("BUILTIN(__builtin_neon_");
582
583   // If all types are the same size, bitcasting the args will take care 
584   // of arg checking.  The actual signedness etc. will be taken care of with
585   // special enums.
586   if (proto.find('s') == std::string::npos)
587     ck = ClassB;
588   
589   s += MangleName(name, typestr, ck);
590   s += ", \"";
591   
592   for (unsigned i = 0, e = proto.size(); i != e; ++i)
593     s += BuiltinTypeString(proto[i], typestr, ck, i == 0);
594
595   // Extra constant integer to hold type class enum for this function, e.g. s8
596   if (ck == ClassB)
597     s += "i";
598   
599   s += "\", \"n\")";
600   return s;
601 }
602
603 void NeonEmitter::run(raw_ostream &OS) {
604   EmitSourceFileHeader("ARM NEON Header", OS);
605   
606   // FIXME: emit license into file?
607   
608   OS << "#ifndef __ARM_NEON_H\n";
609   OS << "#define __ARM_NEON_H\n\n";
610   
611   OS << "#ifndef __ARM_NEON__\n";
612   OS << "#error \"NEON support not enabled\"\n";
613   OS << "#endif\n\n";
614
615   OS << "#include <stdint.h>\n\n";
616
617   // Emit NEON-specific scalar typedefs.
618   // FIXME: probably need to do something better for polynomial types.
619   // FIXME: is this the correct thing to do for float16?
620   OS << "typedef float float32_t;\n";
621   OS << "typedef uint8_t poly8_t;\n";
622   OS << "typedef uint16_t poly16_t;\n";
623   OS << "typedef uint16_t float16_t;\n";
624   
625   // Emit Neon vector typedefs.
626   std::string TypedefTypes("cQcsQsiQilQlUcQUcUsQUsUiQUiUlQUlhQhfQfPcQPcPsQPs");
627   SmallVector<StringRef, 24> TDTypeVec;
628   ParseTypes(0, TypedefTypes, TDTypeVec);
629
630   // Emit vector typedefs.
631   for (unsigned i = 0, e = TDTypeVec.size(); i != e; ++i) {
632     bool dummy, quad = false;
633     (void) ClassifyType(TDTypeVec[i], quad, dummy, dummy);
634     OS << "typedef __attribute__(( __vector_size__(";
635     OS << (quad ? "16) )) " : "8) ))  ");
636     OS << TypeString('s', TDTypeVec[i]);
637     OS << " __neon_";
638     OS << TypeString('d', TDTypeVec[i]) << ";\n";
639   }
640   OS << "\n";
641
642   // Emit struct typedefs.
643   for (unsigned vi = 1; vi != 5; ++vi) {
644     for (unsigned i = 0, e = TDTypeVec.size(); i != e; ++i) {
645       std::string ts = TypeString('d', TDTypeVec[i]);
646       std::string vs = (vi > 1) ? TypeString('0' + vi, TDTypeVec[i]) : ts;
647       OS << "typedef struct __" << vs << " {\n";
648       OS << "  __neon_" << ts << " val";
649       if (vi > 1)
650         OS << "[" << utostr(vi) << "]";
651       OS << ";\n} " << vs << ";\n\n";
652     }
653   }
654   
655   OS << "#define __ai static __attribute__((__always_inline__))\n\n";
656
657   std::vector<Record*> RV = Records.getAllDerivedDefinitions("Inst");
658   
659   // Unique the return+pattern types, and assign them.
660   for (unsigned i = 0, e = RV.size(); i != e; ++i) {
661     Record *R = RV[i];
662     std::string name = LowercaseString(R->getName());
663     std::string Proto = R->getValueAsString("Prototype");
664     std::string Types = R->getValueAsString("Types");
665     
666     SmallVector<StringRef, 16> TypeVec;
667     ParseTypes(R, Types, TypeVec);
668     
669     OpKind k = OpMap[R->getValueAsDef("Operand")->getName()];
670     
671     for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) {
672       assert(!Proto.empty() && "");
673       
674       // static always inline + return type
675       OS << "__ai " << TypeString(Proto[0], TypeVec[ti]);
676       
677       // Function name with type suffix
678       OS << " " << MangleName(name, TypeVec[ti], ClassS);
679       
680       // Function arguments
681       OS << GenArgs(Proto, TypeVec[ti]);
682       
683       // Definition.
684       OS << " { ";
685       
686       if (k != OpNone) {
687         OS << GenOpString(k, Proto, TypeVec[ti]);
688       } else {
689         if (R->getSuperClasses().size() < 2)
690           throw TGError(R->getLoc(), "Builtin has no class kind");
691         
692         ClassKind ck = ClassMap[R->getSuperClasses()[1]];
693
694         if (ck == ClassNone)
695           throw TGError(R->getLoc(), "Builtin has no class kind");
696         OS << GenBuiltin(name, Proto, TypeVec[ti], ck);
697       }
698
699       OS << " }\n";
700     }
701     OS << "\n";
702   }
703   OS << "#undef __ai\n\n";
704   OS << "#endif /* __ARM_NEON_H */\n";
705 }
706
707 void NeonEmitter::runHeader(raw_ostream &OS) {
708   std::vector<Record*> RV = Records.getAllDerivedDefinitions("Inst");
709
710   StringMap<OpKind> EmittedMap;
711   
712   for (unsigned i = 0, e = RV.size(); i != e; ++i) {
713     Record *R = RV[i];
714
715     OpKind k = OpMap[R->getValueAsDef("Operand")->getName()];
716     if (k != OpNone)
717       continue;
718     
719     std::string name = LowercaseString(R->getName());
720     std::string Proto = R->getValueAsString("Prototype");
721     std::string Types = R->getValueAsString("Types");
722
723     SmallVector<StringRef, 16> TypeVec;
724     ParseTypes(R, Types, TypeVec);
725
726     if (R->getSuperClasses().size() < 2)
727       throw TGError(R->getLoc(), "Builtin has no class kind");
728     
729     ClassKind ck = ClassMap[R->getSuperClasses()[1]];
730     
731     for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) {
732       std::string bd = GenBuiltinDef(name, Proto, TypeVec[ti], ck);
733       if (EmittedMap.count(bd))
734         continue;
735       
736       EmittedMap[bd] = OpNone;
737       OS << bd << "\n";
738     }
739   }
740 }