NeonEmitter.cpp revision c327f8705ecb8753555822d479f899bd2234386d
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  }
683c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
68451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return s;
68551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
68651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
687c327f8705ecb8753555822d479f899bd2234386dMichael Gottesmanstatic void PreprocessInstruction(const StringRef &Name,
688c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                  const std::string &InstName,
689c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                  std::string &Prefix,
690c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                  bool &HasNPostfix,
691c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                  bool &HasLanePostfix,
692c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                  bool &HasDupPostfix,
693c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                  bool &IsSpecialVCvt,
694c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                  size_t &TBNumber) {
695c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // All of our instruction name fields from arm_neon.td are of the form
696c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  //   <instructionname>_...
697c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // Thus we grab our instruction name via computation of said Prefix.
698c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  const size_t PrefixEnd = Name.find_first_of('_');
699c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // If InstName is passed in, we use that instead of our name Prefix.
700c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  Prefix = InstName.size() == 0? Name.slice(0, PrefixEnd).str() : InstName;
701c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
702c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  const StringRef Postfix = Name.slice(PrefixEnd, Name.size());
703c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
704c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  HasNPostfix = Postfix.count("_n");
705c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  HasLanePostfix = Postfix.count("_lane");
706c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  HasDupPostfix = Postfix.count("_dup");
707c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  IsSpecialVCvt = Postfix.size() != 0 && Name.count("vcvt");
708c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
709c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  if (InstName.compare("vtbl") == 0 ||
710c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      InstName.compare("vtbx") == 0) {
711c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    // If we have a vtblN/vtbxN instruction, use the instruction's ASCII
712c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    // encoding to get its true value.
713c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    TBNumber = Name[Name.size()-1] - 48;
714c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  }
715c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman}
716c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
717c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman/// GenerateRegisterCheckPatternsForLoadStores - Given a bunch of data we have
718c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman/// extracted, generate a FileCheck pattern for a Load Or Store
719c327f8705ecb8753555822d479f899bd2234386dMichael Gottesmanstatic void
720c327f8705ecb8753555822d479f899bd2234386dMichael GottesmanGenerateRegisterCheckPatternForLoadStores(const StringRef &NameRef,
721c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                          const std::string& OutTypeCode,
722c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                          const bool &IsQuad,
723c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                          const bool &HasDupPostfix,
724c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                          const bool &HasLanePostfix,
725c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                          const size_t Count,
726c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                          std::string &RegisterSuffix) {
727c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  const bool IsLDSTOne = NameRef.count("vld1") || NameRef.count("vst1");
728c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // If N == 3 || N == 4 and we are dealing with a quad instruction, Clang
729c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // will output a series of v{ld,st}1s, so we have to handle it specially.
730c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  if ((Count == 3 || Count == 4) && IsQuad) {
731c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    RegisterSuffix += "{";
732c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    for (size_t i = 0; i < Count; i++) {
733c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      RegisterSuffix += "d{{[0-9]+}}";
734c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      if (HasDupPostfix) {
735c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman        RegisterSuffix += "[]";
736c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      }
737c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      if (HasLanePostfix) {
738c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman        RegisterSuffix += "[{{[0-9]+}}]";
739c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      }
740c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      if (i < Count-1) {
741c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman        RegisterSuffix += ", ";
742c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      }
743c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    }
744c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    RegisterSuffix += "}";
745c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  } else {
746c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
747c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    // Handle normal loads and stores.
748c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    RegisterSuffix += "{";
749c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    for (size_t i = 0; i < Count; i++) {
750c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      RegisterSuffix += "d{{[0-9]+}}";
751c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      if (HasDupPostfix) {
752c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman        RegisterSuffix += "[]";
753c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      }
754c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      if (HasLanePostfix) {
755c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman        RegisterSuffix += "[{{[0-9]+}}]";
756c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      }
757c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      if (IsQuad && !HasLanePostfix) {
758c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman        RegisterSuffix += ", d{{[0-9]+}}";
759c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman        if (HasDupPostfix) {
760c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman          RegisterSuffix += "[]";
761c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman        }
762c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      }
763c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      if (i < Count-1) {
764c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman        RegisterSuffix += ", ";
765c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      }
766c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    }
767c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    RegisterSuffix += "}, [r{{[0-9]+}}";
768c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
769c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    // We only include the alignment hint if we have a vld1.*64 or
770c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    // a dup/lane instruction.
771c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    if (IsLDSTOne) {
772c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      if ((HasLanePostfix || HasDupPostfix) && OutTypeCode != "8") {
773c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman        RegisterSuffix += ", :" + OutTypeCode;
774c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      } else if (OutTypeCode == "64") {
775c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman        RegisterSuffix += ", :64";
776c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      }
777c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    }
778c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
779c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    RegisterSuffix += "]";
780c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  }
781c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman}
782c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
783c327f8705ecb8753555822d479f899bd2234386dMichael Gottesmanstatic bool HasNPostfixAndScalarArgs(const StringRef &NameRef,
784c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                     const bool &HasNPostfix) {
785c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  return (NameRef.count("vmla") ||
786c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman          NameRef.count("vmlal") ||
787c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman          NameRef.count("vmlsl") ||
788c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman          NameRef.count("vmull") ||
789c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman          NameRef.count("vqdmlal") ||
790c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman          NameRef.count("vqdmlsl") ||
791c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman          NameRef.count("vqdmulh") ||
792c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman          NameRef.count("vqdmull") ||
793c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman          NameRef.count("vqrdmulh")) && HasNPostfix;
794c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman}
795c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
796c327f8705ecb8753555822d479f899bd2234386dMichael Gottesmanstatic bool IsFiveOperandLaneAccumulator(const StringRef &NameRef,
797c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                         const bool &HasLanePostfix) {
798c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  return (NameRef.count("vmla") ||
799c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman          NameRef.count("vmls") ||
800c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman          NameRef.count("vmlal") ||
801c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman          NameRef.count("vmlsl") ||
802c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman          (NameRef.count("vmul") && NameRef.size() == 3)||
803c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman          NameRef.count("vqdmlal") ||
804c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman          NameRef.count("vqdmlsl") ||
805c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman          NameRef.count("vqdmulh") ||
806c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman          NameRef.count("vqrdmulh")) && HasLanePostfix;
807c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman}
808c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
809c327f8705ecb8753555822d479f899bd2234386dMichael Gottesmanstatic bool IsSpecialLaneMultiply(const StringRef &NameRef,
810c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                  const bool &HasLanePostfix,
811c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                  const bool &IsQuad) {
812c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  const bool IsVMulOrMulh = (NameRef.count("vmul") || NameRef.count("mulh"))
813c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                               && IsQuad;
814c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  const bool IsVMull = NameRef.count("mull") && !IsQuad;
815c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  return (IsVMulOrMulh || IsVMull) && HasLanePostfix;
816c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman}
817c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
818c327f8705ecb8753555822d479f899bd2234386dMichael Gottesmanstatic void NormalizeProtoForRegisterPatternCreation(const std::string &Name,
819c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                                     const std::string &Proto,
820c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                                     const bool &HasNPostfix,
821c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                                     const bool &IsQuad,
822c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                                     const bool &HasLanePostfix,
823c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                                     const bool &HasDupPostfix,
824c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                                     std::string &NormedProto) {
825c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // Handle generic case.
826c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  const StringRef NameRef(Name);
827c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  for (size_t i = 0, end = Proto.size(); i < end; i++) {
828c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    switch (Proto[i]) {
829c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    case 'u':
830c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    case 'f':
831c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    case 'd':
832c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    case 's':
833c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    case 'x':
834c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    case 't':
835c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    case 'n':
836c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      NormedProto += IsQuad? 'q' : 'd';
837c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      break;
838c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    case 'w':
839c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    case 'k':
840c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      NormedProto += 'q';
841c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      break;
842c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    case 'g':
843c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    case 'h':
844c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    case 'e':
845c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      NormedProto += 'd';
846c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      break;
847c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    case 'i':
848c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      NormedProto += HasLanePostfix? 'a' : 'i';
849c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      break;
850c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    case 'a':
851c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      if (HasLanePostfix) {
852c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman        NormedProto += 'a';
853c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      } else if (HasNPostfixAndScalarArgs(NameRef, HasNPostfix)) {
854c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman        NormedProto += IsQuad? 'q' : 'd';
855c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      } else {
856c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman        NormedProto += 'i';
857c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      }
858c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      break;
859c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    }
860c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  }
861c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
862c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // Handle Special Cases.
863c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  const bool IsNotVExt = !NameRef.count("vext");
864c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  const bool IsVPADAL = NameRef.count("vpadal");
865c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  const bool Is5OpLaneAccum = IsFiveOperandLaneAccumulator(NameRef,
866c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                                           HasLanePostfix);
867c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  const bool IsSpecialLaneMul = IsSpecialLaneMultiply(NameRef, HasLanePostfix,
868c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                                      IsQuad);
869c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
870c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  if (IsSpecialLaneMul) {
871c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    // If
872c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    NormedProto[2] = NormedProto[3];
873c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    NormedProto.erase(3);
874c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  } else if (NormedProto.size() == 4 &&
875c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman             NormedProto[0] == NormedProto[1] &&
876c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman             IsNotVExt) {
877c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    // If NormedProto.size() == 4 and the first two proto characters are the
878c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    // same, ignore the first.
879c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    NormedProto = NormedProto.substr(1, 3);
880c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  } else if (Is5OpLaneAccum) {
881c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    // If we have a 5 op lane accumulator operation, we take characters 1,2,4
882c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    std::string tmp = NormedProto.substr(1,2);
883c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    tmp += NormedProto[4];
884c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    NormedProto = tmp;
885c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  } else if (IsVPADAL) {
886c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    // If we have VPADAL, ignore the first character.
887c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    NormedProto = NormedProto.substr(0, 2);
888c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  } else if (NameRef.count("vdup") && NormedProto.size() > 2) {
889c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    // If our instruction is a dup instruction, keep only the first and
890c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    // last characters.
891c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    std::string tmp = "";
892c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    tmp += NormedProto[0];
893c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    tmp += NormedProto[NormedProto.size()-1];
894c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    NormedProto = tmp;
895c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  }
896c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman}
897c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
898c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman/// GenerateRegisterCheckPatterns - Given a bunch of data we have
899c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman/// extracted, generate a FileCheck pattern to check that an
900c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman/// instruction's arguments are correct.
901c327f8705ecb8753555822d479f899bd2234386dMichael Gottesmanstatic void GenerateRegisterCheckPattern(const std::string &Name,
902c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                         const std::string &Proto,
903c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                         const std::string &OutTypeCode,
904c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                         const bool &HasNPostfix,
905c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                         const bool &IsQuad,
906c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                         const bool &HasLanePostfix,
907c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                         const bool &HasDupPostfix,
908c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                         const size_t &TBNumber,
909c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                         std::string &RegisterSuffix) {
910c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
911c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  RegisterSuffix = "";
912c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
913c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  const StringRef NameRef(Name);
914c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  const StringRef ProtoRef(Proto);
915c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
916c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  if ((NameRef.count("vdup") || NameRef.count("vmov")) && HasNPostfix) {
917c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    return;
918c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  }
919c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
920c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  const bool IsLoadStore = NameRef.count("vld") || NameRef.count("vst");
921c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  const bool IsTBXOrTBL = NameRef.count("vtbl") || NameRef.count("vtbx");
922c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
923c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  if (IsLoadStore) {
924c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    // Grab N value from  v{ld,st}N using its ascii representation.
925c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    const size_t Count = NameRef[3] - 48;
926c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
927c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    GenerateRegisterCheckPatternForLoadStores(NameRef, OutTypeCode, IsQuad,
928c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                              HasDupPostfix, HasLanePostfix,
929c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                              Count, RegisterSuffix);
930c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  } else if (IsTBXOrTBL) {
931c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    RegisterSuffix += "d{{[0-9]+}}, {";
932c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    for (size_t i = 0; i < TBNumber-1; i++) {
933c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      RegisterSuffix += "d{{[0-9]+}}, ";
934c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    }
935c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    RegisterSuffix += "d{{[0-9]+}}}, d{{[0-9]+}}";
936c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  } else {
937c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    // Handle a normal instruction.
938c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    if (NameRef.count("vget") || NameRef.count("vset"))
939c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      return;
940c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
941c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    // We first normalize our proto, since we only need to emit 4
942c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    // different types of checks, yet have more than 4 proto types
943c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    // that map onto those 4 patterns.
944c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    std::string NormalizedProto("");
945c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    NormalizeProtoForRegisterPatternCreation(Name, Proto, HasNPostfix, IsQuad,
946c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                             HasLanePostfix, HasDupPostfix,
947c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                             NormalizedProto);
948c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
949c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    for (size_t i = 0, end = NormalizedProto.size(); i < end; i++) {
950c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      const char &c = NormalizedProto[i];
951c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      switch (c) {
952c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      case 'q':
953c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman        RegisterSuffix += "q{{[0-9]+}}, ";
954c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman        break;
955c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
956c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      case 'd':
957c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman        RegisterSuffix += "d{{[0-9]+}}, ";
958c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman        break;
959c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
960c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      case 'i':
961c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman        RegisterSuffix += "#{{[0-9]+}}, ";
962c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman        break;
963c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
964c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      case 'a':
965c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman        RegisterSuffix += "d{{[0-9]+}}[{{[0-9]}}], ";
966c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman        break;
967c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      }
968c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    }
969c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
970c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    // Remove extra ", ".
971c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    RegisterSuffix = RegisterSuffix.substr(0, RegisterSuffix.size()-2);
972c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  }
973c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman}
974c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
975c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman/// GenerateChecksForIntrinsic - Given a specific instruction name +
976c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman/// typestr + class kind, generate the proper set of FileCheck
977c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman/// Patterns to check for. We could just return a string, but instead
978c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman/// use a vector since it provides us with the extra flexibility of
979c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman/// emitting multiple checks, which comes in handy for certain cases
980c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman/// like mla where we want to check for 2 different instructions.
981c327f8705ecb8753555822d479f899bd2234386dMichael Gottesmanstatic void GenerateChecksForIntrinsic(const std::string &Name,
982c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                       const std::string &Proto,
983c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                       StringRef &OutTypeStr,
984c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                       StringRef &InTypeStr,
985c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                       ClassKind Ck,
986c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                       const std::string &InstName,
987c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                       bool IsHiddenLOp,
988c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                       std::vector<std::string>& Result) {
989c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
990c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // If Ck is a ClassNoTest instruction, just return so no test is
991c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // emitted.
992c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  if(Ck == ClassNoTest)
993c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    return;
994c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
995c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  if (Name == "vcvt_f32_f16") {
996c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    Result.push_back("vcvt.f32.f16");
997c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    return;
998c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  }
999c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1000c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1001c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // Now we preprocess our instruction given the data we have to get the
1002c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // data that we need.
1003c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // Create a StringRef for String Manipulation of our Name.
1004c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  const StringRef NameRef(Name);
1005c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // Instruction Prefix.
1006c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  std::string Prefix;
1007c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // The type code for our out type string.
1008c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  std::string OutTypeCode;
1009c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // To handle our different cases, we need to check for different postfixes.
1010c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // Is our instruction a quad instruction.
1011c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  bool IsQuad = false;
1012c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // Our instruction is of the form <instructionname>_n.
1013c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  bool HasNPostfix = false;
1014c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // Our instruction is of the form <instructionname>_lane.
1015c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  bool HasLanePostfix = false;
1016c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // Our instruction is of the form <instructionname>_dup.
1017c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  bool HasDupPostfix  = false;
1018c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // Our instruction is a vcvt instruction which requires special handling.
1019c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  bool IsSpecialVCvt = false;
1020c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // If we have a vtbxN or vtblN instruction, this is set to N.
1021c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  size_t TBNumber = -1;
1022c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // Register Suffix
1023c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  std::string RegisterSuffix;
1024c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1025c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  PreprocessInstruction(NameRef, InstName, Prefix,
1026c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                        HasNPostfix, HasLanePostfix, HasDupPostfix,
1027c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                        IsSpecialVCvt, TBNumber);
1028c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1029c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  InstructionTypeCode(OutTypeStr, Ck, IsQuad, OutTypeCode);
1030c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  GenerateRegisterCheckPattern(Name, Proto, OutTypeCode, HasNPostfix, IsQuad,
1031c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                               HasLanePostfix, HasDupPostfix, TBNumber,
1032c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                               RegisterSuffix);
1033c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1034c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // In the following section, we handle a bunch of special cases. You can tell
1035c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // a special case by the fact we are returning early.
1036c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1037c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // If our instruction is a logical instruction without postfix or a
1038c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // hidden LOp just return the current Prefix.
1039c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  if (Ck == ClassL || IsHiddenLOp) {
1040c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    Result.push_back(Prefix + " " + RegisterSuffix);
1041c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    return;
1042c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  }
1043c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1044c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // If we have a vmov, due to the many different cases, some of which
1045c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // vary within the different intrinsics generated for a single
1046c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // instruction type, just output a vmov. (e.g. given an instruction
1047c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // A, A.u32 might be vmov and A.u8 might be vmov.8).
1048c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  //
1049c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // FIXME: Maybe something can be done about this. The two cases that we care
1050c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // about are vmov as an LType and vmov as a WType.
1051c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  if (Prefix == "vmov") {
1052c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    Result.push_back(Prefix + " " + RegisterSuffix);
1053c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    return;
1054c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  }
1055c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1056c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // In the following section, we handle special cases.
1057c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1058c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  if (OutTypeCode == "64") {
1059c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    // If we have a 64 bit vdup/vext and are handling an uint64x1_t
1060c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    // type, the intrinsic will be optimized away, so just return
1061c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    // nothing.  On the other hand if we are handling an uint64x2_t
1062c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    // (i.e. quad instruction), vdup/vmov instructions should be
1063c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    // emitted.
1064c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    if (Prefix == "vdup" || Prefix == "vext") {
1065c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      if (IsQuad) {
1066c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman        Result.push_back("{{vmov|vdup}}");
1067c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      }
1068c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      return;
1069c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    }
1070c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1071c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    // v{st,ld}{2,3,4}_{u,s}64 emit v{st,ld}1.64 instructions with
1072c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    // multiple register operands.
1073c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    bool MultiLoadPrefix = Prefix == "vld2" || Prefix == "vld3"
1074c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                            || Prefix == "vld4";
1075c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    bool MultiStorePrefix = Prefix == "vst2" || Prefix == "vst3"
1076c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                            || Prefix == "vst4";
1077c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    if (MultiLoadPrefix || MultiStorePrefix) {
1078c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      Result.push_back(NameRef.slice(0, 3).str() + "1.64");
1079c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      return;
1080c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    }
1081c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1082c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    // v{st,ld}1_{lane,dup}_{u64,s64} use vldr/vstr/vmov/str instead of
1083c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    // emitting said instructions. So return a check for
1084c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    // vldr/vstr/vmov/str instead.
1085c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    if (HasLanePostfix || HasDupPostfix) {
1086c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      if (Prefix == "vst1") {
1087c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman        Result.push_back("{{str|vstr|vmov}}");
1088c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman        return;
1089c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      } else if (Prefix == "vld1") {
1090c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman        Result.push_back("{{ldr|vldr|vmov}}");
1091c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman        return;
1092c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      }
1093c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    }
1094c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  }
1095c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1096c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // vzip.32/vuzp.32 are the same instruction as vtrn.32 and are
1097c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // sometimes disassembled as vtrn.32. We use a regex to handle both
1098c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // cases.
1099c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  if ((Prefix == "vzip" || Prefix == "vuzp") && OutTypeCode == "32") {
1100c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    Result.push_back("{{vtrn|" + Prefix + "}}.32 " + RegisterSuffix);
1101c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    return;
1102c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  }
1103c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1104c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // Currently on most ARM processors, we do not use vmla/vmls for
1105c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // quad floating point operations. Instead we output vmul + vadd. So
1106c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // check if we have one of those instructions and just output a
1107c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // check for vmul.
1108c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  if (OutTypeCode == "f32") {
1109c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    if (Prefix == "vmls") {
1110c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      Result.push_back("vmul." + OutTypeCode + " " + RegisterSuffix);
1111c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      Result.push_back("vsub." + OutTypeCode);
1112c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      return;
1113c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    } else if (Prefix == "vmla") {
1114c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      Result.push_back("vmul." + OutTypeCode + " " + RegisterSuffix);
1115c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      Result.push_back("vadd." + OutTypeCode);
1116c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      return;
1117c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    }
1118c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  }
1119c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1120c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // If we have vcvt, get the input type from the instruction name
1121c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // (which should be of the form instname_inputtype) and append it
1122c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // before the output type.
1123c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  if (Prefix == "vcvt") {
1124c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    const std::string inTypeCode = NameRef.substr(NameRef.find_last_of("_")+1);
1125c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    Prefix += "." + inTypeCode;
1126c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  }
1127c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1128c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // Append output type code to get our final mangled instruction.
1129c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  Prefix += "." + OutTypeCode;
1130c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1131c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  Result.push_back(Prefix + " " + RegisterSuffix);
1132c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman}
1133c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
113451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// UseMacro - Examine the prototype string to determine if the intrinsic
113551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// should be defined as a preprocessor macro instead of an inline function.
113651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic bool UseMacro(const std::string &proto) {
113751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // If this builtin takes an immediate argument, we need to #define it rather
113851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // than use a standard declaration, so that SemaChecking can range check
113951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // the immediate passed by the user.
114051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (proto.find('i') != std::string::npos)
114151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    return true;
114251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
114351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Pointer arguments need to use macros to avoid hiding aligned attributes
114451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // from the pointer type.
114551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (proto.find('p') != std::string::npos ||
114651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      proto.find('c') != std::string::npos)
114751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    return true;
114851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
114951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return false;
115051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
115151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
115251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// MacroArgUsedDirectly - Return true if argument i for an intrinsic that is
115351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// defined as a macro should be accessed directly instead of being first
115451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// assigned to a local temporary.
115551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic bool MacroArgUsedDirectly(const std::string &proto, unsigned i) {
115651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // True for constant ints (i), pointers (p) and const pointers (c).
115751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return (proto[i] == 'i' || proto[i] == 'p' || proto[i] == 'c');
115851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
115951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
116051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne// Generate the string "(argtype a, argtype b, ...)"
116151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic std::string GenArgs(const std::string &proto, StringRef typestr) {
116251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool define = UseMacro(proto);
116351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  char arg = 'a';
116451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
116551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string s;
116651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += "(";
116751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
116851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) {
116951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (define) {
117051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      // Some macro arguments are used directly instead of being assigned
117151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      // to local temporaries; prepend an underscore prefix to make their
117251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      // names consistent with the local temporaries.
117351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (MacroArgUsedDirectly(proto, i))
117451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        s += "__";
117551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    } else {
117651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += TypeString(proto[i], typestr) + " __";
117751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
117851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s.push_back(arg);
117951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if ((i + 1) < e)
118051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += ", ";
118151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
118251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
118351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += ")";
118451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return s;
118551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
118651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
118751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne// Macro arguments are not type-checked like inline function arguments, so
118851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne// assign them to local temporaries to get the right type checking.
118951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic std::string GenMacroLocals(const std::string &proto, StringRef typestr) {
119051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  char arg = 'a';
119151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string s;
119251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool generatedLocal = false;
119351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
119451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) {
119551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // Do not create a temporary for an immediate argument.
119651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // That would defeat the whole point of using a macro!
119751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (MacroArgUsedDirectly(proto, i))
119851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      continue;
119951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    generatedLocal = true;
120051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
120151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += TypeString(proto[i], typestr) + " __";
120251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s.push_back(arg);
120351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += " = (";
120451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s.push_back(arg);
120551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "); ";
120651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
120751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
120851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (generatedLocal)
120951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "\\\n  ";
121051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return s;
121151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
121251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
121351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne// Use the vmovl builtin to sign-extend or zero-extend a vector.
121451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic std::string Extend(StringRef typestr, const std::string &a) {
121551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string s;
121651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s = MangleName("vmovl", typestr, ClassS);
121751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += "(" + a + ")";
121851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return s;
121951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
122051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
122151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic std::string Duplicate(unsigned nElts, StringRef typestr,
122251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                             const std::string &a) {
122351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string s;
122451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
122551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s = "(" + TypeString('d', typestr) + "){ ";
122651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 0; i != nElts; ++i) {
122751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += a;
122851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if ((i + 1) < nElts)
122951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += ", ";
123051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
123151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += " }";
123251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
123351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return s;
123451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
123551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
123651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic std::string SplatLane(unsigned nElts, const std::string &vec,
123751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                             const std::string &lane) {
123851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string s = "__builtin_shufflevector(" + vec + ", " + vec;
123951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 0; i < nElts; ++i)
124051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += ", " + lane;
124151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += ")";
124251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return s;
124351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
124451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
124551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic unsigned GetNumElements(StringRef typestr, bool &quad) {
124651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  quad = false;
124751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool dummy = false;
124851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  char type = ClassifyType(typestr, quad, dummy, dummy);
124951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  unsigned nElts = 0;
125051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  switch (type) {
125151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case 'c': nElts = 8; break;
125251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case 's': nElts = 4; break;
125351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case 'i': nElts = 2; break;
125451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case 'l': nElts = 1; break;
125551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case 'h': nElts = 4; break;
125651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case 'f': nElts = 2; break;
125751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  default:
125838859ee4a3c1253d5a45ed3f6b52e77702bfd913Joerg Sonnenberger    PrintFatalError("unhandled type!");
125951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
126051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (quad) nElts <<= 1;
126151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return nElts;
126251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
126351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
126451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne// Generate the definition for this intrinsic, e.g. "a + b" for OpAdd.
126551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic std::string GenOpString(OpKind op, const std::string &proto,
126651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                               StringRef typestr) {
126751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool quad;
126851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  unsigned nElts = GetNumElements(typestr, quad);
126951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool define = UseMacro(proto);
127051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
127151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string ts = TypeString(proto[0], typestr);
127251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string s;
127351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (!define) {
127451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s = "return ";
127551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
127651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
127751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  switch(op) {
127851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpAdd:
127951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a + __b;";
128051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
128151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpAddl:
128251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += Extend(typestr, "__a") + " + " + Extend(typestr, "__b") + ";";
128351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
128451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpAddw:
128551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a + " + Extend(typestr, "__b") + ";";
128651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
128751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpSub:
128851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a - __b;";
128951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
129051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpSubl:
129151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += Extend(typestr, "__a") + " - " + Extend(typestr, "__b") + ";";
129251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
129351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpSubw:
129451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a - " + Extend(typestr, "__b") + ";";
129551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
129651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpMulN:
129751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a * " + Duplicate(nElts, typestr, "__b") + ";";
129851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
129951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpMulLane:
130051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a * " + SplatLane(nElts, "__b", "__c") + ";";
130151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
130251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpMul:
130351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a * __b;";
130451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
130551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpMullLane:
130651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += MangleName("vmull", typestr, ClassS) + "(__a, " +
130751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      SplatLane(nElts, "__b", "__c") + ");";
130851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
130951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpMlaN:
131051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a + (__b * " + Duplicate(nElts, typestr, "__c") + ");";
131151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
131251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpMlaLane:
131351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a + (__b * " + SplatLane(nElts, "__c", "__d") + ");";
131451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
131551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpMla:
131651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a + (__b * __c);";
131751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
131851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpMlalN:
131951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a + " + MangleName("vmull", typestr, ClassS) + "(__b, " +
132051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      Duplicate(nElts, typestr, "__c") + ");";
132151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
132251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpMlalLane:
132351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a + " + MangleName("vmull", typestr, ClassS) + "(__b, " +
132451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      SplatLane(nElts, "__c", "__d") + ");";
132551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
132651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpMlal:
132751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a + " + MangleName("vmull", typestr, ClassS) + "(__b, __c);";
132851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
132951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpMlsN:
133051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a - (__b * " + Duplicate(nElts, typestr, "__c") + ");";
133151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
133251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpMlsLane:
133351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a - (__b * " + SplatLane(nElts, "__c", "__d") + ");";
133451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
133551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpMls:
133651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a - (__b * __c);";
133751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
133851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpMlslN:
133951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a - " + MangleName("vmull", typestr, ClassS) + "(__b, " +
134051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      Duplicate(nElts, typestr, "__c") + ");";
134151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
134251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpMlslLane:
134351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a - " + MangleName("vmull", typestr, ClassS) + "(__b, " +
134451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      SplatLane(nElts, "__c", "__d") + ");";
134551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
134651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpMlsl:
134751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a - " + MangleName("vmull", typestr, ClassS) + "(__b, __c);";
134851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
134951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpQDMullLane:
135051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += MangleName("vqdmull", typestr, ClassS) + "(__a, " +
135151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      SplatLane(nElts, "__b", "__c") + ");";
135251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
135351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpQDMlalLane:
135451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += MangleName("vqdmlal", typestr, ClassS) + "(__a, __b, " +
135551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      SplatLane(nElts, "__c", "__d") + ");";
135651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
135751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpQDMlslLane:
135851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += MangleName("vqdmlsl", typestr, ClassS) + "(__a, __b, " +
135951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      SplatLane(nElts, "__c", "__d") + ");";
136051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
136151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpQDMulhLane:
136251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += MangleName("vqdmulh", typestr, ClassS) + "(__a, " +
136351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      SplatLane(nElts, "__b", "__c") + ");";
136451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
136551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpQRDMulhLane:
136651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += MangleName("vqrdmulh", typestr, ClassS) + "(__a, " +
136751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      SplatLane(nElts, "__b", "__c") + ");";
136851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
136951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpEq:
137051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "(" + ts + ")(__a == __b);";
137151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
137251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpGe:
137351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "(" + ts + ")(__a >= __b);";
137451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
137551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpLe:
137651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "(" + ts + ")(__a <= __b);";
137751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
137851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpGt:
137951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "(" + ts + ")(__a > __b);";
138051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
138151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpLt:
138251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "(" + ts + ")(__a < __b);";
138351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
138451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpNeg:
138551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += " -__a;";
138651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
138751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpNot:
138851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += " ~__a;";
138951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
139051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpAnd:
139151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a & __b;";
139251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
139351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpOr:
139451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a | __b;";
139551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
139651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpXor:
139751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a ^ __b;";
139851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
139951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpAndNot:
140051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a & ~__b;";
140151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
140251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpOrNot:
140351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a | ~__b;";
140451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
140551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpCast:
140651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "(" + ts + ")__a;";
140751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
140851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpConcat:
140951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "(" + ts + ")__builtin_shufflevector((int64x1_t)__a";
141051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += ", (int64x1_t)__b, 0, 1);";
141151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
141251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpHi:
141351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "(" + ts +
141451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      ")__builtin_shufflevector((int64x2_t)__a, (int64x2_t)__a, 1);";
141551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
141651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpLo:
141751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "(" + ts +
141851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      ")__builtin_shufflevector((int64x2_t)__a, (int64x2_t)__a, 0);";
141951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
142051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpDup:
142151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += Duplicate(nElts, typestr, "__a") + ";";
142251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
142351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpDupLane:
142451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += SplatLane(nElts, "__a", "__b") + ";";
142551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
142651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpSelect:
142751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // ((0 & 1) | (~0 & 2))
142851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "(" + ts + ")";
142951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    ts = TypeString(proto[1], typestr);
143051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "((__a & (" + ts + ")__b) | ";
143151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "(~__a & (" + ts + ")__c));";
143251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
143351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpRev16:
143451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__builtin_shufflevector(__a, __a";
143551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    for (unsigned i = 2; i <= nElts; i += 2)
143651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      for (unsigned j = 0; j != 2; ++j)
143751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        s += ", " + utostr(i - j - 1);
143851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += ");";
143951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
144051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpRev32: {
144151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    unsigned WordElts = nElts >> (1 + (int)quad);
144251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__builtin_shufflevector(__a, __a";
144351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    for (unsigned i = WordElts; i <= nElts; i += WordElts)
144451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      for (unsigned j = 0; j != WordElts; ++j)
144551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        s += ", " + utostr(i - j - 1);
144651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += ");";
144751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
144851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
144951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpRev64: {
145051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    unsigned DblWordElts = nElts >> (int)quad;
145151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__builtin_shufflevector(__a, __a";
145251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    for (unsigned i = DblWordElts; i <= nElts; i += DblWordElts)
145351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      for (unsigned j = 0; j != DblWordElts; ++j)
145451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        s += ", " + utostr(i - j - 1);
145551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += ");";
145651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
145751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
145851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpAbdl: {
145951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::string abd = MangleName("vabd", typestr, ClassS) + "(__a, __b)";
146051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (typestr[0] != 'U') {
146151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      // vabd results are always unsigned and must be zero-extended.
146251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      std::string utype = "U" + typestr.str();
146351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += "(" + TypeString(proto[0], typestr) + ")";
146451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      abd = "(" + TypeString('d', utype) + ")" + abd;
146551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += Extend(utype, abd) + ";";
146651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    } else {
146751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += Extend(typestr, abd) + ";";
146851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
146951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
147051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
147151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpAba:
147251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a + " + MangleName("vabd", typestr, ClassS) + "(__b, __c);";
147351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
147451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case OpAbal: {
147551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__a + ";
147651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::string abd = MangleName("vabd", typestr, ClassS) + "(__b, __c)";
147751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (typestr[0] != 'U') {
147851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      // vabd results are always unsigned and must be zero-extended.
147951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      std::string utype = "U" + typestr.str();
148051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += "(" + TypeString(proto[0], typestr) + ")";
148151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      abd = "(" + TypeString('d', utype) + ")" + abd;
148251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += Extend(utype, abd) + ";";
148351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    } else {
148451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += Extend(typestr, abd) + ";";
148551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
148651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
148751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
148851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  default:
148938859ee4a3c1253d5a45ed3f6b52e77702bfd913Joerg Sonnenberger    PrintFatalError("unknown OpKind!");
149051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
149151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return s;
149251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
149351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
149451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic unsigned GetNeonEnum(const std::string &proto, StringRef typestr) {
149551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  unsigned mod = proto[0];
149651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
149751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (mod == 'v' || mod == 'f')
149851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    mod = proto[1];
149951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
150051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool quad = false;
150151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool poly = false;
150251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool usgn = false;
150351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool scal = false;
150451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool cnst = false;
150551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool pntr = false;
150651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
150751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Base type to get the type string for.
150851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  char type = ClassifyType(typestr, quad, poly, usgn);
150951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
151051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Based on the modifying character, change the type and width if necessary.
151151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  type = ModType(mod, type, quad, poly, usgn, scal, cnst, pntr);
151251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
1513da95f73b59f9af964e33725c515139d34c90c863Bob Wilson  NeonTypeFlags::EltType ET;
151451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  switch (type) {
151551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'c':
1516da95f73b59f9af964e33725c515139d34c90c863Bob Wilson      ET = poly ? NeonTypeFlags::Poly8 : NeonTypeFlags::Int8;
151751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
151851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 's':
1519da95f73b59f9af964e33725c515139d34c90c863Bob Wilson      ET = poly ? NeonTypeFlags::Poly16 : NeonTypeFlags::Int16;
152051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
152151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'i':
1522da95f73b59f9af964e33725c515139d34c90c863Bob Wilson      ET = NeonTypeFlags::Int32;
152351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
152451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'l':
1525da95f73b59f9af964e33725c515139d34c90c863Bob Wilson      ET = NeonTypeFlags::Int64;
152651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
152751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'h':
1528da95f73b59f9af964e33725c515139d34c90c863Bob Wilson      ET = NeonTypeFlags::Float16;
152951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
153051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'f':
1531da95f73b59f9af964e33725c515139d34c90c863Bob Wilson      ET = NeonTypeFlags::Float32;
153251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
153351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    default:
153438859ee4a3c1253d5a45ed3f6b52e77702bfd913Joerg Sonnenberger      PrintFatalError("unhandled type!");
153551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
1536da95f73b59f9af964e33725c515139d34c90c863Bob Wilson  NeonTypeFlags Flags(ET, usgn, quad && proto[1] != 'g');
1537da95f73b59f9af964e33725c515139d34c90c863Bob Wilson  return Flags.getFlags();
153851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
153951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
154051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne// Generate the definition for this intrinsic, e.g. __builtin_neon_cls(a)
154151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic std::string GenBuiltin(const std::string &name, const std::string &proto,
154251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                              StringRef typestr, ClassKind ck) {
154351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string s;
154451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
154551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // If this builtin returns a struct 2, 3, or 4 vectors, pass it as an implicit
154651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // sret-like argument.
154751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool sret = (proto[0] >= '2' && proto[0] <= '4');
154851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
154951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool define = UseMacro(proto);
155051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
155151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Check if the prototype has a scalar operand with the type of the vector
155251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // elements.  If not, bitcasting the args will take care of arg checking.
155351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // The actual signedness etc. will be taken care of with special enums.
155451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (proto.find('s') == std::string::npos)
155551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    ck = ClassB;
155651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
155751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (proto[0] != 'v') {
155851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::string ts = TypeString(proto[0], typestr);
155951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
156051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (define) {
156151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (sret)
156251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        s += ts + " r; ";
156351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      else
156451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        s += "(" + ts + ")";
156551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    } else if (sret) {
156651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += ts + " r; ";
156751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    } else {
156851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += "return (" + ts + ")";
156951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
157051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
157151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
157251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool splat = proto.find('a') != std::string::npos;
157351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
157451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += "__builtin_neon_";
157551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (splat) {
157651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // Call the non-splat builtin: chop off the "_n" suffix from the name.
157751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::string vname(name, 0, name.size()-2);
157851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += MangleName(vname, typestr, ck);
157951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  } else {
158051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += MangleName(name, typestr, ck);
158151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
158251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += "(";
158351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
158451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Pass the address of the return variable as the first argument to sret-like
158551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // builtins.
158651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (sret)
158751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "&r, ";
158851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
158951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  char arg = 'a';
159051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) {
159151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::string args = std::string(&arg, 1);
159251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
159351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // Use the local temporaries instead of the macro arguments.
159451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    args = "__" + args;
159551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
159651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    bool argQuad = false;
159751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    bool argPoly = false;
159851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    bool argUsgn = false;
159951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    bool argScalar = false;
160051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    bool dummy = false;
160151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    char argType = ClassifyType(typestr, argQuad, argPoly, argUsgn);
160251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    argType = ModType(proto[i], argType, argQuad, argPoly, argUsgn, argScalar,
160351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                      dummy, dummy);
160451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
160551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // Handle multiple-vector values specially, emitting each subvector as an
160651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // argument to the __builtin.
160751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (proto[i] >= '2' && proto[i] <= '4') {
160851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      // Check if an explicit cast is needed.
160951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (argType != 'c' || argPoly || argUsgn)
161051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        args = (argQuad ? "(int8x16_t)" : "(int8x8_t)") + args;
161151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
161251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      for (unsigned vi = 0, ve = proto[i] - '0'; vi != ve; ++vi) {
161351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        s += args + ".val[" + utostr(vi) + "]";
161451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        if ((vi + 1) < ve)
161551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne          s += ", ";
161651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      }
161751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if ((i + 1) < e)
161851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        s += ", ";
161951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
162051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      continue;
162151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
162251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
162351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (splat && (i + 1) == e)
162451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      args = Duplicate(GetNumElements(typestr, argQuad), typestr, args);
162551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
162651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // Check if an explicit cast is needed.
162751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if ((splat || !argScalar) &&
162851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        ((ck == ClassB && argType != 'c') || argPoly || argUsgn)) {
162951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      std::string argTypeStr = "c";
163051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (ck != ClassB)
163151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        argTypeStr = argType;
163251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (argQuad)
163351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        argTypeStr = "Q" + argTypeStr;
163451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      args = "(" + TypeString('d', argTypeStr) + ")" + args;
163551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
163651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
163751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += args;
163851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if ((i + 1) < e)
163951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += ", ";
164051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
164151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
164251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Extra constant integer to hold type class enum for this function, e.g. s8
164351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (ck == ClassB)
164451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += ", " + utostr(GetNeonEnum(proto, typestr));
164551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
164651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += ");";
164751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
164851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (proto[0] != 'v' && sret) {
164951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (define)
165051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += " r;";
165151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    else
165251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += " return r;";
165351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
165451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return s;
165551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
165651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
165751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic std::string GenBuiltinDef(const std::string &name,
165851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                                 const std::string &proto,
165951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                                 StringRef typestr, ClassKind ck) {
166051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string s("BUILTIN(__builtin_neon_");
166151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
166251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // If all types are the same size, bitcasting the args will take care
166351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // of arg checking.  The actual signedness etc. will be taken care of with
166451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // special enums.
166551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (proto.find('s') == std::string::npos)
166651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    ck = ClassB;
166751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
166851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += MangleName(name, typestr, ck);
166951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += ", \"";
167051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
167151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 0, e = proto.size(); i != e; ++i)
167251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += BuiltinTypeString(proto[i], typestr, ck, i == 0);
167351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
167451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Extra constant integer to hold type class enum for this function, e.g. s8
167551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (ck == ClassB)
167651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "i";
167751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
167851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += "\", \"n\")";
167951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return s;
168051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
168151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
168251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic std::string GenIntrinsic(const std::string &name,
168351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                                const std::string &proto,
168451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                                StringRef outTypeStr, StringRef inTypeStr,
168551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                                OpKind kind, ClassKind classKind) {
168651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  assert(!proto.empty() && "");
1687667381b21f75d6964bbdf6af143308a02b9198a8Jim Grosbach  bool define = UseMacro(proto) && kind != OpUnavailable;
168851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string s;
168951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
169051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // static always inline + return type
169151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (define)
169251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "#define ";
169351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  else
169451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "__ai " + TypeString(proto[0], outTypeStr) + " ";
169551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
169651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Function name with type suffix
169751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string mangledName = MangleName(name, outTypeStr, ClassS);
169851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (outTypeStr != inTypeStr) {
169951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // If the input type is different (e.g., for vreinterpret), append a suffix
170051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // for the input type.  String off a "Q" (quad) prefix so that MangleName
170151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // does not insert another "q" in the name.
170251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    unsigned typeStrOff = (inTypeStr[0] == 'Q' ? 1 : 0);
170351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    StringRef inTypeNoQuad = inTypeStr.substr(typeStrOff);
170451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    mangledName = MangleName(mangledName, inTypeNoQuad, ClassS);
170551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
170651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += mangledName;
170751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
170851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Function arguments
170951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += GenArgs(proto, inTypeStr);
171051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
171151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Definition.
171251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (define) {
171351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += " __extension__ ({ \\\n  ";
171451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += GenMacroLocals(proto, inTypeStr);
1715667381b21f75d6964bbdf6af143308a02b9198a8Jim Grosbach  } else if (kind == OpUnavailable) {
1716667381b21f75d6964bbdf6af143308a02b9198a8Jim Grosbach    s += " __attribute__((unavailable));\n";
1717667381b21f75d6964bbdf6af143308a02b9198a8Jim Grosbach    return s;
1718667381b21f75d6964bbdf6af143308a02b9198a8Jim Grosbach  } else
171966981c7ca1fcef529d7d5e5c53b07020ff23d8e3Jim Grosbach    s += " {\n  ";
172051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
172151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (kind != OpNone)
172251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += GenOpString(kind, proto, outTypeStr);
172351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  else
172451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += GenBuiltin(name, proto, outTypeStr, classKind);
172551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (define)
172651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += " })";
172751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  else
172851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += " }";
172951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += "\n";
173051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return s;
173151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
173251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
173351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// run - Read the records in arm_neon.td and output arm_neon.h.  arm_neon.h
173451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// is comprised of type definitions and function declarations.
173551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournevoid NeonEmitter::run(raw_ostream &OS) {
173651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS <<
173751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    "/*===---- arm_neon.h - ARM Neon intrinsics ------------------------------"
173851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    "---===\n"
173951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " *\n"
174051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " * Permission is hereby granted, free of charge, to any person obtaining "
174151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    "a copy\n"
174251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " * of this software and associated documentation files (the \"Software\"),"
174351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " to deal\n"
174451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " * in the Software without restriction, including without limitation the "
174551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    "rights\n"
174651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " * to use, copy, modify, merge, publish, distribute, sublicense, "
174751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    "and/or sell\n"
174851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " * copies of the Software, and to permit persons to whom the Software is\n"
174951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " * furnished to do so, subject to the following conditions:\n"
175051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " *\n"
175151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " * The above copyright notice and this permission notice shall be "
175251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    "included in\n"
175351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " * all copies or substantial portions of the Software.\n"
175451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " *\n"
175551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, "
175651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    "EXPRESS OR\n"
175751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF "
175851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    "MERCHANTABILITY,\n"
175951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT "
176051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    "SHALL THE\n"
176151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR "
176251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    "OTHER\n"
176351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, "
176451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    "ARISING FROM,\n"
176551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER "
176651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    "DEALINGS IN\n"
176751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " * THE SOFTWARE.\n"
176851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " *\n"
176951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " *===--------------------------------------------------------------------"
177051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    "---===\n"
177151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    " */\n\n";
177251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
177351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#ifndef __ARM_NEON_H\n";
177451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#define __ARM_NEON_H\n\n";
177551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
177651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#ifndef __ARM_NEON__\n";
177751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#error \"NEON support not enabled\"\n";
177851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#endif\n\n";
177951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
178051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#include <stdint.h>\n\n";
178151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
178251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Emit NEON-specific scalar typedefs.
178351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "typedef float float32_t;\n";
178451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "typedef int8_t poly8_t;\n";
178551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "typedef int16_t poly16_t;\n";
178651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "typedef uint16_t float16_t;\n";
178751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
178851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Emit Neon vector typedefs.
178951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string TypedefTypes("cQcsQsiQilQlUcQUcUsQUsUiQUiUlQUlhQhfQfPcQPcPsQPs");
179051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  SmallVector<StringRef, 24> TDTypeVec;
179151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  ParseTypes(0, TypedefTypes, TDTypeVec);
179251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
179351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Emit vector typedefs.
179451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 0, e = TDTypeVec.size(); i != e; ++i) {
179551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    bool dummy, quad = false, poly = false;
179651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    (void) ClassifyType(TDTypeVec[i], quad, poly, dummy);
179751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (poly)
179851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      OS << "typedef __attribute__((neon_polyvector_type(";
179951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    else
180051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      OS << "typedef __attribute__((neon_vector_type(";
180151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
180251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    unsigned nElts = GetNumElements(TDTypeVec[i], quad);
180351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    OS << utostr(nElts) << "))) ";
180451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (nElts < 10)
180551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      OS << " ";
180651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
180751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    OS << TypeString('s', TDTypeVec[i]);
180851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    OS << " " << TypeString('d', TDTypeVec[i]) << ";\n";
180951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
181051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "\n";
181151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
181251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Emit struct typedefs.
181351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned vi = 2; vi != 5; ++vi) {
181451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    for (unsigned i = 0, e = TDTypeVec.size(); i != e; ++i) {
181551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      std::string ts = TypeString('d', TDTypeVec[i]);
181651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      std::string vs = TypeString('0' + vi, TDTypeVec[i]);
181751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      OS << "typedef struct " << vs << " {\n";
181851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      OS << "  " << ts << " val";
181951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      OS << "[" << utostr(vi) << "]";
182051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      OS << ";\n} ";
182151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      OS << vs << ";\n\n";
182251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
182351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
182451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
18251e8058f8d90fab1b9011adf62caa52e19e61382cBob Wilson  OS<<"#define __ai static inline __attribute__((__always_inline__, __nodebug__))\n\n";
182651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
182751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::vector<Record*> RV = Records.getAllDerivedDefinitions("Inst");
182851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
182951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Emit vmovl, vmull and vabd intrinsics first so they can be used by other
183051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // intrinsics.  (Some of the saturating multiply instructions are also
183151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // used to implement the corresponding "_lane" variants, but tablegen
183251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // sorts the records into alphabetical order so that the "_lane" variants
183351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // come after the intrinsics they use.)
183451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  emitIntrinsic(OS, Records.getDef("VMOVL"));
183551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  emitIntrinsic(OS, Records.getDef("VMULL"));
183651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  emitIntrinsic(OS, Records.getDef("VABD"));
183751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
183851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 0, e = RV.size(); i != e; ++i) {
183951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    Record *R = RV[i];
184051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (R->getName() != "VMOVL" &&
184151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        R->getName() != "VMULL" &&
184251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        R->getName() != "VABD")
184351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      emitIntrinsic(OS, R);
184451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
184551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
184651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#undef __ai\n\n";
184751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#endif /* __ARM_NEON_H */\n";
184851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
184951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
185051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// emitIntrinsic - Write out the arm_neon.h header file definitions for the
185151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// intrinsics specified by record R.
185251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournevoid NeonEmitter::emitIntrinsic(raw_ostream &OS, Record *R) {
185351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string name = R->getValueAsString("Name");
185451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string Proto = R->getValueAsString("Prototype");
185551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string Types = R->getValueAsString("Types");
185651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
185751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  SmallVector<StringRef, 16> TypeVec;
185851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  ParseTypes(R, Types, TypeVec);
185951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
186051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OpKind kind = OpMap[R->getValueAsDef("Operand")->getName()];
186151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
186251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  ClassKind classKind = ClassNone;
186351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (R->getSuperClasses().size() >= 2)
186451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    classKind = ClassMap[R->getSuperClasses()[1]];
186551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (classKind == ClassNone && kind == OpNone)
186638859ee4a3c1253d5a45ed3f6b52e77702bfd913Joerg Sonnenberger    PrintFatalError(R->getLoc(), "Builtin has no class kind");
186751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
186851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) {
186951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (kind == OpReinterpret) {
187051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      bool outQuad = false;
187151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      bool dummy = false;
187251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      (void)ClassifyType(TypeVec[ti], outQuad, dummy, dummy);
187351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      for (unsigned srcti = 0, srcte = TypeVec.size();
187451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne           srcti != srcte; ++srcti) {
187551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        bool inQuad = false;
187651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        (void)ClassifyType(TypeVec[srcti], inQuad, dummy, dummy);
187751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        if (srcti == ti || inQuad != outQuad)
187851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne          continue;
187951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        OS << GenIntrinsic(name, Proto, TypeVec[ti], TypeVec[srcti],
188051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                           OpCast, ClassS);
188151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      }
188251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    } else {
188351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      OS << GenIntrinsic(name, Proto, TypeVec[ti], TypeVec[ti],
188451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                         kind, classKind);
188551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
188651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
188751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "\n";
188851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
188951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
189051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic unsigned RangeFromType(const char mod, StringRef typestr) {
189151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // base type to get the type string for.
189251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool quad = false, dummy = false;
189351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  char type = ClassifyType(typestr, quad, dummy, dummy);
189451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  type = ModType(mod, type, quad, dummy, dummy, dummy, dummy, dummy);
189551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
189651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  switch (type) {
189751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'c':
189851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      return (8 << (int)quad) - 1;
189951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'h':
190051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 's':
190151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      return (4 << (int)quad) - 1;
190251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'f':
190351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'i':
190451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      return (2 << (int)quad) - 1;
190551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'l':
190651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      return (1 << (int)quad) - 1;
190751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    default:
190838859ee4a3c1253d5a45ed3f6b52e77702bfd913Joerg Sonnenberger      PrintFatalError("unhandled type!");
190951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
191051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
191151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
191251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// runHeader - Emit a file with sections defining:
191351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// 1. the NEON section of BuiltinsARM.def.
191451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// 2. the SemaChecking code for the type overload checking.
1915667381b21f75d6964bbdf6af143308a02b9198a8Jim Grosbach/// 3. the SemaChecking code for validation of intrinsic immediate arguments.
191651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournevoid NeonEmitter::runHeader(raw_ostream &OS) {
191751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::vector<Record*> RV = Records.getAllDerivedDefinitions("Inst");
191851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
191951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  StringMap<OpKind> EmittedMap;
192051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
192151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Generate BuiltinsARM.def for NEON
192251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#ifdef GET_NEON_BUILTINS\n";
192351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 0, e = RV.size(); i != e; ++i) {
192451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    Record *R = RV[i];
192551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    OpKind k = OpMap[R->getValueAsDef("Operand")->getName()];
192651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (k != OpNone)
192751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      continue;
192851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
192951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::string Proto = R->getValueAsString("Prototype");
193051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
193151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // Functions with 'a' (the splat code) in the type prototype should not get
193251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // their own builtin as they use the non-splat variant.
193351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (Proto.find('a') != std::string::npos)
193451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      continue;
193551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
193651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::string Types = R->getValueAsString("Types");
193751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    SmallVector<StringRef, 16> TypeVec;
193851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    ParseTypes(R, Types, TypeVec);
193951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
194051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (R->getSuperClasses().size() < 2)
194138859ee4a3c1253d5a45ed3f6b52e77702bfd913Joerg Sonnenberger      PrintFatalError(R->getLoc(), "Builtin has no class kind");
194251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
194351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::string name = R->getValueAsString("Name");
194451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    ClassKind ck = ClassMap[R->getSuperClasses()[1]];
194551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
194651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) {
194751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      // Generate the BuiltinsARM.def declaration for this builtin, ensuring
194851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      // that each unique BUILTIN() macro appears only once in the output
194951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      // stream.
195051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      std::string bd = GenBuiltinDef(name, Proto, TypeVec[ti], ck);
195151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (EmittedMap.count(bd))
195251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        continue;
195351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
195451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      EmittedMap[bd] = OpNone;
195551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      OS << bd << "\n";
195651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
195751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
195851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#endif\n\n";
195951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
196051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Generate the overloaded type checking code for SemaChecking.cpp
196151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#ifdef GET_NEON_OVERLOAD_CHECK\n";
196251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 0, e = RV.size(); i != e; ++i) {
196351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    Record *R = RV[i];
196451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    OpKind k = OpMap[R->getValueAsDef("Operand")->getName()];
196551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (k != OpNone)
196651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      continue;
196751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
196851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::string Proto = R->getValueAsString("Prototype");
196951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::string Types = R->getValueAsString("Types");
197051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::string name = R->getValueAsString("Name");
197151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
197251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // Functions with 'a' (the splat code) in the type prototype should not get
197351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // their own builtin as they use the non-splat variant.
197451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (Proto.find('a') != std::string::npos)
197551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      continue;
197651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
197751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // Functions which have a scalar argument cannot be overloaded, no need to
197851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // check them if we are emitting the type checking code.
197951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (Proto.find('s') != std::string::npos)
198051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      continue;
198151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
198251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    SmallVector<StringRef, 16> TypeVec;
198351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    ParseTypes(R, Types, TypeVec);
198451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
198551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (R->getSuperClasses().size() < 2)
198638859ee4a3c1253d5a45ed3f6b52e77702bfd913Joerg Sonnenberger      PrintFatalError(R->getLoc(), "Builtin has no class kind");
198751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
198851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    int si = -1, qi = -1;
1989f8ee6bc1ef0eec8e22b413dfc2baa3cfa4f19f91Richard Smith    uint64_t mask = 0, qmask = 0;
199051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) {
199151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      // Generate the switch case(s) for this builtin for the type validation.
199251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      bool quad = false, poly = false, usgn = false;
199351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      (void) ClassifyType(TypeVec[ti], quad, poly, usgn);
199451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
199551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (quad) {
199651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        qi = ti;
1997f8ee6bc1ef0eec8e22b413dfc2baa3cfa4f19f91Richard Smith        qmask |= 1ULL << GetNeonEnum(Proto, TypeVec[ti]);
199851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      } else {
199951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        si = ti;
2000f8ee6bc1ef0eec8e22b413dfc2baa3cfa4f19f91Richard Smith        mask |= 1ULL << GetNeonEnum(Proto, TypeVec[ti]);
200151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      }
200251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
20034648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson
20044648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson    // Check if the builtin function has a pointer or const pointer argument.
20054648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson    int PtrArgNum = -1;
20064648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson    bool HasConstPtr = false;
20074648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson    for (unsigned arg = 1, arge = Proto.size(); arg != arge; ++arg) {
20084648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson      char ArgType = Proto[arg];
20094648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson      if (ArgType == 'c') {
20104648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson        HasConstPtr = true;
20114648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson        PtrArgNum = arg - 1;
20124648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson        break;
20134648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson      }
20144648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson      if (ArgType == 'p') {
20154648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson        PtrArgNum = arg - 1;
20164648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson        break;
20174648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson      }
20184648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson    }
20194648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson    // For sret builtins, adjust the pointer argument index.
20204648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson    if (PtrArgNum >= 0 && (Proto[0] >= '2' && Proto[0] <= '4'))
20214648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson      PtrArgNum += 1;
20224648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson
20239082cddf28e03c2f718e92457e2d9c7390056b2dBob Wilson    // Omit type checking for the pointer arguments of vld1_lane, vld1_dup,
20249082cddf28e03c2f718e92457e2d9c7390056b2dBob Wilson    // and vst1_lane intrinsics.  Using a pointer to the vector element
20259082cddf28e03c2f718e92457e2d9c7390056b2dBob Wilson    // type with one of those operations causes codegen to select an aligned
20269082cddf28e03c2f718e92457e2d9c7390056b2dBob Wilson    // load/store instruction.  If you want an unaligned operation,
20279082cddf28e03c2f718e92457e2d9c7390056b2dBob Wilson    // the pointer argument needs to have less alignment than element type,
20289082cddf28e03c2f718e92457e2d9c7390056b2dBob Wilson    // so just accept any pointer type.
20299082cddf28e03c2f718e92457e2d9c7390056b2dBob Wilson    if (name == "vld1_lane" || name == "vld1_dup" || name == "vst1_lane") {
20309082cddf28e03c2f718e92457e2d9c7390056b2dBob Wilson      PtrArgNum = -1;
20319082cddf28e03c2f718e92457e2d9c7390056b2dBob Wilson      HasConstPtr = false;
20329082cddf28e03c2f718e92457e2d9c7390056b2dBob Wilson    }
20339082cddf28e03c2f718e92457e2d9c7390056b2dBob Wilson
20346f9f03ef370ad48ece0c5d10edda28f39ccadb5dBob Wilson    if (mask) {
203551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      OS << "case ARM::BI__builtin_neon_"
203651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne         << MangleName(name, TypeVec[si], ClassB)
2037b27660a733d420967371bbf578a75db21116895cRichard Smith         << ": mask = " << "0x" << utohexstr(mask) << "ULL";
20384648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson      if (PtrArgNum >= 0)
20394648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson        OS << "; PtrArgNum = " << PtrArgNum;
20406f9f03ef370ad48ece0c5d10edda28f39ccadb5dBob Wilson      if (HasConstPtr)
20416f9f03ef370ad48ece0c5d10edda28f39ccadb5dBob Wilson        OS << "; HasConstPtr = true";
20426f9f03ef370ad48ece0c5d10edda28f39ccadb5dBob Wilson      OS << "; break;\n";
20436f9f03ef370ad48ece0c5d10edda28f39ccadb5dBob Wilson    }
20446f9f03ef370ad48ece0c5d10edda28f39ccadb5dBob Wilson    if (qmask) {
204551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      OS << "case ARM::BI__builtin_neon_"
204651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne         << MangleName(name, TypeVec[qi], ClassB)
2047b27660a733d420967371bbf578a75db21116895cRichard Smith         << ": mask = " << "0x" << utohexstr(qmask) << "ULL";
20484648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson      if (PtrArgNum >= 0)
20494648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson        OS << "; PtrArgNum = " << PtrArgNum;
20506f9f03ef370ad48ece0c5d10edda28f39ccadb5dBob Wilson      if (HasConstPtr)
20516f9f03ef370ad48ece0c5d10edda28f39ccadb5dBob Wilson        OS << "; HasConstPtr = true";
20526f9f03ef370ad48ece0c5d10edda28f39ccadb5dBob Wilson      OS << "; break;\n";
20536f9f03ef370ad48ece0c5d10edda28f39ccadb5dBob Wilson    }
205451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
205551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#endif\n\n";
205651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
205751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Generate the intrinsic range checking code for shift/lane immediates.
205851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#ifdef GET_NEON_IMMEDIATE_CHECK\n";
205951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 0, e = RV.size(); i != e; ++i) {
206051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    Record *R = RV[i];
206151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
206251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    OpKind k = OpMap[R->getValueAsDef("Operand")->getName()];
206351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (k != OpNone)
206451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      continue;
206551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
206651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::string name = R->getValueAsString("Name");
206751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::string Proto = R->getValueAsString("Prototype");
206851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::string Types = R->getValueAsString("Types");
206951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
207051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // Functions with 'a' (the splat code) in the type prototype should not get
207151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // their own builtin as they use the non-splat variant.
207251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (Proto.find('a') != std::string::npos)
207351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      continue;
207451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
207551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // Functions which do not have an immediate do not need to have range
207651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // checking code emitted.
207751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    size_t immPos = Proto.find('i');
207851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (immPos == std::string::npos)
207951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      continue;
208051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
208151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    SmallVector<StringRef, 16> TypeVec;
208251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    ParseTypes(R, Types, TypeVec);
208351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
208451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (R->getSuperClasses().size() < 2)
208538859ee4a3c1253d5a45ed3f6b52e77702bfd913Joerg Sonnenberger      PrintFatalError(R->getLoc(), "Builtin has no class kind");
208651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
208751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    ClassKind ck = ClassMap[R->getSuperClasses()[1]];
208851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
208951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) {
209051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      std::string namestr, shiftstr, rangestr;
209151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
209251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (R->getValueAsBit("isVCVT_N")) {
209351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        // VCVT between floating- and fixed-point values takes an immediate
209451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        // in the range 1 to 32.
209551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        ck = ClassB;
209651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        rangestr = "l = 1; u = 31"; // upper bound = l + u
209751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      } else if (Proto.find('s') == std::string::npos) {
209851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        // Builtins which are overloaded by type will need to have their upper
209951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        // bound computed at Sema time based on the type constant.
210051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        ck = ClassB;
210151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        if (R->getValueAsBit("isShift")) {
210251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne          shiftstr = ", true";
210351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
210451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne          // Right shifts have an 'r' in the name, left shifts do not.
210551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne          if (name.find('r') != std::string::npos)
210651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne            rangestr = "l = 1; ";
210751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        }
210851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        rangestr += "u = RFT(TV" + shiftstr + ")";
210951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      } else {
211051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        // The immediate generally refers to a lane in the preceding argument.
211151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        assert(immPos > 0 && "unexpected immediate operand");
211251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        rangestr = "u = " + utostr(RangeFromType(Proto[immPos-1], TypeVec[ti]));
211351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      }
211451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      // Make sure cases appear only once by uniquing them in a string map.
211551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      namestr = MangleName(name, TypeVec[ti], ck);
211651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (EmittedMap.count(namestr))
211751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        continue;
211851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      EmittedMap[namestr] = OpNone;
211951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
212051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      // Calculate the index of the immediate that should be range checked.
212151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      unsigned immidx = 0;
212251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
212351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      // Builtins that return a struct of multiple vectors have an extra
212451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      // leading arg for the struct return.
212551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (Proto[0] >= '2' && Proto[0] <= '4')
212651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        ++immidx;
212751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
212851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      // Add one to the index for each argument until we reach the immediate
212951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      // to be checked.  Structs of vectors are passed as multiple arguments.
213051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      for (unsigned ii = 1, ie = Proto.size(); ii != ie; ++ii) {
213151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        switch (Proto[ii]) {
213251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne          default:  immidx += 1; break;
213351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne          case '2': immidx += 2; break;
213451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne          case '3': immidx += 3; break;
213551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne          case '4': immidx += 4; break;
213651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne          case 'i': ie = ii + 1; break;
213751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        }
213851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      }
213951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      OS << "case ARM::BI__builtin_neon_" << MangleName(name, TypeVec[ti], ck)
214051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne         << ": i = " << immidx << "; " << rangestr << "; break;\n";
214151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
214251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
214351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#endif\n\n";
214451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
214551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
214651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// GenTest - Write out a test for the intrinsic specified by the name and
214751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// type strings, including the embedded patterns for FileCheck to match.
214851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic std::string GenTest(const std::string &name,
214951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                           const std::string &proto,
215051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                           StringRef outTypeStr, StringRef inTypeStr,
21517200bd673af6b58d7d2f0c5d048050abe5b8858cMichael Gottesman                           bool isShift, bool isHiddenLOp,
21527200bd673af6b58d7d2f0c5d048050abe5b8858cMichael Gottesman                           ClassKind ck, const std::string &InstName) {
215351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  assert(!proto.empty() && "");
215451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string s;
215551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
215651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Function name with type suffix
215751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string mangledName = MangleName(name, outTypeStr, ClassS);
215851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (outTypeStr != inTypeStr) {
215951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // If the input type is different (e.g., for vreinterpret), append a suffix
216051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // for the input type.  String off a "Q" (quad) prefix so that MangleName
216151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // does not insert another "q" in the name.
216251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    unsigned typeStrOff = (inTypeStr[0] == 'Q' ? 1 : 0);
216351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    StringRef inTypeNoQuad = inTypeStr.substr(typeStrOff);
216451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    mangledName = MangleName(mangledName, inTypeNoQuad, ClassS);
216551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
216651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
2167c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  std::vector<std::string> FileCheckPatterns;
2168c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  GenerateChecksForIntrinsic(name, proto, outTypeStr, inTypeStr, ck, InstName,
2169c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                             isHiddenLOp, FileCheckPatterns);
2170c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
217151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Emit the FileCheck patterns.
217251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += "// CHECK: test_" + mangledName + "\n";
2173c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // If for any reason we do not want to emit a check, mangledInst
2174c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  // will be the empty string.
2175c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  if (FileCheckPatterns.size()) {
2176c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    for (std::vector<std::string>::const_iterator i = FileCheckPatterns.begin(),
2177c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman                                                  e = FileCheckPatterns.end();
2178c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman         i != e;
2179c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman         ++i) {
2180c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman      s += "// CHECK: " + *i + "\n";
2181c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    }
2182c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  }
218351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
218451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Emit the start of the test function.
218551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += TypeString(proto[0], outTypeStr) + " test_" + mangledName + "(";
218651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  char arg = 'a';
218751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string comma;
218851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) {
218951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // Do not create arguments for values that must be immediate constants.
219051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (proto[i] == 'i')
219151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      continue;
219251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += comma + TypeString(proto[i], inTypeStr) + " ";
219351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s.push_back(arg);
219451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    comma = ", ";
219551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
2196b4a542549c2e0c9eeb6ece3f95767ccdd141fa3eJim Grosbach  s += ") {\n  ";
219751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
219851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (proto[0] != 'v')
219951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    s += "return ";
220051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += mangledName + "(";
220151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  arg = 'a';
220251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) {
220351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (proto[i] == 'i') {
220451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      // For immediate operands, test the maximum value.
220551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (isShift)
220651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        s += "1"; // FIXME
220751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      else
220851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        // The immediate generally refers to a lane in the preceding argument.
220951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        s += utostr(RangeFromType(proto[i-1], inTypeStr));
221051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    } else {
221151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s.push_back(arg);
221251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
221351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if ((i + 1) < e)
221451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      s += ", ";
221551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
221651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  s += ");\n}\n\n";
221751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return s;
221851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
221951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
222051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// runTests - Write out a complete set of tests for all of the Neon
222151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// intrinsics.
222251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournevoid NeonEmitter::runTests(raw_ostream &OS) {
222351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS <<
222451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    "// RUN: %clang_cc1 -triple thumbv7-apple-darwin \\\n"
2225fb9929ee2a0ed47d473a58b0ba5c7a7a7a095b73Michael Gottesman    "// RUN:  -target-cpu swift -ffreestanding -Os -S -o - %s\\\n"
2226fb9929ee2a0ed47d473a58b0ba5c7a7a7a095b73Michael Gottesman    "// RUN:  | FileCheck %s\n"
222751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    "\n"
222851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    "#include <arm_neon.h>\n"
222951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    "\n";
223051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
223151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::vector<Record*> RV = Records.getAllDerivedDefinitions("Inst");
223251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 0, e = RV.size(); i != e; ++i) {
223351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    Record *R = RV[i];
223451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::string name = R->getValueAsString("Name");
223551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::string Proto = R->getValueAsString("Prototype");
223651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::string Types = R->getValueAsString("Types");
223751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    bool isShift = R->getValueAsBit("isShift");
22387200bd673af6b58d7d2f0c5d048050abe5b8858cMichael Gottesman    std::string InstName = R->getValueAsString("InstName");
22397200bd673af6b58d7d2f0c5d048050abe5b8858cMichael Gottesman    bool isHiddenLOp = R->getValueAsBit("isHiddenLInst");
224051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
224151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    SmallVector<StringRef, 16> TypeVec;
224251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    ParseTypes(R, Types, TypeVec);
224351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
22447200bd673af6b58d7d2f0c5d048050abe5b8858cMichael Gottesman    ClassKind ck = ClassMap[R->getSuperClasses()[1]];
224551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    OpKind kind = OpMap[R->getValueAsDef("Operand")->getName()];
2246667381b21f75d6964bbdf6af143308a02b9198a8Jim Grosbach    if (kind == OpUnavailable)
2247667381b21f75d6964bbdf6af143308a02b9198a8Jim Grosbach      continue;
224851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) {
224951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (kind == OpReinterpret) {
225051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        bool outQuad = false;
225151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        bool dummy = false;
225251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        (void)ClassifyType(TypeVec[ti], outQuad, dummy, dummy);
225351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        for (unsigned srcti = 0, srcte = TypeVec.size();
225451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne             srcti != srcte; ++srcti) {
225551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne          bool inQuad = false;
225651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne          (void)ClassifyType(TypeVec[srcti], inQuad, dummy, dummy);
225751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne          if (srcti == ti || inQuad != outQuad)
225851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne            continue;
22597200bd673af6b58d7d2f0c5d048050abe5b8858cMichael Gottesman          OS << GenTest(name, Proto, TypeVec[ti], TypeVec[srcti],
22607200bd673af6b58d7d2f0c5d048050abe5b8858cMichael Gottesman                        isShift, isHiddenLOp, ck, InstName);
226151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        }
226251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      } else {
22637200bd673af6b58d7d2f0c5d048050abe5b8858cMichael Gottesman        OS << GenTest(name, Proto, TypeVec[ti], TypeVec[ti],
22647200bd673af6b58d7d2f0c5d048050abe5b8858cMichael Gottesman                      isShift, isHiddenLOp, ck, InstName);
226551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      }
226651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
226751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    OS << "\n";
226851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
226951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
227051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
22713cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesennamespace clang {
22723cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesenvoid EmitNeon(RecordKeeper &Records, raw_ostream &OS) {
22733cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  NeonEmitter(Records).run(OS);
22743cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen}
22753cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesenvoid EmitNeonSema(RecordKeeper &Records, raw_ostream &OS) {
22763cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  NeonEmitter(Records).runHeader(OS);
22773cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen}
22783cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesenvoid EmitNeonTest(RecordKeeper &Records, raw_ostream &OS) {
22793cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  NeonEmitter(Records).runTests(OS);
22803cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen}
22813cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen} // End namespace clang
2282