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
263cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen#include "llvm/ADT/DenseMap.h"
2751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne#include "llvm/ADT/SmallString.h"
2851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne#include "llvm/ADT/SmallVector.h"
2951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne#include "llvm/ADT/StringExtras.h"
303cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen#include "llvm/ADT/StringMap.h"
317530c034c0c71a64c5a9173206d9742ae847af8bDavid Blaikie#include "llvm/Support/ErrorHandling.h"
323cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen#include "llvm/TableGen/Error.h"
333cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen#include "llvm/TableGen/Record.h"
343cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen#include "llvm/TableGen/TableGenBackend.h"
3551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne#include <string>
3651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourneusing namespace llvm;
3751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
383cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesenenum OpKind {
393cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpNone,
403cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpUnavailable,
413cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpAdd,
423cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpAddl,
433cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpAddw,
443cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpSub,
453cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpSubl,
463cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpSubw,
473cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpMul,
483cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpMla,
493cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpMlal,
503cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpMls,
513cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpMlsl,
523cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpMulN,
533cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpMlaN,
543cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpMlsN,
553cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpMlalN,
563cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpMlslN,
573cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpMulLane,
583cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpMullLane,
593cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpMlaLane,
603cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpMlsLane,
613cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpMlalLane,
623cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpMlslLane,
633cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpQDMullLane,
643cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpQDMlalLane,
653cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpQDMlslLane,
663cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpQDMulhLane,
673cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpQRDMulhLane,
683cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpEq,
693cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpGe,
703cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpLe,
713cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpGt,
723cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpLt,
733cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpNeg,
743cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpNot,
753cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpAnd,
763cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpOr,
773cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpXor,
783cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpAndNot,
793cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpOrNot,
803cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpCast,
813cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpConcat,
823cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpDup,
833cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpDupLane,
843cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpHi,
853cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpLo,
863cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpSelect,
873cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpRev16,
883cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpRev32,
893cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpRev64,
903cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpReinterpret,
913cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpAbdl,
923cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpAba,
933cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  OpAbal
943cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen};
953cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen
963cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesenenum ClassKind {
973cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  ClassNone,
983cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  ClassI,           // generic integer instruction, e.g., "i8" suffix
993cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  ClassS,           // signed/unsigned/poly, e.g., "s8", "u8" or "p8" suffix
1003cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  ClassW,           // width-specific instruction, e.g., "8" suffix
1013cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  ClassB            // bitcast arguments with enum argument to specify type
1023cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen};
1033cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen
1043cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen/// NeonTypeFlags - Flags to identify the types for overloaded Neon
1053cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen/// builtins.  These must be kept in sync with the flags in
1063cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen/// include/clang/Basic/TargetBuiltins.h.
1073cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesennamespace {
1083cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesenclass NeonTypeFlags {
1093cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  enum {
1103cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    EltTypeMask = 0xf,
1113cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    UnsignedFlag = 0x10,
1123cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    QuadFlag = 0x20
1133cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  };
1143cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  uint32_t Flags;
1153cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen
1163cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesenpublic:
1173cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  enum EltType {
1183cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    Int8,
1193cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    Int16,
1203cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    Int32,
1213cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    Int64,
1223cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    Poly8,
1233cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    Poly16,
1243cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    Float16,
1253cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    Float32
1263cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  };
1273cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen
1283cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  NeonTypeFlags(unsigned F) : Flags(F) {}
1293cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  NeonTypeFlags(EltType ET, bool IsUnsigned, bool IsQuad) : Flags(ET) {
1303cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    if (IsUnsigned)
1313cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen      Flags |= UnsignedFlag;
1323cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    if (IsQuad)
1333cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen      Flags |= QuadFlag;
1343cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  }
1353cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen
1363cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  uint32_t getFlags() const { return Flags; }
1373cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen};
1383cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen} // end anonymous namespace
1393cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen
1403cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesennamespace {
1413cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesenclass NeonEmitter {
1423cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  RecordKeeper &Records;
1433cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  StringMap<OpKind> OpMap;
1443cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  DenseMap<Record*, ClassKind> ClassMap;
1453cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen
1463cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesenpublic:
1473cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  NeonEmitter(RecordKeeper &R) : Records(R) {
1483cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_NONE"]  = OpNone;
1493cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_UNAVAILABLE"] = OpUnavailable;
1503cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_ADD"]   = OpAdd;
1513cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_ADDL"]  = OpAddl;
1523cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_ADDW"]  = OpAddw;
1533cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_SUB"]   = OpSub;
1543cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_SUBL"]  = OpSubl;
1553cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_SUBW"]  = OpSubw;
1563cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_MUL"]   = OpMul;
1573cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_MLA"]   = OpMla;
1583cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_MLAL"]  = OpMlal;
1593cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_MLS"]   = OpMls;
1603cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_MLSL"]  = OpMlsl;
1613cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_MUL_N"] = OpMulN;
1623cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_MLA_N"] = OpMlaN;
1633cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_MLS_N"] = OpMlsN;
1643cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_MLAL_N"] = OpMlalN;
1653cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_MLSL_N"] = OpMlslN;
1663cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_MUL_LN"]= OpMulLane;
1673cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_MULL_LN"] = OpMullLane;
1683cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_MLA_LN"]= OpMlaLane;
1693cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_MLS_LN"]= OpMlsLane;
1703cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_MLAL_LN"] = OpMlalLane;
1713cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_MLSL_LN"] = OpMlslLane;
1723cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_QDMULL_LN"] = OpQDMullLane;
1733cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_QDMLAL_LN"] = OpQDMlalLane;
1743cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_QDMLSL_LN"] = OpQDMlslLane;
1753cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_QDMULH_LN"] = OpQDMulhLane;
1763cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_QRDMULH_LN"] = OpQRDMulhLane;
1773cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_EQ"]    = OpEq;
1783cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_GE"]    = OpGe;
1793cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_LE"]    = OpLe;
1803cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_GT"]    = OpGt;
1813cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_LT"]    = OpLt;
1823cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_NEG"]   = OpNeg;
1833cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_NOT"]   = OpNot;
1843cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_AND"]   = OpAnd;
1853cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_OR"]    = OpOr;
1863cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_XOR"]   = OpXor;
1873cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_ANDN"]  = OpAndNot;
1883cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_ORN"]   = OpOrNot;
1893cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_CAST"]  = OpCast;
1903cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_CONC"]  = OpConcat;
1913cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_HI"]    = OpHi;
1923cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_LO"]    = OpLo;
1933cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_DUP"]   = OpDup;
1943cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_DUP_LN"] = OpDupLane;
1953cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_SEL"]   = OpSelect;
1963cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_REV16"] = OpRev16;
1973cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_REV32"] = OpRev32;
1983cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_REV64"] = OpRev64;
1993cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_REINT"] = OpReinterpret;
2003cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_ABDL"]  = OpAbdl;
2013cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_ABA"]   = OpAba;
2023cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_ABAL"]  = OpAbal;
2033cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen
2043cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    Record *SI = R.getClass("SInst");
2053cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    Record *II = R.getClass("IInst");
2063cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    Record *WI = R.getClass("WInst");
2073cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    ClassMap[SI] = ClassS;
2083cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    ClassMap[II] = ClassI;
2093cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    ClassMap[WI] = ClassW;
2103cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  }
2113cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen
2123cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  // run - Emit arm_neon.h.inc
2133cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  void run(raw_ostream &o);
2143cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen
2153cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  // runHeader - Emit all the __builtin prototypes used in arm_neon.h
2163cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  void runHeader(raw_ostream &o);
2173cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen
2183cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  // runTests - Emit tests for all the Neon intrinsics.
2193cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  void runTests(raw_ostream &o);
2203cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen
2213cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesenprivate:
2223cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  void emitIntrinsic(raw_ostream &OS, Record *R);
2233cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen};
2243cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen} // end anonymous namespace
2253cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen
22651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// ParseTypes - break down a string such as "fQf" into a vector of StringRefs,
22751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// which each StringRef representing a single type declared in the string.
22851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// for "fQf" we would end up with 2 StringRefs, "f", and "Qf", representing
22951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// 2xfloat and 4xfloat respectively.
23051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic void ParseTypes(Record *r, std::string &s,
23151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                       SmallVectorImpl<StringRef> &TV) {
23251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  const char *data = s.data();
23351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  int len = 0;
23451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
23551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 0, e = s.size(); i != e; ++i, ++len) {
23651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (data[len] == 'P' || data[len] == 'Q' || data[len] == 'U')
23751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      continue;
23851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
23951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    switch (data[len]) {
24051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      case 'c':
24151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      case 's':
24251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      case 'i':
24351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      case 'l':
24451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      case 'h':
24551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      case 'f':
24651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        break;
24751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      default:
24851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        throw TGError(r->getLoc(),
24951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                      "Unexpected letter: " + std::string(data + len, 1));
25051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
25151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    TV.push_back(StringRef(data, len + 1));
25251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    data += len + 1;
25351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    len = -1;
25451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
25551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
25651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
25751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// Widen - Convert a type code into the next wider type.  char -> short,
25851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// short -> int, etc.
25951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic char Widen(const char t) {
26051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  switch (t) {
26151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'c':
26251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      return 's';
26351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 's':
26451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      return 'i';
26551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'i':
26651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      return 'l';
26751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'h':
26851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      return 'f';
26951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    default: throw "unhandled type in widen!";
27051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
27151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
27251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
27351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// Narrow - Convert a type code into the next smaller type.  short -> char,
27451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// float -> half float, etc.
27551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic char Narrow(const char t) {
27651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  switch (t) {
27751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 's':
27851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      return 'c';
27951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'i':
28051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      return 's';
28151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'l':
28251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      return 'i';
28351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'f':
28451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      return 'h';
28551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    default: throw "unhandled type in narrow!";
28651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
28751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
28851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
28951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// For a particular StringRef, return the base type code, and whether it has
29051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// the quad-vector, polynomial, or unsigned modifiers set.
29151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic char ClassifyType(StringRef ty, bool &quad, bool &poly, bool &usgn) {
29251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  unsigned off = 0;
29351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
29451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // remember quad.
29551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (ty[off] == 'Q') {
29651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    quad = true;
29751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    ++off;
29851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
29951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
30051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // remember poly.
30151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (ty[off] == 'P') {
30251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    poly = true;
30351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    ++off;
30451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
30551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
30651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // remember unsigned.
30751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (ty[off] == 'U') {
30851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    usgn = true;
30951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    ++off;
31051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
31151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
31251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // base type to get the type string for.
31351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return ty[off];
31451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
31551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
31651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// ModType - Transform a type code and its modifiers based on a mod code. The
31751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// mod code definitions may be found at the top of arm_neon.td.
31851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic char ModType(const char mod, char type, bool &quad, bool &poly,
31951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                    bool &usgn, bool &scal, bool &cnst, bool &pntr) {
32051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  switch (mod) {
32151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 't':
32251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (poly) {
32351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        poly = false;
32451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        usgn = true;
32551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      }
32651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
32751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'u':
32851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      usgn = true;
32951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      poly = false;
33051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (type == 'f')
33151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        type = 'i';
33251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
33351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'x':
33451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      usgn = false;
33551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      poly = false;
33651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (type == 'f')
33751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        type = 'i';
33851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
33951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'f':
34051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (type == 'h')
34151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        quad = true;
34251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      type = 'f';
34351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      usgn = false;
34451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
34551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'g':
34651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      quad = false;
34751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
34851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'w':
34951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      type = Widen(type);
35051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      quad = true;
35151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
35251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'n':
35351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      type = Widen(type);
35451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
35551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'i':
35651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      type = 'i';
35751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      scal = true;
35851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
35951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'l':
36051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      type = 'l';
36151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      scal = true;
36251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      usgn = true;
36351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
36451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 's':
36551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'a':
36651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      scal = true;
36751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
36851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'k':
36951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      quad = true;
37051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
37151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'c':
37251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      cnst = true;
37351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'p':
37451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      pntr = true;
37551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      scal = true;
37651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
37751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'h':
37851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      type = Narrow(type);
37951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (type == 'h')
38051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        quad = false;
38151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
38251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'e':
38351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      type = Narrow(type);
38451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      usgn = true;
38551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
38651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    default:
38751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
38851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
38951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return type;
39051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
39151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
39251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// TypeString - for a modifier and type, generate the name of the typedef for
39351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// that type.  QUc -> uint8x8_t.
39451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic std::string TypeString(const char mod, StringRef typestr) {
39551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool quad = false;
39651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool poly = false;
39751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool usgn = false;
39851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool scal = false;
39951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool cnst = false;
40051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool pntr = false;
40151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
40251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (mod == 'v')
40351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    return "void";
40451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (mod == 'i')
40551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    return "int";
40651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
40751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // base type to get the type string for.
40851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  char type = ClassifyType(typestr, quad, poly, usgn);
40951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
41051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Based on the modifying character, change the type and width if necessary.
41151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  type = ModType(mod, type, quad, poly, usgn, scal, cnst, pntr);
41251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
41351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  SmallString<128> s;
41451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
41551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (usgn)
41651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s.push_back('u');
41751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
41851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  switch (type) {
41951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'c':
42051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += poly ? "poly8" : "int8";
42151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (scal)
42251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        break;
42351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += quad ? "x16" : "x8";
42451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
42551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 's':
42651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += poly ? "poly16" : "int16";
42751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (scal)
42851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        break;
42951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += quad ? "x8" : "x4";
43051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
43151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'i':
43251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += "int32";
43351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (scal)
43451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        break;
43551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += quad ? "x4" : "x2";
43651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
43751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'l':
43851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += "int64";
43951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (scal)
44051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        break;
44151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += quad ? "x2" : "x1";
44251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
44351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'h':
44451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += "float16";
44551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (scal)
44651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        break;
44751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += quad ? "x8" : "x4";
44851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
44951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'f':
45051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += "float32";
45151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (scal)
45251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        break;
45351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += quad ? "x4" : "x2";
45451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
45551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    default:
45651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      throw "unhandled type!";
45751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
45851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
45951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (mod == '2')
46051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "x2";
46151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (mod == '3')
46251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "x3";
46351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (mod == '4')
46451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "x4";
46551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
46651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Append _t, finishing the type string typedef type.
46751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += "_t";
46851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
46951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (cnst)
47051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += " const";
47151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
47251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (pntr)
47351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += " *";
47451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
47551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return s.str();
47651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
47751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
47851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// BuiltinTypeString - for a modifier and type, generate the clang
47951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// BuiltinsARM.def prototype code for the function.  See the top of clang's
48051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// Builtins.def for a description of the type strings.
48151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic std::string BuiltinTypeString(const char mod, StringRef typestr,
48251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                                     ClassKind ck, bool ret) {
48351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool quad = false;
48451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool poly = false;
48551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool usgn = false;
48651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool scal = false;
48751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool cnst = false;
48851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool pntr = false;
48951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
49051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (mod == 'v')
49151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    return "v"; // void
49251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (mod == 'i')
49351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    return "i"; // int
49451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
49551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // base type to get the type string for.
49651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  char type = ClassifyType(typestr, quad, poly, usgn);
49751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
49851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Based on the modifying character, change the type and width if necessary.
49951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  type = ModType(mod, type, quad, poly, usgn, scal, cnst, pntr);
50051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
50151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // All pointers are void* pointers.  Change type to 'v' now.
50251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (pntr) {
50351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    usgn = false;
50451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    poly = false;
50551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    type = 'v';
50651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
50751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Treat half-float ('h') types as unsigned short ('s') types.
50851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (type == 'h') {
50951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    type = 's';
51051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    usgn = true;
51151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
51251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  usgn = usgn | poly | ((ck == ClassI || ck == ClassW) && scal && type != 'f');
51351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
51451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (scal) {
51551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    SmallString<128> s;
51651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
51751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (usgn)
51851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s.push_back('U');
51951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    else if (type == 'c')
52051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s.push_back('S'); // make chars explicitly signed
52151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
52251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (type == 'l') // 64-bit long
52351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += "LLi";
52451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    else
52551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s.push_back(type);
52651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
52751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (cnst)
52851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s.push_back('C');
52951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (pntr)
53051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s.push_back('*');
53151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    return s.str();
53251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
53351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
53451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Since the return value must be one type, return a vector type of the
53551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // appropriate width which we will bitcast.  An exception is made for
53651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // returning structs of 2, 3, or 4 vectors which are returned in a sret-like
53751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // fashion, storing them to a pointer arg.
53851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (ret) {
53951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (mod >= '2' && mod <= '4')
54051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      return "vv*"; // void result with void* first argument
54151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (mod == 'f' || (ck != ClassB && type == 'f'))
54251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      return quad ? "V4f" : "V2f";
54351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (ck != ClassB && type == 's')
54451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      return quad ? "V8s" : "V4s";
54551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (ck != ClassB && type == 'i')
54651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      return quad ? "V4i" : "V2i";
54751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (ck != ClassB && type == 'l')
54851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      return quad ? "V2LLi" : "V1LLi";
54951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
55051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    return quad ? "V16Sc" : "V8Sc";
55151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
55251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
55351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Non-return array types are passed as individual vectors.
55451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (mod == '2')
55551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    return quad ? "V16ScV16Sc" : "V8ScV8Sc";
55651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (mod == '3')
55751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    return quad ? "V16ScV16ScV16Sc" : "V8ScV8ScV8Sc";
55851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (mod == '4')
55951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    return quad ? "V16ScV16ScV16ScV16Sc" : "V8ScV8ScV8ScV8Sc";
56051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
56151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (mod == 'f' || (ck != ClassB && type == 'f'))
56251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    return quad ? "V4f" : "V2f";
56351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (ck != ClassB && type == 's')
56451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    return quad ? "V8s" : "V4s";
56551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (ck != ClassB && type == 'i')
56651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    return quad ? "V4i" : "V2i";
56751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (ck != ClassB && type == 'l')
56851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    return quad ? "V2LLi" : "V1LLi";
56951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
57051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return quad ? "V16Sc" : "V8Sc";
57151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
57251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
57351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// MangleName - Append a type or width suffix to a base neon function name,
57451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// and insert a 'q' in the appropriate location if the operation works on
57551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// 128b rather than 64b.   E.g. turn "vst2_lane" into "vst2q_lane_f32", etc.
57651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic std::string MangleName(const std::string &name, StringRef typestr,
57751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                              ClassKind ck) {
57851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (name == "vcvt_f32_f16")
57951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    return name;
58051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
58151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool quad = false;
58251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool poly = false;
58351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool usgn = false;
58451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  char type = ClassifyType(typestr, quad, poly, usgn);
58551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
58651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string s = name;
58751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
58851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  switch (type) {
58951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case 'c':
59051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    switch (ck) {
59151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case ClassS: s += poly ? "_p8" : usgn ? "_u8" : "_s8"; break;
59251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case ClassI: s += "_i8"; break;
59351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case ClassW: s += "_8"; break;
59451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    default: break;
59551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
59651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
59751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case 's':
59851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    switch (ck) {
59951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case ClassS: s += poly ? "_p16" : usgn ? "_u16" : "_s16"; break;
60051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case ClassI: s += "_i16"; break;
60151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case ClassW: s += "_16"; break;
60251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    default: break;
60351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
60451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
60551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case 'i':
60651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    switch (ck) {
60751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case ClassS: s += usgn ? "_u32" : "_s32"; break;
60851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case ClassI: s += "_i32"; break;
60951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case ClassW: s += "_32"; break;
61051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    default: break;
61151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
61251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
61351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case 'l':
61451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    switch (ck) {
61551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case ClassS: s += usgn ? "_u64" : "_s64"; break;
61651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case ClassI: s += "_i64"; break;
61751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case ClassW: s += "_64"; break;
61851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    default: break;
61951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
62051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
62151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case 'h':
62251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    switch (ck) {
62351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case ClassS:
62451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case ClassI: s += "_f16"; break;
62551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case ClassW: s += "_16"; break;
62651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    default: break;
62751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
62851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
62951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case 'f':
63051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    switch (ck) {
63151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case ClassS:
63251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case ClassI: s += "_f32"; break;
63351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case ClassW: s += "_32"; break;
63451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    default: break;
63551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
63651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
63751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  default:
63851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    throw "unhandled type!";
63951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
64051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (ck == ClassB)
64151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "_v";
64251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
64351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Insert a 'q' before the first '_' character so that it ends up before
64451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // _lane or _n on vector-scalar operations.
64551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (quad) {
64651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    size_t pos = s.find('_');
64751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s = s.insert(pos, "q");
64851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
64951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return s;
65051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
65151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
65251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// UseMacro - Examine the prototype string to determine if the intrinsic
65351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// should be defined as a preprocessor macro instead of an inline function.
65451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic bool UseMacro(const std::string &proto) {
65551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // If this builtin takes an immediate argument, we need to #define it rather
65651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // than use a standard declaration, so that SemaChecking can range check
65751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // the immediate passed by the user.
65851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (proto.find('i') != std::string::npos)
65951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    return true;
66051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
66151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Pointer arguments need to use macros to avoid hiding aligned attributes
66251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // from the pointer type.
66351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (proto.find('p') != std::string::npos ||
66451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      proto.find('c') != std::string::npos)
66551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    return true;
66651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
66751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return false;
66851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
66951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
67051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// MacroArgUsedDirectly - Return true if argument i for an intrinsic that is
67151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// defined as a macro should be accessed directly instead of being first
67251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// assigned to a local temporary.
67351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic bool MacroArgUsedDirectly(const std::string &proto, unsigned i) {
67451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // True for constant ints (i), pointers (p) and const pointers (c).
67551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return (proto[i] == 'i' || proto[i] == 'p' || proto[i] == 'c');
67651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
67751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
67851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne// Generate the string "(argtype a, argtype b, ...)"
67951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic std::string GenArgs(const std::string &proto, StringRef typestr) {
68051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool define = UseMacro(proto);
68151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  char arg = 'a';
68251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
68351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string s;
68451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += "(";
68551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
68651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) {
68751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (define) {
68851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      // Some macro arguments are used directly instead of being assigned
68951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      // to local temporaries; prepend an underscore prefix to make their
69051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      // names consistent with the local temporaries.
69151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (MacroArgUsedDirectly(proto, i))
69251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        s += "__";
69351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    } else {
69451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += TypeString(proto[i], typestr) + " __";
69551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
69651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s.push_back(arg);
69751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if ((i + 1) < e)
69851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += ", ";
69951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
70051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
70151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += ")";
70251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return s;
70351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
70451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
70551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne// Macro arguments are not type-checked like inline function arguments, so
70651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne// assign them to local temporaries to get the right type checking.
70751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic std::string GenMacroLocals(const std::string &proto, StringRef typestr) {
70851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  char arg = 'a';
70951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string s;
71051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool generatedLocal = false;
71151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
71251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) {
71351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // Do not create a temporary for an immediate argument.
71451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // That would defeat the whole point of using a macro!
71551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (MacroArgUsedDirectly(proto, i))
71651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      continue;
71751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    generatedLocal = true;
71851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
71951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += TypeString(proto[i], typestr) + " __";
72051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s.push_back(arg);
72151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += " = (";
72251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s.push_back(arg);
72351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "); ";
72451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
72551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
72651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (generatedLocal)
72751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "\\\n  ";
72851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return s;
72951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
73051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
73151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne// Use the vmovl builtin to sign-extend or zero-extend a vector.
73251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic std::string Extend(StringRef typestr, const std::string &a) {
73351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string s;
73451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s = MangleName("vmovl", typestr, ClassS);
73551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += "(" + a + ")";
73651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return s;
73751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
73851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
73951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic std::string Duplicate(unsigned nElts, StringRef typestr,
74051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                             const std::string &a) {
74151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string s;
74251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
74351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s = "(" + TypeString('d', typestr) + "){ ";
74451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 0; i != nElts; ++i) {
74551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += a;
74651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if ((i + 1) < nElts)
74751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += ", ";
74851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
74951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += " }";
75051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
75151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return s;
75251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
75351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
75451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic std::string SplatLane(unsigned nElts, const std::string &vec,
75551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                             const std::string &lane) {
75651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string s = "__builtin_shufflevector(" + vec + ", " + vec;
75751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 0; i < nElts; ++i)
75851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += ", " + lane;
75951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += ")";
76051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return s;
76151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
76251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
76351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic unsigned GetNumElements(StringRef typestr, bool &quad) {
76451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  quad = false;
76551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool dummy = false;
76651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  char type = ClassifyType(typestr, quad, dummy, dummy);
76751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  unsigned nElts = 0;
76851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  switch (type) {
76951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case 'c': nElts = 8; break;
77051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case 's': nElts = 4; break;
77151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case 'i': nElts = 2; break;
77251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case 'l': nElts = 1; break;
77351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case 'h': nElts = 4; break;
77451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case 'f': nElts = 2; break;
77551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  default:
77651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    throw "unhandled type!";
77751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
77851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (quad) nElts <<= 1;
77951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return nElts;
78051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
78151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
78251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne// Generate the definition for this intrinsic, e.g. "a + b" for OpAdd.
78351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic std::string GenOpString(OpKind op, const std::string &proto,
78451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                               StringRef typestr) {
78551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool quad;
78651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  unsigned nElts = GetNumElements(typestr, quad);
78751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool define = UseMacro(proto);
78851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
78951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string ts = TypeString(proto[0], typestr);
79051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string s;
79151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (!define) {
79251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s = "return ";
79351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
79451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
79551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  switch(op) {
79651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpAdd:
79751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a + __b;";
79851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
79951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpAddl:
80051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += Extend(typestr, "__a") + " + " + Extend(typestr, "__b") + ";";
80151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
80251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpAddw:
80351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a + " + Extend(typestr, "__b") + ";";
80451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
80551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpSub:
80651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a - __b;";
80751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
80851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpSubl:
80951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += Extend(typestr, "__a") + " - " + Extend(typestr, "__b") + ";";
81051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
81151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpSubw:
81251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a - " + Extend(typestr, "__b") + ";";
81351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
81451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpMulN:
81551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a * " + Duplicate(nElts, typestr, "__b") + ";";
81651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
81751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpMulLane:
81851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a * " + SplatLane(nElts, "__b", "__c") + ";";
81951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
82051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpMul:
82151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a * __b;";
82251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
82351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpMullLane:
82451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += MangleName("vmull", typestr, ClassS) + "(__a, " +
82551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      SplatLane(nElts, "__b", "__c") + ");";
82651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
82751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpMlaN:
82851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a + (__b * " + Duplicate(nElts, typestr, "__c") + ");";
82951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
83051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpMlaLane:
83151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a + (__b * " + SplatLane(nElts, "__c", "__d") + ");";
83251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
83351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpMla:
83451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a + (__b * __c);";
83551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
83651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpMlalN:
83751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a + " + MangleName("vmull", typestr, ClassS) + "(__b, " +
83851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      Duplicate(nElts, typestr, "__c") + ");";
83951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
84051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpMlalLane:
84151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a + " + MangleName("vmull", typestr, ClassS) + "(__b, " +
84251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      SplatLane(nElts, "__c", "__d") + ");";
84351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
84451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpMlal:
84551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a + " + MangleName("vmull", typestr, ClassS) + "(__b, __c);";
84651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
84751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpMlsN:
84851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a - (__b * " + Duplicate(nElts, typestr, "__c") + ");";
84951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
85051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpMlsLane:
85151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a - (__b * " + SplatLane(nElts, "__c", "__d") + ");";
85251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
85351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpMls:
85451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a - (__b * __c);";
85551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
85651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpMlslN:
85751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a - " + MangleName("vmull", typestr, ClassS) + "(__b, " +
85851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      Duplicate(nElts, typestr, "__c") + ");";
85951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
86051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpMlslLane:
86151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a - " + MangleName("vmull", typestr, ClassS) + "(__b, " +
86251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      SplatLane(nElts, "__c", "__d") + ");";
86351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
86451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpMlsl:
86551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a - " + MangleName("vmull", typestr, ClassS) + "(__b, __c);";
86651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
86751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpQDMullLane:
86851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += MangleName("vqdmull", typestr, ClassS) + "(__a, " +
86951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      SplatLane(nElts, "__b", "__c") + ");";
87051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
87151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpQDMlalLane:
87251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += MangleName("vqdmlal", typestr, ClassS) + "(__a, __b, " +
87351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      SplatLane(nElts, "__c", "__d") + ");";
87451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
87551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpQDMlslLane:
87651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += MangleName("vqdmlsl", typestr, ClassS) + "(__a, __b, " +
87751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      SplatLane(nElts, "__c", "__d") + ");";
87851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
87951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpQDMulhLane:
88051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += MangleName("vqdmulh", typestr, ClassS) + "(__a, " +
88151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      SplatLane(nElts, "__b", "__c") + ");";
88251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
88351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpQRDMulhLane:
88451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += MangleName("vqrdmulh", typestr, ClassS) + "(__a, " +
88551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      SplatLane(nElts, "__b", "__c") + ");";
88651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
88751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpEq:
88851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "(" + ts + ")(__a == __b);";
88951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
89051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpGe:
89151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "(" + ts + ")(__a >= __b);";
89251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
89351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpLe:
89451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "(" + ts + ")(__a <= __b);";
89551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
89651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpGt:
89751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "(" + ts + ")(__a > __b);";
89851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
89951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpLt:
90051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "(" + ts + ")(__a < __b);";
90151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
90251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpNeg:
90351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += " -__a;";
90451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
90551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpNot:
90651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += " ~__a;";
90751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
90851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpAnd:
90951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a & __b;";
91051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
91151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpOr:
91251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a | __b;";
91351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
91451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpXor:
91551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a ^ __b;";
91651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
91751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpAndNot:
91851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a & ~__b;";
91951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
92051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpOrNot:
92151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a | ~__b;";
92251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
92351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpCast:
92451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "(" + ts + ")__a;";
92551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
92651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpConcat:
92751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "(" + ts + ")__builtin_shufflevector((int64x1_t)__a";
92851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += ", (int64x1_t)__b, 0, 1);";
92951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
93051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpHi:
93151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "(" + ts +
93251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      ")__builtin_shufflevector((int64x2_t)__a, (int64x2_t)__a, 1);";
93351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
93451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpLo:
93551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "(" + ts +
93651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      ")__builtin_shufflevector((int64x2_t)__a, (int64x2_t)__a, 0);";
93751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
93851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpDup:
93951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += Duplicate(nElts, typestr, "__a") + ";";
94051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
94151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpDupLane:
94251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += SplatLane(nElts, "__a", "__b") + ";";
94351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
94451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpSelect:
94551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // ((0 & 1) | (~0 & 2))
94651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "(" + ts + ")";
94751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    ts = TypeString(proto[1], typestr);
94851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "((__a & (" + ts + ")__b) | ";
94951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "(~__a & (" + ts + ")__c));";
95051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
95151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpRev16:
95251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__builtin_shufflevector(__a, __a";
95351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    for (unsigned i = 2; i <= nElts; i += 2)
95451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      for (unsigned j = 0; j != 2; ++j)
95551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        s += ", " + utostr(i - j - 1);
95651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += ");";
95751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
95851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpRev32: {
95951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    unsigned WordElts = nElts >> (1 + (int)quad);
96051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__builtin_shufflevector(__a, __a";
96151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    for (unsigned i = WordElts; i <= nElts; i += WordElts)
96251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      for (unsigned j = 0; j != WordElts; ++j)
96351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        s += ", " + utostr(i - j - 1);
96451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += ");";
96551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
96651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
96751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpRev64: {
96851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    unsigned DblWordElts = nElts >> (int)quad;
96951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__builtin_shufflevector(__a, __a";
97051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    for (unsigned i = DblWordElts; i <= nElts; i += DblWordElts)
97151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      for (unsigned j = 0; j != DblWordElts; ++j)
97251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        s += ", " + utostr(i - j - 1);
97351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += ");";
97451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
97551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
97651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpAbdl: {
97751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::string abd = MangleName("vabd", typestr, ClassS) + "(__a, __b)";
97851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (typestr[0] != 'U') {
97951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      // vabd results are always unsigned and must be zero-extended.
98051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      std::string utype = "U" + typestr.str();
98151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += "(" + TypeString(proto[0], typestr) + ")";
98251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      abd = "(" + TypeString('d', utype) + ")" + abd;
98351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += Extend(utype, abd) + ";";
98451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    } else {
98551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += Extend(typestr, abd) + ";";
98651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
98751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
98851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
98951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpAba:
99051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a + " + MangleName("vabd", typestr, ClassS) + "(__b, __c);";
99151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
99251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpAbal: {
99351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a + ";
99451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::string abd = MangleName("vabd", typestr, ClassS) + "(__b, __c)";
99551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (typestr[0] != 'U') {
99651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      // vabd results are always unsigned and must be zero-extended.
99751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      std::string utype = "U" + typestr.str();
99851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += "(" + TypeString(proto[0], typestr) + ")";
99951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      abd = "(" + TypeString('d', utype) + ")" + abd;
100051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += Extend(utype, abd) + ";";
100151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    } else {
100251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += Extend(typestr, abd) + ";";
100351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
100451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
100551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
100651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  default:
100751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    throw "unknown OpKind!";
100851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
100951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return s;
101051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
101151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
101251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic unsigned GetNeonEnum(const std::string &proto, StringRef typestr) {
101351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  unsigned mod = proto[0];
101451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
101551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (mod == 'v' || mod == 'f')
101651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    mod = proto[1];
101751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
101851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool quad = false;
101951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool poly = false;
102051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool usgn = false;
102151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool scal = false;
102251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool cnst = false;
102351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool pntr = false;
102451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
102551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Base type to get the type string for.
102651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  char type = ClassifyType(typestr, quad, poly, usgn);
102751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
102851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Based on the modifying character, change the type and width if necessary.
102951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  type = ModType(mod, type, quad, poly, usgn, scal, cnst, pntr);
103051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
1031da95f73b59f9af964e33725c515139d34c90c863Bob Wilson  NeonTypeFlags::EltType ET;
103251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  switch (type) {
103351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'c':
1034da95f73b59f9af964e33725c515139d34c90c863Bob Wilson      ET = poly ? NeonTypeFlags::Poly8 : NeonTypeFlags::Int8;
103551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
103651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 's':
1037da95f73b59f9af964e33725c515139d34c90c863Bob Wilson      ET = poly ? NeonTypeFlags::Poly16 : NeonTypeFlags::Int16;
103851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
103951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'i':
1040da95f73b59f9af964e33725c515139d34c90c863Bob Wilson      ET = NeonTypeFlags::Int32;
104151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
104251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'l':
1043da95f73b59f9af964e33725c515139d34c90c863Bob Wilson      ET = NeonTypeFlags::Int64;
104451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
104551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'h':
1046da95f73b59f9af964e33725c515139d34c90c863Bob Wilson      ET = NeonTypeFlags::Float16;
104751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
104851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'f':
1049da95f73b59f9af964e33725c515139d34c90c863Bob Wilson      ET = NeonTypeFlags::Float32;
105051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
105151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    default:
105251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      throw "unhandled type!";
105351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
1054da95f73b59f9af964e33725c515139d34c90c863Bob Wilson  NeonTypeFlags Flags(ET, usgn, quad && proto[1] != 'g');
1055da95f73b59f9af964e33725c515139d34c90c863Bob Wilson  return Flags.getFlags();
105651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
105751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
105851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne// Generate the definition for this intrinsic, e.g. __builtin_neon_cls(a)
105951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic std::string GenBuiltin(const std::string &name, const std::string &proto,
106051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                              StringRef typestr, ClassKind ck) {
106151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string s;
106251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
106351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // If this builtin returns a struct 2, 3, or 4 vectors, pass it as an implicit
106451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // sret-like argument.
106551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool sret = (proto[0] >= '2' && proto[0] <= '4');
106651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
106751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool define = UseMacro(proto);
106851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
106951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Check if the prototype has a scalar operand with the type of the vector
107051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // elements.  If not, bitcasting the args will take care of arg checking.
107151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // The actual signedness etc. will be taken care of with special enums.
107251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (proto.find('s') == std::string::npos)
107351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    ck = ClassB;
107451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
107551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (proto[0] != 'v') {
107651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::string ts = TypeString(proto[0], typestr);
107751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
107851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (define) {
107951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (sret)
108051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        s += ts + " r; ";
108151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      else
108251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        s += "(" + ts + ")";
108351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    } else if (sret) {
108451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += ts + " r; ";
108551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    } else {
108651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += "return (" + ts + ")";
108751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
108851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
108951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
109051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool splat = proto.find('a') != std::string::npos;
109151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
109251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += "__builtin_neon_";
109351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (splat) {
109451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // Call the non-splat builtin: chop off the "_n" suffix from the name.
109551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::string vname(name, 0, name.size()-2);
109651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += MangleName(vname, typestr, ck);
109751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  } else {
109851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += MangleName(name, typestr, ck);
109951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
110051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += "(";
110151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
110251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Pass the address of the return variable as the first argument to sret-like
110351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // builtins.
110451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (sret)
110551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "&r, ";
110651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
110751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  char arg = 'a';
110851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) {
110951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::string args = std::string(&arg, 1);
111051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
111151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // Use the local temporaries instead of the macro arguments.
111251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    args = "__" + args;
111351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
111451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    bool argQuad = false;
111551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    bool argPoly = false;
111651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    bool argUsgn = false;
111751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    bool argScalar = false;
111851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    bool dummy = false;
111951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    char argType = ClassifyType(typestr, argQuad, argPoly, argUsgn);
112051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    argType = ModType(proto[i], argType, argQuad, argPoly, argUsgn, argScalar,
112151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                      dummy, dummy);
112251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
112351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // Handle multiple-vector values specially, emitting each subvector as an
112451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // argument to the __builtin.
112551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (proto[i] >= '2' && proto[i] <= '4') {
112651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      // Check if an explicit cast is needed.
112751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (argType != 'c' || argPoly || argUsgn)
112851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        args = (argQuad ? "(int8x16_t)" : "(int8x8_t)") + args;
112951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
113051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      for (unsigned vi = 0, ve = proto[i] - '0'; vi != ve; ++vi) {
113151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        s += args + ".val[" + utostr(vi) + "]";
113251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        if ((vi + 1) < ve)
113351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne          s += ", ";
113451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      }
113551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if ((i + 1) < e)
113651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        s += ", ";
113751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
113851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      continue;
113951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
114051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
114151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (splat && (i + 1) == e)
114251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      args = Duplicate(GetNumElements(typestr, argQuad), typestr, args);
114351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
114451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // Check if an explicit cast is needed.
114551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if ((splat || !argScalar) &&
114651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        ((ck == ClassB && argType != 'c') || argPoly || argUsgn)) {
114751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      std::string argTypeStr = "c";
114851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (ck != ClassB)
114951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        argTypeStr = argType;
115051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (argQuad)
115151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        argTypeStr = "Q" + argTypeStr;
115251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      args = "(" + TypeString('d', argTypeStr) + ")" + args;
115351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
115451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
115551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += args;
115651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if ((i + 1) < e)
115751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += ", ";
115851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
115951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
116051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Extra constant integer to hold type class enum for this function, e.g. s8
116151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (ck == ClassB)
116251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += ", " + utostr(GetNeonEnum(proto, typestr));
116351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
116451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += ");";
116551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
116651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (proto[0] != 'v' && sret) {
116751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (define)
116851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += " r;";
116951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    else
117051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += " return r;";
117151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
117251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return s;
117351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
117451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
117551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic std::string GenBuiltinDef(const std::string &name,
117651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                                 const std::string &proto,
117751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                                 StringRef typestr, ClassKind ck) {
117851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string s("BUILTIN(__builtin_neon_");
117951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
118051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // If all types are the same size, bitcasting the args will take care
118151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // of arg checking.  The actual signedness etc. will be taken care of with
118251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // special enums.
118351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (proto.find('s') == std::string::npos)
118451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    ck = ClassB;
118551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
118651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += MangleName(name, typestr, ck);
118751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += ", \"";
118851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
118951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 0, e = proto.size(); i != e; ++i)
119051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += BuiltinTypeString(proto[i], typestr, ck, i == 0);
119151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
119251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Extra constant integer to hold type class enum for this function, e.g. s8
119351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (ck == ClassB)
119451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "i";
119551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
119651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += "\", \"n\")";
119751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return s;
119851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
119951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
120051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic std::string GenIntrinsic(const std::string &name,
120151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                                const std::string &proto,
120251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                                StringRef outTypeStr, StringRef inTypeStr,
120351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                                OpKind kind, ClassKind classKind) {
120451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  assert(!proto.empty() && "");
1205667381b21f75d6964bbdf6af143308a02b9198a8Jim Grosbach  bool define = UseMacro(proto) && kind != OpUnavailable;
120651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string s;
120751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
120851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // static always inline + return type
120951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (define)
121051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "#define ";
121151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  else
121251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__ai " + TypeString(proto[0], outTypeStr) + " ";
121351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
121451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Function name with type suffix
121551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string mangledName = MangleName(name, outTypeStr, ClassS);
121651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (outTypeStr != inTypeStr) {
121751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // If the input type is different (e.g., for vreinterpret), append a suffix
121851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // for the input type.  String off a "Q" (quad) prefix so that MangleName
121951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // does not insert another "q" in the name.
122051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    unsigned typeStrOff = (inTypeStr[0] == 'Q' ? 1 : 0);
122151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    StringRef inTypeNoQuad = inTypeStr.substr(typeStrOff);
122251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    mangledName = MangleName(mangledName, inTypeNoQuad, ClassS);
122351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
122451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += mangledName;
122551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
122651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Function arguments
122751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += GenArgs(proto, inTypeStr);
122851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
122951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Definition.
123051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (define) {
123151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += " __extension__ ({ \\\n  ";
123251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += GenMacroLocals(proto, inTypeStr);
1233667381b21f75d6964bbdf6af143308a02b9198a8Jim Grosbach  } else if (kind == OpUnavailable) {
1234667381b21f75d6964bbdf6af143308a02b9198a8Jim Grosbach    s += " __attribute__((unavailable));\n";
1235667381b21f75d6964bbdf6af143308a02b9198a8Jim Grosbach    return s;
1236667381b21f75d6964bbdf6af143308a02b9198a8Jim Grosbach  } else
123766981c7ca1fcef529d7d5e5c53b07020ff23d8e3Jim Grosbach    s += " {\n  ";
123851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
123951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (kind != OpNone)
124051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += GenOpString(kind, proto, outTypeStr);
124151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  else
124251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += GenBuiltin(name, proto, outTypeStr, classKind);
124351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (define)
124451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += " })";
124551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  else
124651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += " }";
124751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += "\n";
124851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return s;
124951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
125051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
125151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// run - Read the records in arm_neon.td and output arm_neon.h.  arm_neon.h
125251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// is comprised of type definitions and function declarations.
125351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournevoid NeonEmitter::run(raw_ostream &OS) {
125451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS <<
125551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    "/*===---- arm_neon.h - ARM Neon intrinsics ------------------------------"
125651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    "---===\n"
125751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " *\n"
125851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " * Permission is hereby granted, free of charge, to any person obtaining "
125951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    "a copy\n"
126051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " * of this software and associated documentation files (the \"Software\"),"
126151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " to deal\n"
126251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " * in the Software without restriction, including without limitation the "
126351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    "rights\n"
126451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " * to use, copy, modify, merge, publish, distribute, sublicense, "
126551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    "and/or sell\n"
126651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " * copies of the Software, and to permit persons to whom the Software is\n"
126751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " * furnished to do so, subject to the following conditions:\n"
126851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " *\n"
126951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " * The above copyright notice and this permission notice shall be "
127051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    "included in\n"
127151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " * all copies or substantial portions of the Software.\n"
127251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " *\n"
127351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, "
127451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    "EXPRESS OR\n"
127551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF "
127651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    "MERCHANTABILITY,\n"
127751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT "
127851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    "SHALL THE\n"
127951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR "
128051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    "OTHER\n"
128151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, "
128251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    "ARISING FROM,\n"
128351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER "
128451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    "DEALINGS IN\n"
128551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " * THE SOFTWARE.\n"
128651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " *\n"
128751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " *===--------------------------------------------------------------------"
128851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    "---===\n"
128951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " */\n\n";
129051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
129151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#ifndef __ARM_NEON_H\n";
129251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#define __ARM_NEON_H\n\n";
129351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
129451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#ifndef __ARM_NEON__\n";
129551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#error \"NEON support not enabled\"\n";
129651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#endif\n\n";
129751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
129851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#include <stdint.h>\n\n";
129951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
130051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Emit NEON-specific scalar typedefs.
130151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "typedef float float32_t;\n";
130251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "typedef int8_t poly8_t;\n";
130351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "typedef int16_t poly16_t;\n";
130451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "typedef uint16_t float16_t;\n";
130551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
130651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Emit Neon vector typedefs.
130751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string TypedefTypes("cQcsQsiQilQlUcQUcUsQUsUiQUiUlQUlhQhfQfPcQPcPsQPs");
130851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  SmallVector<StringRef, 24> TDTypeVec;
130951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  ParseTypes(0, TypedefTypes, TDTypeVec);
131051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
131151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Emit vector typedefs.
131251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 0, e = TDTypeVec.size(); i != e; ++i) {
131351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    bool dummy, quad = false, poly = false;
131451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    (void) ClassifyType(TDTypeVec[i], quad, poly, dummy);
131551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (poly)
131651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      OS << "typedef __attribute__((neon_polyvector_type(";
131751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    else
131851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      OS << "typedef __attribute__((neon_vector_type(";
131951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
132051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    unsigned nElts = GetNumElements(TDTypeVec[i], quad);
132151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    OS << utostr(nElts) << "))) ";
132251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (nElts < 10)
132351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      OS << " ";
132451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
132551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    OS << TypeString('s', TDTypeVec[i]);
132651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    OS << " " << TypeString('d', TDTypeVec[i]) << ";\n";
132751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
132851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "\n";
132951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
133051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Emit struct typedefs.
133151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned vi = 2; vi != 5; ++vi) {
133251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    for (unsigned i = 0, e = TDTypeVec.size(); i != e; ++i) {
133351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      std::string ts = TypeString('d', TDTypeVec[i]);
133451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      std::string vs = TypeString('0' + vi, TDTypeVec[i]);
133551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      OS << "typedef struct " << vs << " {\n";
133651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      OS << "  " << ts << " val";
133751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      OS << "[" << utostr(vi) << "]";
133851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      OS << ";\n} ";
133951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      OS << vs << ";\n\n";
134051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
134151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
134251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
1343d1af3b901a2176bc7f4b7e2fadcd25110576b454Bob Wilson  OS<<"#define __ai static __attribute__((__always_inline__, __nodebug__))\n\n";
134451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
134551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::vector<Record*> RV = Records.getAllDerivedDefinitions("Inst");
134651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
134751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Emit vmovl, vmull and vabd intrinsics first so they can be used by other
134851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // intrinsics.  (Some of the saturating multiply instructions are also
134951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // used to implement the corresponding "_lane" variants, but tablegen
135051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // sorts the records into alphabetical order so that the "_lane" variants
135151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // come after the intrinsics they use.)
135251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  emitIntrinsic(OS, Records.getDef("VMOVL"));
135351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  emitIntrinsic(OS, Records.getDef("VMULL"));
135451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  emitIntrinsic(OS, Records.getDef("VABD"));
135551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
135651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 0, e = RV.size(); i != e; ++i) {
135751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    Record *R = RV[i];
135851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (R->getName() != "VMOVL" &&
135951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        R->getName() != "VMULL" &&
136051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        R->getName() != "VABD")
136151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      emitIntrinsic(OS, R);
136251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
136351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
136451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#undef __ai\n\n";
136551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#endif /* __ARM_NEON_H */\n";
136651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
136751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
136851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// emitIntrinsic - Write out the arm_neon.h header file definitions for the
136951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// intrinsics specified by record R.
137051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournevoid NeonEmitter::emitIntrinsic(raw_ostream &OS, Record *R) {
137151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string name = R->getValueAsString("Name");
137251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string Proto = R->getValueAsString("Prototype");
137351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string Types = R->getValueAsString("Types");
137451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
137551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  SmallVector<StringRef, 16> TypeVec;
137651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  ParseTypes(R, Types, TypeVec);
137751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
137851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OpKind kind = OpMap[R->getValueAsDef("Operand")->getName()];
137951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
138051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  ClassKind classKind = ClassNone;
138151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (R->getSuperClasses().size() >= 2)
138251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    classKind = ClassMap[R->getSuperClasses()[1]];
138351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (classKind == ClassNone && kind == OpNone)
138451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    throw TGError(R->getLoc(), "Builtin has no class kind");
138551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
138651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) {
138751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (kind == OpReinterpret) {
138851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      bool outQuad = false;
138951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      bool dummy = false;
139051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      (void)ClassifyType(TypeVec[ti], outQuad, dummy, dummy);
139151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      for (unsigned srcti = 0, srcte = TypeVec.size();
139251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne           srcti != srcte; ++srcti) {
139351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        bool inQuad = false;
139451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        (void)ClassifyType(TypeVec[srcti], inQuad, dummy, dummy);
139551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        if (srcti == ti || inQuad != outQuad)
139651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne          continue;
139751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        OS << GenIntrinsic(name, Proto, TypeVec[ti], TypeVec[srcti],
139851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                           OpCast, ClassS);
139951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      }
140051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    } else {
140151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      OS << GenIntrinsic(name, Proto, TypeVec[ti], TypeVec[ti],
140251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                         kind, classKind);
140351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
140451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
140551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "\n";
140651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
140751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
140851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic unsigned RangeFromType(const char mod, StringRef typestr) {
140951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // base type to get the type string for.
141051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool quad = false, dummy = false;
141151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  char type = ClassifyType(typestr, quad, dummy, dummy);
141251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  type = ModType(mod, type, quad, dummy, dummy, dummy, dummy, dummy);
141351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
141451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  switch (type) {
141551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'c':
141651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      return (8 << (int)quad) - 1;
141751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'h':
141851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 's':
141951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      return (4 << (int)quad) - 1;
142051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'f':
142151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'i':
142251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      return (2 << (int)quad) - 1;
142351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'l':
142451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      return (1 << (int)quad) - 1;
142551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    default:
142651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      throw "unhandled type!";
142751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
142851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
142951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
143051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// runHeader - Emit a file with sections defining:
143151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// 1. the NEON section of BuiltinsARM.def.
143251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// 2. the SemaChecking code for the type overload checking.
1433667381b21f75d6964bbdf6af143308a02b9198a8Jim Grosbach/// 3. the SemaChecking code for validation of intrinsic immediate arguments.
143451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournevoid NeonEmitter::runHeader(raw_ostream &OS) {
143551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::vector<Record*> RV = Records.getAllDerivedDefinitions("Inst");
143651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
143751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  StringMap<OpKind> EmittedMap;
143851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
143951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Generate BuiltinsARM.def for NEON
144051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#ifdef GET_NEON_BUILTINS\n";
144151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 0, e = RV.size(); i != e; ++i) {
144251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    Record *R = RV[i];
144351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    OpKind k = OpMap[R->getValueAsDef("Operand")->getName()];
144451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (k != OpNone)
144551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      continue;
144651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
144751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::string Proto = R->getValueAsString("Prototype");
144851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
144951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // Functions with 'a' (the splat code) in the type prototype should not get
145051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // their own builtin as they use the non-splat variant.
145151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (Proto.find('a') != std::string::npos)
145251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      continue;
145351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
145451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::string Types = R->getValueAsString("Types");
145551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    SmallVector<StringRef, 16> TypeVec;
145651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    ParseTypes(R, Types, TypeVec);
145751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
145851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (R->getSuperClasses().size() < 2)
145951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      throw TGError(R->getLoc(), "Builtin has no class kind");
146051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
146151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::string name = R->getValueAsString("Name");
146251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    ClassKind ck = ClassMap[R->getSuperClasses()[1]];
146351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
146451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) {
146551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      // Generate the BuiltinsARM.def declaration for this builtin, ensuring
146651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      // that each unique BUILTIN() macro appears only once in the output
146751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      // stream.
146851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      std::string bd = GenBuiltinDef(name, Proto, TypeVec[ti], ck);
146951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (EmittedMap.count(bd))
147051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        continue;
147151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
147251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      EmittedMap[bd] = OpNone;
147351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      OS << bd << "\n";
147451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
147551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
147651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#endif\n\n";
147751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
147851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Generate the overloaded type checking code for SemaChecking.cpp
147951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#ifdef GET_NEON_OVERLOAD_CHECK\n";
148051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 0, e = RV.size(); i != e; ++i) {
148151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    Record *R = RV[i];
148251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    OpKind k = OpMap[R->getValueAsDef("Operand")->getName()];
148351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (k != OpNone)
148451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      continue;
148551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
148651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::string Proto = R->getValueAsString("Prototype");
148751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::string Types = R->getValueAsString("Types");
148851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::string name = R->getValueAsString("Name");
148951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
149051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // Functions with 'a' (the splat code) in the type prototype should not get
149151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // their own builtin as they use the non-splat variant.
149251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (Proto.find('a') != std::string::npos)
149351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      continue;
149451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
149551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // Functions which have a scalar argument cannot be overloaded, no need to
149651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // check them if we are emitting the type checking code.
149751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (Proto.find('s') != std::string::npos)
149851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      continue;
149951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
150051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    SmallVector<StringRef, 16> TypeVec;
150151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    ParseTypes(R, Types, TypeVec);
150251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
150351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (R->getSuperClasses().size() < 2)
150451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      throw TGError(R->getLoc(), "Builtin has no class kind");
150551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
150651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    int si = -1, qi = -1;
1507f8ee6bc1ef0eec8e22b413dfc2baa3cfa4f19f91Richard Smith    uint64_t mask = 0, qmask = 0;
150851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) {
150951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      // Generate the switch case(s) for this builtin for the type validation.
151051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      bool quad = false, poly = false, usgn = false;
151151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      (void) ClassifyType(TypeVec[ti], quad, poly, usgn);
151251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
151351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (quad) {
151451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        qi = ti;
1515f8ee6bc1ef0eec8e22b413dfc2baa3cfa4f19f91Richard Smith        qmask |= 1ULL << GetNeonEnum(Proto, TypeVec[ti]);
151651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      } else {
151751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        si = ti;
1518f8ee6bc1ef0eec8e22b413dfc2baa3cfa4f19f91Richard Smith        mask |= 1ULL << GetNeonEnum(Proto, TypeVec[ti]);
151951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      }
152051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
15214648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson
15224648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson    // Check if the builtin function has a pointer or const pointer argument.
15234648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson    int PtrArgNum = -1;
15244648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson    bool HasConstPtr = false;
15254648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson    for (unsigned arg = 1, arge = Proto.size(); arg != arge; ++arg) {
15264648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson      char ArgType = Proto[arg];
15274648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson      if (ArgType == 'c') {
15284648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson        HasConstPtr = true;
15294648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson        PtrArgNum = arg - 1;
15304648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson        break;
15314648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson      }
15324648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson      if (ArgType == 'p') {
15334648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson        PtrArgNum = arg - 1;
15344648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson        break;
15354648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson      }
15364648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson    }
15374648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson    // For sret builtins, adjust the pointer argument index.
15384648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson    if (PtrArgNum >= 0 && (Proto[0] >= '2' && Proto[0] <= '4'))
15394648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson      PtrArgNum += 1;
15404648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson
15419082cddf28e03c2f718e92457e2d9c7390056b2dBob Wilson    // Omit type checking for the pointer arguments of vld1_lane, vld1_dup,
15429082cddf28e03c2f718e92457e2d9c7390056b2dBob Wilson    // and vst1_lane intrinsics.  Using a pointer to the vector element
15439082cddf28e03c2f718e92457e2d9c7390056b2dBob Wilson    // type with one of those operations causes codegen to select an aligned
15449082cddf28e03c2f718e92457e2d9c7390056b2dBob Wilson    // load/store instruction.  If you want an unaligned operation,
15459082cddf28e03c2f718e92457e2d9c7390056b2dBob Wilson    // the pointer argument needs to have less alignment than element type,
15469082cddf28e03c2f718e92457e2d9c7390056b2dBob Wilson    // so just accept any pointer type.
15479082cddf28e03c2f718e92457e2d9c7390056b2dBob Wilson    if (name == "vld1_lane" || name == "vld1_dup" || name == "vst1_lane") {
15489082cddf28e03c2f718e92457e2d9c7390056b2dBob Wilson      PtrArgNum = -1;
15499082cddf28e03c2f718e92457e2d9c7390056b2dBob Wilson      HasConstPtr = false;
15509082cddf28e03c2f718e92457e2d9c7390056b2dBob Wilson    }
15519082cddf28e03c2f718e92457e2d9c7390056b2dBob Wilson
15526f9f03ef370ad48ece0c5d10edda28f39ccadb5dBob Wilson    if (mask) {
155351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      OS << "case ARM::BI__builtin_neon_"
155451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne         << MangleName(name, TypeVec[si], ClassB)
1555b27660a733d420967371bbf578a75db21116895cRichard Smith         << ": mask = " << "0x" << utohexstr(mask) << "ULL";
15564648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson      if (PtrArgNum >= 0)
15574648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson        OS << "; PtrArgNum = " << PtrArgNum;
15586f9f03ef370ad48ece0c5d10edda28f39ccadb5dBob Wilson      if (HasConstPtr)
15596f9f03ef370ad48ece0c5d10edda28f39ccadb5dBob Wilson        OS << "; HasConstPtr = true";
15606f9f03ef370ad48ece0c5d10edda28f39ccadb5dBob Wilson      OS << "; break;\n";
15616f9f03ef370ad48ece0c5d10edda28f39ccadb5dBob Wilson    }
15626f9f03ef370ad48ece0c5d10edda28f39ccadb5dBob Wilson    if (qmask) {
156351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      OS << "case ARM::BI__builtin_neon_"
156451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne         << MangleName(name, TypeVec[qi], ClassB)
1565b27660a733d420967371bbf578a75db21116895cRichard Smith         << ": mask = " << "0x" << utohexstr(qmask) << "ULL";
15664648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson      if (PtrArgNum >= 0)
15674648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson        OS << "; PtrArgNum = " << PtrArgNum;
15686f9f03ef370ad48ece0c5d10edda28f39ccadb5dBob Wilson      if (HasConstPtr)
15696f9f03ef370ad48ece0c5d10edda28f39ccadb5dBob Wilson        OS << "; HasConstPtr = true";
15706f9f03ef370ad48ece0c5d10edda28f39ccadb5dBob Wilson      OS << "; break;\n";
15716f9f03ef370ad48ece0c5d10edda28f39ccadb5dBob Wilson    }
157251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
157351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#endif\n\n";
157451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
157551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Generate the intrinsic range checking code for shift/lane immediates.
157651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#ifdef GET_NEON_IMMEDIATE_CHECK\n";
157751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 0, e = RV.size(); i != e; ++i) {
157851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    Record *R = RV[i];
157951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
158051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    OpKind k = OpMap[R->getValueAsDef("Operand")->getName()];
158151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (k != OpNone)
158251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      continue;
158351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
158451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::string name = R->getValueAsString("Name");
158551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::string Proto = R->getValueAsString("Prototype");
158651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::string Types = R->getValueAsString("Types");
158751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
158851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // Functions with 'a' (the splat code) in the type prototype should not get
158951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // their own builtin as they use the non-splat variant.
159051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (Proto.find('a') != std::string::npos)
159151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      continue;
159251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
159351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // Functions which do not have an immediate do not need to have range
159451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // checking code emitted.
159551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    size_t immPos = Proto.find('i');
159651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (immPos == std::string::npos)
159751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      continue;
159851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
159951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    SmallVector<StringRef, 16> TypeVec;
160051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    ParseTypes(R, Types, TypeVec);
160151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
160251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (R->getSuperClasses().size() < 2)
160351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      throw TGError(R->getLoc(), "Builtin has no class kind");
160451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
160551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    ClassKind ck = ClassMap[R->getSuperClasses()[1]];
160651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
160751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) {
160851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      std::string namestr, shiftstr, rangestr;
160951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
161051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (R->getValueAsBit("isVCVT_N")) {
161151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        // VCVT between floating- and fixed-point values takes an immediate
161251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        // in the range 1 to 32.
161351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        ck = ClassB;
161451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        rangestr = "l = 1; u = 31"; // upper bound = l + u
161551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      } else if (Proto.find('s') == std::string::npos) {
161651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        // Builtins which are overloaded by type will need to have their upper
161751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        // bound computed at Sema time based on the type constant.
161851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        ck = ClassB;
161951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        if (R->getValueAsBit("isShift")) {
162051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne          shiftstr = ", true";
162151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
162251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne          // Right shifts have an 'r' in the name, left shifts do not.
162351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne          if (name.find('r') != std::string::npos)
162451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne            rangestr = "l = 1; ";
162551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        }
162651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        rangestr += "u = RFT(TV" + shiftstr + ")";
162751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      } else {
162851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        // The immediate generally refers to a lane in the preceding argument.
162951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        assert(immPos > 0 && "unexpected immediate operand");
163051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        rangestr = "u = " + utostr(RangeFromType(Proto[immPos-1], TypeVec[ti]));
163151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      }
163251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      // Make sure cases appear only once by uniquing them in a string map.
163351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      namestr = MangleName(name, TypeVec[ti], ck);
163451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (EmittedMap.count(namestr))
163551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        continue;
163651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      EmittedMap[namestr] = OpNone;
163751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
163851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      // Calculate the index of the immediate that should be range checked.
163951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      unsigned immidx = 0;
164051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
164151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      // Builtins that return a struct of multiple vectors have an extra
164251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      // leading arg for the struct return.
164351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (Proto[0] >= '2' && Proto[0] <= '4')
164451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        ++immidx;
164551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
164651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      // Add one to the index for each argument until we reach the immediate
164751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      // to be checked.  Structs of vectors are passed as multiple arguments.
164851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      for (unsigned ii = 1, ie = Proto.size(); ii != ie; ++ii) {
164951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        switch (Proto[ii]) {
165051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne          default:  immidx += 1; break;
165151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne          case '2': immidx += 2; break;
165251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne          case '3': immidx += 3; break;
165351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne          case '4': immidx += 4; break;
165451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne          case 'i': ie = ii + 1; break;
165551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        }
165651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      }
165751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      OS << "case ARM::BI__builtin_neon_" << MangleName(name, TypeVec[ti], ck)
165851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne         << ": i = " << immidx << "; " << rangestr << "; break;\n";
165951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
166051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
166151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#endif\n\n";
166251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
166351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
166451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// GenTest - Write out a test for the intrinsic specified by the name and
166551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// type strings, including the embedded patterns for FileCheck to match.
166651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic std::string GenTest(const std::string &name,
166751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                           const std::string &proto,
166851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                           StringRef outTypeStr, StringRef inTypeStr,
166951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                           bool isShift) {
167051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  assert(!proto.empty() && "");
167151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string s;
167251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
167351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Function name with type suffix
167451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string mangledName = MangleName(name, outTypeStr, ClassS);
167551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (outTypeStr != inTypeStr) {
167651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // If the input type is different (e.g., for vreinterpret), append a suffix
167751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // for the input type.  String off a "Q" (quad) prefix so that MangleName
167851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // does not insert another "q" in the name.
167951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    unsigned typeStrOff = (inTypeStr[0] == 'Q' ? 1 : 0);
168051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    StringRef inTypeNoQuad = inTypeStr.substr(typeStrOff);
168151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    mangledName = MangleName(mangledName, inTypeNoQuad, ClassS);
168251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
168351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
168451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Emit the FileCheck patterns.
168551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += "// CHECK: test_" + mangledName + "\n";
168651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // s += "// CHECK: \n"; // FIXME: + expected instruction opcode.
168751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
168851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Emit the start of the test function.
168951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += TypeString(proto[0], outTypeStr) + " test_" + mangledName + "(";
169051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  char arg = 'a';
169151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string comma;
169251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) {
169351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // Do not create arguments for values that must be immediate constants.
169451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (proto[i] == 'i')
169551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      continue;
169651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += comma + TypeString(proto[i], inTypeStr) + " ";
169751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s.push_back(arg);
169851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    comma = ", ";
169951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
1700b4a542549c2e0c9eeb6ece3f95767ccdd141fa3eJim Grosbach  s += ") {\n  ";
170151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
170251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (proto[0] != 'v')
170351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "return ";
170451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += mangledName + "(";
170551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  arg = 'a';
170651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) {
170751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (proto[i] == 'i') {
170851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      // For immediate operands, test the maximum value.
170951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (isShift)
171051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        s += "1"; // FIXME
171151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      else
171251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        // The immediate generally refers to a lane in the preceding argument.
171351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        s += utostr(RangeFromType(proto[i-1], inTypeStr));
171451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    } else {
171551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s.push_back(arg);
171651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
171751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if ((i + 1) < e)
171851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += ", ";
171951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
172051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += ");\n}\n\n";
172151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return s;
172251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
172351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
172451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// runTests - Write out a complete set of tests for all of the Neon
172551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// intrinsics.
172651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournevoid NeonEmitter::runTests(raw_ostream &OS) {
172751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS <<
172851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    "// RUN: %clang_cc1 -triple thumbv7-apple-darwin \\\n"
172951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    "// RUN:  -target-cpu cortex-a9 -ffreestanding -S -o - %s | FileCheck %s\n"
173051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    "\n"
173151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    "#include <arm_neon.h>\n"
173251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    "\n";
173351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
173451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::vector<Record*> RV = Records.getAllDerivedDefinitions("Inst");
173551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 0, e = RV.size(); i != e; ++i) {
173651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    Record *R = RV[i];
173751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::string name = R->getValueAsString("Name");
173851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::string Proto = R->getValueAsString("Prototype");
173951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::string Types = R->getValueAsString("Types");
174051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    bool isShift = R->getValueAsBit("isShift");
174151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
174251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    SmallVector<StringRef, 16> TypeVec;
174351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    ParseTypes(R, Types, TypeVec);
174451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
174551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    OpKind kind = OpMap[R->getValueAsDef("Operand")->getName()];
1746667381b21f75d6964bbdf6af143308a02b9198a8Jim Grosbach    if (kind == OpUnavailable)
1747667381b21f75d6964bbdf6af143308a02b9198a8Jim Grosbach      continue;
174851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) {
174951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (kind == OpReinterpret) {
175051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        bool outQuad = false;
175151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        bool dummy = false;
175251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        (void)ClassifyType(TypeVec[ti], outQuad, dummy, dummy);
175351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        for (unsigned srcti = 0, srcte = TypeVec.size();
175451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne             srcti != srcte; ++srcti) {
175551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne          bool inQuad = false;
175651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne          (void)ClassifyType(TypeVec[srcti], inQuad, dummy, dummy);
175751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne          if (srcti == ti || inQuad != outQuad)
175851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne            continue;
175951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne          OS << GenTest(name, Proto, TypeVec[ti], TypeVec[srcti], isShift);
176051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        }
176151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      } else {
176251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        OS << GenTest(name, Proto, TypeVec[ti], TypeVec[ti], isShift);
176351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      }
176451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
176551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    OS << "\n";
176651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
176751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
176851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
17693cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesennamespace clang {
17703cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesenvoid EmitNeon(RecordKeeper &Records, raw_ostream &OS) {
17713cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  NeonEmitter(Records).run(OS);
17723cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen}
17733cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesenvoid EmitNeonSema(RecordKeeper &Records, raw_ostream &OS) {
17743cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  NeonEmitter(Records).runHeader(OS);
17753cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen}
17763cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesenvoid EmitNeonTest(RecordKeeper &Records, raw_ostream &OS) {
17773cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  NeonEmitter(Records).runTests(OS);
17783cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen}
17793cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen} // End namespace clang
1780