NeonEmitter.cpp revision d1af3b901a2176bc7f4b7e2fadcd25110576b454
151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne//===- NeonEmitter.cpp - Generate arm_neon.h for use with clang -*- C++ -*-===//
251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne//
351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne//                     The LLVM Compiler Infrastructure
451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne//
551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne// This file is distributed under the University of Illinois Open Source
651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne// License. See LICENSE.TXT for details.
751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne//
851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne//===----------------------------------------------------------------------===//
951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne//
1051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne// This tablegen backend is responsible for emitting arm_neon.h, which includes
1151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne// a declaration and definition of each function specified by the ARM NEON
1251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne// compiler interface.  See ARM document DUI0348B.
1351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne//
1451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne// Each NEON instruction is implemented in terms of 1 or more functions which
1551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne// are suffixed with the element type of the input vectors.  Functions may be
1651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne// implemented in terms of generic vector operations such as +, *, -, etc. or
1751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne// by calling a __builtin_-prefixed function which will be handled by clang's
1851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne// CodeGen library.
1951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne//
2051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne// Additional validation code can be generated by this file when runHeader() is
2151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne// called, rather than the normal run() entry point.  A complete set of tests
2251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne// for Neon intrinsics can be generated by calling the runTests() entry point.
2351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne//
2451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne//===----------------------------------------------------------------------===//
2551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
2651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne#include "NeonEmitter.h"
2751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne#include "llvm/TableGen/Error.h"
2851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne#include "llvm/ADT/SmallString.h"
2951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne#include "llvm/ADT/SmallVector.h"
3051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne#include "llvm/ADT/StringExtras.h"
3151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne#include <string>
3251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
3351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourneusing namespace llvm;
3451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
3551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// ParseTypes - break down a string such as "fQf" into a vector of StringRefs,
3651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// which each StringRef representing a single type declared in the string.
3751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// for "fQf" we would end up with 2 StringRefs, "f", and "Qf", representing
3851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// 2xfloat and 4xfloat respectively.
3951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic void ParseTypes(Record *r, std::string &s,
4051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                       SmallVectorImpl<StringRef> &TV) {
4151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  const char *data = s.data();
4251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  int len = 0;
4351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
4451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 0, e = s.size(); i != e; ++i, ++len) {
4551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (data[len] == 'P' || data[len] == 'Q' || data[len] == 'U')
4651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      continue;
4751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
4851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    switch (data[len]) {
4951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      case 'c':
5051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      case 's':
5151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      case 'i':
5251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      case 'l':
5351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      case 'h':
5451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      case 'f':
5551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        break;
5651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      default:
5751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        throw TGError(r->getLoc(),
5851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                      "Unexpected letter: " + std::string(data + len, 1));
5951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        break;
6051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
6151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    TV.push_back(StringRef(data, len + 1));
6251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    data += len + 1;
6351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    len = -1;
6451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
6551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
6651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
6751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// Widen - Convert a type code into the next wider type.  char -> short,
6851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// short -> int, etc.
6951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic char Widen(const char t) {
7051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  switch (t) {
7151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'c':
7251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      return 's';
7351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 's':
7451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      return 'i';
7551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'i':
7651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      return 'l';
7751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'h':
7851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      return 'f';
7951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    default: throw "unhandled type in widen!";
8051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
8151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return '\0';
8251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
8351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
8451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// Narrow - Convert a type code into the next smaller type.  short -> char,
8551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// float -> half float, etc.
8651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic char Narrow(const char t) {
8751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  switch (t) {
8851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 's':
8951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      return 'c';
9051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'i':
9151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      return 's';
9251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'l':
9351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      return 'i';
9451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'f':
9551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      return 'h';
9651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    default: throw "unhandled type in narrow!";
9751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
9851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return '\0';
9951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
10051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
10151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// For a particular StringRef, return the base type code, and whether it has
10251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// the quad-vector, polynomial, or unsigned modifiers set.
10351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic char ClassifyType(StringRef ty, bool &quad, bool &poly, bool &usgn) {
10451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  unsigned off = 0;
10551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
10651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // remember quad.
10751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (ty[off] == 'Q') {
10851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    quad = true;
10951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    ++off;
11051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
11151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
11251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // remember poly.
11351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (ty[off] == 'P') {
11451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    poly = true;
11551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    ++off;
11651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
11751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
11851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // remember unsigned.
11951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (ty[off] == 'U') {
12051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    usgn = true;
12151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    ++off;
12251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
12351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
12451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // base type to get the type string for.
12551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return ty[off];
12651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
12751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
12851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// ModType - Transform a type code and its modifiers based on a mod code. The
12951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// mod code definitions may be found at the top of arm_neon.td.
13051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic char ModType(const char mod, char type, bool &quad, bool &poly,
13151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                    bool &usgn, bool &scal, bool &cnst, bool &pntr) {
13251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  switch (mod) {
13351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 't':
13451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (poly) {
13551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        poly = false;
13651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        usgn = true;
13751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      }
13851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
13951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'u':
14051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      usgn = true;
14151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      poly = false;
14251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (type == 'f')
14351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        type = 'i';
14451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
14551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'x':
14651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      usgn = false;
14751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      poly = false;
14851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (type == 'f')
14951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        type = 'i';
15051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
15151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'f':
15251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (type == 'h')
15351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        quad = true;
15451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      type = 'f';
15551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      usgn = false;
15651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
15751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'g':
15851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      quad = false;
15951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
16051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'w':
16151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      type = Widen(type);
16251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      quad = true;
16351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
16451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'n':
16551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      type = Widen(type);
16651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
16751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'i':
16851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      type = 'i';
16951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      scal = true;
17051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
17151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'l':
17251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      type = 'l';
17351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      scal = true;
17451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      usgn = true;
17551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
17651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 's':
17751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'a':
17851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      scal = true;
17951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
18051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'k':
18151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      quad = true;
18251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
18351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'c':
18451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      cnst = true;
18551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'p':
18651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      pntr = true;
18751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      scal = true;
18851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
18951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'h':
19051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      type = Narrow(type);
19151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (type == 'h')
19251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        quad = false;
19351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
19451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'e':
19551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      type = Narrow(type);
19651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      usgn = true;
19751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
19851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    default:
19951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
20051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
20151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return type;
20251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
20351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
20451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// TypeString - for a modifier and type, generate the name of the typedef for
20551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// that type.  QUc -> uint8x8_t.
20651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic std::string TypeString(const char mod, StringRef typestr) {
20751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool quad = false;
20851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool poly = false;
20951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool usgn = false;
21051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool scal = false;
21151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool cnst = false;
21251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool pntr = false;
21351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
21451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (mod == 'v')
21551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    return "void";
21651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (mod == 'i')
21751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    return "int";
21851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
21951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // base type to get the type string for.
22051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  char type = ClassifyType(typestr, quad, poly, usgn);
22151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
22251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Based on the modifying character, change the type and width if necessary.
22351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  type = ModType(mod, type, quad, poly, usgn, scal, cnst, pntr);
22451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
22551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  SmallString<128> s;
22651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
22751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (usgn)
22851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s.push_back('u');
22951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
23051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  switch (type) {
23151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'c':
23251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += poly ? "poly8" : "int8";
23351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (scal)
23451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        break;
23551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += quad ? "x16" : "x8";
23651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
23751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 's':
23851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += poly ? "poly16" : "int16";
23951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (scal)
24051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        break;
24151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += quad ? "x8" : "x4";
24251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
24351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'i':
24451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += "int32";
24551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (scal)
24651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        break;
24751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += quad ? "x4" : "x2";
24851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
24951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'l':
25051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += "int64";
25151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (scal)
25251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        break;
25351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += quad ? "x2" : "x1";
25451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
25551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'h':
25651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += "float16";
25751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (scal)
25851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        break;
25951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += quad ? "x8" : "x4";
26051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
26151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'f':
26251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += "float32";
26351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (scal)
26451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        break;
26551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += quad ? "x4" : "x2";
26651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
26751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    default:
26851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      throw "unhandled type!";
26951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
27051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
27151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
27251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (mod == '2')
27351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "x2";
27451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (mod == '3')
27551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "x3";
27651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (mod == '4')
27751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "x4";
27851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
27951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Append _t, finishing the type string typedef type.
28051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += "_t";
28151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
28251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (cnst)
28351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += " const";
28451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
28551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (pntr)
28651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += " *";
28751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
28851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return s.str();
28951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
29051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
29151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// BuiltinTypeString - for a modifier and type, generate the clang
29251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// BuiltinsARM.def prototype code for the function.  See the top of clang's
29351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// Builtins.def for a description of the type strings.
29451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic std::string BuiltinTypeString(const char mod, StringRef typestr,
29551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                                     ClassKind ck, bool ret) {
29651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool quad = false;
29751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool poly = false;
29851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool usgn = false;
29951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool scal = false;
30051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool cnst = false;
30151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool pntr = false;
30251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
30351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (mod == 'v')
30451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    return "v"; // void
30551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (mod == 'i')
30651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    return "i"; // int
30751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
30851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // base type to get the type string for.
30951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  char type = ClassifyType(typestr, quad, poly, usgn);
31051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
31151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Based on the modifying character, change the type and width if necessary.
31251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  type = ModType(mod, type, quad, poly, usgn, scal, cnst, pntr);
31351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
31451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // All pointers are void* pointers.  Change type to 'v' now.
31551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (pntr) {
31651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    usgn = false;
31751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    poly = false;
31851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    type = 'v';
31951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
32051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Treat half-float ('h') types as unsigned short ('s') types.
32151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (type == 'h') {
32251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    type = 's';
32351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    usgn = true;
32451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
32551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  usgn = usgn | poly | ((ck == ClassI || ck == ClassW) && scal && type != 'f');
32651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
32751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (scal) {
32851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    SmallString<128> s;
32951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
33051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (usgn)
33151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s.push_back('U');
33251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    else if (type == 'c')
33351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s.push_back('S'); // make chars explicitly signed
33451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
33551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (type == 'l') // 64-bit long
33651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += "LLi";
33751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    else
33851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s.push_back(type);
33951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
34051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (cnst)
34151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s.push_back('C');
34251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (pntr)
34351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s.push_back('*');
34451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    return s.str();
34551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
34651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
34751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Since the return value must be one type, return a vector type of the
34851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // appropriate width which we will bitcast.  An exception is made for
34951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // returning structs of 2, 3, or 4 vectors which are returned in a sret-like
35051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // fashion, storing them to a pointer arg.
35151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (ret) {
35251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (mod >= '2' && mod <= '4')
35351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      return "vv*"; // void result with void* first argument
35451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (mod == 'f' || (ck != ClassB && type == 'f'))
35551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      return quad ? "V4f" : "V2f";
35651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (ck != ClassB && type == 's')
35751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      return quad ? "V8s" : "V4s";
35851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (ck != ClassB && type == 'i')
35951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      return quad ? "V4i" : "V2i";
36051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (ck != ClassB && type == 'l')
36151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      return quad ? "V2LLi" : "V1LLi";
36251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
36351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    return quad ? "V16Sc" : "V8Sc";
36451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
36551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
36651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Non-return array types are passed as individual vectors.
36751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (mod == '2')
36851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    return quad ? "V16ScV16Sc" : "V8ScV8Sc";
36951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (mod == '3')
37051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    return quad ? "V16ScV16ScV16Sc" : "V8ScV8ScV8Sc";
37151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (mod == '4')
37251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    return quad ? "V16ScV16ScV16ScV16Sc" : "V8ScV8ScV8ScV8Sc";
37351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
37451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (mod == 'f' || (ck != ClassB && type == 'f'))
37551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    return quad ? "V4f" : "V2f";
37651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (ck != ClassB && type == 's')
37751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    return quad ? "V8s" : "V4s";
37851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (ck != ClassB && type == 'i')
37951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    return quad ? "V4i" : "V2i";
38051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (ck != ClassB && type == 'l')
38151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    return quad ? "V2LLi" : "V1LLi";
38251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
38351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return quad ? "V16Sc" : "V8Sc";
38451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
38551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
38651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// MangleName - Append a type or width suffix to a base neon function name,
38751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// and insert a 'q' in the appropriate location if the operation works on
38851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// 128b rather than 64b.   E.g. turn "vst2_lane" into "vst2q_lane_f32", etc.
38951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic std::string MangleName(const std::string &name, StringRef typestr,
39051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                              ClassKind ck) {
39151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (name == "vcvt_f32_f16")
39251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    return name;
39351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
39451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool quad = false;
39551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool poly = false;
39651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool usgn = false;
39751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  char type = ClassifyType(typestr, quad, poly, usgn);
39851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
39951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string s = name;
40051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
40151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  switch (type) {
40251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case 'c':
40351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    switch (ck) {
40451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case ClassS: s += poly ? "_p8" : usgn ? "_u8" : "_s8"; break;
40551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case ClassI: s += "_i8"; break;
40651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case ClassW: s += "_8"; break;
40751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    default: break;
40851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
40951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
41051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case 's':
41151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    switch (ck) {
41251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case ClassS: s += poly ? "_p16" : usgn ? "_u16" : "_s16"; break;
41351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case ClassI: s += "_i16"; break;
41451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case ClassW: s += "_16"; break;
41551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    default: break;
41651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
41751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
41851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case 'i':
41951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    switch (ck) {
42051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case ClassS: s += usgn ? "_u32" : "_s32"; break;
42151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case ClassI: s += "_i32"; break;
42251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case ClassW: s += "_32"; break;
42351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    default: break;
42451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
42551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
42651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case 'l':
42751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    switch (ck) {
42851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case ClassS: s += usgn ? "_u64" : "_s64"; break;
42951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case ClassI: s += "_i64"; break;
43051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case ClassW: s += "_64"; break;
43151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    default: break;
43251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
43351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
43451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case 'h':
43551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    switch (ck) {
43651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case ClassS:
43751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case ClassI: s += "_f16"; break;
43851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case ClassW: s += "_16"; break;
43951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    default: break;
44051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
44151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
44251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case 'f':
44351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    switch (ck) {
44451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case ClassS:
44551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case ClassI: s += "_f32"; break;
44651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case ClassW: s += "_32"; break;
44751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    default: break;
44851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
44951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
45051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  default:
45151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    throw "unhandled type!";
45251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
45351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
45451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (ck == ClassB)
45551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "_v";
45651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
45751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Insert a 'q' before the first '_' character so that it ends up before
45851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // _lane or _n on vector-scalar operations.
45951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (quad) {
46051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    size_t pos = s.find('_');
46151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s = s.insert(pos, "q");
46251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
46351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return s;
46451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
46551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
46651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// UseMacro - Examine the prototype string to determine if the intrinsic
46751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// should be defined as a preprocessor macro instead of an inline function.
46851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic bool UseMacro(const std::string &proto) {
46951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // If this builtin takes an immediate argument, we need to #define it rather
47051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // than use a standard declaration, so that SemaChecking can range check
47151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // the immediate passed by the user.
47251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (proto.find('i') != std::string::npos)
47351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    return true;
47451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
47551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Pointer arguments need to use macros to avoid hiding aligned attributes
47651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // from the pointer type.
47751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (proto.find('p') != std::string::npos ||
47851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      proto.find('c') != std::string::npos)
47951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    return true;
48051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
48151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return false;
48251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
48351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
48451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// MacroArgUsedDirectly - Return true if argument i for an intrinsic that is
48551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// defined as a macro should be accessed directly instead of being first
48651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// assigned to a local temporary.
48751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic bool MacroArgUsedDirectly(const std::string &proto, unsigned i) {
48851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // True for constant ints (i), pointers (p) and const pointers (c).
48951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return (proto[i] == 'i' || proto[i] == 'p' || proto[i] == 'c');
49051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
49151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
49251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne// Generate the string "(argtype a, argtype b, ...)"
49351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic std::string GenArgs(const std::string &proto, StringRef typestr) {
49451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool define = UseMacro(proto);
49551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  char arg = 'a';
49651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
49751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string s;
49851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += "(";
49951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
50051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) {
50151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (define) {
50251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      // Some macro arguments are used directly instead of being assigned
50351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      // to local temporaries; prepend an underscore prefix to make their
50451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      // names consistent with the local temporaries.
50551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (MacroArgUsedDirectly(proto, i))
50651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        s += "__";
50751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    } else {
50851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += TypeString(proto[i], typestr) + " __";
50951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
51051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s.push_back(arg);
51151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if ((i + 1) < e)
51251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += ", ";
51351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
51451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
51551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += ")";
51651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return s;
51751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
51851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
51951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne// Macro arguments are not type-checked like inline function arguments, so
52051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne// assign them to local temporaries to get the right type checking.
52151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic std::string GenMacroLocals(const std::string &proto, StringRef typestr) {
52251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  char arg = 'a';
52351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string s;
52451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool generatedLocal = false;
52551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
52651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) {
52751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // Do not create a temporary for an immediate argument.
52851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // That would defeat the whole point of using a macro!
52951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // FIXME: For other (non-immediate) arguments that are used directly, a
53051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // local temporary (or some other method) is still needed to get the
53151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // correct type checking, even if that temporary is not used for anything.
53251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // This is omitted for now because it turns out the the use of
53351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // "__extension__" in the macro disables any warnings from the pointer
53451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // assignment.
53551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (MacroArgUsedDirectly(proto, i))
53651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      continue;
53751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    generatedLocal = true;
53851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
53951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += TypeString(proto[i], typestr) + " __";
54051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s.push_back(arg);
54151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += " = (";
54251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s.push_back(arg);
54351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "); ";
54451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
54551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
54651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (generatedLocal)
54751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "\\\n  ";
54851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return s;
54951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
55051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
55151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne// Use the vmovl builtin to sign-extend or zero-extend a vector.
55251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic std::string Extend(StringRef typestr, const std::string &a) {
55351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string s;
55451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s = MangleName("vmovl", typestr, ClassS);
55551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += "(" + a + ")";
55651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return s;
55751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
55851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
55951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic std::string Duplicate(unsigned nElts, StringRef typestr,
56051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                             const std::string &a) {
56151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string s;
56251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
56351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s = "(" + TypeString('d', typestr) + "){ ";
56451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 0; i != nElts; ++i) {
56551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += a;
56651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if ((i + 1) < nElts)
56751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += ", ";
56851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
56951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += " }";
57051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
57151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return s;
57251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
57351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
57451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic std::string SplatLane(unsigned nElts, const std::string &vec,
57551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                             const std::string &lane) {
57651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string s = "__builtin_shufflevector(" + vec + ", " + vec;
57751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 0; i < nElts; ++i)
57851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += ", " + lane;
57951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += ")";
58051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return s;
58151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
58251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
58351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic unsigned GetNumElements(StringRef typestr, bool &quad) {
58451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  quad = false;
58551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool dummy = false;
58651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  char type = ClassifyType(typestr, quad, dummy, dummy);
58751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  unsigned nElts = 0;
58851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  switch (type) {
58951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case 'c': nElts = 8; break;
59051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case 's': nElts = 4; break;
59151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case 'i': nElts = 2; break;
59251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case 'l': nElts = 1; break;
59351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case 'h': nElts = 4; break;
59451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case 'f': nElts = 2; break;
59551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  default:
59651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    throw "unhandled type!";
59751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
59851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
59951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (quad) nElts <<= 1;
60051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return nElts;
60151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
60251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
60351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne// Generate the definition for this intrinsic, e.g. "a + b" for OpAdd.
60451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic std::string GenOpString(OpKind op, const std::string &proto,
60551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                               StringRef typestr) {
60651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool quad;
60751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  unsigned nElts = GetNumElements(typestr, quad);
60851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool define = UseMacro(proto);
60951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
61051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string ts = TypeString(proto[0], typestr);
61151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string s;
61251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (!define) {
61351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s = "return ";
61451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
61551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
61651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  switch(op) {
61751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpAdd:
61851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a + __b;";
61951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
62051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpAddl:
62151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += Extend(typestr, "__a") + " + " + Extend(typestr, "__b") + ";";
62251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
62351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpAddw:
62451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a + " + Extend(typestr, "__b") + ";";
62551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
62651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpSub:
62751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a - __b;";
62851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
62951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpSubl:
63051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += Extend(typestr, "__a") + " - " + Extend(typestr, "__b") + ";";
63151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
63251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpSubw:
63351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a - " + Extend(typestr, "__b") + ";";
63451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
63551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpMulN:
63651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a * " + Duplicate(nElts, typestr, "__b") + ";";
63751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
63851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpMulLane:
63951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a * " + SplatLane(nElts, "__b", "__c") + ";";
64051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
64151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpMul:
64251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a * __b;";
64351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
64451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpMullLane:
64551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += MangleName("vmull", typestr, ClassS) + "(__a, " +
64651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      SplatLane(nElts, "__b", "__c") + ");";
64751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
64851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpMlaN:
64951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a + (__b * " + Duplicate(nElts, typestr, "__c") + ");";
65051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
65151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpMlaLane:
65251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a + (__b * " + SplatLane(nElts, "__c", "__d") + ");";
65351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
65451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpMla:
65551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a + (__b * __c);";
65651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
65751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpMlalN:
65851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a + " + MangleName("vmull", typestr, ClassS) + "(__b, " +
65951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      Duplicate(nElts, typestr, "__c") + ");";
66051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
66151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpMlalLane:
66251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a + " + MangleName("vmull", typestr, ClassS) + "(__b, " +
66351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      SplatLane(nElts, "__c", "__d") + ");";
66451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
66551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpMlal:
66651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a + " + MangleName("vmull", typestr, ClassS) + "(__b, __c);";
66751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
66851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpMlsN:
66951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a - (__b * " + Duplicate(nElts, typestr, "__c") + ");";
67051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
67151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpMlsLane:
67251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a - (__b * " + SplatLane(nElts, "__c", "__d") + ");";
67351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
67451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpMls:
67551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a - (__b * __c);";
67651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
67751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpMlslN:
67851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a - " + MangleName("vmull", typestr, ClassS) + "(__b, " +
67951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      Duplicate(nElts, typestr, "__c") + ");";
68051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
68151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpMlslLane:
68251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a - " + MangleName("vmull", typestr, ClassS) + "(__b, " +
68351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      SplatLane(nElts, "__c", "__d") + ");";
68451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
68551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpMlsl:
68651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a - " + MangleName("vmull", typestr, ClassS) + "(__b, __c);";
68751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
68851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpQDMullLane:
68951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += MangleName("vqdmull", typestr, ClassS) + "(__a, " +
69051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      SplatLane(nElts, "__b", "__c") + ");";
69151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
69251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpQDMlalLane:
69351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += MangleName("vqdmlal", typestr, ClassS) + "(__a, __b, " +
69451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      SplatLane(nElts, "__c", "__d") + ");";
69551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
69651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpQDMlslLane:
69751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += MangleName("vqdmlsl", typestr, ClassS) + "(__a, __b, " +
69851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      SplatLane(nElts, "__c", "__d") + ");";
69951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
70051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpQDMulhLane:
70151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += MangleName("vqdmulh", typestr, ClassS) + "(__a, " +
70251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      SplatLane(nElts, "__b", "__c") + ");";
70351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
70451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpQRDMulhLane:
70551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += MangleName("vqrdmulh", typestr, ClassS) + "(__a, " +
70651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      SplatLane(nElts, "__b", "__c") + ");";
70751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
70851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpEq:
70951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "(" + ts + ")(__a == __b);";
71051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
71151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpGe:
71251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "(" + ts + ")(__a >= __b);";
71351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
71451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpLe:
71551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "(" + ts + ")(__a <= __b);";
71651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
71751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpGt:
71851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "(" + ts + ")(__a > __b);";
71951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
72051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpLt:
72151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "(" + ts + ")(__a < __b);";
72251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
72351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpNeg:
72451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += " -__a;";
72551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
72651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpNot:
72751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += " ~__a;";
72851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
72951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpAnd:
73051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a & __b;";
73151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
73251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpOr:
73351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a | __b;";
73451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
73551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpXor:
73651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a ^ __b;";
73751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
73851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpAndNot:
73951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a & ~__b;";
74051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
74151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpOrNot:
74251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a | ~__b;";
74351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
74451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpCast:
74551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "(" + ts + ")__a;";
74651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
74751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpConcat:
74851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "(" + ts + ")__builtin_shufflevector((int64x1_t)__a";
74951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += ", (int64x1_t)__b, 0, 1);";
75051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
75151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpHi:
75251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "(" + ts +
75351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      ")__builtin_shufflevector((int64x2_t)__a, (int64x2_t)__a, 1);";
75451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
75551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpLo:
75651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "(" + ts +
75751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      ")__builtin_shufflevector((int64x2_t)__a, (int64x2_t)__a, 0);";
75851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
75951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpDup:
76051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += Duplicate(nElts, typestr, "__a") + ";";
76151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
76251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpDupLane:
76351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += SplatLane(nElts, "__a", "__b") + ";";
76451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
76551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpSelect:
76651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // ((0 & 1) | (~0 & 2))
76751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "(" + ts + ")";
76851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    ts = TypeString(proto[1], typestr);
76951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "((__a & (" + ts + ")__b) | ";
77051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "(~__a & (" + ts + ")__c));";
77151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
77251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpRev16:
77351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__builtin_shufflevector(__a, __a";
77451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    for (unsigned i = 2; i <= nElts; i += 2)
77551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      for (unsigned j = 0; j != 2; ++j)
77651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        s += ", " + utostr(i - j - 1);
77751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += ");";
77851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
77951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpRev32: {
78051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    unsigned WordElts = nElts >> (1 + (int)quad);
78151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__builtin_shufflevector(__a, __a";
78251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    for (unsigned i = WordElts; i <= nElts; i += WordElts)
78351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      for (unsigned j = 0; j != WordElts; ++j)
78451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        s += ", " + utostr(i - j - 1);
78551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += ");";
78651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
78751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
78851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpRev64: {
78951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    unsigned DblWordElts = nElts >> (int)quad;
79051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__builtin_shufflevector(__a, __a";
79151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    for (unsigned i = DblWordElts; i <= nElts; i += DblWordElts)
79251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      for (unsigned j = 0; j != DblWordElts; ++j)
79351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        s += ", " + utostr(i - j - 1);
79451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += ");";
79551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
79651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
79751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpAbdl: {
79851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::string abd = MangleName("vabd", typestr, ClassS) + "(__a, __b)";
79951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (typestr[0] != 'U') {
80051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      // vabd results are always unsigned and must be zero-extended.
80151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      std::string utype = "U" + typestr.str();
80251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += "(" + TypeString(proto[0], typestr) + ")";
80351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      abd = "(" + TypeString('d', utype) + ")" + abd;
80451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += Extend(utype, abd) + ";";
80551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    } else {
80651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += Extend(typestr, abd) + ";";
80751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
80851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
80951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
81051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpAba:
81151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a + " + MangleName("vabd", typestr, ClassS) + "(__b, __c);";
81251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
81351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpAbal: {
81451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a + ";
81551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::string abd = MangleName("vabd", typestr, ClassS) + "(__b, __c)";
81651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (typestr[0] != 'U') {
81751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      // vabd results are always unsigned and must be zero-extended.
81851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      std::string utype = "U" + typestr.str();
81951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += "(" + TypeString(proto[0], typestr) + ")";
82051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      abd = "(" + TypeString('d', utype) + ")" + abd;
82151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += Extend(utype, abd) + ";";
82251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    } else {
82351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += Extend(typestr, abd) + ";";
82451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
82551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
82651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
82751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  default:
82851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    throw "unknown OpKind!";
82951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
83051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
83151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return s;
83251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
83351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
83451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic unsigned GetNeonEnum(const std::string &proto, StringRef typestr) {
83551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  unsigned mod = proto[0];
83651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  unsigned ret = 0;
83751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
83851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (mod == 'v' || mod == 'f')
83951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    mod = proto[1];
84051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
84151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool quad = false;
84251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool poly = false;
84351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool usgn = false;
84451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool scal = false;
84551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool cnst = false;
84651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool pntr = false;
84751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
84851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Base type to get the type string for.
84951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  char type = ClassifyType(typestr, quad, poly, usgn);
85051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
85151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Based on the modifying character, change the type and width if necessary.
85251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  type = ModType(mod, type, quad, poly, usgn, scal, cnst, pntr);
85351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
85451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (usgn)
85551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    ret |= 0x08;
85651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (quad && proto[1] != 'g')
85751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    ret |= 0x10;
85851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
85951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  switch (type) {
86051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'c':
86151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      ret |= poly ? 5 : 0;
86251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
86351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 's':
86451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      ret |= poly ? 6 : 1;
86551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
86651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'i':
86751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      ret |= 2;
86851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
86951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'l':
87051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      ret |= 3;
87151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
87251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'h':
87351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      ret |= 7;
87451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
87551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'f':
87651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      ret |= 4;
87751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
87851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    default:
87951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      throw "unhandled type!";
88051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
88151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
88251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return ret;
88351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
88451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
88551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne// Generate the definition for this intrinsic, e.g. __builtin_neon_cls(a)
88651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic std::string GenBuiltin(const std::string &name, const std::string &proto,
88751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                              StringRef typestr, ClassKind ck) {
88851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string s;
88951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
89051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // If this builtin returns a struct 2, 3, or 4 vectors, pass it as an implicit
89151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // sret-like argument.
89251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool sret = (proto[0] >= '2' && proto[0] <= '4');
89351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
89451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool define = UseMacro(proto);
89551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
89651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Check if the prototype has a scalar operand with the type of the vector
89751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // elements.  If not, bitcasting the args will take care of arg checking.
89851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // The actual signedness etc. will be taken care of with special enums.
89951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (proto.find('s') == std::string::npos)
90051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    ck = ClassB;
90151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
90251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (proto[0] != 'v') {
90351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::string ts = TypeString(proto[0], typestr);
90451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
90551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (define) {
90651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (sret)
90751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        s += ts + " r; ";
90851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      else
90951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        s += "(" + ts + ")";
91051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    } else if (sret) {
91151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += ts + " r; ";
91251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    } else {
91351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += "return (" + ts + ")";
91451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
91551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
91651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
91751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool splat = proto.find('a') != std::string::npos;
91851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
91951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += "__builtin_neon_";
92051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (splat) {
92151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // Call the non-splat builtin: chop off the "_n" suffix from the name.
92251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::string vname(name, 0, name.size()-2);
92351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += MangleName(vname, typestr, ck);
92451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  } else {
92551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += MangleName(name, typestr, ck);
92651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
92751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += "(";
92851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
92951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Pass the address of the return variable as the first argument to sret-like
93051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // builtins.
93151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (sret)
93251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "&r, ";
93351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
93451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  char arg = 'a';
93551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) {
93651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::string args = std::string(&arg, 1);
93751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
93851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // Use the local temporaries instead of the macro arguments.
93951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    args = "__" + args;
94051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
94151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    bool argQuad = false;
94251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    bool argPoly = false;
94351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    bool argUsgn = false;
94451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    bool argScalar = false;
94551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    bool dummy = false;
94651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    char argType = ClassifyType(typestr, argQuad, argPoly, argUsgn);
94751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    argType = ModType(proto[i], argType, argQuad, argPoly, argUsgn, argScalar,
94851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                      dummy, dummy);
94951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
95051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // Handle multiple-vector values specially, emitting each subvector as an
95151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // argument to the __builtin.
95251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (proto[i] >= '2' && proto[i] <= '4') {
95351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      // Check if an explicit cast is needed.
95451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (argType != 'c' || argPoly || argUsgn)
95551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        args = (argQuad ? "(int8x16_t)" : "(int8x8_t)") + args;
95651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
95751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      for (unsigned vi = 0, ve = proto[i] - '0'; vi != ve; ++vi) {
95851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        s += args + ".val[" + utostr(vi) + "]";
95951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        if ((vi + 1) < ve)
96051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne          s += ", ";
96151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      }
96251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if ((i + 1) < e)
96351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        s += ", ";
96451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
96551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      continue;
96651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
96751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
96851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (splat && (i + 1) == e)
96951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      args = Duplicate(GetNumElements(typestr, argQuad), typestr, args);
97051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
97151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // Check if an explicit cast is needed.
97251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if ((splat || !argScalar) &&
97351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        ((ck == ClassB && argType != 'c') || argPoly || argUsgn)) {
97451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      std::string argTypeStr = "c";
97551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (ck != ClassB)
97651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        argTypeStr = argType;
97751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (argQuad)
97851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        argTypeStr = "Q" + argTypeStr;
97951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      args = "(" + TypeString('d', argTypeStr) + ")" + args;
98051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
98151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
98251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += args;
98351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if ((i + 1) < e)
98451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += ", ";
98551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
98651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
98751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Extra constant integer to hold type class enum for this function, e.g. s8
98851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (ck == ClassB)
98951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += ", " + utostr(GetNeonEnum(proto, typestr));
99051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
99151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += ");";
99251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
99351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (proto[0] != 'v' && sret) {
99451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (define)
99551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += " r;";
99651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    else
99751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += " return r;";
99851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
99951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return s;
100051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
100151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
100251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic std::string GenBuiltinDef(const std::string &name,
100351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                                 const std::string &proto,
100451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                                 StringRef typestr, ClassKind ck) {
100551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string s("BUILTIN(__builtin_neon_");
100651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
100751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // If all types are the same size, bitcasting the args will take care
100851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // of arg checking.  The actual signedness etc. will be taken care of with
100951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // special enums.
101051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (proto.find('s') == std::string::npos)
101151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    ck = ClassB;
101251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
101351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += MangleName(name, typestr, ck);
101451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += ", \"";
101551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
101651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 0, e = proto.size(); i != e; ++i)
101751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += BuiltinTypeString(proto[i], typestr, ck, i == 0);
101851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
101951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Extra constant integer to hold type class enum for this function, e.g. s8
102051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (ck == ClassB)
102151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "i";
102251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
102351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += "\", \"n\")";
102451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return s;
102551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
102651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
102751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic std::string GenIntrinsic(const std::string &name,
102851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                                const std::string &proto,
102951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                                StringRef outTypeStr, StringRef inTypeStr,
103051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                                OpKind kind, ClassKind classKind) {
103151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  assert(!proto.empty() && "");
103251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool define = UseMacro(proto);
103351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string s;
103451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
103551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // static always inline + return type
103651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (define)
103751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "#define ";
103851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  else
103951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__ai " + TypeString(proto[0], outTypeStr) + " ";
104051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
104151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Function name with type suffix
104251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string mangledName = MangleName(name, outTypeStr, ClassS);
104351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (outTypeStr != inTypeStr) {
104451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // If the input type is different (e.g., for vreinterpret), append a suffix
104551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // for the input type.  String off a "Q" (quad) prefix so that MangleName
104651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // does not insert another "q" in the name.
104751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    unsigned typeStrOff = (inTypeStr[0] == 'Q' ? 1 : 0);
104851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    StringRef inTypeNoQuad = inTypeStr.substr(typeStrOff);
104951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    mangledName = MangleName(mangledName, inTypeNoQuad, ClassS);
105051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
105151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += mangledName;
105251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
105351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Function arguments
105451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += GenArgs(proto, inTypeStr);
105551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
105651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Definition.
105751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (define) {
105851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += " __extension__ ({ \\\n  ";
105951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += GenMacroLocals(proto, inTypeStr);
106051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  } else {
106151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += " { \\\n  ";
106251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
106351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
106451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (kind != OpNone)
106551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += GenOpString(kind, proto, outTypeStr);
106651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  else
106751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += GenBuiltin(name, proto, outTypeStr, classKind);
106851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (define)
106951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += " })";
107051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  else
107151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += " }";
107251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += "\n";
107351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return s;
107451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
107551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
107651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// run - Read the records in arm_neon.td and output arm_neon.h.  arm_neon.h
107751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// is comprised of type definitions and function declarations.
107851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournevoid NeonEmitter::run(raw_ostream &OS) {
107951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS <<
108051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    "/*===---- arm_neon.h - ARM Neon intrinsics ------------------------------"
108151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    "---===\n"
108251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " *\n"
108351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " * Permission is hereby granted, free of charge, to any person obtaining "
108451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    "a copy\n"
108551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " * of this software and associated documentation files (the \"Software\"),"
108651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " to deal\n"
108751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " * in the Software without restriction, including without limitation the "
108851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    "rights\n"
108951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " * to use, copy, modify, merge, publish, distribute, sublicense, "
109051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    "and/or sell\n"
109151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " * copies of the Software, and to permit persons to whom the Software is\n"
109251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " * furnished to do so, subject to the following conditions:\n"
109351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " *\n"
109451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " * The above copyright notice and this permission notice shall be "
109551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    "included in\n"
109651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " * all copies or substantial portions of the Software.\n"
109751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " *\n"
109851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, "
109951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    "EXPRESS OR\n"
110051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF "
110151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    "MERCHANTABILITY,\n"
110251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT "
110351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    "SHALL THE\n"
110451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR "
110551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    "OTHER\n"
110651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, "
110751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    "ARISING FROM,\n"
110851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER "
110951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    "DEALINGS IN\n"
111051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " * THE SOFTWARE.\n"
111151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " *\n"
111251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " *===--------------------------------------------------------------------"
111351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    "---===\n"
111451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " */\n\n";
111551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
111651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#ifndef __ARM_NEON_H\n";
111751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#define __ARM_NEON_H\n\n";
111851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
111951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#ifndef __ARM_NEON__\n";
112051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#error \"NEON support not enabled\"\n";
112151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#endif\n\n";
112251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
112351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#include <stdint.h>\n\n";
112451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
112551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Emit NEON-specific scalar typedefs.
112651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "typedef float float32_t;\n";
112751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "typedef int8_t poly8_t;\n";
112851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "typedef int16_t poly16_t;\n";
112951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "typedef uint16_t float16_t;\n";
113051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
113151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Emit Neon vector typedefs.
113251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string TypedefTypes("cQcsQsiQilQlUcQUcUsQUsUiQUiUlQUlhQhfQfPcQPcPsQPs");
113351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  SmallVector<StringRef, 24> TDTypeVec;
113451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  ParseTypes(0, TypedefTypes, TDTypeVec);
113551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
113651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Emit vector typedefs.
113751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 0, e = TDTypeVec.size(); i != e; ++i) {
113851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    bool dummy, quad = false, poly = false;
113951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    (void) ClassifyType(TDTypeVec[i], quad, poly, dummy);
114051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (poly)
114151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      OS << "typedef __attribute__((neon_polyvector_type(";
114251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    else
114351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      OS << "typedef __attribute__((neon_vector_type(";
114451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
114551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    unsigned nElts = GetNumElements(TDTypeVec[i], quad);
114651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    OS << utostr(nElts) << "))) ";
114751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (nElts < 10)
114851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      OS << " ";
114951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
115051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    OS << TypeString('s', TDTypeVec[i]);
115151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    OS << " " << TypeString('d', TDTypeVec[i]) << ";\n";
115251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
115351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "\n";
115451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
115551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Emit struct typedefs.
115651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned vi = 2; vi != 5; ++vi) {
115751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    for (unsigned i = 0, e = TDTypeVec.size(); i != e; ++i) {
115851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      std::string ts = TypeString('d', TDTypeVec[i]);
115951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      std::string vs = TypeString('0' + vi, TDTypeVec[i]);
116051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      OS << "typedef struct " << vs << " {\n";
116151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      OS << "  " << ts << " val";
116251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      OS << "[" << utostr(vi) << "]";
116351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      OS << ";\n} ";
116451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      OS << vs << ";\n\n";
116551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
116651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
116751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
1168d1af3b901a2176bc7f4b7e2fadcd25110576b454Bob Wilson  OS<<"#define __ai static __attribute__((__always_inline__, __nodebug__))\n\n";
116951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
117051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::vector<Record*> RV = Records.getAllDerivedDefinitions("Inst");
117151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
117251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Emit vmovl, vmull and vabd intrinsics first so they can be used by other
117351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // intrinsics.  (Some of the saturating multiply instructions are also
117451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // used to implement the corresponding "_lane" variants, but tablegen
117551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // sorts the records into alphabetical order so that the "_lane" variants
117651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // come after the intrinsics they use.)
117751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  emitIntrinsic(OS, Records.getDef("VMOVL"));
117851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  emitIntrinsic(OS, Records.getDef("VMULL"));
117951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  emitIntrinsic(OS, Records.getDef("VABD"));
118051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
118151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 0, e = RV.size(); i != e; ++i) {
118251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    Record *R = RV[i];
118351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (R->getName() != "VMOVL" &&
118451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        R->getName() != "VMULL" &&
118551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        R->getName() != "VABD")
118651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      emitIntrinsic(OS, R);
118751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
118851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
118951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#undef __ai\n\n";
119051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#endif /* __ARM_NEON_H */\n";
119151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
119251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
119351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// emitIntrinsic - Write out the arm_neon.h header file definitions for the
119451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// intrinsics specified by record R.
119551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournevoid NeonEmitter::emitIntrinsic(raw_ostream &OS, Record *R) {
119651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string name = R->getValueAsString("Name");
119751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string Proto = R->getValueAsString("Prototype");
119851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string Types = R->getValueAsString("Types");
119951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
120051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  SmallVector<StringRef, 16> TypeVec;
120151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  ParseTypes(R, Types, TypeVec);
120251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
120351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OpKind kind = OpMap[R->getValueAsDef("Operand")->getName()];
120451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
120551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  ClassKind classKind = ClassNone;
120651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (R->getSuperClasses().size() >= 2)
120751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    classKind = ClassMap[R->getSuperClasses()[1]];
120851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (classKind == ClassNone && kind == OpNone)
120951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    throw TGError(R->getLoc(), "Builtin has no class kind");
121051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
121151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) {
121251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (kind == OpReinterpret) {
121351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      bool outQuad = false;
121451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      bool dummy = false;
121551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      (void)ClassifyType(TypeVec[ti], outQuad, dummy, dummy);
121651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      for (unsigned srcti = 0, srcte = TypeVec.size();
121751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne           srcti != srcte; ++srcti) {
121851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        bool inQuad = false;
121951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        (void)ClassifyType(TypeVec[srcti], inQuad, dummy, dummy);
122051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        if (srcti == ti || inQuad != outQuad)
122151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne          continue;
122251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        OS << GenIntrinsic(name, Proto, TypeVec[ti], TypeVec[srcti],
122351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                           OpCast, ClassS);
122451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      }
122551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    } else {
122651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      OS << GenIntrinsic(name, Proto, TypeVec[ti], TypeVec[ti],
122751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                         kind, classKind);
122851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
122951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
123051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "\n";
123151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
123251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
123351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic unsigned RangeFromType(const char mod, StringRef typestr) {
123451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // base type to get the type string for.
123551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool quad = false, dummy = false;
123651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  char type = ClassifyType(typestr, quad, dummy, dummy);
123751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  type = ModType(mod, type, quad, dummy, dummy, dummy, dummy, dummy);
123851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
123951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  switch (type) {
124051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'c':
124151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      return (8 << (int)quad) - 1;
124251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'h':
124351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 's':
124451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      return (4 << (int)quad) - 1;
124551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'f':
124651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'i':
124751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      return (2 << (int)quad) - 1;
124851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'l':
124951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      return (1 << (int)quad) - 1;
125051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    default:
125151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      throw "unhandled type!";
125251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
125351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
125451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  assert(0 && "unreachable");
125551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return 0;
125651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
125751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
125851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// runHeader - Emit a file with sections defining:
125951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// 1. the NEON section of BuiltinsARM.def.
126051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// 2. the SemaChecking code for the type overload checking.
126151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// 3. the SemaChecking code for validation of intrinsic immedate arguments.
126251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournevoid NeonEmitter::runHeader(raw_ostream &OS) {
126351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::vector<Record*> RV = Records.getAllDerivedDefinitions("Inst");
126451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
126551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  StringMap<OpKind> EmittedMap;
126651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
126751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Generate BuiltinsARM.def for NEON
126851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#ifdef GET_NEON_BUILTINS\n";
126951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 0, e = RV.size(); i != e; ++i) {
127051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    Record *R = RV[i];
127151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    OpKind k = OpMap[R->getValueAsDef("Operand")->getName()];
127251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (k != OpNone)
127351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      continue;
127451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
127551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::string Proto = R->getValueAsString("Prototype");
127651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
127751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // Functions with 'a' (the splat code) in the type prototype should not get
127851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // their own builtin as they use the non-splat variant.
127951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (Proto.find('a') != std::string::npos)
128051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      continue;
128151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
128251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::string Types = R->getValueAsString("Types");
128351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    SmallVector<StringRef, 16> TypeVec;
128451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    ParseTypes(R, Types, TypeVec);
128551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
128651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (R->getSuperClasses().size() < 2)
128751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      throw TGError(R->getLoc(), "Builtin has no class kind");
128851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
128951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::string name = R->getValueAsString("Name");
129051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    ClassKind ck = ClassMap[R->getSuperClasses()[1]];
129151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
129251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) {
129351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      // Generate the BuiltinsARM.def declaration for this builtin, ensuring
129451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      // that each unique BUILTIN() macro appears only once in the output
129551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      // stream.
129651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      std::string bd = GenBuiltinDef(name, Proto, TypeVec[ti], ck);
129751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (EmittedMap.count(bd))
129851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        continue;
129951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
130051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      EmittedMap[bd] = OpNone;
130151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      OS << bd << "\n";
130251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
130351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
130451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#endif\n\n";
130551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
130651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Generate the overloaded type checking code for SemaChecking.cpp
130751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#ifdef GET_NEON_OVERLOAD_CHECK\n";
130851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 0, e = RV.size(); i != e; ++i) {
130951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    Record *R = RV[i];
131051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    OpKind k = OpMap[R->getValueAsDef("Operand")->getName()];
131151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (k != OpNone)
131251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      continue;
131351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
131451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::string Proto = R->getValueAsString("Prototype");
131551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::string Types = R->getValueAsString("Types");
131651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::string name = R->getValueAsString("Name");
131751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
131851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // Functions with 'a' (the splat code) in the type prototype should not get
131951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // their own builtin as they use the non-splat variant.
132051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (Proto.find('a') != std::string::npos)
132151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      continue;
132251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
132351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // Functions which have a scalar argument cannot be overloaded, no need to
132451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // check them if we are emitting the type checking code.
132551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (Proto.find('s') != std::string::npos)
132651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      continue;
132751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
132851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    SmallVector<StringRef, 16> TypeVec;
132951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    ParseTypes(R, Types, TypeVec);
133051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
133151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (R->getSuperClasses().size() < 2)
133251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      throw TGError(R->getLoc(), "Builtin has no class kind");
133351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
133451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    int si = -1, qi = -1;
133551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    unsigned mask = 0, qmask = 0;
133651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) {
133751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      // Generate the switch case(s) for this builtin for the type validation.
133851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      bool quad = false, poly = false, usgn = false;
133951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      (void) ClassifyType(TypeVec[ti], quad, poly, usgn);
134051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
134151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (quad) {
134251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        qi = ti;
134351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        qmask |= 1 << GetNeonEnum(Proto, TypeVec[ti]);
134451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      } else {
134551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        si = ti;
134651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        mask |= 1 << GetNeonEnum(Proto, TypeVec[ti]);
134751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      }
134851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
134951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (mask)
135051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      OS << "case ARM::BI__builtin_neon_"
135151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne         << MangleName(name, TypeVec[si], ClassB)
135251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne         << ": mask = " << "0x" << utohexstr(mask) << "; break;\n";
135351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (qmask)
135451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      OS << "case ARM::BI__builtin_neon_"
135551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne         << MangleName(name, TypeVec[qi], ClassB)
135651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne         << ": mask = " << "0x" << utohexstr(qmask) << "; break;\n";
135751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
135851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#endif\n\n";
135951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
136051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Generate the intrinsic range checking code for shift/lane immediates.
136151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#ifdef GET_NEON_IMMEDIATE_CHECK\n";
136251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 0, e = RV.size(); i != e; ++i) {
136351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    Record *R = RV[i];
136451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
136551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    OpKind k = OpMap[R->getValueAsDef("Operand")->getName()];
136651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (k != OpNone)
136751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      continue;
136851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
136951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::string name = R->getValueAsString("Name");
137051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::string Proto = R->getValueAsString("Prototype");
137151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::string Types = R->getValueAsString("Types");
137251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
137351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // Functions with 'a' (the splat code) in the type prototype should not get
137451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // their own builtin as they use the non-splat variant.
137551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (Proto.find('a') != std::string::npos)
137651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      continue;
137751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
137851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // Functions which do not have an immediate do not need to have range
137951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // checking code emitted.
138051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    size_t immPos = Proto.find('i');
138151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (immPos == std::string::npos)
138251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      continue;
138351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
138451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    SmallVector<StringRef, 16> TypeVec;
138551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    ParseTypes(R, Types, TypeVec);
138651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
138751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (R->getSuperClasses().size() < 2)
138851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      throw TGError(R->getLoc(), "Builtin has no class kind");
138951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
139051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    ClassKind ck = ClassMap[R->getSuperClasses()[1]];
139151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
139251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) {
139351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      std::string namestr, shiftstr, rangestr;
139451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
139551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (R->getValueAsBit("isVCVT_N")) {
139651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        // VCVT between floating- and fixed-point values takes an immediate
139751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        // in the range 1 to 32.
139851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        ck = ClassB;
139951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        rangestr = "l = 1; u = 31"; // upper bound = l + u
140051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      } else if (Proto.find('s') == std::string::npos) {
140151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        // Builtins which are overloaded by type will need to have their upper
140251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        // bound computed at Sema time based on the type constant.
140351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        ck = ClassB;
140451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        if (R->getValueAsBit("isShift")) {
140551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne          shiftstr = ", true";
140651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
140751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne          // Right shifts have an 'r' in the name, left shifts do not.
140851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne          if (name.find('r') != std::string::npos)
140951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne            rangestr = "l = 1; ";
141051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        }
141151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        rangestr += "u = RFT(TV" + shiftstr + ")";
141251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      } else {
141351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        // The immediate generally refers to a lane in the preceding argument.
141451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        assert(immPos > 0 && "unexpected immediate operand");
141551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        rangestr = "u = " + utostr(RangeFromType(Proto[immPos-1], TypeVec[ti]));
141651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      }
141751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      // Make sure cases appear only once by uniquing them in a string map.
141851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      namestr = MangleName(name, TypeVec[ti], ck);
141951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (EmittedMap.count(namestr))
142051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        continue;
142151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      EmittedMap[namestr] = OpNone;
142251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
142351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      // Calculate the index of the immediate that should be range checked.
142451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      unsigned immidx = 0;
142551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
142651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      // Builtins that return a struct of multiple vectors have an extra
142751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      // leading arg for the struct return.
142851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (Proto[0] >= '2' && Proto[0] <= '4')
142951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        ++immidx;
143051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
143151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      // Add one to the index for each argument until we reach the immediate
143251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      // to be checked.  Structs of vectors are passed as multiple arguments.
143351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      for (unsigned ii = 1, ie = Proto.size(); ii != ie; ++ii) {
143451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        switch (Proto[ii]) {
143551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne          default:  immidx += 1; break;
143651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne          case '2': immidx += 2; break;
143751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne          case '3': immidx += 3; break;
143851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne          case '4': immidx += 4; break;
143951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne          case 'i': ie = ii + 1; break;
144051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        }
144151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      }
144251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      OS << "case ARM::BI__builtin_neon_" << MangleName(name, TypeVec[ti], ck)
144351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne         << ": i = " << immidx << "; " << rangestr << "; break;\n";
144451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
144551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
144651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#endif\n\n";
144751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
144851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
144951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// GenTest - Write out a test for the intrinsic specified by the name and
145051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// type strings, including the embedded patterns for FileCheck to match.
145151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic std::string GenTest(const std::string &name,
145251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                           const std::string &proto,
145351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                           StringRef outTypeStr, StringRef inTypeStr,
145451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                           bool isShift) {
145551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  assert(!proto.empty() && "");
145651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string s;
145751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
145851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Function name with type suffix
145951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string mangledName = MangleName(name, outTypeStr, ClassS);
146051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (outTypeStr != inTypeStr) {
146151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // If the input type is different (e.g., for vreinterpret), append a suffix
146251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // for the input type.  String off a "Q" (quad) prefix so that MangleName
146351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // does not insert another "q" in the name.
146451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    unsigned typeStrOff = (inTypeStr[0] == 'Q' ? 1 : 0);
146551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    StringRef inTypeNoQuad = inTypeStr.substr(typeStrOff);
146651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    mangledName = MangleName(mangledName, inTypeNoQuad, ClassS);
146751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
146851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
146951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Emit the FileCheck patterns.
147051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += "// CHECK: test_" + mangledName + "\n";
147151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // s += "// CHECK: \n"; // FIXME: + expected instruction opcode.
147251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
147351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Emit the start of the test function.
147451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += TypeString(proto[0], outTypeStr) + " test_" + mangledName + "(";
147551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  char arg = 'a';
147651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string comma;
147751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) {
147851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // Do not create arguments for values that must be immediate constants.
147951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (proto[i] == 'i')
148051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      continue;
148151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += comma + TypeString(proto[i], inTypeStr) + " ";
148251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s.push_back(arg);
148351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    comma = ", ";
148451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
148551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += ") { \\\n  ";
148651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
148751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (proto[0] != 'v')
148851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "return ";
148951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += mangledName + "(";
149051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  arg = 'a';
149151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) {
149251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (proto[i] == 'i') {
149351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      // For immediate operands, test the maximum value.
149451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (isShift)
149551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        s += "1"; // FIXME
149651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      else
149751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        // The immediate generally refers to a lane in the preceding argument.
149851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        s += utostr(RangeFromType(proto[i-1], inTypeStr));
149951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    } else {
150051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s.push_back(arg);
150151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
150251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if ((i + 1) < e)
150351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += ", ";
150451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
150551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += ");\n}\n\n";
150651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return s;
150751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
150851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
150951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// runTests - Write out a complete set of tests for all of the Neon
151051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// intrinsics.
151151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournevoid NeonEmitter::runTests(raw_ostream &OS) {
151251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS <<
151351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    "// RUN: %clang_cc1 -triple thumbv7-apple-darwin \\\n"
151451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    "// RUN:  -target-cpu cortex-a9 -ffreestanding -S -o - %s | FileCheck %s\n"
151551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    "\n"
151651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    "#include <arm_neon.h>\n"
151751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    "\n";
151851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
151951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::vector<Record*> RV = Records.getAllDerivedDefinitions("Inst");
152051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 0, e = RV.size(); i != e; ++i) {
152151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    Record *R = RV[i];
152251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::string name = R->getValueAsString("Name");
152351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::string Proto = R->getValueAsString("Prototype");
152451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::string Types = R->getValueAsString("Types");
152551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    bool isShift = R->getValueAsBit("isShift");
152651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
152751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    SmallVector<StringRef, 16> TypeVec;
152851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    ParseTypes(R, Types, TypeVec);
152951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
153051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    OpKind kind = OpMap[R->getValueAsDef("Operand")->getName()];
153151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) {
153251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (kind == OpReinterpret) {
153351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        bool outQuad = false;
153451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        bool dummy = false;
153551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        (void)ClassifyType(TypeVec[ti], outQuad, dummy, dummy);
153651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        for (unsigned srcti = 0, srcte = TypeVec.size();
153751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne             srcti != srcte; ++srcti) {
153851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne          bool inQuad = false;
153951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne          (void)ClassifyType(TypeVec[srcti], inQuad, dummy, dummy);
154051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne          if (srcti == ti || inQuad != outQuad)
154151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne            continue;
154251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne          OS << GenTest(name, Proto, TypeVec[ti], TypeVec[srcti], isShift);
154351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        }
154451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      } else {
154551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        OS << GenTest(name, Proto, TypeVec[ti], TypeVec[ti], isShift);
154651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      }
154751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
154851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    OS << "\n";
154951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
155051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
155151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
1552