NeonEmitter.cpp revision fb9929ee2a0ed47d473a58b0ba5c7a7a7a095b73
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
10121e4e940ed3ad172f344a3aa3faf1d8437441313Michael Gottesman  ClassB,           // bitcast arguments with enum argument to specify type
10221e4e940ed3ad172f344a3aa3faf1d8437441313Michael Gottesman  ClassL,           // Logical instructions which are op instructions
10321e4e940ed3ad172f344a3aa3faf1d8437441313Michael Gottesman                    // but we need to not emit any suffix for in our
10421e4e940ed3ad172f344a3aa3faf1d8437441313Michael Gottesman                    // tests.
10521e4e940ed3ad172f344a3aa3faf1d8437441313Michael Gottesman  ClassNoTest       // Instructions which we do not test since they are
10621e4e940ed3ad172f344a3aa3faf1d8437441313Michael Gottesman                    // not TRUE instructions.
1073cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen};
1083cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen
1093cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen/// NeonTypeFlags - Flags to identify the types for overloaded Neon
1103cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen/// builtins.  These must be kept in sync with the flags in
1113cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen/// include/clang/Basic/TargetBuiltins.h.
1123cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesennamespace {
1133cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesenclass NeonTypeFlags {
1143cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  enum {
1153cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    EltTypeMask = 0xf,
1163cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    UnsignedFlag = 0x10,
1173cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    QuadFlag = 0x20
1183cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  };
1193cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  uint32_t Flags;
1203cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen
1213cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesenpublic:
1223cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  enum EltType {
1233cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    Int8,
1243cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    Int16,
1253cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    Int32,
1263cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    Int64,
1273cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    Poly8,
1283cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    Poly16,
1293cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    Float16,
1303cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    Float32
1313cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  };
1323cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen
1333cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  NeonTypeFlags(unsigned F) : Flags(F) {}
1343cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  NeonTypeFlags(EltType ET, bool IsUnsigned, bool IsQuad) : Flags(ET) {
1353cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    if (IsUnsigned)
1363cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen      Flags |= UnsignedFlag;
1373cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    if (IsQuad)
1383cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen      Flags |= QuadFlag;
1393cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  }
1403cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen
1413cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  uint32_t getFlags() const { return Flags; }
1423cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen};
1433cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen} // end anonymous namespace
1443cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen
1453cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesennamespace {
1463cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesenclass NeonEmitter {
1473cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  RecordKeeper &Records;
1483cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  StringMap<OpKind> OpMap;
1493cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  DenseMap<Record*, ClassKind> ClassMap;
1503cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen
1513cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesenpublic:
1523cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  NeonEmitter(RecordKeeper &R) : Records(R) {
1533cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_NONE"]  = OpNone;
1543cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_UNAVAILABLE"] = OpUnavailable;
1553cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_ADD"]   = OpAdd;
1563cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_ADDL"]  = OpAddl;
1573cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_ADDW"]  = OpAddw;
1583cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_SUB"]   = OpSub;
1593cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_SUBL"]  = OpSubl;
1603cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_SUBW"]  = OpSubw;
1613cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_MUL"]   = OpMul;
1623cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_MLA"]   = OpMla;
1633cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_MLAL"]  = OpMlal;
1643cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_MLS"]   = OpMls;
1653cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_MLSL"]  = OpMlsl;
1663cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_MUL_N"] = OpMulN;
1673cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_MLA_N"] = OpMlaN;
1683cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_MLS_N"] = OpMlsN;
1693cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_MLAL_N"] = OpMlalN;
1703cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_MLSL_N"] = OpMlslN;
1713cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_MUL_LN"]= OpMulLane;
1723cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_MULL_LN"] = OpMullLane;
1733cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_MLA_LN"]= OpMlaLane;
1743cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_MLS_LN"]= OpMlsLane;
1753cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_MLAL_LN"] = OpMlalLane;
1763cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_MLSL_LN"] = OpMlslLane;
1773cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_QDMULL_LN"] = OpQDMullLane;
1783cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_QDMLAL_LN"] = OpQDMlalLane;
1793cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_QDMLSL_LN"] = OpQDMlslLane;
1803cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_QDMULH_LN"] = OpQDMulhLane;
1813cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_QRDMULH_LN"] = OpQRDMulhLane;
1823cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_EQ"]    = OpEq;
1833cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_GE"]    = OpGe;
1843cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_LE"]    = OpLe;
1853cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_GT"]    = OpGt;
1863cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_LT"]    = OpLt;
1873cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_NEG"]   = OpNeg;
1883cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_NOT"]   = OpNot;
1893cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_AND"]   = OpAnd;
1903cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_OR"]    = OpOr;
1913cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_XOR"]   = OpXor;
1923cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_ANDN"]  = OpAndNot;
1933cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_ORN"]   = OpOrNot;
1943cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_CAST"]  = OpCast;
1953cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_CONC"]  = OpConcat;
1963cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_HI"]    = OpHi;
1973cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_LO"]    = OpLo;
1983cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_DUP"]   = OpDup;
1993cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_DUP_LN"] = OpDupLane;
2003cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_SEL"]   = OpSelect;
2013cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_REV16"] = OpRev16;
2023cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_REV32"] = OpRev32;
2033cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_REV64"] = OpRev64;
2043cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_REINT"] = OpReinterpret;
2053cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_ABDL"]  = OpAbdl;
2063cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_ABA"]   = OpAba;
2073cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    OpMap["OP_ABAL"]  = OpAbal;
2083cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen
2093cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    Record *SI = R.getClass("SInst");
2103cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    Record *II = R.getClass("IInst");
2113cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    Record *WI = R.getClass("WInst");
21221e4e940ed3ad172f344a3aa3faf1d8437441313Michael Gottesman    Record *SOpI = R.getClass("SOpInst");
21321e4e940ed3ad172f344a3aa3faf1d8437441313Michael Gottesman    Record *IOpI = R.getClass("IOpInst");
21421e4e940ed3ad172f344a3aa3faf1d8437441313Michael Gottesman    Record *WOpI = R.getClass("WOpInst");
21521e4e940ed3ad172f344a3aa3faf1d8437441313Michael Gottesman    Record *LOpI = R.getClass("LOpInst");
21621e4e940ed3ad172f344a3aa3faf1d8437441313Michael Gottesman    Record *NoTestOpI = R.getClass("NoTestOpInst");
21721e4e940ed3ad172f344a3aa3faf1d8437441313Michael Gottesman
2183cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    ClassMap[SI] = ClassS;
2193cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    ClassMap[II] = ClassI;
2203cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    ClassMap[WI] = ClassW;
22121e4e940ed3ad172f344a3aa3faf1d8437441313Michael Gottesman    ClassMap[SOpI] = ClassS;
22221e4e940ed3ad172f344a3aa3faf1d8437441313Michael Gottesman    ClassMap[IOpI] = ClassI;
22321e4e940ed3ad172f344a3aa3faf1d8437441313Michael Gottesman    ClassMap[WOpI] = ClassW;
22421e4e940ed3ad172f344a3aa3faf1d8437441313Michael Gottesman    ClassMap[LOpI] = ClassL;
22521e4e940ed3ad172f344a3aa3faf1d8437441313Michael Gottesman    ClassMap[NoTestOpI] = ClassNoTest;
2263cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  }
2273cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen
2283cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  // run - Emit arm_neon.h.inc
2293cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  void run(raw_ostream &o);
2303cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen
2313cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  // runHeader - Emit all the __builtin prototypes used in arm_neon.h
2323cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  void runHeader(raw_ostream &o);
2333cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen
2343cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  // runTests - Emit tests for all the Neon intrinsics.
2353cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  void runTests(raw_ostream &o);
2363cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen
2373cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesenprivate:
2383cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  void emitIntrinsic(raw_ostream &OS, Record *R);
2393cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen};
2403cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen} // end anonymous namespace
2413cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen
24251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// ParseTypes - break down a string such as "fQf" into a vector of StringRefs,
24351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// which each StringRef representing a single type declared in the string.
24451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// for "fQf" we would end up with 2 StringRefs, "f", and "Qf", representing
24551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// 2xfloat and 4xfloat respectively.
24651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic void ParseTypes(Record *r, std::string &s,
24751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                       SmallVectorImpl<StringRef> &TV) {
24851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  const char *data = s.data();
24951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  int len = 0;
25051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
25151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 0, e = s.size(); i != e; ++i, ++len) {
25251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (data[len] == 'P' || data[len] == 'Q' || data[len] == 'U')
25351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      continue;
25451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
25551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    switch (data[len]) {
25651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      case 'c':
25751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      case 's':
25851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      case 'i':
25951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      case 'l':
26051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      case 'h':
26151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      case 'f':
26251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        break;
26351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      default:
26438859ee4a3c1253d5a45ed3f6b52e77702bfd913Joerg Sonnenberger        PrintFatalError(r->getLoc(),
26551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                      "Unexpected letter: " + std::string(data + len, 1));
26651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
26751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    TV.push_back(StringRef(data, len + 1));
26851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    data += len + 1;
26951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    len = -1;
27051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
27151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
27251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
27351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// Widen - Convert a type code into the next wider type.  char -> short,
27451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// short -> int, etc.
27551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic char Widen(const char t) {
27651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  switch (t) {
27751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'c':
27851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      return 's';
27951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 's':
28051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      return 'i';
28151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'i':
28251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      return 'l';
28351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'h':
28451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      return 'f';
28538859ee4a3c1253d5a45ed3f6b52e77702bfd913Joerg Sonnenberger    default:
28638859ee4a3c1253d5a45ed3f6b52e77702bfd913Joerg Sonnenberger      PrintFatalError("unhandled type in widen!");
28751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
28851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
28951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
29051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// Narrow - Convert a type code into the next smaller type.  short -> char,
29151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// float -> half float, etc.
29251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic char Narrow(const char t) {
29351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  switch (t) {
29451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 's':
29551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      return 'c';
29651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'i':
29751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      return 's';
29851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'l':
29951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      return 'i';
30051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'f':
30151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      return 'h';
30238859ee4a3c1253d5a45ed3f6b52e77702bfd913Joerg Sonnenberger    default:
30338859ee4a3c1253d5a45ed3f6b52e77702bfd913Joerg Sonnenberger      PrintFatalError("unhandled type in narrow!");
30451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
30551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
30651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
30751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// For a particular StringRef, return the base type code, and whether it has
30851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// the quad-vector, polynomial, or unsigned modifiers set.
30951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic char ClassifyType(StringRef ty, bool &quad, bool &poly, bool &usgn) {
31051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  unsigned off = 0;
31151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
31251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // remember quad.
31351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (ty[off] == 'Q') {
31451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    quad = true;
31551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    ++off;
31651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
31751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
31851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // remember poly.
31951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (ty[off] == 'P') {
32051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    poly = true;
32151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    ++off;
32251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
32351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
32451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // remember unsigned.
32551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (ty[off] == 'U') {
32651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    usgn = true;
32751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    ++off;
32851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
32951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
33051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // base type to get the type string for.
33151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return ty[off];
33251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
33351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
33451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// ModType - Transform a type code and its modifiers based on a mod code. The
33551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// mod code definitions may be found at the top of arm_neon.td.
33651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic char ModType(const char mod, char type, bool &quad, bool &poly,
33751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                    bool &usgn, bool &scal, bool &cnst, bool &pntr) {
33851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  switch (mod) {
33951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 't':
34051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (poly) {
34151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        poly = false;
34251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        usgn = true;
34351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      }
34451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
34551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'u':
34651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      usgn = true;
34751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      poly = false;
34851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (type == 'f')
34951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        type = 'i';
35051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
35151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'x':
35251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      usgn = false;
35351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      poly = false;
35451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (type == 'f')
35551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        type = 'i';
35651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
35751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'f':
35851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (type == 'h')
35951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        quad = true;
36051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      type = 'f';
36151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      usgn = false;
36251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
36351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'g':
36451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      quad = false;
36551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
36651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'w':
36751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      type = Widen(type);
36851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      quad = true;
36951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
37051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'n':
37151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      type = Widen(type);
37251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
37351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'i':
37451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      type = 'i';
37551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      scal = true;
37651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
37751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'l':
37851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      type = 'l';
37951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      scal = true;
38051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      usgn = true;
38151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
38251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 's':
38351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'a':
38451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      scal = true;
38551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
38651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'k':
38751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      quad = true;
38851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
38951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'c':
39051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      cnst = true;
39151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'p':
39251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      pntr = true;
39351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      scal = true;
39451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
39551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'h':
39651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      type = Narrow(type);
39751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (type == 'h')
39851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        quad = false;
39951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
40051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'e':
40151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      type = Narrow(type);
40251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      usgn = true;
40351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
40451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    default:
40551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
40651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
40751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return type;
40851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
40951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
41051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// TypeString - for a modifier and type, generate the name of the typedef for
41151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// that type.  QUc -> uint8x8_t.
41251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic std::string TypeString(const char mod, StringRef typestr) {
41351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool quad = false;
41451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool poly = false;
41551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool usgn = false;
41651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool scal = false;
41751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool cnst = false;
41851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool pntr = false;
41951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
42051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (mod == 'v')
42151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    return "void";
42251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (mod == 'i')
42351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    return "int";
42451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
42551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // base type to get the type string for.
42651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  char type = ClassifyType(typestr, quad, poly, usgn);
42751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
42851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Based on the modifying character, change the type and width if necessary.
42951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  type = ModType(mod, type, quad, poly, usgn, scal, cnst, pntr);
43051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
43151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  SmallString<128> s;
43251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
43351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (usgn)
43451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s.push_back('u');
43551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
43651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  switch (type) {
43751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'c':
43851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += poly ? "poly8" : "int8";
43951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (scal)
44051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        break;
44151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += quad ? "x16" : "x8";
44251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
44351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 's':
44451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += poly ? "poly16" : "int16";
44551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (scal)
44651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        break;
44751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += quad ? "x8" : "x4";
44851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
44951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'i':
45051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += "int32";
45151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (scal)
45251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        break;
45351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += quad ? "x4" : "x2";
45451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
45551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'l':
45651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += "int64";
45751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (scal)
45851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        break;
45951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += quad ? "x2" : "x1";
46051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
46151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'h':
46251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += "float16";
46351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (scal)
46451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        break;
46551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += quad ? "x8" : "x4";
46651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
46751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'f':
46851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += "float32";
46951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (scal)
47051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        break;
47151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += quad ? "x4" : "x2";
47251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
47351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    default:
47438859ee4a3c1253d5a45ed3f6b52e77702bfd913Joerg Sonnenberger      PrintFatalError("unhandled type!");
47551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
47651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
47751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (mod == '2')
47851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "x2";
47951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (mod == '3')
48051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "x3";
48151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (mod == '4')
48251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "x4";
48351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
48451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Append _t, finishing the type string typedef type.
48551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += "_t";
48651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
48751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (cnst)
48851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += " const";
48951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
49051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (pntr)
49151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += " *";
49251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
49351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return s.str();
49451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
49551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
49651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// BuiltinTypeString - for a modifier and type, generate the clang
49751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// BuiltinsARM.def prototype code for the function.  See the top of clang's
49851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// Builtins.def for a description of the type strings.
49951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic std::string BuiltinTypeString(const char mod, StringRef typestr,
50051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                                     ClassKind ck, bool ret) {
50151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool quad = false;
50251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool poly = false;
50351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool usgn = false;
50451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool scal = false;
50551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool cnst = false;
50651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool pntr = false;
50751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
50851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (mod == 'v')
50951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    return "v"; // void
51051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (mod == 'i')
51151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    return "i"; // int
51251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
51351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // base type to get the type string for.
51451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  char type = ClassifyType(typestr, quad, poly, usgn);
51551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
51651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Based on the modifying character, change the type and width if necessary.
51751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  type = ModType(mod, type, quad, poly, usgn, scal, cnst, pntr);
51851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
51951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // All pointers are void* pointers.  Change type to 'v' now.
52051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (pntr) {
52151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    usgn = false;
52251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    poly = false;
52351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    type = 'v';
52451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
52551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Treat half-float ('h') types as unsigned short ('s') types.
52651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (type == 'h') {
52751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    type = 's';
52851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    usgn = true;
52951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
53051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  usgn = usgn | poly | ((ck == ClassI || ck == ClassW) && scal && type != 'f');
53151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
53251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (scal) {
53351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    SmallString<128> s;
53451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
53551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (usgn)
53651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s.push_back('U');
53751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    else if (type == 'c')
53851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s.push_back('S'); // make chars explicitly signed
53951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
54051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (type == 'l') // 64-bit long
54151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += "LLi";
54251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    else
54351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s.push_back(type);
54451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
54551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (cnst)
54651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s.push_back('C');
54751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (pntr)
54851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s.push_back('*');
54951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    return s.str();
55051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
55151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
55251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Since the return value must be one type, return a vector type of the
55351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // appropriate width which we will bitcast.  An exception is made for
55451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // returning structs of 2, 3, or 4 vectors which are returned in a sret-like
55551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // fashion, storing them to a pointer arg.
55651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (ret) {
55751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (mod >= '2' && mod <= '4')
55851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      return "vv*"; // void result with void* first argument
55951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (mod == 'f' || (ck != ClassB && type == 'f'))
56051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      return quad ? "V4f" : "V2f";
56151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (ck != ClassB && type == 's')
56251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      return quad ? "V8s" : "V4s";
56351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (ck != ClassB && type == 'i')
56451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      return quad ? "V4i" : "V2i";
56551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (ck != ClassB && type == 'l')
56651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      return quad ? "V2LLi" : "V1LLi";
56751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
56851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    return quad ? "V16Sc" : "V8Sc";
56951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
57051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
57151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Non-return array types are passed as individual vectors.
57251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (mod == '2')
57351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    return quad ? "V16ScV16Sc" : "V8ScV8Sc";
57451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (mod == '3')
57551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    return quad ? "V16ScV16ScV16Sc" : "V8ScV8ScV8Sc";
57651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (mod == '4')
57751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    return quad ? "V16ScV16ScV16ScV16Sc" : "V8ScV8ScV8ScV8Sc";
57851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
57951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (mod == 'f' || (ck != ClassB && type == 'f'))
58051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    return quad ? "V4f" : "V2f";
58151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (ck != ClassB && type == 's')
58251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    return quad ? "V8s" : "V4s";
58351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (ck != ClassB && type == 'i')
58451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    return quad ? "V4i" : "V2i";
58551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (ck != ClassB && type == 'l')
58651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    return quad ? "V2LLi" : "V1LLi";
58751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
58851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return quad ? "V16Sc" : "V8Sc";
58951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
59051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
591fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman/// InstructionTypeCode - Computes the ARM argument character code and
592fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman/// quad status for a specific type string and ClassKind.
593fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesmanstatic void InstructionTypeCode(const StringRef &typeStr,
594fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman                                const ClassKind ck,
595fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman                                bool &quad,
596fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman                                std::string &typeCode) {
59751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool poly = false;
59851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool usgn = false;
599fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman  char type = ClassifyType(typeStr, quad, poly, usgn);
60051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
60151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  switch (type) {
60251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case 'c':
60351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    switch (ck) {
604fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman    case ClassS: typeCode = poly ? "p8" : usgn ? "u8" : "s8"; break;
605fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman    case ClassI: typeCode = "i8"; break;
606fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman    case ClassW: typeCode = "8"; break;
60751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    default: break;
60851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
60951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
61051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case 's':
61151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    switch (ck) {
612fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman    case ClassS: typeCode = poly ? "p16" : usgn ? "u16" : "s16"; break;
613fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman    case ClassI: typeCode = "i16"; break;
614fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman    case ClassW: typeCode = "16"; break;
61551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    default: break;
61651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
61751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
61851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case 'i':
61951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    switch (ck) {
620fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman    case ClassS: typeCode = usgn ? "u32" : "s32"; break;
621fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman    case ClassI: typeCode = "i32"; break;
622fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman    case ClassW: typeCode = "32"; break;
62351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    default: break;
62451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
62551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
62651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case 'l':
62751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    switch (ck) {
628fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman    case ClassS: typeCode = usgn ? "u64" : "s64"; break;
629fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman    case ClassI: typeCode = "i64"; break;
630fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman    case ClassW: typeCode = "64"; break;
63151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    default: break;
63251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
63351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
63451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case 'h':
63551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    switch (ck) {
63651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case ClassS:
637fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman    case ClassI: typeCode = "f16"; break;
638fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman    case ClassW: typeCode = "16"; break;
63951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    default: break;
64051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
64151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
64251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case 'f':
64351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    switch (ck) {
64451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case ClassS:
645fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman    case ClassI: typeCode = "f32"; break;
646fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman    case ClassW: typeCode = "32"; break;
64751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    default: break;
64851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
64951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
65051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  default:
65138859ee4a3c1253d5a45ed3f6b52e77702bfd913Joerg Sonnenberger    PrintFatalError("unhandled type!");
65251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
653fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman}
654fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman
655fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman/// MangleName - Append a type or width suffix to a base neon function name,
656fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman/// and insert a 'q' in the appropriate location if the operation works on
657fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman/// 128b rather than 64b.   E.g. turn "vst2_lane" into "vst2q_lane_f32", etc.
658fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesmanstatic std::string MangleName(const std::string &name, StringRef typestr,
659fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman                              ClassKind ck) {
660fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman  if (name == "vcvt_f32_f16")
661fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman    return name;
662fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman
663fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman  bool quad = false;
664fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman  std::string typeCode = "";
665fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman
666fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman  InstructionTypeCode(typestr, ck, quad, typeCode);
667fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman
668fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman  std::string s = name;
669fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman
670fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman  if (typeCode.size() > 0) {
671fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman    s += "_" + typeCode;
672fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman  }
673fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman
67451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (ck == ClassB)
67551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "_v";
67651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
67751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Insert a 'q' before the first '_' character so that it ends up before
67851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // _lane or _n on vector-scalar operations.
67951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (quad) {
68051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    size_t pos = s.find('_');
68151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s = s.insert(pos, "q");
68251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
68351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return s;
68451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
68551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
68651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// UseMacro - Examine the prototype string to determine if the intrinsic
68751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// should be defined as a preprocessor macro instead of an inline function.
68851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic bool UseMacro(const std::string &proto) {
68951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // If this builtin takes an immediate argument, we need to #define it rather
69051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // than use a standard declaration, so that SemaChecking can range check
69151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // the immediate passed by the user.
69251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (proto.find('i') != std::string::npos)
69351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    return true;
69451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
69551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Pointer arguments need to use macros to avoid hiding aligned attributes
69651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // from the pointer type.
69751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (proto.find('p') != std::string::npos ||
69851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      proto.find('c') != std::string::npos)
69951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    return true;
70051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
70151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return false;
70251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
70351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
70451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// MacroArgUsedDirectly - Return true if argument i for an intrinsic that is
70551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// defined as a macro should be accessed directly instead of being first
70651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// assigned to a local temporary.
70751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic bool MacroArgUsedDirectly(const std::string &proto, unsigned i) {
70851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // True for constant ints (i), pointers (p) and const pointers (c).
70951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return (proto[i] == 'i' || proto[i] == 'p' || proto[i] == 'c');
71051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
71151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
71251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne// Generate the string "(argtype a, argtype b, ...)"
71351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic std::string GenArgs(const std::string &proto, StringRef typestr) {
71451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool define = UseMacro(proto);
71551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  char arg = 'a';
71651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
71751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string s;
71851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += "(";
71951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
72051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) {
72151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (define) {
72251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      // Some macro arguments are used directly instead of being assigned
72351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      // to local temporaries; prepend an underscore prefix to make their
72451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      // names consistent with the local temporaries.
72551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (MacroArgUsedDirectly(proto, i))
72651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        s += "__";
72751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    } else {
72851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += TypeString(proto[i], typestr) + " __";
72951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
73051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s.push_back(arg);
73151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if ((i + 1) < e)
73251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += ", ";
73351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
73451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
73551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += ")";
73651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return s;
73751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
73851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
73951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne// Macro arguments are not type-checked like inline function arguments, so
74051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne// assign them to local temporaries to get the right type checking.
74151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic std::string GenMacroLocals(const std::string &proto, StringRef typestr) {
74251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  char arg = 'a';
74351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string s;
74451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool generatedLocal = false;
74551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
74651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) {
74751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // Do not create a temporary for an immediate argument.
74851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // That would defeat the whole point of using a macro!
74951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (MacroArgUsedDirectly(proto, i))
75051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      continue;
75151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    generatedLocal = true;
75251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
75351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += TypeString(proto[i], typestr) + " __";
75451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s.push_back(arg);
75551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += " = (";
75651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s.push_back(arg);
75751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "); ";
75851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
75951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
76051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (generatedLocal)
76151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "\\\n  ";
76251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return s;
76351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
76451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
76551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne// Use the vmovl builtin to sign-extend or zero-extend a vector.
76651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic std::string Extend(StringRef typestr, const std::string &a) {
76751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string s;
76851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s = MangleName("vmovl", typestr, ClassS);
76951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += "(" + a + ")";
77051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return s;
77151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
77251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
77351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic std::string Duplicate(unsigned nElts, StringRef typestr,
77451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                             const std::string &a) {
77551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string s;
77651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
77751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s = "(" + TypeString('d', typestr) + "){ ";
77851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 0; i != nElts; ++i) {
77951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += a;
78051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if ((i + 1) < nElts)
78151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += ", ";
78251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
78351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += " }";
78451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
78551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return s;
78651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
78751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
78851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic std::string SplatLane(unsigned nElts, const std::string &vec,
78951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                             const std::string &lane) {
79051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string s = "__builtin_shufflevector(" + vec + ", " + vec;
79151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 0; i < nElts; ++i)
79251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += ", " + lane;
79351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += ")";
79451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return s;
79551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
79651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
79751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic unsigned GetNumElements(StringRef typestr, bool &quad) {
79851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  quad = false;
79951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool dummy = false;
80051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  char type = ClassifyType(typestr, quad, dummy, dummy);
80151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  unsigned nElts = 0;
80251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  switch (type) {
80351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case 'c': nElts = 8; break;
80451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case 's': nElts = 4; break;
80551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case 'i': nElts = 2; break;
80651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case 'l': nElts = 1; break;
80751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case 'h': nElts = 4; break;
80851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case 'f': nElts = 2; break;
80951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  default:
81038859ee4a3c1253d5a45ed3f6b52e77702bfd913Joerg Sonnenberger    PrintFatalError("unhandled type!");
81151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
81251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (quad) nElts <<= 1;
81351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return nElts;
81451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
81551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
81651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne// Generate the definition for this intrinsic, e.g. "a + b" for OpAdd.
81751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic std::string GenOpString(OpKind op, const std::string &proto,
81851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                               StringRef typestr) {
81951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool quad;
82051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  unsigned nElts = GetNumElements(typestr, quad);
82151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool define = UseMacro(proto);
82251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
82351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string ts = TypeString(proto[0], typestr);
82451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string s;
82551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (!define) {
82651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s = "return ";
82751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
82851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
82951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  switch(op) {
83051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpAdd:
83151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a + __b;";
83251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
83351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpAddl:
83451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += Extend(typestr, "__a") + " + " + Extend(typestr, "__b") + ";";
83551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
83651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpAddw:
83751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a + " + Extend(typestr, "__b") + ";";
83851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
83951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpSub:
84051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a - __b;";
84151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
84251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpSubl:
84351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += Extend(typestr, "__a") + " - " + Extend(typestr, "__b") + ";";
84451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
84551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpSubw:
84651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a - " + Extend(typestr, "__b") + ";";
84751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
84851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpMulN:
84951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a * " + Duplicate(nElts, typestr, "__b") + ";";
85051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
85151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpMulLane:
85251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a * " + SplatLane(nElts, "__b", "__c") + ";";
85351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
85451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpMul:
85551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a * __b;";
85651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
85751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpMullLane:
85851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += MangleName("vmull", typestr, ClassS) + "(__a, " +
85951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      SplatLane(nElts, "__b", "__c") + ");";
86051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
86151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpMlaN:
86251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a + (__b * " + Duplicate(nElts, typestr, "__c") + ");";
86351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
86451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpMlaLane:
86551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a + (__b * " + SplatLane(nElts, "__c", "__d") + ");";
86651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
86751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpMla:
86851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a + (__b * __c);";
86951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
87051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpMlalN:
87151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a + " + MangleName("vmull", typestr, ClassS) + "(__b, " +
87251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      Duplicate(nElts, typestr, "__c") + ");";
87351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
87451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpMlalLane:
87551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a + " + MangleName("vmull", typestr, ClassS) + "(__b, " +
87651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      SplatLane(nElts, "__c", "__d") + ");";
87751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
87851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpMlal:
87951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a + " + MangleName("vmull", typestr, ClassS) + "(__b, __c);";
88051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
88151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpMlsN:
88251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a - (__b * " + Duplicate(nElts, typestr, "__c") + ");";
88351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
88451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpMlsLane:
88551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a - (__b * " + SplatLane(nElts, "__c", "__d") + ");";
88651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
88751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpMls:
88851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a - (__b * __c);";
88951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
89051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpMlslN:
89151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a - " + MangleName("vmull", typestr, ClassS) + "(__b, " +
89251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      Duplicate(nElts, typestr, "__c") + ");";
89351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
89451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpMlslLane:
89551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a - " + MangleName("vmull", typestr, ClassS) + "(__b, " +
89651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      SplatLane(nElts, "__c", "__d") + ");";
89751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
89851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpMlsl:
89951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a - " + MangleName("vmull", typestr, ClassS) + "(__b, __c);";
90051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
90151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpQDMullLane:
90251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += MangleName("vqdmull", typestr, ClassS) + "(__a, " +
90351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      SplatLane(nElts, "__b", "__c") + ");";
90451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
90551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpQDMlalLane:
90651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += MangleName("vqdmlal", typestr, ClassS) + "(__a, __b, " +
90751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      SplatLane(nElts, "__c", "__d") + ");";
90851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
90951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpQDMlslLane:
91051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += MangleName("vqdmlsl", typestr, ClassS) + "(__a, __b, " +
91151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      SplatLane(nElts, "__c", "__d") + ");";
91251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
91351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpQDMulhLane:
91451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += MangleName("vqdmulh", typestr, ClassS) + "(__a, " +
91551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      SplatLane(nElts, "__b", "__c") + ");";
91651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
91751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpQRDMulhLane:
91851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += MangleName("vqrdmulh", typestr, ClassS) + "(__a, " +
91951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      SplatLane(nElts, "__b", "__c") + ");";
92051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
92151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpEq:
92251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "(" + ts + ")(__a == __b);";
92351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
92451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpGe:
92551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "(" + ts + ")(__a >= __b);";
92651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
92751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpLe:
92851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "(" + ts + ")(__a <= __b);";
92951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
93051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpGt:
93151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "(" + ts + ")(__a > __b);";
93251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
93351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpLt:
93451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "(" + ts + ")(__a < __b);";
93551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
93651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpNeg:
93751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += " -__a;";
93851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
93951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpNot:
94051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += " ~__a;";
94151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
94251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpAnd:
94351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a & __b;";
94451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
94551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpOr:
94651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a | __b;";
94751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
94851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpXor:
94951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a ^ __b;";
95051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
95151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpAndNot:
95251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a & ~__b;";
95351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
95451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpOrNot:
95551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a | ~__b;";
95651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
95751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpCast:
95851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "(" + ts + ")__a;";
95951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
96051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpConcat:
96151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "(" + ts + ")__builtin_shufflevector((int64x1_t)__a";
96251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += ", (int64x1_t)__b, 0, 1);";
96351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
96451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpHi:
96551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "(" + ts +
96651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      ")__builtin_shufflevector((int64x2_t)__a, (int64x2_t)__a, 1);";
96751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
96851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpLo:
96951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "(" + ts +
97051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      ")__builtin_shufflevector((int64x2_t)__a, (int64x2_t)__a, 0);";
97151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
97251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpDup:
97351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += Duplicate(nElts, typestr, "__a") + ";";
97451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
97551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpDupLane:
97651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += SplatLane(nElts, "__a", "__b") + ";";
97751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
97851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpSelect:
97951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // ((0 & 1) | (~0 & 2))
98051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "(" + ts + ")";
98151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    ts = TypeString(proto[1], typestr);
98251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "((__a & (" + ts + ")__b) | ";
98351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "(~__a & (" + ts + ")__c));";
98451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
98551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpRev16:
98651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__builtin_shufflevector(__a, __a";
98751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    for (unsigned i = 2; i <= nElts; i += 2)
98851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      for (unsigned j = 0; j != 2; ++j)
98951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        s += ", " + utostr(i - j - 1);
99051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += ");";
99151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
99251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpRev32: {
99351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    unsigned WordElts = nElts >> (1 + (int)quad);
99451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__builtin_shufflevector(__a, __a";
99551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    for (unsigned i = WordElts; i <= nElts; i += WordElts)
99651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      for (unsigned j = 0; j != WordElts; ++j)
99751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        s += ", " + utostr(i - j - 1);
99851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += ");";
99951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
100051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
100151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpRev64: {
100251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    unsigned DblWordElts = nElts >> (int)quad;
100351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__builtin_shufflevector(__a, __a";
100451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    for (unsigned i = DblWordElts; i <= nElts; i += DblWordElts)
100551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      for (unsigned j = 0; j != DblWordElts; ++j)
100651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        s += ", " + utostr(i - j - 1);
100751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += ");";
100851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
100951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
101051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpAbdl: {
101151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::string abd = MangleName("vabd", typestr, ClassS) + "(__a, __b)";
101251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (typestr[0] != 'U') {
101351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      // vabd results are always unsigned and must be zero-extended.
101451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      std::string utype = "U" + typestr.str();
101551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += "(" + TypeString(proto[0], typestr) + ")";
101651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      abd = "(" + TypeString('d', utype) + ")" + abd;
101751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += Extend(utype, abd) + ";";
101851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    } else {
101951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += Extend(typestr, abd) + ";";
102051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
102151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
102251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
102351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpAba:
102451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a + " + MangleName("vabd", typestr, ClassS) + "(__b, __c);";
102551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
102651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpAbal: {
102751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a + ";
102851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::string abd = MangleName("vabd", typestr, ClassS) + "(__b, __c)";
102951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (typestr[0] != 'U') {
103051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      // vabd results are always unsigned and must be zero-extended.
103151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      std::string utype = "U" + typestr.str();
103251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += "(" + TypeString(proto[0], typestr) + ")";
103351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      abd = "(" + TypeString('d', utype) + ")" + abd;
103451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += Extend(utype, abd) + ";";
103551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    } else {
103651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += Extend(typestr, abd) + ";";
103751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
103851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
103951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
104051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  default:
104138859ee4a3c1253d5a45ed3f6b52e77702bfd913Joerg Sonnenberger    PrintFatalError("unknown OpKind!");
104251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
104351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return s;
104451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
104551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
104651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic unsigned GetNeonEnum(const std::string &proto, StringRef typestr) {
104751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  unsigned mod = proto[0];
104851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
104951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (mod == 'v' || mod == 'f')
105051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    mod = proto[1];
105151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
105251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool quad = false;
105351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool poly = false;
105451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool usgn = false;
105551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool scal = false;
105651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool cnst = false;
105751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool pntr = false;
105851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
105951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Base type to get the type string for.
106051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  char type = ClassifyType(typestr, quad, poly, usgn);
106151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
106251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Based on the modifying character, change the type and width if necessary.
106351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  type = ModType(mod, type, quad, poly, usgn, scal, cnst, pntr);
106451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
1065da95f73b59f9af964e33725c515139d34c90c863Bob Wilson  NeonTypeFlags::EltType ET;
106651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  switch (type) {
106751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'c':
1068da95f73b59f9af964e33725c515139d34c90c863Bob Wilson      ET = poly ? NeonTypeFlags::Poly8 : NeonTypeFlags::Int8;
106951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
107051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 's':
1071da95f73b59f9af964e33725c515139d34c90c863Bob Wilson      ET = poly ? NeonTypeFlags::Poly16 : NeonTypeFlags::Int16;
107251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
107351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'i':
1074da95f73b59f9af964e33725c515139d34c90c863Bob Wilson      ET = NeonTypeFlags::Int32;
107551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
107651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'l':
1077da95f73b59f9af964e33725c515139d34c90c863Bob Wilson      ET = NeonTypeFlags::Int64;
107851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
107951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'h':
1080da95f73b59f9af964e33725c515139d34c90c863Bob Wilson      ET = NeonTypeFlags::Float16;
108151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
108251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'f':
1083da95f73b59f9af964e33725c515139d34c90c863Bob Wilson      ET = NeonTypeFlags::Float32;
108451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
108551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    default:
108638859ee4a3c1253d5a45ed3f6b52e77702bfd913Joerg Sonnenberger      PrintFatalError("unhandled type!");
108751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
1088da95f73b59f9af964e33725c515139d34c90c863Bob Wilson  NeonTypeFlags Flags(ET, usgn, quad && proto[1] != 'g');
1089da95f73b59f9af964e33725c515139d34c90c863Bob Wilson  return Flags.getFlags();
109051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
109151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
109251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne// Generate the definition for this intrinsic, e.g. __builtin_neon_cls(a)
109351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic std::string GenBuiltin(const std::string &name, const std::string &proto,
109451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                              StringRef typestr, ClassKind ck) {
109551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string s;
109651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
109751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // If this builtin returns a struct 2, 3, or 4 vectors, pass it as an implicit
109851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // sret-like argument.
109951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool sret = (proto[0] >= '2' && proto[0] <= '4');
110051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
110151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool define = UseMacro(proto);
110251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
110351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Check if the prototype has a scalar operand with the type of the vector
110451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // elements.  If not, bitcasting the args will take care of arg checking.
110551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // The actual signedness etc. will be taken care of with special enums.
110651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (proto.find('s') == std::string::npos)
110751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    ck = ClassB;
110851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
110951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (proto[0] != 'v') {
111051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::string ts = TypeString(proto[0], typestr);
111151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
111251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (define) {
111351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (sret)
111451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        s += ts + " r; ";
111551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      else
111651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        s += "(" + ts + ")";
111751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    } else if (sret) {
111851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += ts + " r; ";
111951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    } else {
112051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += "return (" + ts + ")";
112151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
112251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
112351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
112451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool splat = proto.find('a') != std::string::npos;
112551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
112651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += "__builtin_neon_";
112751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (splat) {
112851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // Call the non-splat builtin: chop off the "_n" suffix from the name.
112951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::string vname(name, 0, name.size()-2);
113051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += MangleName(vname, typestr, ck);
113151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  } else {
113251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += MangleName(name, typestr, ck);
113351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
113451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += "(";
113551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
113651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Pass the address of the return variable as the first argument to sret-like
113751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // builtins.
113851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (sret)
113951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "&r, ";
114051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
114151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  char arg = 'a';
114251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) {
114351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::string args = std::string(&arg, 1);
114451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
114551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // Use the local temporaries instead of the macro arguments.
114651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    args = "__" + args;
114751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
114851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    bool argQuad = false;
114951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    bool argPoly = false;
115051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    bool argUsgn = false;
115151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    bool argScalar = false;
115251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    bool dummy = false;
115351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    char argType = ClassifyType(typestr, argQuad, argPoly, argUsgn);
115451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    argType = ModType(proto[i], argType, argQuad, argPoly, argUsgn, argScalar,
115551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                      dummy, dummy);
115651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
115751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // Handle multiple-vector values specially, emitting each subvector as an
115851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // argument to the __builtin.
115951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (proto[i] >= '2' && proto[i] <= '4') {
116051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      // Check if an explicit cast is needed.
116151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (argType != 'c' || argPoly || argUsgn)
116251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        args = (argQuad ? "(int8x16_t)" : "(int8x8_t)") + args;
116351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
116451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      for (unsigned vi = 0, ve = proto[i] - '0'; vi != ve; ++vi) {
116551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        s += args + ".val[" + utostr(vi) + "]";
116651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        if ((vi + 1) < ve)
116751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne          s += ", ";
116851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      }
116951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if ((i + 1) < e)
117051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        s += ", ";
117151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
117251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      continue;
117351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
117451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
117551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (splat && (i + 1) == e)
117651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      args = Duplicate(GetNumElements(typestr, argQuad), typestr, args);
117751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
117851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // Check if an explicit cast is needed.
117951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if ((splat || !argScalar) &&
118051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        ((ck == ClassB && argType != 'c') || argPoly || argUsgn)) {
118151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      std::string argTypeStr = "c";
118251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (ck != ClassB)
118351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        argTypeStr = argType;
118451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (argQuad)
118551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        argTypeStr = "Q" + argTypeStr;
118651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      args = "(" + TypeString('d', argTypeStr) + ")" + args;
118751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
118851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
118951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += args;
119051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if ((i + 1) < e)
119151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += ", ";
119251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
119351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
119451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Extra constant integer to hold type class enum for this function, e.g. s8
119551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (ck == ClassB)
119651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += ", " + utostr(GetNeonEnum(proto, typestr));
119751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
119851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += ");";
119951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
120051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (proto[0] != 'v' && sret) {
120151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (define)
120251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += " r;";
120351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    else
120451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += " return r;";
120551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
120651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return s;
120751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
120851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
120951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic std::string GenBuiltinDef(const std::string &name,
121051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                                 const std::string &proto,
121151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                                 StringRef typestr, ClassKind ck) {
121251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string s("BUILTIN(__builtin_neon_");
121351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
121451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // If all types are the same size, bitcasting the args will take care
121551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // of arg checking.  The actual signedness etc. will be taken care of with
121651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // special enums.
121751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (proto.find('s') == std::string::npos)
121851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    ck = ClassB;
121951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
122051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += MangleName(name, typestr, ck);
122151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += ", \"";
122251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
122351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 0, e = proto.size(); i != e; ++i)
122451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += BuiltinTypeString(proto[i], typestr, ck, i == 0);
122551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
122651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Extra constant integer to hold type class enum for this function, e.g. s8
122751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (ck == ClassB)
122851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "i";
122951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
123051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += "\", \"n\")";
123151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return s;
123251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
123351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
123451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic std::string GenIntrinsic(const std::string &name,
123551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                                const std::string &proto,
123651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                                StringRef outTypeStr, StringRef inTypeStr,
123751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                                OpKind kind, ClassKind classKind) {
123851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  assert(!proto.empty() && "");
1239667381b21f75d6964bbdf6af143308a02b9198a8Jim Grosbach  bool define = UseMacro(proto) && kind != OpUnavailable;
124051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string s;
124151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
124251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // static always inline + return type
124351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (define)
124451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "#define ";
124551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  else
124651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__ai " + TypeString(proto[0], outTypeStr) + " ";
124751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
124851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Function name with type suffix
124951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string mangledName = MangleName(name, outTypeStr, ClassS);
125051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (outTypeStr != inTypeStr) {
125151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // If the input type is different (e.g., for vreinterpret), append a suffix
125251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // for the input type.  String off a "Q" (quad) prefix so that MangleName
125351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // does not insert another "q" in the name.
125451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    unsigned typeStrOff = (inTypeStr[0] == 'Q' ? 1 : 0);
125551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    StringRef inTypeNoQuad = inTypeStr.substr(typeStrOff);
125651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    mangledName = MangleName(mangledName, inTypeNoQuad, ClassS);
125751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
125851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += mangledName;
125951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
126051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Function arguments
126151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += GenArgs(proto, inTypeStr);
126251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
126351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Definition.
126451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (define) {
126551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += " __extension__ ({ \\\n  ";
126651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += GenMacroLocals(proto, inTypeStr);
1267667381b21f75d6964bbdf6af143308a02b9198a8Jim Grosbach  } else if (kind == OpUnavailable) {
1268667381b21f75d6964bbdf6af143308a02b9198a8Jim Grosbach    s += " __attribute__((unavailable));\n";
1269667381b21f75d6964bbdf6af143308a02b9198a8Jim Grosbach    return s;
1270667381b21f75d6964bbdf6af143308a02b9198a8Jim Grosbach  } else
127166981c7ca1fcef529d7d5e5c53b07020ff23d8e3Jim Grosbach    s += " {\n  ";
127251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
127351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (kind != OpNone)
127451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += GenOpString(kind, proto, outTypeStr);
127551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  else
127651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += GenBuiltin(name, proto, outTypeStr, classKind);
127751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (define)
127851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += " })";
127951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  else
128051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += " }";
128151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += "\n";
128251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return s;
128351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
128451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
128551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// run - Read the records in arm_neon.td and output arm_neon.h.  arm_neon.h
128651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// is comprised of type definitions and function declarations.
128751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournevoid NeonEmitter::run(raw_ostream &OS) {
128851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS <<
128951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    "/*===---- arm_neon.h - ARM Neon intrinsics ------------------------------"
129051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    "---===\n"
129151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " *\n"
129251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " * Permission is hereby granted, free of charge, to any person obtaining "
129351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    "a copy\n"
129451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " * of this software and associated documentation files (the \"Software\"),"
129551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " to deal\n"
129651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " * in the Software without restriction, including without limitation the "
129751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    "rights\n"
129851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " * to use, copy, modify, merge, publish, distribute, sublicense, "
129951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    "and/or sell\n"
130051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " * copies of the Software, and to permit persons to whom the Software is\n"
130151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " * furnished to do so, subject to the following conditions:\n"
130251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " *\n"
130351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " * The above copyright notice and this permission notice shall be "
130451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    "included in\n"
130551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " * all copies or substantial portions of the Software.\n"
130651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " *\n"
130751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, "
130851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    "EXPRESS OR\n"
130951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF "
131051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    "MERCHANTABILITY,\n"
131151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT "
131251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    "SHALL THE\n"
131351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR "
131451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    "OTHER\n"
131551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, "
131651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    "ARISING FROM,\n"
131751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER "
131851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    "DEALINGS IN\n"
131951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " * THE SOFTWARE.\n"
132051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " *\n"
132151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " *===--------------------------------------------------------------------"
132251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    "---===\n"
132351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " */\n\n";
132451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
132551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#ifndef __ARM_NEON_H\n";
132651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#define __ARM_NEON_H\n\n";
132751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
132851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#ifndef __ARM_NEON__\n";
132951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#error \"NEON support not enabled\"\n";
133051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#endif\n\n";
133151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
133251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#include <stdint.h>\n\n";
133351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
133451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Emit NEON-specific scalar typedefs.
133551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "typedef float float32_t;\n";
133651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "typedef int8_t poly8_t;\n";
133751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "typedef int16_t poly16_t;\n";
133851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "typedef uint16_t float16_t;\n";
133951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
134051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Emit Neon vector typedefs.
134151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string TypedefTypes("cQcsQsiQilQlUcQUcUsQUsUiQUiUlQUlhQhfQfPcQPcPsQPs");
134251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  SmallVector<StringRef, 24> TDTypeVec;
134351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  ParseTypes(0, TypedefTypes, TDTypeVec);
134451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
134551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Emit vector typedefs.
134651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 0, e = TDTypeVec.size(); i != e; ++i) {
134751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    bool dummy, quad = false, poly = false;
134851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    (void) ClassifyType(TDTypeVec[i], quad, poly, dummy);
134951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (poly)
135051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      OS << "typedef __attribute__((neon_polyvector_type(";
135151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    else
135251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      OS << "typedef __attribute__((neon_vector_type(";
135351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
135451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    unsigned nElts = GetNumElements(TDTypeVec[i], quad);
135551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    OS << utostr(nElts) << "))) ";
135651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (nElts < 10)
135751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      OS << " ";
135851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
135951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    OS << TypeString('s', TDTypeVec[i]);
136051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    OS << " " << TypeString('d', TDTypeVec[i]) << ";\n";
136151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
136251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "\n";
136351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
136451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Emit struct typedefs.
136551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned vi = 2; vi != 5; ++vi) {
136651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    for (unsigned i = 0, e = TDTypeVec.size(); i != e; ++i) {
136751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      std::string ts = TypeString('d', TDTypeVec[i]);
136851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      std::string vs = TypeString('0' + vi, TDTypeVec[i]);
136951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      OS << "typedef struct " << vs << " {\n";
137051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      OS << "  " << ts << " val";
137151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      OS << "[" << utostr(vi) << "]";
137251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      OS << ";\n} ";
137351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      OS << vs << ";\n\n";
137451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
137551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
137651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
13771e8058f8d90fab1b9011adf62caa52e19e61382cBob Wilson  OS<<"#define __ai static inline __attribute__((__always_inline__, __nodebug__))\n\n";
137851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
137951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::vector<Record*> RV = Records.getAllDerivedDefinitions("Inst");
138051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
138151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Emit vmovl, vmull and vabd intrinsics first so they can be used by other
138251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // intrinsics.  (Some of the saturating multiply instructions are also
138351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // used to implement the corresponding "_lane" variants, but tablegen
138451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // sorts the records into alphabetical order so that the "_lane" variants
138551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // come after the intrinsics they use.)
138651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  emitIntrinsic(OS, Records.getDef("VMOVL"));
138751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  emitIntrinsic(OS, Records.getDef("VMULL"));
138851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  emitIntrinsic(OS, Records.getDef("VABD"));
138951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
139051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 0, e = RV.size(); i != e; ++i) {
139151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    Record *R = RV[i];
139251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (R->getName() != "VMOVL" &&
139351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        R->getName() != "VMULL" &&
139451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        R->getName() != "VABD")
139551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      emitIntrinsic(OS, R);
139651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
139751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
139851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#undef __ai\n\n";
139951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#endif /* __ARM_NEON_H */\n";
140051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
140151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
140251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// emitIntrinsic - Write out the arm_neon.h header file definitions for the
140351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// intrinsics specified by record R.
140451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournevoid NeonEmitter::emitIntrinsic(raw_ostream &OS, Record *R) {
140551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string name = R->getValueAsString("Name");
140651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string Proto = R->getValueAsString("Prototype");
140751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string Types = R->getValueAsString("Types");
140851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
140951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  SmallVector<StringRef, 16> TypeVec;
141051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  ParseTypes(R, Types, TypeVec);
141151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
141251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OpKind kind = OpMap[R->getValueAsDef("Operand")->getName()];
141351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
141451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  ClassKind classKind = ClassNone;
141551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (R->getSuperClasses().size() >= 2)
141651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    classKind = ClassMap[R->getSuperClasses()[1]];
141751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (classKind == ClassNone && kind == OpNone)
141838859ee4a3c1253d5a45ed3f6b52e77702bfd913Joerg Sonnenberger    PrintFatalError(R->getLoc(), "Builtin has no class kind");
141951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
142051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) {
142151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (kind == OpReinterpret) {
142251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      bool outQuad = false;
142351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      bool dummy = false;
142451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      (void)ClassifyType(TypeVec[ti], outQuad, dummy, dummy);
142551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      for (unsigned srcti = 0, srcte = TypeVec.size();
142651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne           srcti != srcte; ++srcti) {
142751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        bool inQuad = false;
142851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        (void)ClassifyType(TypeVec[srcti], inQuad, dummy, dummy);
142951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        if (srcti == ti || inQuad != outQuad)
143051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne          continue;
143151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        OS << GenIntrinsic(name, Proto, TypeVec[ti], TypeVec[srcti],
143251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                           OpCast, ClassS);
143351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      }
143451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    } else {
143551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      OS << GenIntrinsic(name, Proto, TypeVec[ti], TypeVec[ti],
143651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                         kind, classKind);
143751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
143851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
143951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "\n";
144051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
144151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
144251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic unsigned RangeFromType(const char mod, StringRef typestr) {
144351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // base type to get the type string for.
144451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool quad = false, dummy = false;
144551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  char type = ClassifyType(typestr, quad, dummy, dummy);
144651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  type = ModType(mod, type, quad, dummy, dummy, dummy, dummy, dummy);
144751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
144851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  switch (type) {
144951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'c':
145051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      return (8 << (int)quad) - 1;
145151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'h':
145251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 's':
145351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      return (4 << (int)quad) - 1;
145451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'f':
145551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'i':
145651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      return (2 << (int)quad) - 1;
145751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'l':
145851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      return (1 << (int)quad) - 1;
145951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    default:
146038859ee4a3c1253d5a45ed3f6b52e77702bfd913Joerg Sonnenberger      PrintFatalError("unhandled type!");
146151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
146251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
146351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
146451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// runHeader - Emit a file with sections defining:
146551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// 1. the NEON section of BuiltinsARM.def.
146651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// 2. the SemaChecking code for the type overload checking.
1467667381b21f75d6964bbdf6af143308a02b9198a8Jim Grosbach/// 3. the SemaChecking code for validation of intrinsic immediate arguments.
146851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournevoid NeonEmitter::runHeader(raw_ostream &OS) {
146951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::vector<Record*> RV = Records.getAllDerivedDefinitions("Inst");
147051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
147151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  StringMap<OpKind> EmittedMap;
147251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
147351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Generate BuiltinsARM.def for NEON
147451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#ifdef GET_NEON_BUILTINS\n";
147551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 0, e = RV.size(); i != e; ++i) {
147651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    Record *R = RV[i];
147751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    OpKind k = OpMap[R->getValueAsDef("Operand")->getName()];
147851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (k != OpNone)
147951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      continue;
148051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
148151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::string Proto = R->getValueAsString("Prototype");
148251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
148351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // Functions with 'a' (the splat code) in the type prototype should not get
148451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // their own builtin as they use the non-splat variant.
148551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (Proto.find('a') != std::string::npos)
148651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      continue;
148751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
148851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::string Types = R->getValueAsString("Types");
148951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    SmallVector<StringRef, 16> TypeVec;
149051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    ParseTypes(R, Types, TypeVec);
149151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
149251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (R->getSuperClasses().size() < 2)
149338859ee4a3c1253d5a45ed3f6b52e77702bfd913Joerg Sonnenberger      PrintFatalError(R->getLoc(), "Builtin has no class kind");
149451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
149551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::string name = R->getValueAsString("Name");
149651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    ClassKind ck = ClassMap[R->getSuperClasses()[1]];
149751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
149851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) {
149951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      // Generate the BuiltinsARM.def declaration for this builtin, ensuring
150051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      // that each unique BUILTIN() macro appears only once in the output
150151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      // stream.
150251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      std::string bd = GenBuiltinDef(name, Proto, TypeVec[ti], ck);
150351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (EmittedMap.count(bd))
150451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        continue;
150551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
150651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      EmittedMap[bd] = OpNone;
150751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      OS << bd << "\n";
150851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
150951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
151051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#endif\n\n";
151151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
151251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Generate the overloaded type checking code for SemaChecking.cpp
151351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#ifdef GET_NEON_OVERLOAD_CHECK\n";
151451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 0, e = RV.size(); i != e; ++i) {
151551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    Record *R = RV[i];
151651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    OpKind k = OpMap[R->getValueAsDef("Operand")->getName()];
151751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (k != OpNone)
151851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      continue;
151951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
152051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::string Proto = R->getValueAsString("Prototype");
152151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::string Types = R->getValueAsString("Types");
152251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::string name = R->getValueAsString("Name");
152351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
152451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // Functions with 'a' (the splat code) in the type prototype should not get
152551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // their own builtin as they use the non-splat variant.
152651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (Proto.find('a') != std::string::npos)
152751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      continue;
152851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
152951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // Functions which have a scalar argument cannot be overloaded, no need to
153051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // check them if we are emitting the type checking code.
153151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (Proto.find('s') != std::string::npos)
153251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      continue;
153351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
153451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    SmallVector<StringRef, 16> TypeVec;
153551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    ParseTypes(R, Types, TypeVec);
153651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
153751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (R->getSuperClasses().size() < 2)
153838859ee4a3c1253d5a45ed3f6b52e77702bfd913Joerg Sonnenberger      PrintFatalError(R->getLoc(), "Builtin has no class kind");
153951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
154051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    int si = -1, qi = -1;
1541f8ee6bc1ef0eec8e22b413dfc2baa3cfa4f19f91Richard Smith    uint64_t mask = 0, qmask = 0;
154251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) {
154351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      // Generate the switch case(s) for this builtin for the type validation.
154451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      bool quad = false, poly = false, usgn = false;
154551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      (void) ClassifyType(TypeVec[ti], quad, poly, usgn);
154651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
154751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (quad) {
154851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        qi = ti;
1549f8ee6bc1ef0eec8e22b413dfc2baa3cfa4f19f91Richard Smith        qmask |= 1ULL << GetNeonEnum(Proto, TypeVec[ti]);
155051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      } else {
155151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        si = ti;
1552f8ee6bc1ef0eec8e22b413dfc2baa3cfa4f19f91Richard Smith        mask |= 1ULL << GetNeonEnum(Proto, TypeVec[ti]);
155351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      }
155451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
15554648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson
15564648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson    // Check if the builtin function has a pointer or const pointer argument.
15574648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson    int PtrArgNum = -1;
15584648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson    bool HasConstPtr = false;
15594648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson    for (unsigned arg = 1, arge = Proto.size(); arg != arge; ++arg) {
15604648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson      char ArgType = Proto[arg];
15614648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson      if (ArgType == 'c') {
15624648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson        HasConstPtr = true;
15634648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson        PtrArgNum = arg - 1;
15644648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson        break;
15654648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson      }
15664648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson      if (ArgType == 'p') {
15674648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson        PtrArgNum = arg - 1;
15684648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson        break;
15694648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson      }
15704648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson    }
15714648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson    // For sret builtins, adjust the pointer argument index.
15724648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson    if (PtrArgNum >= 0 && (Proto[0] >= '2' && Proto[0] <= '4'))
15734648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson      PtrArgNum += 1;
15744648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson
15759082cddf28e03c2f718e92457e2d9c7390056b2dBob Wilson    // Omit type checking for the pointer arguments of vld1_lane, vld1_dup,
15769082cddf28e03c2f718e92457e2d9c7390056b2dBob Wilson    // and vst1_lane intrinsics.  Using a pointer to the vector element
15779082cddf28e03c2f718e92457e2d9c7390056b2dBob Wilson    // type with one of those operations causes codegen to select an aligned
15789082cddf28e03c2f718e92457e2d9c7390056b2dBob Wilson    // load/store instruction.  If you want an unaligned operation,
15799082cddf28e03c2f718e92457e2d9c7390056b2dBob Wilson    // the pointer argument needs to have less alignment than element type,
15809082cddf28e03c2f718e92457e2d9c7390056b2dBob Wilson    // so just accept any pointer type.
15819082cddf28e03c2f718e92457e2d9c7390056b2dBob Wilson    if (name == "vld1_lane" || name == "vld1_dup" || name == "vst1_lane") {
15829082cddf28e03c2f718e92457e2d9c7390056b2dBob Wilson      PtrArgNum = -1;
15839082cddf28e03c2f718e92457e2d9c7390056b2dBob Wilson      HasConstPtr = false;
15849082cddf28e03c2f718e92457e2d9c7390056b2dBob Wilson    }
15859082cddf28e03c2f718e92457e2d9c7390056b2dBob Wilson
15866f9f03ef370ad48ece0c5d10edda28f39ccadb5dBob Wilson    if (mask) {
158751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      OS << "case ARM::BI__builtin_neon_"
158851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne         << MangleName(name, TypeVec[si], ClassB)
1589b27660a733d420967371bbf578a75db21116895cRichard Smith         << ": mask = " << "0x" << utohexstr(mask) << "ULL";
15904648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson      if (PtrArgNum >= 0)
15914648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson        OS << "; PtrArgNum = " << PtrArgNum;
15926f9f03ef370ad48ece0c5d10edda28f39ccadb5dBob Wilson      if (HasConstPtr)
15936f9f03ef370ad48ece0c5d10edda28f39ccadb5dBob Wilson        OS << "; HasConstPtr = true";
15946f9f03ef370ad48ece0c5d10edda28f39ccadb5dBob Wilson      OS << "; break;\n";
15956f9f03ef370ad48ece0c5d10edda28f39ccadb5dBob Wilson    }
15966f9f03ef370ad48ece0c5d10edda28f39ccadb5dBob Wilson    if (qmask) {
159751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      OS << "case ARM::BI__builtin_neon_"
159851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne         << MangleName(name, TypeVec[qi], ClassB)
1599b27660a733d420967371bbf578a75db21116895cRichard Smith         << ": mask = " << "0x" << utohexstr(qmask) << "ULL";
16004648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson      if (PtrArgNum >= 0)
16014648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson        OS << "; PtrArgNum = " << PtrArgNum;
16026f9f03ef370ad48ece0c5d10edda28f39ccadb5dBob Wilson      if (HasConstPtr)
16036f9f03ef370ad48ece0c5d10edda28f39ccadb5dBob Wilson        OS << "; HasConstPtr = true";
16046f9f03ef370ad48ece0c5d10edda28f39ccadb5dBob Wilson      OS << "; break;\n";
16056f9f03ef370ad48ece0c5d10edda28f39ccadb5dBob Wilson    }
160651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
160751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#endif\n\n";
160851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
160951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Generate the intrinsic range checking code for shift/lane immediates.
161051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#ifdef GET_NEON_IMMEDIATE_CHECK\n";
161151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 0, e = RV.size(); i != e; ++i) {
161251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    Record *R = RV[i];
161351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
161451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    OpKind k = OpMap[R->getValueAsDef("Operand")->getName()];
161551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (k != OpNone)
161651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      continue;
161751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
161851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::string name = R->getValueAsString("Name");
161951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::string Proto = R->getValueAsString("Prototype");
162051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::string Types = R->getValueAsString("Types");
162151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
162251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // Functions with 'a' (the splat code) in the type prototype should not get
162351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // their own builtin as they use the non-splat variant.
162451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (Proto.find('a') != std::string::npos)
162551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      continue;
162651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
162751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // Functions which do not have an immediate do not need to have range
162851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // checking code emitted.
162951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    size_t immPos = Proto.find('i');
163051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (immPos == std::string::npos)
163151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      continue;
163251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
163351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    SmallVector<StringRef, 16> TypeVec;
163451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    ParseTypes(R, Types, TypeVec);
163551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
163651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (R->getSuperClasses().size() < 2)
163738859ee4a3c1253d5a45ed3f6b52e77702bfd913Joerg Sonnenberger      PrintFatalError(R->getLoc(), "Builtin has no class kind");
163851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
163951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    ClassKind ck = ClassMap[R->getSuperClasses()[1]];
164051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
164151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) {
164251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      std::string namestr, shiftstr, rangestr;
164351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
164451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (R->getValueAsBit("isVCVT_N")) {
164551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        // VCVT between floating- and fixed-point values takes an immediate
164651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        // in the range 1 to 32.
164751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        ck = ClassB;
164851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        rangestr = "l = 1; u = 31"; // upper bound = l + u
164951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      } else if (Proto.find('s') == std::string::npos) {
165051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        // Builtins which are overloaded by type will need to have their upper
165151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        // bound computed at Sema time based on the type constant.
165251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        ck = ClassB;
165351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        if (R->getValueAsBit("isShift")) {
165451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne          shiftstr = ", true";
165551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
165651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne          // Right shifts have an 'r' in the name, left shifts do not.
165751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne          if (name.find('r') != std::string::npos)
165851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne            rangestr = "l = 1; ";
165951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        }
166051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        rangestr += "u = RFT(TV" + shiftstr + ")";
166151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      } else {
166251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        // The immediate generally refers to a lane in the preceding argument.
166351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        assert(immPos > 0 && "unexpected immediate operand");
166451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        rangestr = "u = " + utostr(RangeFromType(Proto[immPos-1], TypeVec[ti]));
166551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      }
166651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      // Make sure cases appear only once by uniquing them in a string map.
166751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      namestr = MangleName(name, TypeVec[ti], ck);
166851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (EmittedMap.count(namestr))
166951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        continue;
167051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      EmittedMap[namestr] = OpNone;
167151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
167251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      // Calculate the index of the immediate that should be range checked.
167351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      unsigned immidx = 0;
167451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
167551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      // Builtins that return a struct of multiple vectors have an extra
167651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      // leading arg for the struct return.
167751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (Proto[0] >= '2' && Proto[0] <= '4')
167851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        ++immidx;
167951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
168051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      // Add one to the index for each argument until we reach the immediate
168151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      // to be checked.  Structs of vectors are passed as multiple arguments.
168251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      for (unsigned ii = 1, ie = Proto.size(); ii != ie; ++ii) {
168351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        switch (Proto[ii]) {
168451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne          default:  immidx += 1; break;
168551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne          case '2': immidx += 2; break;
168651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne          case '3': immidx += 3; break;
168751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne          case '4': immidx += 4; break;
168851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne          case 'i': ie = ii + 1; break;
168951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        }
169051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      }
169151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      OS << "case ARM::BI__builtin_neon_" << MangleName(name, TypeVec[ti], ck)
169251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne         << ": i = " << immidx << "; " << rangestr << "; break;\n";
169351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
169451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
169551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#endif\n\n";
169651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
169751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
169851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// GenTest - Write out a test for the intrinsic specified by the name and
169951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// type strings, including the embedded patterns for FileCheck to match.
170051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic std::string GenTest(const std::string &name,
170151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                           const std::string &proto,
170251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                           StringRef outTypeStr, StringRef inTypeStr,
17037200bd673af6b58d7d2f0c5d048050abe5b8858cMichael Gottesman                           bool isShift, bool isHiddenLOp,
17047200bd673af6b58d7d2f0c5d048050abe5b8858cMichael Gottesman                           ClassKind ck, const std::string &InstName) {
170551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  assert(!proto.empty() && "");
170651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string s;
170751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
170851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Function name with type suffix
170951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string mangledName = MangleName(name, outTypeStr, ClassS);
171051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (outTypeStr != inTypeStr) {
171151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // If the input type is different (e.g., for vreinterpret), append a suffix
171251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // for the input type.  String off a "Q" (quad) prefix so that MangleName
171351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // does not insert another "q" in the name.
171451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    unsigned typeStrOff = (inTypeStr[0] == 'Q' ? 1 : 0);
171551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    StringRef inTypeNoQuad = inTypeStr.substr(typeStrOff);
171651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    mangledName = MangleName(mangledName, inTypeNoQuad, ClassS);
171751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
171851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
171951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Emit the FileCheck patterns.
172051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += "// CHECK: test_" + mangledName + "\n";
172151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // s += "// CHECK: \n"; // FIXME: + expected instruction opcode.
172251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
172351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Emit the start of the test function.
172451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += TypeString(proto[0], outTypeStr) + " test_" + mangledName + "(";
172551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  char arg = 'a';
172651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string comma;
172751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) {
172851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // Do not create arguments for values that must be immediate constants.
172951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (proto[i] == 'i')
173051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      continue;
173151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += comma + TypeString(proto[i], inTypeStr) + " ";
173251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s.push_back(arg);
173351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    comma = ", ";
173451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
1735b4a542549c2e0c9eeb6ece3f95767ccdd141fa3eJim Grosbach  s += ") {\n  ";
173651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
173751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (proto[0] != 'v')
173851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "return ";
173951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += mangledName + "(";
174051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  arg = 'a';
174151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) {
174251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (proto[i] == 'i') {
174351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      // For immediate operands, test the maximum value.
174451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (isShift)
174551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        s += "1"; // FIXME
174651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      else
174751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        // The immediate generally refers to a lane in the preceding argument.
174851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        s += utostr(RangeFromType(proto[i-1], inTypeStr));
174951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    } else {
175051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s.push_back(arg);
175151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
175251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if ((i + 1) < e)
175351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += ", ";
175451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
175551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += ");\n}\n\n";
175651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return s;
175751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
175851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
175951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// runTests - Write out a complete set of tests for all of the Neon
176051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// intrinsics.
176151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournevoid NeonEmitter::runTests(raw_ostream &OS) {
176251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS <<
176351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    "// RUN: %clang_cc1 -triple thumbv7-apple-darwin \\\n"
1764fb9929ee2a0ed47d473a58b0ba5c7a7a7a095b73Michael Gottesman    "// RUN:  -target-cpu swift -ffreestanding -Os -S -o - %s\\\n"
1765fb9929ee2a0ed47d473a58b0ba5c7a7a7a095b73Michael Gottesman    "// RUN:  | FileCheck %s\n"
176651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    "\n"
176751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    "#include <arm_neon.h>\n"
176851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    "\n";
176951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
177051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::vector<Record*> RV = Records.getAllDerivedDefinitions("Inst");
177151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 0, e = RV.size(); i != e; ++i) {
177251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    Record *R = RV[i];
177351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::string name = R->getValueAsString("Name");
177451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::string Proto = R->getValueAsString("Prototype");
177551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::string Types = R->getValueAsString("Types");
177651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    bool isShift = R->getValueAsBit("isShift");
17777200bd673af6b58d7d2f0c5d048050abe5b8858cMichael Gottesman    std::string InstName = R->getValueAsString("InstName");
17787200bd673af6b58d7d2f0c5d048050abe5b8858cMichael Gottesman    bool isHiddenLOp = R->getValueAsBit("isHiddenLInst");
177951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
178051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    SmallVector<StringRef, 16> TypeVec;
178151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    ParseTypes(R, Types, TypeVec);
178251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
17837200bd673af6b58d7d2f0c5d048050abe5b8858cMichael Gottesman    ClassKind ck = ClassMap[R->getSuperClasses()[1]];
178451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    OpKind kind = OpMap[R->getValueAsDef("Operand")->getName()];
1785667381b21f75d6964bbdf6af143308a02b9198a8Jim Grosbach    if (kind == OpUnavailable)
1786667381b21f75d6964bbdf6af143308a02b9198a8Jim Grosbach      continue;
178751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) {
178851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (kind == OpReinterpret) {
178951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        bool outQuad = false;
179051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        bool dummy = false;
179151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        (void)ClassifyType(TypeVec[ti], outQuad, dummy, dummy);
179251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        for (unsigned srcti = 0, srcte = TypeVec.size();
179351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne             srcti != srcte; ++srcti) {
179451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne          bool inQuad = false;
179551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne          (void)ClassifyType(TypeVec[srcti], inQuad, dummy, dummy);
179651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne          if (srcti == ti || inQuad != outQuad)
179751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne            continue;
17987200bd673af6b58d7d2f0c5d048050abe5b8858cMichael Gottesman          OS << GenTest(name, Proto, TypeVec[ti], TypeVec[srcti],
17997200bd673af6b58d7d2f0c5d048050abe5b8858cMichael Gottesman                        isShift, isHiddenLOp, ck, InstName);
180051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        }
180151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      } else {
18027200bd673af6b58d7d2f0c5d048050abe5b8858cMichael Gottesman        OS << GenTest(name, Proto, TypeVec[ti], TypeVec[ti],
18037200bd673af6b58d7d2f0c5d048050abe5b8858cMichael Gottesman                      isShift, isHiddenLOp, ck, InstName);
180451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      }
180551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
180651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    OS << "\n";
180751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
180851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
180951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
18103cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesennamespace clang {
18113cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesenvoid EmitNeon(RecordKeeper &Records, raw_ostream &OS) {
18123cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  NeonEmitter(Records).run(OS);
18133cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen}
18143cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesenvoid EmitNeonSema(RecordKeeper &Records, raw_ostream &OS) {
18153cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  NeonEmitter(Records).runHeader(OS);
18163cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen}
18173cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesenvoid EmitNeonTest(RecordKeeper &Records, raw_ostream &OS) {
18183cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  NeonEmitter(Records).runTests(OS);
18193cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen}
18203cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen} // End namespace clang
1821