clang codegen support
[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 char ModType(const char mod, char type, bool &quad, bool &poly,
104                     bool &usgn, bool &scal, bool &cnst, bool &pntr) {
105   switch (mod) {
106     case 't':
107       if (poly) {
108         poly = false;
109         usgn = true;
110       }
111       break;
112     case 'x':
113       usgn = true;
114       poly = false;
115       if (type == 'f')
116         type = 'i';
117       break;
118     case 'f':
119       type = 'f';
120       usgn = false;
121       break;
122     case 'w':
123       type = Widen(type);
124       quad = true;
125       break;
126     case 'n':
127       type = Widen(type);
128       break;
129     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':
143       usgn = false;
144       poly = false;
145       pntr = true;
146       scal = true;
147       break;
148     case 'h':
149       type = Narrow(type);
150       break;
151     case 'e':
152       type = Narrow(type);
153       usgn = true;
154       break;
155     default:
156       break;
157   }
158   return type;
159 }
160
161 static 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);
180   
181   SmallString<128> s;
182   
183   if (ret)
184     s += "__neon_";
185   
186   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;
226     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
250 static std::string BuiltinTypeString(const char mod, StringRef typestr,
251                                      ClassKind ck, bool ret) {
252   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.
268   type = ModType(mod, type, quad, poly, usgn, scal, cnst, pntr);
269
270   if (pntr)
271     type = 'v';
272   
273   if (type == 'h') {
274     type = 's';
275     usgn = true;
276   }
277   usgn = usgn | poly | ((ck == ClassI || ck == ClassW) && scal && type != 'f');
278
279   if (scal) {
280     SmallString<128> s;
281
282     if (usgn)
283       s.push_back('U');
284     
285     if (type == 'l')
286       s += "LLi";
287     else
288       s.push_back(type);
289  
290     if (cnst)
291       s.push_back('C');
292     if (pntr)
293       s.push_back('*');
294     return s.str();
295   }
296
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.
311   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
321 // Turn "vst2_lane" into "vst2q_lane_f32", etc.
322 static std::string MangleName(const std::string &name, StringRef typestr,
323                               ClassKind ck) {
324   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) {
332   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;
383   }
384   if (ck == ClassB)
385     s += "_v";
386     
387   // 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;
394 }
395
396 // Generate the string "(argtype a, argtype b, ...)"
397 static std::string GenArgs(const std::string &proto, StringRef typestr) {
398   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;
413 }
414
415 // 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"
418 static std::string GenOpString(OpKind op, const std::string &proto,
419                                StringRef typestr, bool structTypes = true) {
420   std::string s("return ");
421   std::string ts = TypeString(proto[0], typestr);
422   if (structTypes)
423     s += "(" + ts + "){";
424   
425   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";
430   
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;
483   case OpCast:
484     s += "(__neon_" + ts + ")" + a;
485     break;
486   default:
487     throw "unknown OpKind!";
488     break;
489   }
490   
491   if (structTypes)
492     s += "}";
493   s += ";";
494   return s;
495 }
496
497 static 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
548 // 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)
551 static std::string GenBuiltin(const std::string &name, const std::string &proto,
552                               StringRef typestr, ClassKind ck,
553                               bool structTypes = true) {
554   char arg = 'a';
555   std::string s;
556
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;
564
565   if (proto[0] != 'v') {
566     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);
573     }
574     
575     s += " r; r";
576     if (structTypes && proto[0] != 's' && proto[0] != 'i' && proto[0] != 'l')
577       s += ".val";
578     
579     s += " = ";
580   }    
581   
582   s += "__builtin_neon_";
583   s += MangleName(name, typestr, ck);
584   s += "(";
585   
586   for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) {
587     // 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     
602     s.push_back(arg);
603     
604     if (structTypes && proto[i] != 's' && proto[i] != 'i' && proto[i] != 'l' &&
605         proto[i] != 'p' && proto[i] != 'c') {
606       s += ".val";
607     }
608     if ((i + 1) < e)
609       s += ", ";
610   }
611   
612   // Extra constant integer to hold type class enum for this function, e.g. s8
613   if (ck == ClassB)
614     s += ", " + utostr(GetNeonEnum(proto, typestr));
615   
616   s += ");";
617
618   if (proto[0] != 'v') {
619     if (unioning)
620       s += " return r.s;";
621     else
622       s += " return r;";
623   }
624   return s;
625 }
626
627 static std::string GenBuiltinDef(const std::string &name, 
628                                  const std::string &proto,
629                                  StringRef typestr, ClassKind ck) {
630   std::string s("BUILTIN(__builtin_neon_");
631
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   
638   s += MangleName(name, typestr, ck);
639   s += ", \"";
640   
641   for (unsigned i = 0, e = proto.size(); i != e; ++i)
642     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";
647   
648   s += "\", \"n\")";
649   return s;
650 }
651
652 void 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";
665
666   // Emit NEON-specific scalar typedefs.
667   // FIXME: probably need to do something better for polynomial types.
668   // FIXME: is this the correct thing to do for float16?
669   OS << "typedef float float32_t;\n";
670   OS << "typedef uint8_t poly8_t;\n";
671   OS << "typedef uint16_t poly16_t;\n";
672   OS << "typedef uint16_t float16_t;\n";
673
674   // Emit Neon vector typedefs.
675   std::string TypedefTypes("cQcsQsiQilQlUcQUcUsQUsUiQUiUlQUlhQhfQfPcQPcPsQPs");
676   SmallVector<StringRef, 24> TDTypeVec;
677   ParseTypes(0, TypedefTypes, TDTypeVec);
678
679   // Emit vector typedefs.
680   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     }
696   }
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   }
711   
712   OS << "#define __ai static __attribute__((__always_inline__))\n\n";
713
714   std::vector<Record*> RV = Records.getAllDerivedDefinitions("Inst");
715   
716   // Unique the return+pattern types, and assign them.
717   for (unsigned i = 0, e = RV.size(); i != e; ++i) {
718     Record *R = RV[i];
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     OpKind k = OpMap[R->getValueAsDef("Operand")->getName()];
727     
728     for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) {
729       assert(!Proto.empty() && "");
730       
731       // static always inline + return type
732       OS << "__ai " << TypeString(Proto[0], TypeVec[ti]);
733       
734       // Function name with type suffix
735       OS << " " << MangleName(name, TypeVec[ti], ClassS);
736       
737       // Function arguments
738       OS << GenArgs(Proto, TypeVec[ti]);
739       
740       // Definition.
741       OS << " { ";
742       
743       if (k != OpNone) {
744         OS << GenOpString(k, Proto, TypeVec[ti]);
745       } 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       }
755
756       OS << " }\n";
757     }
758     OS << "\n";
759   }
760   OS << "#undef __ai\n\n";
761   OS << "#endif /* __ARM_NEON_H */\n";
762 }
763
764 void NeonEmitter::runHeader(raw_ostream &OS) {
765   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   }
797 }