NeonEmitter.cpp revision 6f9f03ef370ad48ece0c5d10edda28f39ccadb5d
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// Each NEON instruction is implemented in terms of 1 or more functions which
15// are suffixed with the element type of the input vectors.  Functions may be
16// implemented in terms of generic vector operations such as +, *, -, etc. or
17// by calling a __builtin_-prefixed function which will be handled by clang's
18// CodeGen library.
19//
20// Additional validation code can be generated by this file when runHeader() is
21// called, rather than the normal run() entry point.  A complete set of tests
22// for Neon intrinsics can be generated by calling the runTests() entry point.
23//
24//===----------------------------------------------------------------------===//
25
26#include "NeonEmitter.h"
27#include "llvm/TableGen/Error.h"
28#include "llvm/ADT/SmallString.h"
29#include "llvm/ADT/SmallVector.h"
30#include "llvm/ADT/StringExtras.h"
31#include <string>
32
33using namespace llvm;
34
35/// ParseTypes - break down a string such as "fQf" into a vector of StringRefs,
36/// which each StringRef representing a single type declared in the string.
37/// for "fQf" we would end up with 2 StringRefs, "f", and "Qf", representing
38/// 2xfloat and 4xfloat respectively.
39static void ParseTypes(Record *r, std::string &s,
40                       SmallVectorImpl<StringRef> &TV) {
41  const char *data = s.data();
42  int len = 0;
43
44  for (unsigned i = 0, e = s.size(); i != e; ++i, ++len) {
45    if (data[len] == 'P' || data[len] == 'Q' || data[len] == 'U')
46      continue;
47
48    switch (data[len]) {
49      case 'c':
50      case 's':
51      case 'i':
52      case 'l':
53      case 'h':
54      case 'f':
55        break;
56      default:
57        throw TGError(r->getLoc(),
58                      "Unexpected letter: " + std::string(data + len, 1));
59        break;
60    }
61    TV.push_back(StringRef(data, len + 1));
62    data += len + 1;
63    len = -1;
64  }
65}
66
67/// Widen - Convert a type code into the next wider type.  char -> short,
68/// short -> int, etc.
69static char Widen(const char t) {
70  switch (t) {
71    case 'c':
72      return 's';
73    case 's':
74      return 'i';
75    case 'i':
76      return 'l';
77    case 'h':
78      return 'f';
79    default: throw "unhandled type in widen!";
80  }
81  return '\0';
82}
83
84/// Narrow - Convert a type code into the next smaller type.  short -> char,
85/// float -> half float, etc.
86static char Narrow(const char t) {
87  switch (t) {
88    case 's':
89      return 'c';
90    case 'i':
91      return 's';
92    case 'l':
93      return 'i';
94    case 'f':
95      return 'h';
96    default: throw "unhandled type in narrow!";
97  }
98  return '\0';
99}
100
101/// For a particular StringRef, return the base type code, and whether it has
102/// the quad-vector, polynomial, or unsigned modifiers set.
103static char ClassifyType(StringRef ty, bool &quad, bool &poly, bool &usgn) {
104  unsigned off = 0;
105
106  // remember quad.
107  if (ty[off] == 'Q') {
108    quad = true;
109    ++off;
110  }
111
112  // remember poly.
113  if (ty[off] == 'P') {
114    poly = true;
115    ++off;
116  }
117
118  // remember unsigned.
119  if (ty[off] == 'U') {
120    usgn = true;
121    ++off;
122  }
123
124  // base type to get the type string for.
125  return ty[off];
126}
127
128/// ModType - Transform a type code and its modifiers based on a mod code. The
129/// mod code definitions may be found at the top of arm_neon.td.
130static char ModType(const char mod, char type, bool &quad, bool &poly,
131                    bool &usgn, bool &scal, bool &cnst, bool &pntr) {
132  switch (mod) {
133    case 't':
134      if (poly) {
135        poly = false;
136        usgn = true;
137      }
138      break;
139    case 'u':
140      usgn = true;
141      poly = false;
142      if (type == 'f')
143        type = 'i';
144      break;
145    case 'x':
146      usgn = false;
147      poly = false;
148      if (type == 'f')
149        type = 'i';
150      break;
151    case 'f':
152      if (type == 'h')
153        quad = true;
154      type = 'f';
155      usgn = false;
156      break;
157    case 'g':
158      quad = false;
159      break;
160    case 'w':
161      type = Widen(type);
162      quad = true;
163      break;
164    case 'n':
165      type = Widen(type);
166      break;
167    case 'i':
168      type = 'i';
169      scal = true;
170      break;
171    case 'l':
172      type = 'l';
173      scal = true;
174      usgn = true;
175      break;
176    case 's':
177    case 'a':
178      scal = true;
179      break;
180    case 'k':
181      quad = true;
182      break;
183    case 'c':
184      cnst = true;
185    case 'p':
186      pntr = true;
187      scal = true;
188      break;
189    case 'h':
190      type = Narrow(type);
191      if (type == 'h')
192        quad = false;
193      break;
194    case 'e':
195      type = Narrow(type);
196      usgn = true;
197      break;
198    default:
199      break;
200  }
201  return type;
202}
203
204/// TypeString - for a modifier and type, generate the name of the typedef for
205/// that type.  QUc -> uint8x8_t.
206static std::string TypeString(const char mod, StringRef typestr) {
207  bool quad = false;
208  bool poly = false;
209  bool usgn = false;
210  bool scal = false;
211  bool cnst = false;
212  bool pntr = false;
213
214  if (mod == 'v')
215    return "void";
216  if (mod == 'i')
217    return "int";
218
219  // base type to get the type string for.
220  char type = ClassifyType(typestr, quad, poly, usgn);
221
222  // Based on the modifying character, change the type and width if necessary.
223  type = ModType(mod, type, quad, poly, usgn, scal, cnst, pntr);
224
225  SmallString<128> s;
226
227  if (usgn)
228    s.push_back('u');
229
230  switch (type) {
231    case 'c':
232      s += poly ? "poly8" : "int8";
233      if (scal)
234        break;
235      s += quad ? "x16" : "x8";
236      break;
237    case 's':
238      s += poly ? "poly16" : "int16";
239      if (scal)
240        break;
241      s += quad ? "x8" : "x4";
242      break;
243    case 'i':
244      s += "int32";
245      if (scal)
246        break;
247      s += quad ? "x4" : "x2";
248      break;
249    case 'l':
250      s += "int64";
251      if (scal)
252        break;
253      s += quad ? "x2" : "x1";
254      break;
255    case 'h':
256      s += "float16";
257      if (scal)
258        break;
259      s += quad ? "x8" : "x4";
260      break;
261    case 'f':
262      s += "float32";
263      if (scal)
264        break;
265      s += quad ? "x4" : "x2";
266      break;
267    default:
268      throw "unhandled type!";
269      break;
270  }
271
272  if (mod == '2')
273    s += "x2";
274  if (mod == '3')
275    s += "x3";
276  if (mod == '4')
277    s += "x4";
278
279  // Append _t, finishing the type string typedef type.
280  s += "_t";
281
282  if (cnst)
283    s += " const";
284
285  if (pntr)
286    s += " *";
287
288  return s.str();
289}
290
291/// BuiltinTypeString - for a modifier and type, generate the clang
292/// BuiltinsARM.def prototype code for the function.  See the top of clang's
293/// Builtins.def for a description of the type strings.
294static std::string BuiltinTypeString(const char mod, StringRef typestr,
295                                     ClassKind ck, bool ret) {
296  bool quad = false;
297  bool poly = false;
298  bool usgn = false;
299  bool scal = false;
300  bool cnst = false;
301  bool pntr = false;
302
303  if (mod == 'v')
304    return "v"; // void
305  if (mod == 'i')
306    return "i"; // int
307
308  // base type to get the type string for.
309  char type = ClassifyType(typestr, quad, poly, usgn);
310
311  // Based on the modifying character, change the type and width if necessary.
312  type = ModType(mod, type, quad, poly, usgn, scal, cnst, pntr);
313
314  // All pointers are void* pointers.  Change type to 'v' now.
315  if (pntr) {
316    usgn = false;
317    poly = false;
318    type = 'v';
319  }
320  // Treat half-float ('h') types as unsigned short ('s') types.
321  if (type == 'h') {
322    type = 's';
323    usgn = true;
324  }
325  usgn = usgn | poly | ((ck == ClassI || ck == ClassW) && scal && type != 'f');
326
327  if (scal) {
328    SmallString<128> s;
329
330    if (usgn)
331      s.push_back('U');
332    else if (type == 'c')
333      s.push_back('S'); // make chars explicitly signed
334
335    if (type == 'l') // 64-bit long
336      s += "LLi";
337    else
338      s.push_back(type);
339
340    if (cnst)
341      s.push_back('C');
342    if (pntr)
343      s.push_back('*');
344    return s.str();
345  }
346
347  // Since the return value must be one type, return a vector type of the
348  // appropriate width which we will bitcast.  An exception is made for
349  // returning structs of 2, 3, or 4 vectors which are returned in a sret-like
350  // fashion, storing them to a pointer arg.
351  if (ret) {
352    if (mod >= '2' && mod <= '4')
353      return "vv*"; // void result with void* first argument
354    if (mod == 'f' || (ck != ClassB && type == 'f'))
355      return quad ? "V4f" : "V2f";
356    if (ck != ClassB && type == 's')
357      return quad ? "V8s" : "V4s";
358    if (ck != ClassB && type == 'i')
359      return quad ? "V4i" : "V2i";
360    if (ck != ClassB && type == 'l')
361      return quad ? "V2LLi" : "V1LLi";
362
363    return quad ? "V16Sc" : "V8Sc";
364  }
365
366  // Non-return array types are passed as individual vectors.
367  if (mod == '2')
368    return quad ? "V16ScV16Sc" : "V8ScV8Sc";
369  if (mod == '3')
370    return quad ? "V16ScV16ScV16Sc" : "V8ScV8ScV8Sc";
371  if (mod == '4')
372    return quad ? "V16ScV16ScV16ScV16Sc" : "V8ScV8ScV8ScV8Sc";
373
374  if (mod == 'f' || (ck != ClassB && type == 'f'))
375    return quad ? "V4f" : "V2f";
376  if (ck != ClassB && type == 's')
377    return quad ? "V8s" : "V4s";
378  if (ck != ClassB && type == 'i')
379    return quad ? "V4i" : "V2i";
380  if (ck != ClassB && type == 'l')
381    return quad ? "V2LLi" : "V1LLi";
382
383  return quad ? "V16Sc" : "V8Sc";
384}
385
386/// MangleName - Append a type or width suffix to a base neon function name,
387/// and insert a 'q' in the appropriate location if the operation works on
388/// 128b rather than 64b.   E.g. turn "vst2_lane" into "vst2q_lane_f32", etc.
389static std::string MangleName(const std::string &name, StringRef typestr,
390                              ClassKind ck) {
391  if (name == "vcvt_f32_f16")
392    return name;
393
394  bool quad = false;
395  bool poly = false;
396  bool usgn = false;
397  char type = ClassifyType(typestr, quad, poly, usgn);
398
399  std::string s = name;
400
401  switch (type) {
402  case 'c':
403    switch (ck) {
404    case ClassS: s += poly ? "_p8" : usgn ? "_u8" : "_s8"; break;
405    case ClassI: s += "_i8"; break;
406    case ClassW: s += "_8"; break;
407    default: break;
408    }
409    break;
410  case 's':
411    switch (ck) {
412    case ClassS: s += poly ? "_p16" : usgn ? "_u16" : "_s16"; break;
413    case ClassI: s += "_i16"; break;
414    case ClassW: s += "_16"; break;
415    default: break;
416    }
417    break;
418  case 'i':
419    switch (ck) {
420    case ClassS: s += usgn ? "_u32" : "_s32"; break;
421    case ClassI: s += "_i32"; break;
422    case ClassW: s += "_32"; break;
423    default: break;
424    }
425    break;
426  case 'l':
427    switch (ck) {
428    case ClassS: s += usgn ? "_u64" : "_s64"; break;
429    case ClassI: s += "_i64"; break;
430    case ClassW: s += "_64"; break;
431    default: break;
432    }
433    break;
434  case 'h':
435    switch (ck) {
436    case ClassS:
437    case ClassI: s += "_f16"; break;
438    case ClassW: s += "_16"; break;
439    default: break;
440    }
441    break;
442  case 'f':
443    switch (ck) {
444    case ClassS:
445    case ClassI: s += "_f32"; break;
446    case ClassW: s += "_32"; break;
447    default: break;
448    }
449    break;
450  default:
451    throw "unhandled type!";
452    break;
453  }
454  if (ck == ClassB)
455    s += "_v";
456
457  // Insert a 'q' before the first '_' character so that it ends up before
458  // _lane or _n on vector-scalar operations.
459  if (quad) {
460    size_t pos = s.find('_');
461    s = s.insert(pos, "q");
462  }
463  return s;
464}
465
466/// UseMacro - Examine the prototype string to determine if the intrinsic
467/// should be defined as a preprocessor macro instead of an inline function.
468static bool UseMacro(const std::string &proto) {
469  // If this builtin takes an immediate argument, we need to #define it rather
470  // than use a standard declaration, so that SemaChecking can range check
471  // the immediate passed by the user.
472  if (proto.find('i') != std::string::npos)
473    return true;
474
475  // Pointer arguments need to use macros to avoid hiding aligned attributes
476  // from the pointer type.
477  if (proto.find('p') != std::string::npos ||
478      proto.find('c') != std::string::npos)
479    return true;
480
481  return false;
482}
483
484/// MacroArgUsedDirectly - Return true if argument i for an intrinsic that is
485/// defined as a macro should be accessed directly instead of being first
486/// assigned to a local temporary.
487static bool MacroArgUsedDirectly(const std::string &proto, unsigned i) {
488  // True for constant ints (i), pointers (p) and const pointers (c).
489  return (proto[i] == 'i' || proto[i] == 'p' || proto[i] == 'c');
490}
491
492// Generate the string "(argtype a, argtype b, ...)"
493static std::string GenArgs(const std::string &proto, StringRef typestr) {
494  bool define = UseMacro(proto);
495  char arg = 'a';
496
497  std::string s;
498  s += "(";
499
500  for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) {
501    if (define) {
502      // Some macro arguments are used directly instead of being assigned
503      // to local temporaries; prepend an underscore prefix to make their
504      // names consistent with the local temporaries.
505      if (MacroArgUsedDirectly(proto, i))
506        s += "__";
507    } else {
508      s += TypeString(proto[i], typestr) + " __";
509    }
510    s.push_back(arg);
511    if ((i + 1) < e)
512      s += ", ";
513  }
514
515  s += ")";
516  return s;
517}
518
519// Macro arguments are not type-checked like inline function arguments, so
520// assign them to local temporaries to get the right type checking.
521static std::string GenMacroLocals(const std::string &proto, StringRef typestr) {
522  char arg = 'a';
523  std::string s;
524  bool generatedLocal = false;
525
526  for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) {
527    // Do not create a temporary for an immediate argument.
528    // That would defeat the whole point of using a macro!
529    if (MacroArgUsedDirectly(proto, i))
530      continue;
531    generatedLocal = true;
532
533    s += TypeString(proto[i], typestr) + " __";
534    s.push_back(arg);
535    s += " = (";
536    s.push_back(arg);
537    s += "); ";
538  }
539
540  if (generatedLocal)
541    s += "\\\n  ";
542  return s;
543}
544
545// Use the vmovl builtin to sign-extend or zero-extend a vector.
546static std::string Extend(StringRef typestr, const std::string &a) {
547  std::string s;
548  s = MangleName("vmovl", typestr, ClassS);
549  s += "(" + a + ")";
550  return s;
551}
552
553static std::string Duplicate(unsigned nElts, StringRef typestr,
554                             const std::string &a) {
555  std::string s;
556
557  s = "(" + TypeString('d', typestr) + "){ ";
558  for (unsigned i = 0; i != nElts; ++i) {
559    s += a;
560    if ((i + 1) < nElts)
561      s += ", ";
562  }
563  s += " }";
564
565  return s;
566}
567
568static std::string SplatLane(unsigned nElts, const std::string &vec,
569                             const std::string &lane) {
570  std::string s = "__builtin_shufflevector(" + vec + ", " + vec;
571  for (unsigned i = 0; i < nElts; ++i)
572    s += ", " + lane;
573  s += ")";
574  return s;
575}
576
577static unsigned GetNumElements(StringRef typestr, bool &quad) {
578  quad = false;
579  bool dummy = false;
580  char type = ClassifyType(typestr, quad, dummy, dummy);
581  unsigned nElts = 0;
582  switch (type) {
583  case 'c': nElts = 8; break;
584  case 's': nElts = 4; break;
585  case 'i': nElts = 2; break;
586  case 'l': nElts = 1; break;
587  case 'h': nElts = 4; break;
588  case 'f': nElts = 2; break;
589  default:
590    throw "unhandled type!";
591    break;
592  }
593  if (quad) nElts <<= 1;
594  return nElts;
595}
596
597// Generate the definition for this intrinsic, e.g. "a + b" for OpAdd.
598static std::string GenOpString(OpKind op, const std::string &proto,
599                               StringRef typestr) {
600  bool quad;
601  unsigned nElts = GetNumElements(typestr, quad);
602  bool define = UseMacro(proto);
603
604  std::string ts = TypeString(proto[0], typestr);
605  std::string s;
606  if (!define) {
607    s = "return ";
608  }
609
610  switch(op) {
611  case OpAdd:
612    s += "__a + __b;";
613    break;
614  case OpAddl:
615    s += Extend(typestr, "__a") + " + " + Extend(typestr, "__b") + ";";
616    break;
617  case OpAddw:
618    s += "__a + " + Extend(typestr, "__b") + ";";
619    break;
620  case OpSub:
621    s += "__a - __b;";
622    break;
623  case OpSubl:
624    s += Extend(typestr, "__a") + " - " + Extend(typestr, "__b") + ";";
625    break;
626  case OpSubw:
627    s += "__a - " + Extend(typestr, "__b") + ";";
628    break;
629  case OpMulN:
630    s += "__a * " + Duplicate(nElts, typestr, "__b") + ";";
631    break;
632  case OpMulLane:
633    s += "__a * " + SplatLane(nElts, "__b", "__c") + ";";
634    break;
635  case OpMul:
636    s += "__a * __b;";
637    break;
638  case OpMullLane:
639    s += MangleName("vmull", typestr, ClassS) + "(__a, " +
640      SplatLane(nElts, "__b", "__c") + ");";
641    break;
642  case OpMlaN:
643    s += "__a + (__b * " + Duplicate(nElts, typestr, "__c") + ");";
644    break;
645  case OpMlaLane:
646    s += "__a + (__b * " + SplatLane(nElts, "__c", "__d") + ");";
647    break;
648  case OpMla:
649    s += "__a + (__b * __c);";
650    break;
651  case OpMlalN:
652    s += "__a + " + MangleName("vmull", typestr, ClassS) + "(__b, " +
653      Duplicate(nElts, typestr, "__c") + ");";
654    break;
655  case OpMlalLane:
656    s += "__a + " + MangleName("vmull", typestr, ClassS) + "(__b, " +
657      SplatLane(nElts, "__c", "__d") + ");";
658    break;
659  case OpMlal:
660    s += "__a + " + MangleName("vmull", typestr, ClassS) + "(__b, __c);";
661    break;
662  case OpMlsN:
663    s += "__a - (__b * " + Duplicate(nElts, typestr, "__c") + ");";
664    break;
665  case OpMlsLane:
666    s += "__a - (__b * " + SplatLane(nElts, "__c", "__d") + ");";
667    break;
668  case OpMls:
669    s += "__a - (__b * __c);";
670    break;
671  case OpMlslN:
672    s += "__a - " + MangleName("vmull", typestr, ClassS) + "(__b, " +
673      Duplicate(nElts, typestr, "__c") + ");";
674    break;
675  case OpMlslLane:
676    s += "__a - " + MangleName("vmull", typestr, ClassS) + "(__b, " +
677      SplatLane(nElts, "__c", "__d") + ");";
678    break;
679  case OpMlsl:
680    s += "__a - " + MangleName("vmull", typestr, ClassS) + "(__b, __c);";
681    break;
682  case OpQDMullLane:
683    s += MangleName("vqdmull", typestr, ClassS) + "(__a, " +
684      SplatLane(nElts, "__b", "__c") + ");";
685    break;
686  case OpQDMlalLane:
687    s += MangleName("vqdmlal", typestr, ClassS) + "(__a, __b, " +
688      SplatLane(nElts, "__c", "__d") + ");";
689    break;
690  case OpQDMlslLane:
691    s += MangleName("vqdmlsl", typestr, ClassS) + "(__a, __b, " +
692      SplatLane(nElts, "__c", "__d") + ");";
693    break;
694  case OpQDMulhLane:
695    s += MangleName("vqdmulh", typestr, ClassS) + "(__a, " +
696      SplatLane(nElts, "__b", "__c") + ");";
697    break;
698  case OpQRDMulhLane:
699    s += MangleName("vqrdmulh", typestr, ClassS) + "(__a, " +
700      SplatLane(nElts, "__b", "__c") + ");";
701    break;
702  case OpEq:
703    s += "(" + ts + ")(__a == __b);";
704    break;
705  case OpGe:
706    s += "(" + ts + ")(__a >= __b);";
707    break;
708  case OpLe:
709    s += "(" + ts + ")(__a <= __b);";
710    break;
711  case OpGt:
712    s += "(" + ts + ")(__a > __b);";
713    break;
714  case OpLt:
715    s += "(" + ts + ")(__a < __b);";
716    break;
717  case OpNeg:
718    s += " -__a;";
719    break;
720  case OpNot:
721    s += " ~__a;";
722    break;
723  case OpAnd:
724    s += "__a & __b;";
725    break;
726  case OpOr:
727    s += "__a | __b;";
728    break;
729  case OpXor:
730    s += "__a ^ __b;";
731    break;
732  case OpAndNot:
733    s += "__a & ~__b;";
734    break;
735  case OpOrNot:
736    s += "__a | ~__b;";
737    break;
738  case OpCast:
739    s += "(" + ts + ")__a;";
740    break;
741  case OpConcat:
742    s += "(" + ts + ")__builtin_shufflevector((int64x1_t)__a";
743    s += ", (int64x1_t)__b, 0, 1);";
744    break;
745  case OpHi:
746    s += "(" + ts +
747      ")__builtin_shufflevector((int64x2_t)__a, (int64x2_t)__a, 1);";
748    break;
749  case OpLo:
750    s += "(" + ts +
751      ")__builtin_shufflevector((int64x2_t)__a, (int64x2_t)__a, 0);";
752    break;
753  case OpDup:
754    s += Duplicate(nElts, typestr, "__a") + ";";
755    break;
756  case OpDupLane:
757    s += SplatLane(nElts, "__a", "__b") + ";";
758    break;
759  case OpSelect:
760    // ((0 & 1) | (~0 & 2))
761    s += "(" + ts + ")";
762    ts = TypeString(proto[1], typestr);
763    s += "((__a & (" + ts + ")__b) | ";
764    s += "(~__a & (" + ts + ")__c));";
765    break;
766  case OpRev16:
767    s += "__builtin_shufflevector(__a, __a";
768    for (unsigned i = 2; i <= nElts; i += 2)
769      for (unsigned j = 0; j != 2; ++j)
770        s += ", " + utostr(i - j - 1);
771    s += ");";
772    break;
773  case OpRev32: {
774    unsigned WordElts = nElts >> (1 + (int)quad);
775    s += "__builtin_shufflevector(__a, __a";
776    for (unsigned i = WordElts; i <= nElts; i += WordElts)
777      for (unsigned j = 0; j != WordElts; ++j)
778        s += ", " + utostr(i - j - 1);
779    s += ");";
780    break;
781  }
782  case OpRev64: {
783    unsigned DblWordElts = nElts >> (int)quad;
784    s += "__builtin_shufflevector(__a, __a";
785    for (unsigned i = DblWordElts; i <= nElts; i += DblWordElts)
786      for (unsigned j = 0; j != DblWordElts; ++j)
787        s += ", " + utostr(i - j - 1);
788    s += ");";
789    break;
790  }
791  case OpAbdl: {
792    std::string abd = MangleName("vabd", typestr, ClassS) + "(__a, __b)";
793    if (typestr[0] != 'U') {
794      // vabd results are always unsigned and must be zero-extended.
795      std::string utype = "U" + typestr.str();
796      s += "(" + TypeString(proto[0], typestr) + ")";
797      abd = "(" + TypeString('d', utype) + ")" + abd;
798      s += Extend(utype, abd) + ";";
799    } else {
800      s += Extend(typestr, abd) + ";";
801    }
802    break;
803  }
804  case OpAba:
805    s += "__a + " + MangleName("vabd", typestr, ClassS) + "(__b, __c);";
806    break;
807  case OpAbal: {
808    s += "__a + ";
809    std::string abd = MangleName("vabd", typestr, ClassS) + "(__b, __c)";
810    if (typestr[0] != 'U') {
811      // vabd results are always unsigned and must be zero-extended.
812      std::string utype = "U" + typestr.str();
813      s += "(" + TypeString(proto[0], typestr) + ")";
814      abd = "(" + TypeString('d', utype) + ")" + abd;
815      s += Extend(utype, abd) + ";";
816    } else {
817      s += Extend(typestr, abd) + ";";
818    }
819    break;
820  }
821  default:
822    throw "unknown OpKind!";
823    break;
824  }
825  return s;
826}
827
828static unsigned GetNeonEnum(const std::string &proto, StringRef typestr) {
829  unsigned mod = proto[0];
830
831  if (mod == 'v' || mod == 'f')
832    mod = proto[1];
833
834  bool quad = false;
835  bool poly = false;
836  bool usgn = false;
837  bool scal = false;
838  bool cnst = false;
839  bool pntr = false;
840
841  // Base type to get the type string for.
842  char type = ClassifyType(typestr, quad, poly, usgn);
843
844  // Based on the modifying character, change the type and width if necessary.
845  type = ModType(mod, type, quad, poly, usgn, scal, cnst, pntr);
846
847  NeonTypeFlags::EltType ET;
848  switch (type) {
849    case 'c':
850      ET = poly ? NeonTypeFlags::Poly8 : NeonTypeFlags::Int8;
851      break;
852    case 's':
853      ET = poly ? NeonTypeFlags::Poly16 : NeonTypeFlags::Int16;
854      break;
855    case 'i':
856      ET = NeonTypeFlags::Int32;
857      break;
858    case 'l':
859      ET = NeonTypeFlags::Int64;
860      break;
861    case 'h':
862      ET = NeonTypeFlags::Float16;
863      break;
864    case 'f':
865      ET = NeonTypeFlags::Float32;
866      break;
867    default:
868      throw "unhandled type!";
869      break;
870  }
871  NeonTypeFlags Flags(ET, usgn, quad && proto[1] != 'g');
872  return Flags.getFlags();
873}
874
875// Generate the definition for this intrinsic, e.g. __builtin_neon_cls(a)
876static std::string GenBuiltin(const std::string &name, const std::string &proto,
877                              StringRef typestr, ClassKind ck) {
878  std::string s;
879
880  // If this builtin returns a struct 2, 3, or 4 vectors, pass it as an implicit
881  // sret-like argument.
882  bool sret = (proto[0] >= '2' && proto[0] <= '4');
883
884  bool define = UseMacro(proto);
885
886  // Check if the prototype has a scalar operand with the type of the vector
887  // elements.  If not, bitcasting the args will take care of arg checking.
888  // The actual signedness etc. will be taken care of with special enums.
889  if (proto.find('s') == std::string::npos)
890    ck = ClassB;
891
892  if (proto[0] != 'v') {
893    std::string ts = TypeString(proto[0], typestr);
894
895    if (define) {
896      if (sret)
897        s += ts + " r; ";
898      else
899        s += "(" + ts + ")";
900    } else if (sret) {
901      s += ts + " r; ";
902    } else {
903      s += "return (" + ts + ")";
904    }
905  }
906
907  bool splat = proto.find('a') != std::string::npos;
908
909  s += "__builtin_neon_";
910  if (splat) {
911    // Call the non-splat builtin: chop off the "_n" suffix from the name.
912    std::string vname(name, 0, name.size()-2);
913    s += MangleName(vname, typestr, ck);
914  } else {
915    s += MangleName(name, typestr, ck);
916  }
917  s += "(";
918
919  // Pass the address of the return variable as the first argument to sret-like
920  // builtins.
921  if (sret)
922    s += "&r, ";
923
924  char arg = 'a';
925  for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) {
926    std::string args = std::string(&arg, 1);
927
928    // Use the local temporaries instead of the macro arguments.
929    args = "__" + args;
930
931    bool argQuad = false;
932    bool argPoly = false;
933    bool argUsgn = false;
934    bool argScalar = false;
935    bool dummy = false;
936    char argType = ClassifyType(typestr, argQuad, argPoly, argUsgn);
937    argType = ModType(proto[i], argType, argQuad, argPoly, argUsgn, argScalar,
938                      dummy, dummy);
939
940    // Handle multiple-vector values specially, emitting each subvector as an
941    // argument to the __builtin.
942    if (proto[i] >= '2' && proto[i] <= '4') {
943      // Check if an explicit cast is needed.
944      if (argType != 'c' || argPoly || argUsgn)
945        args = (argQuad ? "(int8x16_t)" : "(int8x8_t)") + args;
946
947      for (unsigned vi = 0, ve = proto[i] - '0'; vi != ve; ++vi) {
948        s += args + ".val[" + utostr(vi) + "]";
949        if ((vi + 1) < ve)
950          s += ", ";
951      }
952      if ((i + 1) < e)
953        s += ", ";
954
955      continue;
956    }
957
958    if (splat && (i + 1) == e)
959      args = Duplicate(GetNumElements(typestr, argQuad), typestr, args);
960
961    // Check if an explicit cast is needed.
962    if ((splat || !argScalar) &&
963        ((ck == ClassB && argType != 'c') || argPoly || argUsgn)) {
964      std::string argTypeStr = "c";
965      if (ck != ClassB)
966        argTypeStr = argType;
967      if (argQuad)
968        argTypeStr = "Q" + argTypeStr;
969      args = "(" + TypeString('d', argTypeStr) + ")" + args;
970    }
971
972    s += args;
973    if ((i + 1) < e)
974      s += ", ";
975  }
976
977  // Extra constant integer to hold type class enum for this function, e.g. s8
978  if (ck == ClassB)
979    s += ", " + utostr(GetNeonEnum(proto, typestr));
980
981  s += ");";
982
983  if (proto[0] != 'v' && sret) {
984    if (define)
985      s += " r;";
986    else
987      s += " return r;";
988  }
989  return s;
990}
991
992static std::string GenBuiltinDef(const std::string &name,
993                                 const std::string &proto,
994                                 StringRef typestr, ClassKind ck) {
995  std::string s("BUILTIN(__builtin_neon_");
996
997  // If all types are the same size, bitcasting the args will take care
998  // of arg checking.  The actual signedness etc. will be taken care of with
999  // special enums.
1000  if (proto.find('s') == std::string::npos)
1001    ck = ClassB;
1002
1003  s += MangleName(name, typestr, ck);
1004  s += ", \"";
1005
1006  for (unsigned i = 0, e = proto.size(); i != e; ++i)
1007    s += BuiltinTypeString(proto[i], typestr, ck, i == 0);
1008
1009  // Extra constant integer to hold type class enum for this function, e.g. s8
1010  if (ck == ClassB)
1011    s += "i";
1012
1013  s += "\", \"n\")";
1014  return s;
1015}
1016
1017static std::string GenIntrinsic(const std::string &name,
1018                                const std::string &proto,
1019                                StringRef outTypeStr, StringRef inTypeStr,
1020                                OpKind kind, ClassKind classKind) {
1021  assert(!proto.empty() && "");
1022  bool define = UseMacro(proto);
1023  std::string s;
1024
1025  // static always inline + return type
1026  if (define)
1027    s += "#define ";
1028  else
1029    s += "__ai " + TypeString(proto[0], outTypeStr) + " ";
1030
1031  // Function name with type suffix
1032  std::string mangledName = MangleName(name, outTypeStr, ClassS);
1033  if (outTypeStr != inTypeStr) {
1034    // If the input type is different (e.g., for vreinterpret), append a suffix
1035    // for the input type.  String off a "Q" (quad) prefix so that MangleName
1036    // does not insert another "q" in the name.
1037    unsigned typeStrOff = (inTypeStr[0] == 'Q' ? 1 : 0);
1038    StringRef inTypeNoQuad = inTypeStr.substr(typeStrOff);
1039    mangledName = MangleName(mangledName, inTypeNoQuad, ClassS);
1040  }
1041  s += mangledName;
1042
1043  // Function arguments
1044  s += GenArgs(proto, inTypeStr);
1045
1046  // Definition.
1047  if (define) {
1048    s += " __extension__ ({ \\\n  ";
1049    s += GenMacroLocals(proto, inTypeStr);
1050  } else {
1051    s += " { \\\n  ";
1052  }
1053
1054  if (kind != OpNone)
1055    s += GenOpString(kind, proto, outTypeStr);
1056  else
1057    s += GenBuiltin(name, proto, outTypeStr, classKind);
1058  if (define)
1059    s += " })";
1060  else
1061    s += " }";
1062  s += "\n";
1063  return s;
1064}
1065
1066/// run - Read the records in arm_neon.td and output arm_neon.h.  arm_neon.h
1067/// is comprised of type definitions and function declarations.
1068void NeonEmitter::run(raw_ostream &OS) {
1069  OS <<
1070    "/*===---- arm_neon.h - ARM Neon intrinsics ------------------------------"
1071    "---===\n"
1072    " *\n"
1073    " * Permission is hereby granted, free of charge, to any person obtaining "
1074    "a copy\n"
1075    " * of this software and associated documentation files (the \"Software\"),"
1076    " to deal\n"
1077    " * in the Software without restriction, including without limitation the "
1078    "rights\n"
1079    " * to use, copy, modify, merge, publish, distribute, sublicense, "
1080    "and/or sell\n"
1081    " * copies of the Software, and to permit persons to whom the Software is\n"
1082    " * furnished to do so, subject to the following conditions:\n"
1083    " *\n"
1084    " * The above copyright notice and this permission notice shall be "
1085    "included in\n"
1086    " * all copies or substantial portions of the Software.\n"
1087    " *\n"
1088    " * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, "
1089    "EXPRESS OR\n"
1090    " * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF "
1091    "MERCHANTABILITY,\n"
1092    " * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT "
1093    "SHALL THE\n"
1094    " * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR "
1095    "OTHER\n"
1096    " * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, "
1097    "ARISING FROM,\n"
1098    " * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER "
1099    "DEALINGS IN\n"
1100    " * THE SOFTWARE.\n"
1101    " *\n"
1102    " *===--------------------------------------------------------------------"
1103    "---===\n"
1104    " */\n\n";
1105
1106  OS << "#ifndef __ARM_NEON_H\n";
1107  OS << "#define __ARM_NEON_H\n\n";
1108
1109  OS << "#ifndef __ARM_NEON__\n";
1110  OS << "#error \"NEON support not enabled\"\n";
1111  OS << "#endif\n\n";
1112
1113  OS << "#include <stdint.h>\n\n";
1114
1115  // Emit NEON-specific scalar typedefs.
1116  OS << "typedef float float32_t;\n";
1117  OS << "typedef int8_t poly8_t;\n";
1118  OS << "typedef int16_t poly16_t;\n";
1119  OS << "typedef uint16_t float16_t;\n";
1120
1121  // Emit Neon vector typedefs.
1122  std::string TypedefTypes("cQcsQsiQilQlUcQUcUsQUsUiQUiUlQUlhQhfQfPcQPcPsQPs");
1123  SmallVector<StringRef, 24> TDTypeVec;
1124  ParseTypes(0, TypedefTypes, TDTypeVec);
1125
1126  // Emit vector typedefs.
1127  for (unsigned i = 0, e = TDTypeVec.size(); i != e; ++i) {
1128    bool dummy, quad = false, poly = false;
1129    (void) ClassifyType(TDTypeVec[i], quad, poly, dummy);
1130    if (poly)
1131      OS << "typedef __attribute__((neon_polyvector_type(";
1132    else
1133      OS << "typedef __attribute__((neon_vector_type(";
1134
1135    unsigned nElts = GetNumElements(TDTypeVec[i], quad);
1136    OS << utostr(nElts) << "))) ";
1137    if (nElts < 10)
1138      OS << " ";
1139
1140    OS << TypeString('s', TDTypeVec[i]);
1141    OS << " " << TypeString('d', TDTypeVec[i]) << ";\n";
1142  }
1143  OS << "\n";
1144
1145  // Emit struct typedefs.
1146  for (unsigned vi = 2; vi != 5; ++vi) {
1147    for (unsigned i = 0, e = TDTypeVec.size(); i != e; ++i) {
1148      std::string ts = TypeString('d', TDTypeVec[i]);
1149      std::string vs = TypeString('0' + vi, TDTypeVec[i]);
1150      OS << "typedef struct " << vs << " {\n";
1151      OS << "  " << ts << " val";
1152      OS << "[" << utostr(vi) << "]";
1153      OS << ";\n} ";
1154      OS << vs << ";\n\n";
1155    }
1156  }
1157
1158  OS<<"#define __ai static __attribute__((__always_inline__, __nodebug__))\n\n";
1159
1160  std::vector<Record*> RV = Records.getAllDerivedDefinitions("Inst");
1161
1162  // Emit vmovl, vmull and vabd intrinsics first so they can be used by other
1163  // intrinsics.  (Some of the saturating multiply instructions are also
1164  // used to implement the corresponding "_lane" variants, but tablegen
1165  // sorts the records into alphabetical order so that the "_lane" variants
1166  // come after the intrinsics they use.)
1167  emitIntrinsic(OS, Records.getDef("VMOVL"));
1168  emitIntrinsic(OS, Records.getDef("VMULL"));
1169  emitIntrinsic(OS, Records.getDef("VABD"));
1170
1171  for (unsigned i = 0, e = RV.size(); i != e; ++i) {
1172    Record *R = RV[i];
1173    if (R->getName() != "VMOVL" &&
1174        R->getName() != "VMULL" &&
1175        R->getName() != "VABD")
1176      emitIntrinsic(OS, R);
1177  }
1178
1179  OS << "#undef __ai\n\n";
1180  OS << "#endif /* __ARM_NEON_H */\n";
1181}
1182
1183/// emitIntrinsic - Write out the arm_neon.h header file definitions for the
1184/// intrinsics specified by record R.
1185void NeonEmitter::emitIntrinsic(raw_ostream &OS, Record *R) {
1186  std::string name = R->getValueAsString("Name");
1187  std::string Proto = R->getValueAsString("Prototype");
1188  std::string Types = R->getValueAsString("Types");
1189
1190  SmallVector<StringRef, 16> TypeVec;
1191  ParseTypes(R, Types, TypeVec);
1192
1193  OpKind kind = OpMap[R->getValueAsDef("Operand")->getName()];
1194
1195  ClassKind classKind = ClassNone;
1196  if (R->getSuperClasses().size() >= 2)
1197    classKind = ClassMap[R->getSuperClasses()[1]];
1198  if (classKind == ClassNone && kind == OpNone)
1199    throw TGError(R->getLoc(), "Builtin has no class kind");
1200
1201  for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) {
1202    if (kind == OpReinterpret) {
1203      bool outQuad = false;
1204      bool dummy = false;
1205      (void)ClassifyType(TypeVec[ti], outQuad, dummy, dummy);
1206      for (unsigned srcti = 0, srcte = TypeVec.size();
1207           srcti != srcte; ++srcti) {
1208        bool inQuad = false;
1209        (void)ClassifyType(TypeVec[srcti], inQuad, dummy, dummy);
1210        if (srcti == ti || inQuad != outQuad)
1211          continue;
1212        OS << GenIntrinsic(name, Proto, TypeVec[ti], TypeVec[srcti],
1213                           OpCast, ClassS);
1214      }
1215    } else {
1216      OS << GenIntrinsic(name, Proto, TypeVec[ti], TypeVec[ti],
1217                         kind, classKind);
1218    }
1219  }
1220  OS << "\n";
1221}
1222
1223static unsigned RangeFromType(const char mod, StringRef typestr) {
1224  // base type to get the type string for.
1225  bool quad = false, dummy = false;
1226  char type = ClassifyType(typestr, quad, dummy, dummy);
1227  type = ModType(mod, type, quad, dummy, dummy, dummy, dummy, dummy);
1228
1229  switch (type) {
1230    case 'c':
1231      return (8 << (int)quad) - 1;
1232    case 'h':
1233    case 's':
1234      return (4 << (int)quad) - 1;
1235    case 'f':
1236    case 'i':
1237      return (2 << (int)quad) - 1;
1238    case 'l':
1239      return (1 << (int)quad) - 1;
1240    default:
1241      throw "unhandled type!";
1242      break;
1243  }
1244  assert(0 && "unreachable");
1245  return 0;
1246}
1247
1248/// runHeader - Emit a file with sections defining:
1249/// 1. the NEON section of BuiltinsARM.def.
1250/// 2. the SemaChecking code for the type overload checking.
1251/// 3. the SemaChecking code for validation of intrinsic immedate arguments.
1252void NeonEmitter::runHeader(raw_ostream &OS) {
1253  std::vector<Record*> RV = Records.getAllDerivedDefinitions("Inst");
1254
1255  StringMap<OpKind> EmittedMap;
1256
1257  // Generate BuiltinsARM.def for NEON
1258  OS << "#ifdef GET_NEON_BUILTINS\n";
1259  for (unsigned i = 0, e = RV.size(); i != e; ++i) {
1260    Record *R = RV[i];
1261    OpKind k = OpMap[R->getValueAsDef("Operand")->getName()];
1262    if (k != OpNone)
1263      continue;
1264
1265    std::string Proto = R->getValueAsString("Prototype");
1266
1267    // Functions with 'a' (the splat code) in the type prototype should not get
1268    // their own builtin as they use the non-splat variant.
1269    if (Proto.find('a') != std::string::npos)
1270      continue;
1271
1272    std::string Types = R->getValueAsString("Types");
1273    SmallVector<StringRef, 16> TypeVec;
1274    ParseTypes(R, Types, TypeVec);
1275
1276    if (R->getSuperClasses().size() < 2)
1277      throw TGError(R->getLoc(), "Builtin has no class kind");
1278
1279    std::string name = R->getValueAsString("Name");
1280    ClassKind ck = ClassMap[R->getSuperClasses()[1]];
1281
1282    for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) {
1283      // Generate the BuiltinsARM.def declaration for this builtin, ensuring
1284      // that each unique BUILTIN() macro appears only once in the output
1285      // stream.
1286      std::string bd = GenBuiltinDef(name, Proto, TypeVec[ti], ck);
1287      if (EmittedMap.count(bd))
1288        continue;
1289
1290      EmittedMap[bd] = OpNone;
1291      OS << bd << "\n";
1292    }
1293  }
1294  OS << "#endif\n\n";
1295
1296  // Generate the overloaded type checking code for SemaChecking.cpp
1297  OS << "#ifdef GET_NEON_OVERLOAD_CHECK\n";
1298  for (unsigned i = 0, e = RV.size(); i != e; ++i) {
1299    Record *R = RV[i];
1300    OpKind k = OpMap[R->getValueAsDef("Operand")->getName()];
1301    if (k != OpNone)
1302      continue;
1303
1304    std::string Proto = R->getValueAsString("Prototype");
1305    std::string Types = R->getValueAsString("Types");
1306    std::string name = R->getValueAsString("Name");
1307
1308    // Functions with 'a' (the splat code) in the type prototype should not get
1309    // their own builtin as they use the non-splat variant.
1310    if (Proto.find('a') != std::string::npos)
1311      continue;
1312
1313    // Functions which have a scalar argument cannot be overloaded, no need to
1314    // check them if we are emitting the type checking code.
1315    if (Proto.find('s') != std::string::npos)
1316      continue;
1317
1318    SmallVector<StringRef, 16> TypeVec;
1319    ParseTypes(R, Types, TypeVec);
1320
1321    if (R->getSuperClasses().size() < 2)
1322      throw TGError(R->getLoc(), "Builtin has no class kind");
1323
1324    int si = -1, qi = -1;
1325    unsigned mask = 0, qmask = 0;
1326    for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) {
1327      // Generate the switch case(s) for this builtin for the type validation.
1328      bool quad = false, poly = false, usgn = false;
1329      (void) ClassifyType(TypeVec[ti], quad, poly, usgn);
1330
1331      if (quad) {
1332        qi = ti;
1333        qmask |= 1 << GetNeonEnum(Proto, TypeVec[ti]);
1334      } else {
1335        si = ti;
1336        mask |= 1 << GetNeonEnum(Proto, TypeVec[ti]);
1337      }
1338    }
1339    bool HasPtr = (Proto.find('p') != std::string::npos);
1340    bool HasConstPtr = (Proto.find('c') != std::string::npos);
1341    if (mask) {
1342      OS << "case ARM::BI__builtin_neon_"
1343         << MangleName(name, TypeVec[si], ClassB)
1344         << ": mask = " << "0x" << utohexstr(mask);
1345      if (HasPtr)
1346        OS << "; HasPtr = true";
1347      if (HasConstPtr)
1348        OS << "; HasConstPtr = true";
1349      OS << "; break;\n";
1350    }
1351    if (qmask) {
1352      OS << "case ARM::BI__builtin_neon_"
1353         << MangleName(name, TypeVec[qi], ClassB)
1354         << ": mask = " << "0x" << utohexstr(qmask);
1355      if (HasPtr)
1356        OS << "; HasPtr = true";
1357      if (HasConstPtr)
1358        OS << "; HasConstPtr = true";
1359      OS << "; break;\n";
1360    }
1361  }
1362  OS << "#endif\n\n";
1363
1364  // Generate the intrinsic range checking code for shift/lane immediates.
1365  OS << "#ifdef GET_NEON_IMMEDIATE_CHECK\n";
1366  for (unsigned i = 0, e = RV.size(); i != e; ++i) {
1367    Record *R = RV[i];
1368
1369    OpKind k = OpMap[R->getValueAsDef("Operand")->getName()];
1370    if (k != OpNone)
1371      continue;
1372
1373    std::string name = R->getValueAsString("Name");
1374    std::string Proto = R->getValueAsString("Prototype");
1375    std::string Types = R->getValueAsString("Types");
1376
1377    // Functions with 'a' (the splat code) in the type prototype should not get
1378    // their own builtin as they use the non-splat variant.
1379    if (Proto.find('a') != std::string::npos)
1380      continue;
1381
1382    // Functions which do not have an immediate do not need to have range
1383    // checking code emitted.
1384    size_t immPos = Proto.find('i');
1385    if (immPos == std::string::npos)
1386      continue;
1387
1388    SmallVector<StringRef, 16> TypeVec;
1389    ParseTypes(R, Types, TypeVec);
1390
1391    if (R->getSuperClasses().size() < 2)
1392      throw TGError(R->getLoc(), "Builtin has no class kind");
1393
1394    ClassKind ck = ClassMap[R->getSuperClasses()[1]];
1395
1396    for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) {
1397      std::string namestr, shiftstr, rangestr;
1398
1399      if (R->getValueAsBit("isVCVT_N")) {
1400        // VCVT between floating- and fixed-point values takes an immediate
1401        // in the range 1 to 32.
1402        ck = ClassB;
1403        rangestr = "l = 1; u = 31"; // upper bound = l + u
1404      } else if (Proto.find('s') == std::string::npos) {
1405        // Builtins which are overloaded by type will need to have their upper
1406        // bound computed at Sema time based on the type constant.
1407        ck = ClassB;
1408        if (R->getValueAsBit("isShift")) {
1409          shiftstr = ", true";
1410
1411          // Right shifts have an 'r' in the name, left shifts do not.
1412          if (name.find('r') != std::string::npos)
1413            rangestr = "l = 1; ";
1414        }
1415        rangestr += "u = RFT(TV" + shiftstr + ")";
1416      } else {
1417        // The immediate generally refers to a lane in the preceding argument.
1418        assert(immPos > 0 && "unexpected immediate operand");
1419        rangestr = "u = " + utostr(RangeFromType(Proto[immPos-1], TypeVec[ti]));
1420      }
1421      // Make sure cases appear only once by uniquing them in a string map.
1422      namestr = MangleName(name, TypeVec[ti], ck);
1423      if (EmittedMap.count(namestr))
1424        continue;
1425      EmittedMap[namestr] = OpNone;
1426
1427      // Calculate the index of the immediate that should be range checked.
1428      unsigned immidx = 0;
1429
1430      // Builtins that return a struct of multiple vectors have an extra
1431      // leading arg for the struct return.
1432      if (Proto[0] >= '2' && Proto[0] <= '4')
1433        ++immidx;
1434
1435      // Add one to the index for each argument until we reach the immediate
1436      // to be checked.  Structs of vectors are passed as multiple arguments.
1437      for (unsigned ii = 1, ie = Proto.size(); ii != ie; ++ii) {
1438        switch (Proto[ii]) {
1439          default:  immidx += 1; break;
1440          case '2': immidx += 2; break;
1441          case '3': immidx += 3; break;
1442          case '4': immidx += 4; break;
1443          case 'i': ie = ii + 1; break;
1444        }
1445      }
1446      OS << "case ARM::BI__builtin_neon_" << MangleName(name, TypeVec[ti], ck)
1447         << ": i = " << immidx << "; " << rangestr << "; break;\n";
1448    }
1449  }
1450  OS << "#endif\n\n";
1451}
1452
1453/// GenTest - Write out a test for the intrinsic specified by the name and
1454/// type strings, including the embedded patterns for FileCheck to match.
1455static std::string GenTest(const std::string &name,
1456                           const std::string &proto,
1457                           StringRef outTypeStr, StringRef inTypeStr,
1458                           bool isShift) {
1459  assert(!proto.empty() && "");
1460  std::string s;
1461
1462  // Function name with type suffix
1463  std::string mangledName = MangleName(name, outTypeStr, ClassS);
1464  if (outTypeStr != inTypeStr) {
1465    // If the input type is different (e.g., for vreinterpret), append a suffix
1466    // for the input type.  String off a "Q" (quad) prefix so that MangleName
1467    // does not insert another "q" in the name.
1468    unsigned typeStrOff = (inTypeStr[0] == 'Q' ? 1 : 0);
1469    StringRef inTypeNoQuad = inTypeStr.substr(typeStrOff);
1470    mangledName = MangleName(mangledName, inTypeNoQuad, ClassS);
1471  }
1472
1473  // Emit the FileCheck patterns.
1474  s += "// CHECK: test_" + mangledName + "\n";
1475  // s += "// CHECK: \n"; // FIXME: + expected instruction opcode.
1476
1477  // Emit the start of the test function.
1478  s += TypeString(proto[0], outTypeStr) + " test_" + mangledName + "(";
1479  char arg = 'a';
1480  std::string comma;
1481  for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) {
1482    // Do not create arguments for values that must be immediate constants.
1483    if (proto[i] == 'i')
1484      continue;
1485    s += comma + TypeString(proto[i], inTypeStr) + " ";
1486    s.push_back(arg);
1487    comma = ", ";
1488  }
1489  s += ") { \\\n  ";
1490
1491  if (proto[0] != 'v')
1492    s += "return ";
1493  s += mangledName + "(";
1494  arg = 'a';
1495  for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) {
1496    if (proto[i] == 'i') {
1497      // For immediate operands, test the maximum value.
1498      if (isShift)
1499        s += "1"; // FIXME
1500      else
1501        // The immediate generally refers to a lane in the preceding argument.
1502        s += utostr(RangeFromType(proto[i-1], inTypeStr));
1503    } else {
1504      s.push_back(arg);
1505    }
1506    if ((i + 1) < e)
1507      s += ", ";
1508  }
1509  s += ");\n}\n\n";
1510  return s;
1511}
1512
1513/// runTests - Write out a complete set of tests for all of the Neon
1514/// intrinsics.
1515void NeonEmitter::runTests(raw_ostream &OS) {
1516  OS <<
1517    "// RUN: %clang_cc1 -triple thumbv7-apple-darwin \\\n"
1518    "// RUN:  -target-cpu cortex-a9 -ffreestanding -S -o - %s | FileCheck %s\n"
1519    "\n"
1520    "#include <arm_neon.h>\n"
1521    "\n";
1522
1523  std::vector<Record*> RV = Records.getAllDerivedDefinitions("Inst");
1524  for (unsigned i = 0, e = RV.size(); i != e; ++i) {
1525    Record *R = RV[i];
1526    std::string name = R->getValueAsString("Name");
1527    std::string Proto = R->getValueAsString("Prototype");
1528    std::string Types = R->getValueAsString("Types");
1529    bool isShift = R->getValueAsBit("isShift");
1530
1531    SmallVector<StringRef, 16> TypeVec;
1532    ParseTypes(R, Types, TypeVec);
1533
1534    OpKind kind = OpMap[R->getValueAsDef("Operand")->getName()];
1535    for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) {
1536      if (kind == OpReinterpret) {
1537        bool outQuad = false;
1538        bool dummy = false;
1539        (void)ClassifyType(TypeVec[ti], outQuad, dummy, dummy);
1540        for (unsigned srcti = 0, srcte = TypeVec.size();
1541             srcti != srcte; ++srcti) {
1542          bool inQuad = false;
1543          (void)ClassifyType(TypeVec[srcti], inQuad, dummy, dummy);
1544          if (srcti == ti || inQuad != outQuad)
1545            continue;
1546          OS << GenTest(name, Proto, TypeVec[ti], TypeVec[srcti], isShift);
1547        }
1548      } else {
1549        OS << GenTest(name, Proto, TypeVec[ti], TypeVec[ti], isShift);
1550      }
1551    }
1552    OS << "\n";
1553  }
1554}
1555
1556