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
21c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines// called, rather than the normal run() entry point.
22c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines//
23c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines// See also the documentation in include/clang/Basic/arm_neon.td.
2451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne//
2551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne//===----------------------------------------------------------------------===//
2651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
273cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen#include "llvm/ADT/DenseMap.h"
28b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar#include "llvm/ADT/STLExtras.h"
2951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne#include "llvm/ADT/SmallString.h"
3051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne#include "llvm/ADT/SmallVector.h"
3151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne#include "llvm/ADT/StringExtras.h"
323cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen#include "llvm/ADT/StringMap.h"
337530c034c0c71a64c5a9173206d9742ae847af8bDavid Blaikie#include "llvm/Support/ErrorHandling.h"
343cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen#include "llvm/TableGen/Error.h"
353cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen#include "llvm/TableGen/Record.h"
36c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines#include "llvm/TableGen/SetTheory.h"
373cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen#include "llvm/TableGen/TableGenBackend.h"
380e2c34f92f00628d48968dfea096d36381f494cbStephen Hines#include <algorithm>
3987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar#include <deque>
400e2c34f92f00628d48968dfea096d36381f494cbStephen Hines#include <map>
41c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines#include <sstream>
420e2c34f92f00628d48968dfea096d36381f494cbStephen Hines#include <string>
434967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar#include <utility>
44c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines#include <vector>
4551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourneusing namespace llvm;
4651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
47c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesnamespace {
48c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
49c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines// While globals are generally bad, this one allows us to perform assertions
50c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines// liberally and somehow still trace them back to the def they indirectly
51c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines// came from.
52c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesstatic Record *CurrentRecord = nullptr;
53c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesstatic void assert_with_loc(bool Assertion, const std::string &Str) {
54c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  if (!Assertion) {
55c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    if (CurrentRecord)
56c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      PrintFatalError(CurrentRecord->getLoc(), Str);
57c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    else
58c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      PrintFatalError(Str);
59c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  }
60c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines}
613cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen
623cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesenenum ClassKind {
633cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  ClassNone,
64c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  ClassI,     // generic integer instruction, e.g., "i8" suffix
65c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  ClassS,     // signed/unsigned/poly, e.g., "s8", "u8" or "p8" suffix
66c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  ClassW,     // width-specific instruction, e.g., "8" suffix
67c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  ClassB,     // bitcast arguments with enum argument to specify type
68c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  ClassL,     // Logical instructions which are op instructions
69c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines              // but we need to not emit any suffix for in our
70c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines              // tests.
71c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  ClassNoTest // Instructions which we do not test since they are
72c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines              // not TRUE instructions.
733cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen};
743cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen
753cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen/// NeonTypeFlags - Flags to identify the types for overloaded Neon
763cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen/// builtins.  These must be kept in sync with the flags in
773cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen/// include/clang/Basic/TargetBuiltins.h.
78c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesnamespace NeonTypeFlags {
79c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesenum { EltTypeMask = 0xf, UnsignedFlag = 0x10, QuadFlag = 0x20 };
80c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
81c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesenum EltType {
82c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  Int8,
83c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  Int16,
84c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  Int32,
85c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  Int64,
86c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  Poly8,
87c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  Poly16,
88c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  Poly64,
89c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  Poly128,
90c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  Float16,
91c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  Float32,
92c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  Float64
93c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines};
94c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines}
95c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
96c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesclass Intrinsic;
97c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesclass NeonEmitter;
98c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesclass Type;
99c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesclass Variable;
1003cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen
101c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines//===----------------------------------------------------------------------===//
102c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines// TypeSpec
103c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines//===----------------------------------------------------------------------===//
104c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
105c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines/// A TypeSpec is just a simple wrapper around a string, but gets its own type
106c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines/// for strong typing purposes.
107c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines///
108c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines/// A TypeSpec can be used to create a type.
109c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesclass TypeSpec : public std::string {
1103cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesenpublic:
111c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  static std::vector<TypeSpec> fromTypeSpecs(StringRef Str) {
112c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    std::vector<TypeSpec> Ret;
113c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    TypeSpec Acc;
114c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    for (char I : Str.str()) {
115c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      if (islower(I)) {
116c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        Acc.push_back(I);
117c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        Ret.push_back(TypeSpec(Acc));
118c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        Acc.clear();
119c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      } else {
120c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        Acc.push_back(I);
121c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      }
122c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    }
123c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    return Ret;
124c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  }
125c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines};
126c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
127c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines//===----------------------------------------------------------------------===//
128c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines// Type
129c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines//===----------------------------------------------------------------------===//
130c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
131c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines/// A Type. Not much more to say here.
132c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesclass Type {
133c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesprivate:
134c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  TypeSpec TS;
135c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
136b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar  bool Float, Signed, Immediate, Void, Poly, Constant, Pointer;
137c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  // ScalarForMangling and NoManglingQ are really not suited to live here as
138c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  // they are not related to the type. But they live in the TypeSpec (not the
139c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  // prototype), so this is really the only place to store them.
140c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  bool ScalarForMangling, NoManglingQ;
141c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  unsigned Bitwidth, ElementBitwidth, NumVectors;
142c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
143c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinespublic:
144c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  Type()
145b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar      : Float(false), Signed(false), Immediate(false), Void(true), Poly(false),
146b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar        Constant(false), Pointer(false), ScalarForMangling(false),
147b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar        NoManglingQ(false), Bitwidth(0), ElementBitwidth(0), NumVectors(0) {}
148c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
149c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  Type(TypeSpec TS, char CharMod)
1504967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar      : TS(std::move(TS)), Float(false), Signed(false), Immediate(false),
1514967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar        Void(false), Poly(false), Constant(false), Pointer(false),
1524967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar        ScalarForMangling(false), NoManglingQ(false), Bitwidth(0),
1534967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar        ElementBitwidth(0), NumVectors(0) {
154c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    applyModifier(CharMod);
155c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  }
156c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
157c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  /// Returns a type representing "void".
158c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  static Type getVoid() { return Type(); }
1593cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen
160c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  bool operator==(const Type &Other) const { return str() == Other.str(); }
161c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  bool operator!=(const Type &Other) const { return !operator==(Other); }
162c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
163c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  //
164c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  // Query functions
165c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  //
166c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  bool isScalarForMangling() const { return ScalarForMangling; }
167c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  bool noManglingQ() const { return NoManglingQ; }
168c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
169c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  bool isPointer() const { return Pointer; }
170c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  bool isFloating() const { return Float; }
171c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  bool isInteger() const { return !Float && !Poly; }
172c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  bool isSigned() const { return Signed; }
173b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar  bool isImmediate() const { return Immediate; }
174c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  bool isScalar() const { return NumVectors == 0; }
175c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  bool isVector() const { return NumVectors > 0; }
176c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  bool isFloat() const { return Float && ElementBitwidth == 32; }
177c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  bool isDouble() const { return Float && ElementBitwidth == 64; }
178c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  bool isHalf() const { return Float && ElementBitwidth == 16; }
179c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  bool isPoly() const { return Poly; }
180c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  bool isChar() const { return ElementBitwidth == 8; }
181c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  bool isShort() const { return !Float && ElementBitwidth == 16; }
182c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  bool isInt() const { return !Float && ElementBitwidth == 32; }
183c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  bool isLong() const { return !Float && ElementBitwidth == 64; }
184c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  bool isVoid() const { return Void; }
185c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  unsigned getNumElements() const { return Bitwidth / ElementBitwidth; }
186c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  unsigned getSizeInBits() const { return Bitwidth; }
187c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  unsigned getElementSizeInBits() const { return ElementBitwidth; }
188c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  unsigned getNumVectors() const { return NumVectors; }
189c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
190c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  //
191c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  // Mutator functions
192c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  //
193c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  void makeUnsigned() { Signed = false; }
194c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  void makeSigned() { Signed = true; }
195c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  void makeInteger(unsigned ElemWidth, bool Sign) {
196c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    Float = false;
197c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    Poly = false;
198c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    Signed = Sign;
199b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar    Immediate = false;
200b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar    ElementBitwidth = ElemWidth;
201b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar  }
202b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar  void makeImmediate(unsigned ElemWidth) {
203b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar    Float = false;
204b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar    Poly = false;
205b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar    Signed = true;
206b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar    Immediate = true;
207c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    ElementBitwidth = ElemWidth;
208c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  }
209c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  void makeScalar() {
210c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    Bitwidth = ElementBitwidth;
211c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    NumVectors = 0;
212c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  }
213c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  void makeOneVector() {
214c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    assert(isVector());
215c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    NumVectors = 1;
2163cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  }
217c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  void doubleLanes() {
218c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    assert_with_loc(Bitwidth != 128, "Can't get bigger than 128!");
219c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    Bitwidth = 128;
220c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  }
221c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  void halveLanes() {
222c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    assert_with_loc(Bitwidth != 64, "Can't get smaller than 64!");
223c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    Bitwidth = 64;
224c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  }
225c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
226c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  /// Return the C string representation of a type, which is the typename
227c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  /// defined in stdint.h or arm_neon.h.
228c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  std::string str() const;
229c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
230c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  /// Return the string representation of a type, which is an encoded
231c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  /// string for passing to the BUILTIN() macro in Builtins.def.
232c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  std::string builtin_str() const;
2333cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen
234c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  /// Return the value in NeonTypeFlags for this type.
235c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  unsigned getNeonEnum() const;
236c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
237c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  /// Parse a type from a stdint.h or arm_neon.h typedef name,
238c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  /// for example uint32x2_t or int64_t.
239c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  static Type fromTypedefName(StringRef Name);
240c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
241c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesprivate:
242c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  /// Creates the type based on the typespec string in TS.
243c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  /// Sets "Quad" to true if the "Q" or "H" modifiers were
244c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  /// seen. This is needed by applyModifier as some modifiers
245c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  /// only take effect if the type size was changed by "Q" or "H".
246c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  void applyTypespec(bool &Quad);
247c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  /// Applies a prototype modifier to the type.
248c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  void applyModifier(char Mod);
2493cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen};
2503cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen
251c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines//===----------------------------------------------------------------------===//
252c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines// Variable
253c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines//===----------------------------------------------------------------------===//
254c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
255c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines/// A variable is a simple class that just has a type and a name.
256c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesclass Variable {
257c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  Type T;
258c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  std::string N;
259c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
260c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinespublic:
261c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  Variable() : T(Type::getVoid()), N("") {}
2624967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar  Variable(Type T, std::string N) : T(std::move(T)), N(std::move(N)) {}
263c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
264c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  Type getType() const { return T; }
265c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  std::string getName() const { return "__" + N; }
266c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines};
267c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
268c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines//===----------------------------------------------------------------------===//
269c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines// Intrinsic
270c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines//===----------------------------------------------------------------------===//
271c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
272c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines/// The main grunt class. This represents an instantiation of an intrinsic with
273c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines/// a particular typespec and prototype.
274c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesclass Intrinsic {
275c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  friend class DagEmitter;
276c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
277c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  /// The Record this intrinsic was created from.
278c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  Record *R;
279c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  /// The unmangled name and prototype.
280c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  std::string Name, Proto;
281c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  /// The input and output typespecs. InTS == OutTS except when
282c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  /// CartesianProductOfTypes is 1 - this is the case for vreinterpret.
283c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  TypeSpec OutTS, InTS;
284c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  /// The base class kind. Most intrinsics use ClassS, which has full type
285c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  /// info for integers (s32/u32). Some use ClassI, which doesn't care about
286c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  /// signedness (i32), while some (ClassB) have no type at all, only a width
287c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  /// (32).
288c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  ClassKind CK;
289c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  /// The list of DAGs for the body. May be empty, in which case we should
290c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  /// emit a builtin call.
291c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  ListInit *Body;
292c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  /// The architectural #ifdef guard.
293c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  std::string Guard;
294c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  /// Set if the Unvailable bit is 1. This means we don't generate a body,
295c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  /// just an "unavailable" attribute on a declaration.
296c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  bool IsUnavailable;
297c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  /// Is this intrinsic safe for big-endian? or does it need its arguments
298c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  /// reversing?
299c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  bool BigEndianSafe;
300c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
301c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  /// The types of return value [0] and parameters [1..].
302c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  std::vector<Type> Types;
303c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  /// The local variables defined.
304c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  std::map<std::string, Variable> Variables;
305c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  /// NeededEarly - set if any other intrinsic depends on this intrinsic.
306c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  bool NeededEarly;
307c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  /// UseMacro - set if we should implement using a macro or unset for a
308c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  ///            function.
309c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  bool UseMacro;
310c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  /// The set of intrinsics that this intrinsic uses/requires.
311c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  std::set<Intrinsic *> Dependencies;
312c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  /// The "base type", which is Type('d', OutTS). InBaseType is only
313c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  /// different if CartesianProductOfTypes = 1 (for vreinterpret).
314c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  Type BaseType, InBaseType;
315c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  /// The return variable.
316c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  Variable RetVar;
317c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  /// A postfix to apply to every variable. Defaults to "".
318c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  std::string VariablePostfix;
319c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
320c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  NeonEmitter &Emitter;
321c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  std::stringstream OS;
322c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
323c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinespublic:
324c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  Intrinsic(Record *R, StringRef Name, StringRef Proto, TypeSpec OutTS,
325c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines            TypeSpec InTS, ClassKind CK, ListInit *Body, NeonEmitter &Emitter,
326c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines            StringRef Guard, bool IsUnavailable, bool BigEndianSafe)
327c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      : R(R), Name(Name.str()), Proto(Proto.str()), OutTS(OutTS), InTS(InTS),
328c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        CK(CK), Body(Body), Guard(Guard.str()), IsUnavailable(IsUnavailable),
329c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        BigEndianSafe(BigEndianSafe), NeededEarly(false), UseMacro(false),
330c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        BaseType(OutTS, 'd'), InBaseType(InTS, 'd'), Emitter(Emitter) {
331c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    // If this builtin takes an immediate argument, we need to #define it rather
332c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    // than use a standard declaration, so that SemaChecking can range check
333c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    // the immediate passed by the user.
334c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    if (Proto.find('i') != std::string::npos)
335c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      UseMacro = true;
336c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
337c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    // Pointer arguments need to use macros to avoid hiding aligned attributes
338c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    // from the pointer type.
339c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    if (Proto.find('p') != std::string::npos ||
340c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        Proto.find('c') != std::string::npos)
341c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      UseMacro = true;
342c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
343c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    // It is not permitted to pass or return an __fp16 by value, so intrinsics
344c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    // taking a scalar float16_t must be implemented as macros.
345c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    if (OutTS.find('h') != std::string::npos &&
346c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        Proto.find('s') != std::string::npos)
347c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      UseMacro = true;
348c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
349c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    // Modify the TypeSpec per-argument to get a concrete Type, and create
350c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    // known variables for each.
351c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    // Types[0] is the return value.
352b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar    Types.emplace_back(OutTS, Proto[0]);
353c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    for (unsigned I = 1; I < Proto.size(); ++I)
354b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar      Types.emplace_back(InTS, Proto[I]);
355c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  }
356c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
357c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  /// Get the Record that this intrinsic is based off.
358c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  Record *getRecord() const { return R; }
359c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  /// Get the set of Intrinsics that this intrinsic calls.
360c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  /// this is the set of immediate dependencies, NOT the
361c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  /// transitive closure.
362c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  const std::set<Intrinsic *> &getDependencies() const { return Dependencies; }
363c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  /// Get the architectural guard string (#ifdef).
364c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  std::string getGuard() const { return Guard; }
365c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  /// Get the non-mangled name.
366c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  std::string getName() const { return Name; }
367c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
368c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  /// Return true if the intrinsic takes an immediate operand.
369c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  bool hasImmediate() const {
370c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    return Proto.find('i') != std::string::npos;
371c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  }
372c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  /// Return the parameter index of the immediate operand.
373c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  unsigned getImmediateIdx() const {
374c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    assert(hasImmediate());
375c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    unsigned Idx = Proto.find('i');
376c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    assert(Idx > 0 && "Can't return an immediate!");
377c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    return Idx - 1;
378c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  }
379c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
380c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  /// Return true if the intrinsic takes an splat operand.
381c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  bool hasSplat() const { return Proto.find('a') != std::string::npos; }
382c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  /// Return the parameter index of the splat operand.
383c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  unsigned getSplatIdx() const {
384c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    assert(hasSplat());
385c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    unsigned Idx = Proto.find('a');
386c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    assert(Idx > 0 && "Can't return a splat!");
387c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    return Idx - 1;
388c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  }
389c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
390c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  unsigned getNumParams() const { return Proto.size() - 1; }
391c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  Type getReturnType() const { return Types[0]; }
392c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  Type getParamType(unsigned I) const { return Types[I + 1]; }
393c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  Type getBaseType() const { return BaseType; }
394c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  /// Return the raw prototype string.
395c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  std::string getProto() const { return Proto; }
396c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
397c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  /// Return true if the prototype has a scalar argument.
398c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  /// This does not return true for the "splat" code ('a').
39987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  bool protoHasScalar() const;
400c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
401c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  /// Return the index that parameter PIndex will sit at
402c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  /// in a generated function call. This is often just PIndex,
403c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  /// but may not be as things such as multiple-vector operands
404c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  /// and sret parameters need to be taken into accont.
405c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  unsigned getGeneratedParamIdx(unsigned PIndex) {
406c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    unsigned Idx = 0;
407c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    if (getReturnType().getNumVectors() > 1)
408c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      // Multiple vectors are passed as sret.
409c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      ++Idx;
410c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
411c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    for (unsigned I = 0; I < PIndex; ++I)
412c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      Idx += std::max(1U, getParamType(I).getNumVectors());
413c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
414c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    return Idx;
415c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  }
416c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
417c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  bool hasBody() const { return Body && Body->getValues().size() > 0; }
418c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
419c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  void setNeededEarly() { NeededEarly = true; }
420c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
421c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  bool operator<(const Intrinsic &Other) const {
422c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    // Sort lexicographically on a two-tuple (Guard, Name)
423c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    if (Guard != Other.Guard)
424c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      return Guard < Other.Guard;
425c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    return Name < Other.Name;
426c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  }
427c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
428c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  ClassKind getClassKind(bool UseClassBIfScalar = false) {
429c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    if (UseClassBIfScalar && !protoHasScalar())
430c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      return ClassB;
431c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    return CK;
432c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  }
433c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
434c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  /// Return the name, mangled with type information.
435c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  /// If ForceClassS is true, use ClassS (u32/s32) instead
436c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  /// of the intrinsic's own type class.
43787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  std::string getMangledName(bool ForceClassS = false) const;
438c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  /// Return the type code for a builtin function call.
43987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  std::string getInstTypeCode(Type T, ClassKind CK) const;
440c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  /// Return the type string for a BUILTIN() macro in Builtins.def.
441c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  std::string getBuiltinTypeStr();
442c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
443c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  /// Generate the intrinsic, returning code.
444c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  std::string generate();
445c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  /// Perform type checking and populate the dependency graph, but
446c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  /// don't generate code yet.
447c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  void indexBody();
448c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
449c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesprivate:
45087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  std::string mangleName(std::string Name, ClassKind CK) const;
451c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
452c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  void initVariables();
453c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  std::string replaceParamsIn(std::string S);
454c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
455c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  void emitBodyAsBuiltinCall();
456c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
457c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  void generateImpl(bool ReverseArguments,
458c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines                    StringRef NamePrefix, StringRef CallPrefix);
459c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  void emitReturn();
460c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  void emitBody(StringRef CallPrefix);
461c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  void emitShadowedArgs();
462c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  void emitArgumentReversal();
463c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  void emitReturnReversal();
464c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  void emitReverseVariable(Variable &Dest, Variable &Src);
465c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  void emitNewLine();
466c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  void emitClosingBrace();
467c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  void emitOpeningBrace();
468c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  void emitPrototype(StringRef NamePrefix);
469c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
470c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  class DagEmitter {
471c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    Intrinsic &Intr;
472c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    StringRef CallPrefix;
473c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
474c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  public:
475c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    DagEmitter(Intrinsic &Intr, StringRef CallPrefix) :
476c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      Intr(Intr), CallPrefix(CallPrefix) {
477c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    }
478c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    std::pair<Type, std::string> emitDagArg(Init *Arg, std::string ArgName);
479c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    std::pair<Type, std::string> emitDagSaveTemp(DagInit *DI);
480c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    std::pair<Type, std::string> emitDagSplat(DagInit *DI);
481c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    std::pair<Type, std::string> emitDagDup(DagInit *DI);
482c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    std::pair<Type, std::string> emitDagShuffle(DagInit *DI);
483c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    std::pair<Type, std::string> emitDagCast(DagInit *DI, bool IsBitCast);
484c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    std::pair<Type, std::string> emitDagCall(DagInit *DI);
485c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    std::pair<Type, std::string> emitDagNameReplace(DagInit *DI);
486c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    std::pair<Type, std::string> emitDagLiteral(DagInit *DI);
487c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    std::pair<Type, std::string> emitDagOp(DagInit *DI);
488c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    std::pair<Type, std::string> emitDag(DagInit *DI);
489c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  };
490c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
491c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines};
492c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
493c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines//===----------------------------------------------------------------------===//
494c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines// NeonEmitter
495c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines//===----------------------------------------------------------------------===//
496c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
4973cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesenclass NeonEmitter {
4983cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  RecordKeeper &Records;
499c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  DenseMap<Record *, ClassKind> ClassMap;
50087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  std::map<std::string, std::deque<Intrinsic>> IntrinsicMap;
501c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  unsigned UniqueNumber;
502c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
503c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  void createIntrinsic(Record *R, SmallVectorImpl<Intrinsic *> &Out);
504c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  void genBuiltinsDef(raw_ostream &OS, SmallVectorImpl<Intrinsic *> &Defs);
505c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  void genOverloadTypeCheckCode(raw_ostream &OS,
506c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines                                SmallVectorImpl<Intrinsic *> &Defs);
507c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  void genIntrinsicRangeCheckCode(raw_ostream &OS,
508c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines                                  SmallVectorImpl<Intrinsic *> &Defs);
5093cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen
5103cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesenpublic:
511c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  /// Called by Intrinsic - this attempts to get an intrinsic that takes
512c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  /// the given types as arguments.
51387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  Intrinsic &getIntrinsic(StringRef Name, ArrayRef<Type> Types);
514c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
515c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  /// Called by Intrinsic - returns a globally-unique number.
516c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  unsigned getUniqueNumber() { return UniqueNumber++; }
5173cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen
518c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  NeonEmitter(RecordKeeper &R) : Records(R), UniqueNumber(0) {
5193cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    Record *SI = R.getClass("SInst");
5203cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    Record *II = R.getClass("IInst");
5213cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    Record *WI = R.getClass("WInst");
52221e4e940ed3ad172f344a3aa3faf1d8437441313Michael Gottesman    Record *SOpI = R.getClass("SOpInst");
52321e4e940ed3ad172f344a3aa3faf1d8437441313Michael Gottesman    Record *IOpI = R.getClass("IOpInst");
52421e4e940ed3ad172f344a3aa3faf1d8437441313Michael Gottesman    Record *WOpI = R.getClass("WOpInst");
52521e4e940ed3ad172f344a3aa3faf1d8437441313Michael Gottesman    Record *LOpI = R.getClass("LOpInst");
52621e4e940ed3ad172f344a3aa3faf1d8437441313Michael Gottesman    Record *NoTestOpI = R.getClass("NoTestOpInst");
52721e4e940ed3ad172f344a3aa3faf1d8437441313Michael Gottesman
5283cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    ClassMap[SI] = ClassS;
5293cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    ClassMap[II] = ClassI;
5303cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen    ClassMap[WI] = ClassW;
53121e4e940ed3ad172f344a3aa3faf1d8437441313Michael Gottesman    ClassMap[SOpI] = ClassS;
53221e4e940ed3ad172f344a3aa3faf1d8437441313Michael Gottesman    ClassMap[IOpI] = ClassI;
53321e4e940ed3ad172f344a3aa3faf1d8437441313Michael Gottesman    ClassMap[WOpI] = ClassW;
53421e4e940ed3ad172f344a3aa3faf1d8437441313Michael Gottesman    ClassMap[LOpI] = ClassL;
53521e4e940ed3ad172f344a3aa3faf1d8437441313Michael Gottesman    ClassMap[NoTestOpI] = ClassNoTest;
5363cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  }
5373cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen
5383cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  // run - Emit arm_neon.h.inc
5393cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  void run(raw_ostream &o);
5403cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen
5413cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  // runHeader - Emit all the __builtin prototypes used in arm_neon.h
5423cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  void runHeader(raw_ostream &o);
5433cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen
5443cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  // runTests - Emit tests for all the Neon intrinsics.
5453cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  void runTests(raw_ostream &o);
5463cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen};
547c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
5483cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen} // end anonymous namespace
5493cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen
550c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines//===----------------------------------------------------------------------===//
551c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines// Type implementation
552c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines//===----------------------------------------------------------------------===//
55351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
554c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesstd::string Type::str() const {
555c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  if (Void)
556c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    return "void";
557c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  std::string S;
558c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
559c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  if (!Signed && isInteger())
560c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    S += "u";
561c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
562c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  if (Poly)
563c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    S += "poly";
564c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  else if (Float)
565c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    S += "float";
566c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  else
567c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    S += "int";
568c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
569c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  S += utostr(ElementBitwidth);
570c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  if (isVector())
571c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    S += "x" + utostr(getNumElements());
572c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  if (NumVectors > 1)
573c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    S += "x" + utostr(NumVectors);
574c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  S += "_t";
575c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
576c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  if (Constant)
577c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    S += " const";
578c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  if (Pointer)
579c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    S += " *";
580c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
581c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  return S;
58251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
58351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
584c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesstd::string Type::builtin_str() const {
585c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  std::string S;
586c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  if (isVoid())
587c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    return "v";
588c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
589c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  if (Pointer)
590c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    // All pointers are void pointers.
591c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    S += "v";
592c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  else if (isInteger())
593c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    switch (ElementBitwidth) {
594c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    case 8: S += "c"; break;
595c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    case 16: S += "s"; break;
596c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    case 32: S += "i"; break;
597c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    case 64: S += "Wi"; break;
598c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    case 128: S += "LLLi"; break;
599c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    default: llvm_unreachable("Unhandled case!");
600c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    }
601c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  else
602c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    switch (ElementBitwidth) {
603c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    case 16: S += "h"; break;
604c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    case 32: S += "f"; break;
605c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    case 64: S += "d"; break;
606c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    default: llvm_unreachable("Unhandled case!");
607c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    }
608c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
609c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  if (isChar() && !Pointer)
610c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    // Make chars explicitly signed.
611c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    S = "S" + S;
612c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  else if (isInteger() && !Pointer && !Signed)
613c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    S = "U" + S;
614c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
615b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar  // Constant indices are "int", but have the "constant expression" modifier.
616b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar  if (isImmediate()) {
617b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar    assert(isInteger() && isSigned());
618b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar    S = "I" + S;
619b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar  }
620b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar
621c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  if (isScalar()) {
622c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    if (Constant) S += "C";
623c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    if (Pointer) S += "*";
624c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    return S;
62551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
626c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
627c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  std::string Ret;
628c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  for (unsigned I = 0; I < NumVectors; ++I)
629c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    Ret += "V" + utostr(getNumElements()) + S;
630c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
631c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  return Ret;
63251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
63351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
634c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesunsigned Type::getNeonEnum() const {
635c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  unsigned Addend;
636c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  switch (ElementBitwidth) {
637c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  case 8: Addend = 0; break;
638c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  case 16: Addend = 1; break;
639c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  case 32: Addend = 2; break;
640c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  case 64: Addend = 3; break;
641c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  case 128: Addend = 4; break;
642c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  default: llvm_unreachable("Unhandled element bitwidth!");
64351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
64451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
645c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  unsigned Base = (unsigned)NeonTypeFlags::Int8 + Addend;
646c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  if (Poly) {
647c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    // Adjustment needed because Poly32 doesn't exist.
648c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    if (Addend >= 2)
649c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      --Addend;
650c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    Base = (unsigned)NeonTypeFlags::Poly8 + Addend;
651097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu  }
652c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  if (Float) {
653c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    assert(Addend != 0 && "Float8 doesn't exist!");
654c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    Base = (unsigned)NeonTypeFlags::Float16 + (Addend - 1);
655c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  }
656c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
657c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  if (Bitwidth == 128)
658c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    Base |= (unsigned)NeonTypeFlags::QuadFlag;
659c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  if (isInteger() && !Signed)
660c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    Base |= (unsigned)NeonTypeFlags::UnsignedFlag;
661097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu
662c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  return Base;
663097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu}
664097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu
665c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen HinesType Type::fromTypedefName(StringRef Name) {
666c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  Type T;
667c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  T.Void = false;
668c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  T.Float = false;
669c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  T.Poly = false;
670c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
671c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  if (Name.front() == 'u') {
672c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    T.Signed = false;
673c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    Name = Name.drop_front();
674c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  } else {
675c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    T.Signed = true;
676944f09ff9b33637465906e1aeadcfa405d66331dKevin Qin  }
677c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
678c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  if (Name.startswith("float")) {
679c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    T.Float = true;
680c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    Name = Name.drop_front(5);
681c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  } else if (Name.startswith("poly")) {
682c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    T.Poly = true;
683c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    Name = Name.drop_front(4);
684c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  } else {
685c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    assert(Name.startswith("int"));
686c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    Name = Name.drop_front(3);
68751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
68851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
689c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  unsigned I = 0;
690c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  for (I = 0; I < Name.size(); ++I) {
691c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    if (!isdigit(Name[I]))
692c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      break;
69351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
694c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  Name.substr(0, I).getAsInteger(10, T.ElementBitwidth);
695c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  Name = Name.drop_front(I);
696c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
697c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  T.Bitwidth = T.ElementBitwidth;
698c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  T.NumVectors = 1;
69951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
700c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  if (Name.front() == 'x') {
701c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    Name = Name.drop_front();
702c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    unsigned I = 0;
703c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    for (I = 0; I < Name.size(); ++I) {
704c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      if (!isdigit(Name[I]))
705c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        break;
706c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    }
707c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    unsigned NumLanes;
708c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    Name.substr(0, I).getAsInteger(10, NumLanes);
709c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    Name = Name.drop_front(I);
710c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    T.Bitwidth = T.ElementBitwidth * NumLanes;
711c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  } else {
712c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    // Was scalar.
713c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    T.NumVectors = 0;
714c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  }
715c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  if (Name.front() == 'x') {
716c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    Name = Name.drop_front();
717c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    unsigned I = 0;
718c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    for (I = 0; I < Name.size(); ++I) {
719c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      if (!isdigit(Name[I]))
720c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        break;
721c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    }
722c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    Name.substr(0, I).getAsInteger(10, T.NumVectors);
723c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    Name = Name.drop_front(I);
72451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
72551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
726c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  assert(Name.startswith("_t") && "Malformed typedef!");
727c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  return T;
72851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
72951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
730c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesvoid Type::applyTypespec(bool &Quad) {
731c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  std::string S = TS;
732c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  ScalarForMangling = false;
733c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  Void = false;
734c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  Poly = Float = false;
735c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  ElementBitwidth = ~0U;
736c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  Signed = true;
737c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  NumVectors = 1;
738c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
739c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  for (char I : S) {
740c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    switch (I) {
741c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    case 'S':
742c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      ScalarForMangling = true;
74351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
744c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    case 'H':
745c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      NoManglingQ = true;
746c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      Quad = true;
7474553a858e46299955333babfa052a512682869fdChad Rosier      break;
748c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    case 'Q':
749c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      Quad = true;
7504553a858e46299955333babfa052a512682869fdChad Rosier      break;
751c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    case 'P':
752c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      Poly = true;
75351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
754c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    case 'U':
755c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      Signed = false;
75651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
75751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'c':
758c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      ElementBitwidth = 8;
75951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
76051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'h':
761c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      Float = true;
762c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    // Fall through
76351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 's':
764c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      ElementBitwidth = 16;
76551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
766c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    case 'f':
767c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      Float = true;
768c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    // Fall through
76951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'i':
770c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      ElementBitwidth = 32;
77151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
772c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    case 'd':
773c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      Float = true;
774c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    // Fall through
77551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    case 'l':
776c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      ElementBitwidth = 64;
77751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      break;
778651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    case 'k':
779c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      ElementBitwidth = 128;
780c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      // Poly doesn't have a 128x1 type.
781c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      if (Poly)
782c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        NumVectors = 0;
783b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover      break;
78451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    default:
785c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      llvm_unreachable("Unhandled type code!");
786c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    }
78751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
788c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  assert(ElementBitwidth != ~0U && "Bad element bitwidth!");
78951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
790c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  Bitwidth = Quad ? 128 : 64;
79151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
79251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
793c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesvoid Type::applyModifier(char Mod) {
794c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  bool AppliedQuad = false;
795c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  applyTypespec(AppliedQuad);
79651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
797c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  switch (Mod) {
798c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  case 'v':
799c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    Void = true;
80051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
801c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  case 't':
802c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    if (Poly) {
803c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      Poly = false;
804c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      Signed = false;
80551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
80651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
807c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  case 'b':
808c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    Signed = false;
809c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    Float = false;
810c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    Poly = false;
811c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    NumVectors = 0;
812c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    Bitwidth = ElementBitwidth;
813c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    break;
814c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  case '$':
815c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    Signed = true;
816c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    Float = false;
817c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    Poly = false;
818c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    NumVectors = 0;
819c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    Bitwidth = ElementBitwidth;
820c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    break;
821c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  case 'u':
822c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    Signed = false;
823c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    Poly = false;
824c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    Float = false;
825c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    break;
826c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  case 'x':
827c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    Signed = true;
828c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    assert(!Poly && "'u' can't be used with poly types!");
829c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    Float = false;
830c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    break;
831c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  case 'o':
832c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    Bitwidth = ElementBitwidth = 64;
833c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    NumVectors = 0;
834c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    Float = true;
835c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    break;
836c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  case 'y':
837c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    Bitwidth = ElementBitwidth = 32;
838c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    NumVectors = 0;
839c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    Float = true;
840c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    break;
841c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  case 'f':
842c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    Float = true;
843c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    ElementBitwidth = 32;
844c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    break;
845c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  case 'F':
846c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    Float = true;
847c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    ElementBitwidth = 64;
848c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    break;
849c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  case 'g':
850c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    if (AppliedQuad)
851c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      Bitwidth /= 2;
852c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    break;
853c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  case 'j':
854c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    if (!AppliedQuad)
855c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      Bitwidth *= 2;
856c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    break;
857c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  case 'w':
858c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    ElementBitwidth *= 2;
859c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    Bitwidth *= 2;
860c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    break;
861c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  case 'n':
862c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    ElementBitwidth *= 2;
863c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    break;
86451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case 'i':
865c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    Float = false;
866c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    Poly = false;
867c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    ElementBitwidth = Bitwidth = 32;
868c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    NumVectors = 0;
869c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    Signed = true;
870b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar    Immediate = true;
87151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
87251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case 'l':
873c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    Float = false;
874c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    Poly = false;
875c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    ElementBitwidth = Bitwidth = 64;
876c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    NumVectors = 0;
877c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    Signed = false;
878b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar    Immediate = true;
879c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    break;
880c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  case 'z':
881c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    ElementBitwidth /= 2;
882c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    Bitwidth = ElementBitwidth;
883c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    NumVectors = 0;
884c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    break;
885c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  case 'r':
886c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    ElementBitwidth *= 2;
887c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    Bitwidth = ElementBitwidth;
888c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    NumVectors = 0;
889c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    break;
890c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  case 's':
891c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  case 'a':
892c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    Bitwidth = ElementBitwidth;
893c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    NumVectors = 0;
89451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
895651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  case 'k':
896c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    Bitwidth *= 2;
897c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    break;
898c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  case 'c':
899c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    Constant = true;
900c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  // Fall through
901c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  case 'p':
902c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    Pointer = true;
903c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    Bitwidth = ElementBitwidth;
904c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    NumVectors = 0;
905651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    break;
90651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  case 'h':
907c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    ElementBitwidth /= 2;
90851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
909c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  case 'q':
910c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    ElementBitwidth /= 2;
911c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    Bitwidth *= 2;
912c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    break;
913c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  case 'e':
914c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    ElementBitwidth /= 2;
915c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    Signed = false;
916c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    break;
917c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  case 'm':
918c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    ElementBitwidth /= 2;
919c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    Bitwidth /= 2;
92051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    break;
921b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  case 'd':
922c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    break;
923c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  case '2':
924c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    NumVectors = 2;
925c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    break;
926c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  case '3':
927c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    NumVectors = 3;
928c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    break;
929c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  case '4':
930c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    NumVectors = 4;
931c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    break;
932c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  case 'B':
933c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    NumVectors = 2;
934c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    if (!AppliedQuad)
935c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      Bitwidth *= 2;
936c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    break;
937c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  case 'C':
938c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    NumVectors = 3;
939c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    if (!AppliedQuad)
940c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      Bitwidth *= 2;
941c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    break;
942c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  case 'D':
943c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    NumVectors = 4;
944c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    if (!AppliedQuad)
945c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      Bitwidth *= 2;
946b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover    break;
94751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  default:
948c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    llvm_unreachable("Unhandled character!");
94951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
950fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman}
951fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman
952c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines//===----------------------------------------------------------------------===//
953c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines// Intrinsic implementation
954c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines//===----------------------------------------------------------------------===//
955c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
95687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainarstd::string Intrinsic::getInstTypeCode(Type T, ClassKind CK) const {
957c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  char typeCode = '\0';
958c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  bool printNumber = true;
959c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
960c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  if (CK == ClassB)
961c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    return "";
962c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
963c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  if (T.isPoly())
964c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    typeCode = 'p';
965c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  else if (T.isInteger())
966c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    typeCode = T.isSigned() ? 's' : 'u';
967c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  else
968c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    typeCode = 'f';
969c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
970c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  if (CK == ClassI) {
971c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    switch (typeCode) {
972c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    default:
973c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      break;
974c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    case 's':
975c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    case 'u':
976c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    case 'p':
977c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      typeCode = 'i';
978c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      break;
979944f09ff9b33637465906e1aeadcfa405d66331dKevin Qin    }
980944f09ff9b33637465906e1aeadcfa405d66331dKevin Qin  }
981c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  if (CK == ClassB) {
982c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    typeCode = '\0';
983dd12780e86575795fa912529a911b01e2abc4677Hao Liu  }
984c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
985c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  std::string S;
986c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  if (typeCode != '\0')
987c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    S.push_back(typeCode);
988c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  if (printNumber)
989c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    S += utostr(T.getElementSizeInBits());
990c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
991c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  return S;
992dd12780e86575795fa912529a911b01e2abc4677Hao Liu}
993dd12780e86575795fa912529a911b01e2abc4677Hao Liu
99487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainarstatic bool isFloatingPointProtoModifier(char Mod) {
99587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  return Mod == 'F' || Mod == 'f';
99687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar}
99787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar
998c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesstd::string Intrinsic::getBuiltinTypeStr() {
999c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  ClassKind LocalCK = getClassKind(true);
1000c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  std::string S;
1001fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman
1002c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  Type RetT = getReturnType();
1003c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  if ((LocalCK == ClassI || LocalCK == ClassW) && RetT.isScalar() &&
1004c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      !RetT.isFloating())
1005c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    RetT.makeInteger(RetT.getElementSizeInBits(), false);
1006fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman
1007c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  // Since the return value must be one type, return a vector type of the
1008c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  // appropriate width which we will bitcast.  An exception is made for
1009c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  // returning structs of 2, 3, or 4 vectors which are returned in a sret-like
1010c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  // fashion, storing them to a pointer arg.
1011c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  if (RetT.getNumVectors() > 1) {
1012c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    S += "vv*"; // void result with void* first argument
1013c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  } else {
1014c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    if (RetT.isPoly())
1015c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      RetT.makeInteger(RetT.getElementSizeInBits(), false);
1016c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    if (!RetT.isScalar() && !RetT.isSigned())
1017c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      RetT.makeSigned();
1018fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman
101987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    bool ForcedVectorFloatingType = isFloatingPointProtoModifier(Proto[0]);
1020c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    if (LocalCK == ClassB && !RetT.isScalar() && !ForcedVectorFloatingType)
1021c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      // Cast to vector of 8-bit elements.
1022c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      RetT.makeInteger(8, true);
1023fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman
1024c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    S += RetT.builtin_str();
1025fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman  }
1026fb599a4cc5665afe8da11d438ae021a5cd8cfdbdMichael Gottesman
1027c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  for (unsigned I = 0; I < getNumParams(); ++I) {
1028c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    Type T = getParamType(I);
1029c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    if (T.isPoly())
1030c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      T.makeInteger(T.getElementSizeInBits(), false);
103151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
103287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    bool ForcedFloatingType = isFloatingPointProtoModifier(Proto[I + 1]);
1033c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    if (LocalCK == ClassB && !T.isScalar() && !ForcedFloatingType)
1034c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      T.makeInteger(8, true);
1035c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    // Halves always get converted to 8-bit elements.
1036c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    if (T.isHalf() && T.isVector() && !T.isScalarForMangling())
1037c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      T.makeInteger(8, true);
1038c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1039c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    if (LocalCK == ClassI)
1040c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      T.makeSigned();
104151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
1042c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    if (hasImmediate() && getImmediateIdx() == I)
1043b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar      T.makeImmediate(32);
1044c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1045c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    S += T.builtin_str();
1046c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  }
1047c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1048c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  // Extra constant integer to hold type class enum for this function, e.g. s8
1049c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  if (LocalCK == ClassB)
1050c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    S += "i";
1051c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1052c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  return S;
1053c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman}
1054c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
105587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainarstd::string Intrinsic::getMangledName(bool ForceClassS) const {
1056c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  // Check if the prototype has a scalar operand with the type of the vector
1057c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  // elements.  If not, bitcasting the args will take care of arg checking.
1058c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  // The actual signedness etc. will be taken care of with special enums.
1059c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  ClassKind LocalCK = CK;
1060c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  if (!protoHasScalar())
1061c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    LocalCK = ClassB;
1062c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1063c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  return mangleName(Name, ForceClassS ? ClassS : LocalCK);
1064c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman}
1065c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
106687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainarstd::string Intrinsic::mangleName(std::string Name, ClassKind LocalCK) const {
1067c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  std::string typeCode = getInstTypeCode(BaseType, LocalCK);
1068c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  std::string S = Name;
1069c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
107087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  if (Name == "vcvt_f16_f32" || Name == "vcvt_f32_f16" ||
107187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      Name == "vcvt_f32_f64" || Name == "vcvt_f64_f32")
1072c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    return Name;
1073c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1074c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  if (typeCode.size() > 0) {
1075c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    // If the name ends with _xN (N = 2,3,4), insert the typeCode before _xN.
1076c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    if (Name.size() >= 3 && isdigit(Name.back()) &&
1077c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        Name[Name.length() - 2] == 'x' && Name[Name.length() - 3] == '_')
1078c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      S.insert(S.length() - 3, "_" + typeCode);
1079c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    else
1080c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      S += "_" + typeCode;
1081c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  }
1082c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1083c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  if (BaseType != InBaseType) {
1084c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    // A reinterpret - out the input base type at the end.
1085c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    S += "_" + getInstTypeCode(InBaseType, LocalCK);
1086c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  }
1087c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1088c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  if (LocalCK == ClassB)
1089c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    S += "_v";
1090c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1091c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  // Insert a 'q' before the first '_' character so that it ends up before
1092c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  // _lane or _n on vector-scalar operations.
1093c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  if (BaseType.getSizeInBits() == 128 && !BaseType.noManglingQ()) {
1094c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    size_t Pos = S.find('_');
1095c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    S.insert(Pos, "q");
1096c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  }
1097c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
1098c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  char Suffix = '\0';
1099c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  if (BaseType.isScalarForMangling()) {
1100c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    switch (BaseType.getElementSizeInBits()) {
1101c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    case 8: Suffix = 'b'; break;
1102c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    case 16: Suffix = 'h'; break;
1103c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    case 32: Suffix = 's'; break;
1104c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    case 64: Suffix = 'd'; break;
1105c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    default: llvm_unreachable("Bad suffix!");
1106c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    }
1107c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  }
1108c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  if (Suffix != '\0') {
1109c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    size_t Pos = S.find('_');
1110c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    S.insert(Pos, &Suffix, 1);
1111c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  }
1112c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1113c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  return S;
1114c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines}
1115c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1116c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesstd::string Intrinsic::replaceParamsIn(std::string S) {
1117c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  while (S.find('$') != std::string::npos) {
1118c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    size_t Pos = S.find('$');
1119c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    size_t End = Pos + 1;
1120c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    while (isalpha(S[End]))
1121c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      ++End;
1122c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1123c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    std::string VarName = S.substr(Pos + 1, End - Pos - 1);
1124c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    assert_with_loc(Variables.find(VarName) != Variables.end(),
1125c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines                    "Variable not defined!");
1126c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    S.replace(Pos, End - Pos, Variables.find(VarName)->second.getName());
1127c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  }
1128c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1129c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  return S;
1130c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines}
1131c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1132c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesvoid Intrinsic::initVariables() {
1133c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  Variables.clear();
1134c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1135c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  // Modify the TypeSpec per-argument to get a concrete Type, and create
1136c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  // known variables for each.
1137c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  for (unsigned I = 1; I < Proto.size(); ++I) {
1138c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    char NameC = '0' + (I - 1);
1139c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    std::string Name = "p";
1140c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    Name.push_back(NameC);
1141c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1142c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    Variables[Name] = Variable(Types[I], Name + VariablePostfix);
1143c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  }
1144c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  RetVar = Variable(Types[0], "ret" + VariablePostfix);
1145c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman}
1146c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1147c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesvoid Intrinsic::emitPrototype(StringRef NamePrefix) {
1148c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  if (UseMacro)
1149c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    OS << "#define ";
1150c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  else
1151c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    OS << "__ai " << Types[0].str() << " ";
1152c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1153c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  OS << NamePrefix.str() << mangleName(Name, ClassS) << "(";
1154c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1155c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  for (unsigned I = 0; I < getNumParams(); ++I) {
1156c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    if (I != 0)
1157c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      OS << ", ";
1158c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1159c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    char NameC = '0' + I;
1160c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    std::string Name = "p";
1161c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    Name.push_back(NameC);
1162c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    assert(Variables.find(Name) != Variables.end());
1163c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    Variable &V = Variables[Name];
1164c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1165c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    if (!UseMacro)
1166c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      OS << V.getType().str() << " ";
1167c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    OS << V.getName();
1168c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  }
1169c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1170c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  OS << ")";
1171c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines}
1172c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1173c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesvoid Intrinsic::emitOpeningBrace() {
1174c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  if (UseMacro)
1175c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    OS << " __extension__ ({";
1176c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  else
1177c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    OS << " {";
1178c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  emitNewLine();
1179c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines}
1180c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1181c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesvoid Intrinsic::emitClosingBrace() {
1182c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  if (UseMacro)
1183c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    OS << "})";
1184c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  else
1185c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    OS << "}";
1186c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines}
1187c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1188c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesvoid Intrinsic::emitNewLine() {
1189c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  if (UseMacro)
1190c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    OS << " \\\n";
1191c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  else
1192c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    OS << "\n";
1193c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines}
1194c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
1195c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesvoid Intrinsic::emitReverseVariable(Variable &Dest, Variable &Src) {
1196c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  if (Dest.getType().getNumVectors() > 1) {
1197c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    emitNewLine();
1198c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
1199c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    for (unsigned K = 0; K < Dest.getType().getNumVectors(); ++K) {
12004967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar      OS << "  " << Dest.getName() << ".val[" << K << "] = "
1201c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines         << "__builtin_shufflevector("
12024967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar         << Src.getName() << ".val[" << K << "], "
12034967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar         << Src.getName() << ".val[" << K << "]";
1204c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      for (int J = Dest.getType().getNumElements() - 1; J >= 0; --J)
12054967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar        OS << ", " << J;
1206c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      OS << ");";
1207c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      emitNewLine();
1208c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    }
1209c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  } else {
1210c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    OS << "  " << Dest.getName()
1211c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines       << " = __builtin_shufflevector(" << Src.getName() << ", " << Src.getName();
1212c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    for (int J = Dest.getType().getNumElements() - 1; J >= 0; --J)
12134967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar      OS << ", " << J;
1214c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    OS << ");";
1215c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    emitNewLine();
1216c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  }
1217c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines}
1218c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1219c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesvoid Intrinsic::emitArgumentReversal() {
1220c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  if (BigEndianSafe)
1221c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    return;
1222c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1223c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  // Reverse all vector arguments.
1224c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  for (unsigned I = 0; I < getNumParams(); ++I) {
1225c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    std::string Name = "p" + utostr(I);
1226c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    std::string NewName = "rev" + utostr(I);
1227c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1228c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    Variable &V = Variables[Name];
1229c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    Variable NewV(V.getType(), NewName + VariablePostfix);
1230c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1231c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    if (!NewV.getType().isVector() || NewV.getType().getNumElements() == 1)
1232c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      continue;
1233c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman
1234c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    OS << "  " << NewV.getType().str() << " " << NewV.getName() << ";";
1235c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    emitReverseVariable(NewV, V);
1236c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    V = NewV;
1237c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  }
123851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
123951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
1240c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesvoid Intrinsic::emitReturnReversal() {
1241c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  if (BigEndianSafe)
1242c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    return;
1243c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  if (!getReturnType().isVector() || getReturnType().isVoid() ||
1244c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      getReturnType().getNumElements() == 1)
1245c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    return;
1246c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  emitReverseVariable(RetVar, RetVar);
124751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
124851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
124951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
1250c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesvoid Intrinsic::emitShadowedArgs() {
1251c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  // Macro arguments are not type-checked like inline function arguments,
1252c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  // so assign them to local temporaries to get the right type checking.
1253c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  if (!UseMacro)
1254c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    return;
125551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
1256c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  for (unsigned I = 0; I < getNumParams(); ++I) {
125751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // Do not create a temporary for an immediate argument.
125851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // That would defeat the whole point of using a macro!
1259c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    if (hasImmediate() && Proto[I+1] == 'i')
1260c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      continue;
1261c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    // Do not create a temporary for pointer arguments. The input
1262c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    // pointer may have an alignment hint.
1263c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    if (getParamType(I).isPointer())
126451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      continue;
126551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
1266c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    std::string Name = "p" + utostr(I);
126751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
1268c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    assert(Variables.find(Name) != Variables.end());
1269c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    Variable &V = Variables[Name];
1270097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu
1271c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    std::string NewName = "s" + utostr(I);
1272c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    Variable V2(V.getType(), NewName + VariablePostfix);
127351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
1274c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    OS << "  " << V2.getType().str() << " " << V2.getName() << " = "
1275c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines       << V.getName() << ";";
1276c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    emitNewLine();
1277097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu
1278c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    V = V2;
1279c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  }
1280097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu}
1281097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu
1282c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines// We don't check 'a' in this function, because for builtin function the
1283c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines// argument matching to 'a' uses a vector type splatted from a scalar type.
128487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainarbool Intrinsic::protoHasScalar() const {
1285c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  return (Proto.find('s') != std::string::npos ||
1286c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines          Proto.find('z') != std::string::npos ||
1287c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines          Proto.find('r') != std::string::npos ||
1288c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines          Proto.find('b') != std::string::npos ||
1289c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines          Proto.find('$') != std::string::npos ||
1290c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines          Proto.find('y') != std::string::npos ||
1291c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines          Proto.find('o') != std::string::npos);
1292097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu}
1293097a4b487897ca29f0f371c81b6a8b6c1ca599e4Jiangning Liu
1294c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesvoid Intrinsic::emitBodyAsBuiltinCall() {
1295c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  std::string S;
129651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
1297c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  // If this builtin returns a struct 2, 3, or 4 vectors, pass it as an implicit
1298c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  // sret-like argument.
1299c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  bool SRet = getReturnType().getNumVectors() >= 2;
1300c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
1301c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  StringRef N = Name;
1302c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  if (hasSplat()) {
1303c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    // Call the non-splat builtin: chop off the "_n" suffix from the name.
1304c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    assert(N.endswith("_n"));
1305c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    N = N.drop_back(2);
130651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
130751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
1308c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  ClassKind LocalCK = CK;
1309c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  if (!protoHasScalar())
1310c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    LocalCK = ClassB;
131151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
1312c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  if (!getReturnType().isVoid() && !SRet)
1313c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    S += "(" + RetVar.getType().str() + ") ";
131451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
1315c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  S += "__builtin_neon_" + mangleName(N, LocalCK) + "(";
1316912502b4996b14db31b498cb1eef2b17d7d66d57Hao Liu
1317c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  if (SRet)
1318c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    S += "&" + RetVar.getName() + ", ";
131951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
1320c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  for (unsigned I = 0; I < getNumParams(); ++I) {
1321c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    Variable &V = Variables["p" + utostr(I)];
1322c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    Type T = V.getType();
132351cc0172a173599b769968696e20638754d1dcd6Ana Pazos
1324c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    // Handle multiple-vector values specially, emitting each subvector as an
1325c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    // argument to the builtin.
1326c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    if (T.getNumVectors() > 1) {
1327c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      // Check if an explicit cast is needed.
1328c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      std::string Cast;
1329c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      if (T.isChar() || T.isPoly() || !T.isSigned()) {
1330c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        Type T2 = T;
1331c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        T2.makeOneVector();
1332c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        T2.makeInteger(8, /*Signed=*/true);
1333c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        Cast = "(" + T2.str() + ")";
1334c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      }
133551cc0172a173599b769968696e20638754d1dcd6Ana Pazos
1336c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      for (unsigned J = 0; J < T.getNumVectors(); ++J)
1337c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        S += Cast + V.getName() + ".val[" + utostr(J) + "], ";
1338c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      continue;
1339c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    }
1340651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
1341c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    std::string Arg;
1342c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    Type CastToType = T;
1343c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    if (hasSplat() && I == getSplatIdx()) {
1344c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      Arg = "(" + BaseType.str() + ") {";
1345c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      for (unsigned J = 0; J < BaseType.getNumElements(); ++J) {
1346c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        if (J != 0)
1347c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines          Arg += ", ";
1348c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        Arg += V.getName();
1349c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      }
1350c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      Arg += "}";
1351651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
1352c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      CastToType = BaseType;
1353c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    } else {
1354c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      Arg = V.getName();
1355c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    }
1356651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
1357c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    // Check if an explicit cast is needed.
1358c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    if (CastToType.isVector()) {
1359c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      CastToType.makeInteger(8, true);
1360c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      Arg = "(" + CastToType.str() + ")" + Arg;
1361c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    }
1362651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
1363c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    S += Arg + ", ";
1364696e2d735c38eb73f1628d9b6166565fec4b9f1bBill Wendling  }
1365651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
1366c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  // Extra constant integer to hold type class enum for this function, e.g. s8
1367c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  if (getClassKind(true) == ClassB) {
1368c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    Type ThisTy = getReturnType();
136987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    if (Proto[0] == 'v' || isFloatingPointProtoModifier(Proto[0]))
1370c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      ThisTy = getParamType(0);
1371c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    if (ThisTy.isPointer())
1372c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      ThisTy = getParamType(1);
1373c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
1374c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    S += utostr(ThisTy.getNeonEnum());
1375c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  } else {
1376c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    // Remove extraneous ", ".
1377c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    S.pop_back();
1378c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    S.pop_back();
1379c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  }
1380c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  S += ");";
1381651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
1382c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  std::string RetExpr;
1383c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  if (!SRet && !RetVar.getType().isVoid())
1384c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    RetExpr = RetVar.getName() + " = ";
1385651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
1386c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  OS << "  " << RetExpr << S;
1387c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  emitNewLine();
1388c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines}
1389651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
1390c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesvoid Intrinsic::emitBody(StringRef CallPrefix) {
1391c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  std::vector<std::string> Lines;
1392696e2d735c38eb73f1628d9b6166565fec4b9f1bBill Wendling
1393c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  assert(RetVar.getType() == Types[0]);
1394c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  // Create a return variable, if we're not void.
1395c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  if (!RetVar.getType().isVoid()) {
1396c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    OS << "  " << RetVar.getType().str() << " " << RetVar.getName() << ";";
1397c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    emitNewLine();
139851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
139951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
1400c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  if (!Body || Body->getValues().size() == 0) {
1401c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    // Nothing specific to output - must output a builtin.
1402c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    emitBodyAsBuiltinCall();
1403c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    return;
1404c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  }
140551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
1406c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  // We have a list of "things to output". The last should be returned.
1407c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  for (auto *I : Body->getValues()) {
1408c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    if (StringInit *SI = dyn_cast<StringInit>(I)) {
1409c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      Lines.push_back(replaceParamsIn(SI->getAsString()));
1410c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    } else if (DagInit *DI = dyn_cast<DagInit>(I)) {
1411c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      DagEmitter DE(*this, CallPrefix);
1412c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      Lines.push_back(DE.emitDag(DI).second + ";");
1413c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    }
1414c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  }
141551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
14160e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  assert(!Lines.empty() && "Empty def?");
1417c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  if (!RetVar.getType().isVoid())
1418c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    Lines.back().insert(0, RetVar.getName() + " = ");
141951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
1420c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  for (auto &L : Lines) {
1421c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    OS << "  " << L;
1422c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    emitNewLine();
1423c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  }
1424c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines}
142551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
1426c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesvoid Intrinsic::emitReturn() {
1427c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  if (RetVar.getType().isVoid())
1428c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    return;
1429c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  if (UseMacro)
1430c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    OS << "  " << RetVar.getName() << ";";
1431c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  else
1432c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    OS << "  return " << RetVar.getName() << ";";
1433c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  emitNewLine();
1434c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines}
143551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
1436c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesstd::pair<Type, std::string> Intrinsic::DagEmitter::emitDag(DagInit *DI) {
1437c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  // At this point we should only be seeing a def.
1438c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  DefInit *DefI = cast<DefInit>(DI->getOperator());
1439c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  std::string Op = DefI->getAsString();
1440c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
1441c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  if (Op == "cast" || Op == "bitcast")
1442c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    return emitDagCast(DI, Op == "bitcast");
1443c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  if (Op == "shuffle")
1444c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    return emitDagShuffle(DI);
1445c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  if (Op == "dup")
1446c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    return emitDagDup(DI);
1447c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  if (Op == "splat")
1448c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    return emitDagSplat(DI);
1449c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  if (Op == "save_temp")
1450c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    return emitDagSaveTemp(DI);
1451c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  if (Op == "op")
1452c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    return emitDagOp(DI);
1453c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  if (Op == "call")
1454c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    return emitDagCall(DI);
1455c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  if (Op == "name_replace")
1456c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    return emitDagNameReplace(DI);
1457c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  if (Op == "literal")
1458c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    return emitDagLiteral(DI);
1459c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  assert_with_loc(false, "Unknown operation!");
1460c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  return std::make_pair(Type::getVoid(), "");
146151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
146251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
1463c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesstd::pair<Type, std::string> Intrinsic::DagEmitter::emitDagOp(DagInit *DI) {
1464c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  std::string Op = cast<StringInit>(DI->getArg(0))->getAsUnquotedString();
1465c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  if (DI->getNumArgs() == 2) {
1466c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    // Unary op.
1467c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    std::pair<Type, std::string> R =
1468c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        emitDagArg(DI->getArg(1), DI->getArgName(1));
1469c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    return std::make_pair(R.first, Op + R.second);
1470c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  } else {
1471c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    assert(DI->getNumArgs() == 3 && "Can only handle unary and binary ops!");
1472c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    std::pair<Type, std::string> R1 =
1473c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        emitDagArg(DI->getArg(1), DI->getArgName(1));
1474c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    std::pair<Type, std::string> R2 =
1475c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        emitDagArg(DI->getArg(2), DI->getArgName(2));
1476c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    assert_with_loc(R1.first == R2.first, "Argument type mismatch!");
1477c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    return std::make_pair(R1.first, R1.second + " " + Op + " " + R2.second);
1478c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  }
14790391691f86fd2a75ef2413d0272bfaf920d0e2b5Jiangning Liu}
14800391691f86fd2a75ef2413d0272bfaf920d0e2b5Jiangning Liu
1481c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesstd::pair<Type, std::string> Intrinsic::DagEmitter::emitDagCall(DagInit *DI) {
1482c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  std::vector<Type> Types;
1483c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  std::vector<std::string> Values;
1484c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  for (unsigned I = 0; I < DI->getNumArgs() - 1; ++I) {
1485c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    std::pair<Type, std::string> R =
1486c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        emitDagArg(DI->getArg(I + 1), DI->getArgName(I + 1));
1487c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    Types.push_back(R.first);
1488c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    Values.push_back(R.second);
1489c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  }
149051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
1491c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  // Look up the called intrinsic.
1492c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  std::string N;
1493c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  if (StringInit *SI = dyn_cast<StringInit>(DI->getArg(0)))
1494c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    N = SI->getAsUnquotedString();
1495c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  else
1496c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    N = emitDagArg(DI->getArg(0), "").second;
149787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  Intrinsic &Callee = Intr.Emitter.getIntrinsic(N, Types);
149851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
1499c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  // Make sure the callee is known as an early def.
150087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  Callee.setNeededEarly();
150187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  Intr.Dependencies.insert(&Callee);
150251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
1503c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  // Now create the call itself.
150487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  std::string S = CallPrefix.str() + Callee.getMangledName(true) + "(";
1505c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  for (unsigned I = 0; I < DI->getNumArgs() - 1; ++I) {
1506c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    if (I != 0)
1507c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      S += ", ";
1508c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    S += Values[I];
1509c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  }
1510c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  S += ")";
151151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
151287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  return std::make_pair(Callee.getReturnType(), S);
1513c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines}
151451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
1515c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesstd::pair<Type, std::string> Intrinsic::DagEmitter::emitDagCast(DagInit *DI,
1516c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines                                                                bool IsBitCast){
1517c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  // (cast MOD* VAL) -> cast VAL to type given by MOD.
1518c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  std::pair<Type, std::string> R = emitDagArg(
1519c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      DI->getArg(DI->getNumArgs() - 1), DI->getArgName(DI->getNumArgs() - 1));
1520c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  Type castToType = R.first;
1521c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  for (unsigned ArgIdx = 0; ArgIdx < DI->getNumArgs() - 1; ++ArgIdx) {
1522c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
1523c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    // MOD can take several forms:
1524c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    //   1. $X - take the type of parameter / variable X.
1525c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    //   2. The value "R" - take the type of the return type.
1526c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    //   3. a type string
1527c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    //   4. The value "U" or "S" to switch the signedness.
1528c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    //   5. The value "H" or "D" to half or double the bitwidth.
1529c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    //   6. The value "8" to convert to 8-bit (signed) integer lanes.
1530c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    if (DI->getArgName(ArgIdx).size()) {
1531c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      assert_with_loc(Intr.Variables.find(DI->getArgName(ArgIdx)) !=
1532c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines                      Intr.Variables.end(),
1533c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines                      "Variable not found");
1534c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      castToType = Intr.Variables[DI->getArgName(ArgIdx)].getType();
153551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    } else {
1536c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      StringInit *SI = dyn_cast<StringInit>(DI->getArg(ArgIdx));
1537c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      assert_with_loc(SI, "Expected string type or $Name for cast type");
1538c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
1539c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      if (SI->getAsUnquotedString() == "R") {
1540c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        castToType = Intr.getReturnType();
1541c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      } else if (SI->getAsUnquotedString() == "U") {
1542c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        castToType.makeUnsigned();
1543c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      } else if (SI->getAsUnquotedString() == "S") {
1544c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        castToType.makeSigned();
1545c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      } else if (SI->getAsUnquotedString() == "H") {
1546c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        castToType.halveLanes();
1547c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      } else if (SI->getAsUnquotedString() == "D") {
1548c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        castToType.doubleLanes();
1549c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      } else if (SI->getAsUnquotedString() == "8") {
1550c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        castToType.makeInteger(8, true);
1551c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      } else {
1552c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        castToType = Type::fromTypedefName(SI->getAsUnquotedString());
1553c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        assert_with_loc(!castToType.isVoid(), "Unknown typedef");
1554c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      }
155551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
155651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
155751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
1558c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  std::string S;
1559c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  if (IsBitCast) {
1560c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    // Emit a reinterpret cast. The second operand must be an lvalue, so create
1561c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    // a temporary.
1562c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    std::string N = "reint";
1563c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    unsigned I = 0;
1564c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    while (Intr.Variables.find(N) != Intr.Variables.end())
1565c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      N = "reint" + utostr(++I);
1566c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    Intr.Variables[N] = Variable(R.first, N + Intr.VariablePostfix);
156751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
1568c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    Intr.OS << R.first.str() << " " << Intr.Variables[N].getName() << " = "
1569c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines            << R.second << ";";
1570c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    Intr.emitNewLine();
1571c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
1572c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    S = "*(" + castToType.str() + " *) &" + Intr.Variables[N].getName() + "";
157351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  } else {
1574c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    // Emit a normal (static) cast.
1575c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    S = "(" + castToType.str() + ")(" + R.second + ")";
157651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
157751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
1578c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  return std::make_pair(castToType, S);
1579c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines}
158051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
1581c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesstd::pair<Type, std::string> Intrinsic::DagEmitter::emitDagShuffle(DagInit *DI){
1582c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  // See the documentation in arm_neon.td for a description of these operators.
1583c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  class LowHalf : public SetTheory::Operator {
1584c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  public:
158558878f85ab89b13e9eea4af3ccf055e42c557bc8Pirama Arumuga Nainar    void apply(SetTheory &ST, DagInit *Expr, SetTheory::RecSet &Elts,
158658878f85ab89b13e9eea4af3ccf055e42c557bc8Pirama Arumuga Nainar               ArrayRef<SMLoc> Loc) override {
1587c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      SetTheory::RecSet Elts2;
1588c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      ST.evaluate(Expr->arg_begin(), Expr->arg_end(), Elts2, Loc);
1589c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      Elts.insert(Elts2.begin(), Elts2.begin() + (Elts2.size() / 2));
15902e22f29b92768ea65ac5c26d354226ecc7509311Jiangning Liu    }
1591c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  };
1592c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  class HighHalf : public SetTheory::Operator {
1593c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  public:
159458878f85ab89b13e9eea4af3ccf055e42c557bc8Pirama Arumuga Nainar    void apply(SetTheory &ST, DagInit *Expr, SetTheory::RecSet &Elts,
159558878f85ab89b13e9eea4af3ccf055e42c557bc8Pirama Arumuga Nainar               ArrayRef<SMLoc> Loc) override {
1596c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      SetTheory::RecSet Elts2;
1597c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      ST.evaluate(Expr->arg_begin(), Expr->arg_end(), Elts2, Loc);
1598c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      Elts.insert(Elts2.begin() + (Elts2.size() / 2), Elts2.end());
1599c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    }
1600c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  };
1601c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  class Rev : public SetTheory::Operator {
1602c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    unsigned ElementSize;
1603c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
1604c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  public:
1605c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    Rev(unsigned ElementSize) : ElementSize(ElementSize) {}
160658878f85ab89b13e9eea4af3ccf055e42c557bc8Pirama Arumuga Nainar    void apply(SetTheory &ST, DagInit *Expr, SetTheory::RecSet &Elts,
160758878f85ab89b13e9eea4af3ccf055e42c557bc8Pirama Arumuga Nainar               ArrayRef<SMLoc> Loc) override {
1608c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      SetTheory::RecSet Elts2;
1609c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      ST.evaluate(Expr->arg_begin() + 1, Expr->arg_end(), Elts2, Loc);
1610c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
1611c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      int64_t VectorSize = cast<IntInit>(Expr->getArg(0))->getValue();
1612c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      VectorSize /= ElementSize;
1613c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
1614c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      std::vector<Record *> Revved;
1615c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      for (unsigned VI = 0; VI < Elts2.size(); VI += VectorSize) {
1616c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        for (int LI = VectorSize - 1; LI >= 0; --LI) {
1617c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines          Revved.push_back(Elts2[VI + LI]);
1618c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        }
161951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      }
162051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
1621c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      Elts.insert(Revved.begin(), Revved.end());
1622c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    }
1623c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  };
1624c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  class MaskExpander : public SetTheory::Expander {
1625c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    unsigned N;
1626c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
1627c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  public:
1628c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    MaskExpander(unsigned N) : N(N) {}
162958878f85ab89b13e9eea4af3ccf055e42c557bc8Pirama Arumuga Nainar    void expand(SetTheory &ST, Record *R, SetTheory::RecSet &Elts) override {
1630c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      unsigned Addend = 0;
1631c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      if (R->getName() == "mask0")
1632c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        Addend = 0;
1633c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      else if (R->getName() == "mask1")
1634c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        Addend = N;
1635c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      else
1636c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        return;
1637c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      for (unsigned I = 0; I < N; ++I)
1638c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        Elts.insert(R->getRecords().getDef("sv" + utostr(I + Addend)));
163951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
1640c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  };
164151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
1642c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  // (shuffle arg1, arg2, sequence)
1643c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  std::pair<Type, std::string> Arg1 =
1644c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      emitDagArg(DI->getArg(0), DI->getArgName(0));
1645c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  std::pair<Type, std::string> Arg2 =
1646c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      emitDagArg(DI->getArg(1), DI->getArgName(1));
1647c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  assert_with_loc(Arg1.first == Arg2.first,
1648c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines                  "Different types in arguments to shuffle!");
1649c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
1650c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  SetTheory ST;
1651c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  SetTheory::RecSet Elts;
1652b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar  ST.addOperator("lowhalf", llvm::make_unique<LowHalf>());
1653b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar  ST.addOperator("highhalf", llvm::make_unique<HighHalf>());
1654b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar  ST.addOperator("rev",
1655b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar                 llvm::make_unique<Rev>(Arg1.first.getElementSizeInBits()));
1656b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar  ST.addExpander("MaskExpand",
1657b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar                 llvm::make_unique<MaskExpander>(Arg1.first.getNumElements()));
1658176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  ST.evaluate(DI->getArg(2), Elts, None);
1659c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
1660c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  std::string S = "__builtin_shufflevector(" + Arg1.second + ", " + Arg2.second;
1661c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  for (auto &E : Elts) {
1662c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    StringRef Name = E->getName();
1663c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    assert_with_loc(Name.startswith("sv"),
1664c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines                    "Incorrect element kind in shuffle mask!");
1665c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    S += ", " + Name.drop_front(2).str();
1666c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  }
1667c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  S += ")";
1668c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
1669c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  // Recalculate the return type - the shuffle may have halved or doubled it.
1670c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  Type T(Arg1.first);
1671c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  if (Elts.size() > T.getNumElements()) {
1672c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    assert_with_loc(
1673c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        Elts.size() == T.getNumElements() * 2,
1674c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        "Can only double or half the number of elements in a shuffle!");
1675c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    T.doubleLanes();
1676c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  } else if (Elts.size() < T.getNumElements()) {
1677c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    assert_with_loc(
1678c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        Elts.size() == T.getNumElements() / 2,
1679c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        "Can only double or half the number of elements in a shuffle!");
1680c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    T.halveLanes();
1681c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  }
1682c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
1683c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  return std::make_pair(T, S);
1684c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines}
168551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
1686c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesstd::pair<Type, std::string> Intrinsic::DagEmitter::emitDagDup(DagInit *DI) {
1687c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  assert_with_loc(DI->getNumArgs() == 1, "dup() expects one argument");
1688c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  std::pair<Type, std::string> A = emitDagArg(DI->getArg(0), DI->getArgName(0));
1689c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  assert_with_loc(A.first.isScalar(), "dup() expects a scalar argument");
169051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
1691c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  Type T = Intr.getBaseType();
1692c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  assert_with_loc(T.isVector(), "dup() used but default type is scalar!");
1693c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  std::string S = "(" + T.str() + ") {";
1694c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  for (unsigned I = 0; I < T.getNumElements(); ++I) {
1695c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    if (I != 0)
1696c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      S += ", ";
1697c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    S += A.second;
169851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
1699c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  S += "}";
170051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
1701c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  return std::make_pair(T, S);
1702c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines}
170351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
1704c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesstd::pair<Type, std::string> Intrinsic::DagEmitter::emitDagSplat(DagInit *DI) {
1705c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  assert_with_loc(DI->getNumArgs() == 2, "splat() expects two arguments");
1706c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  std::pair<Type, std::string> A = emitDagArg(DI->getArg(0), DI->getArgName(0));
1707c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  std::pair<Type, std::string> B = emitDagArg(DI->getArg(1), DI->getArgName(1));
170851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
1709c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  assert_with_loc(B.first.isScalar(),
1710c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines                  "splat() requires a scalar int as the second argument");
1711c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
1712c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  std::string S = "__builtin_shufflevector(" + A.second + ", " + A.second;
1713c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  for (unsigned I = 0; I < Intr.getBaseType().getNumElements(); ++I) {
1714c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    S += ", " + B.second;
171551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
1716c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  S += ")";
1717c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
1718c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  return std::make_pair(Intr.getBaseType(), S);
171951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
172051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
1721c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesstd::pair<Type, std::string> Intrinsic::DagEmitter::emitDagSaveTemp(DagInit *DI) {
1722c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  assert_with_loc(DI->getNumArgs() == 2, "save_temp() expects two arguments");
1723c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  std::pair<Type, std::string> A = emitDagArg(DI->getArg(1), DI->getArgName(1));
172451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
1725c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  assert_with_loc(!A.first.isVoid(),
1726c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines                  "Argument to save_temp() must have non-void type!");
172751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
1728c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  std::string N = DI->getArgName(0);
1729c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  assert_with_loc(N.size(), "save_temp() expects a name as the first argument");
173051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
1731c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  assert_with_loc(Intr.Variables.find(N) == Intr.Variables.end(),
1732c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines                  "Variable already defined!");
1733c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  Intr.Variables[N] = Variable(A.first, N + Intr.VariablePostfix);
173451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
1735c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  std::string S =
1736c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      A.first.str() + " " + Intr.Variables[N].getName() + " = " + A.second;
173751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
1738c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  return std::make_pair(Type::getVoid(), S);
173951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
174051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
1741c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesstd::pair<Type, std::string>
1742c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen HinesIntrinsic::DagEmitter::emitDagNameReplace(DagInit *DI) {
1743c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  std::string S = Intr.Name;
174451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
1745c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  assert_with_loc(DI->getNumArgs() == 2, "name_replace requires 2 arguments!");
1746c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  std::string ToReplace = cast<StringInit>(DI->getArg(0))->getAsUnquotedString();
1747c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  std::string ReplaceWith = cast<StringInit>(DI->getArg(1))->getAsUnquotedString();
174851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
1749c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  size_t Idx = S.find(ToReplace);
175051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
1751c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  assert_with_loc(Idx != std::string::npos, "name should contain '" + ToReplace + "'!");
1752c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  S.replace(Idx, ToReplace.size(), ReplaceWith);
175351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
1754c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  return std::make_pair(Type::getVoid(), S);
1755c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines}
175651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
1757c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesstd::pair<Type, std::string> Intrinsic::DagEmitter::emitDagLiteral(DagInit *DI){
1758c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  std::string Ty = cast<StringInit>(DI->getArg(0))->getAsUnquotedString();
1759c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  std::string Value = cast<StringInit>(DI->getArg(1))->getAsUnquotedString();
1760c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  return std::make_pair(Type::fromTypedefName(Ty), Value);
1761c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines}
1762b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
1763c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesstd::pair<Type, std::string>
1764c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen HinesIntrinsic::DagEmitter::emitDagArg(Init *Arg, std::string ArgName) {
1765c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  if (ArgName.size()) {
1766c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    assert_with_loc(!Arg->isComplete(),
1767c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines                    "Arguments must either be DAGs or names, not both!");
1768c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    assert_with_loc(Intr.Variables.find(ArgName) != Intr.Variables.end(),
1769c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines                    "Variable not defined!");
1770c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    Variable &V = Intr.Variables[ArgName];
1771c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    return std::make_pair(V.getType(), V.getName());
1772c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  }
1773b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
1774c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  assert(Arg && "Neither ArgName nor Arg?!");
1775c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  DagInit *DI = dyn_cast<DagInit>(Arg);
1776c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  assert_with_loc(DI, "Arguments must either be DAGs or names!");
177751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
1778c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  return emitDag(DI);
1779c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines}
178051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
1781c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesstd::string Intrinsic::generate() {
1782c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  // Little endian intrinsics are simple and don't require any argument
1783c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  // swapping.
1784c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  OS << "#ifdef __LITTLE_ENDIAN__\n";
1785b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
1786c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  generateImpl(false, "", "");
178751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
1788c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  OS << "#else\n";
178951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
1790c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  // Big endian intrinsics are more complex. The user intended these
1791c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  // intrinsics to operate on a vector "as-if" loaded by (V)LDR,
1792c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  // but we load as-if (V)LD1. So we should swap all arguments and
1793c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  // swap the return value too.
1794c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  //
1795c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  // If we call sub-intrinsics, we should call a version that does
1796c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  // not re-swap the arguments!
1797c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  generateImpl(true, "", "__noswap_");
1798b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
1799c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  // If we're needed early, create a non-swapping variant for
1800c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  // big-endian.
1801c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  if (NeededEarly) {
1802c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    generateImpl(false, "__noswap_", "__noswap_");
180351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
1804c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  OS << "#endif\n\n";
1805b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
1806c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  return OS.str();
1807c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines}
180851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
1809c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesvoid Intrinsic::generateImpl(bool ReverseArguments,
1810c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines                             StringRef NamePrefix, StringRef CallPrefix) {
1811c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  CurrentRecord = R;
181251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
1813c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  // If we call a macro, our local variables may be corrupted due to
1814c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  // lack of proper lexical scoping. So, add a globally unique postfix
1815c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  // to every variable.
1816c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  //
1817c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  // indexBody() should have set up the Dependencies set by now.
1818c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  for (auto *I : Dependencies)
1819c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    if (I->UseMacro) {
1820c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      VariablePostfix = "_" + utostr(Emitter.getUniqueNumber());
1821c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      break;
1822c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    }
182351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
1824c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  initVariables();
1825b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
1826c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  emitPrototype(NamePrefix);
1827b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
1828c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  if (IsUnavailable) {
1829c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    OS << " __attribute__((unavailable));";
1830c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  } else {
1831c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    emitOpeningBrace();
1832c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    emitShadowedArgs();
1833c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    if (ReverseArguments)
1834c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      emitArgumentReversal();
1835c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    emitBody(CallPrefix);
1836c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    if (ReverseArguments)
1837c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      emitReturnReversal();
1838c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    emitReturn();
1839c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    emitClosingBrace();
184051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
1841c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  OS << "\n";
184251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
1843c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  CurrentRecord = nullptr;
1844c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines}
1845315007b1d459846fcc8fd842a63fbcaad6008ec2Jiangning Liu
1846c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesvoid Intrinsic::indexBody() {
1847c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  CurrentRecord = R;
1848315007b1d459846fcc8fd842a63fbcaad6008ec2Jiangning Liu
1849c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  initVariables();
1850c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  emitBody("");
1851c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  OS.str("");
1852315007b1d459846fcc8fd842a63fbcaad6008ec2Jiangning Liu
1853c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  CurrentRecord = nullptr;
1854651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines}
1855315007b1d459846fcc8fd842a63fbcaad6008ec2Jiangning Liu
1856c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines//===----------------------------------------------------------------------===//
1857c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines// NeonEmitter implementation
1858c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines//===----------------------------------------------------------------------===//
1859c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
186087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga NainarIntrinsic &NeonEmitter::getIntrinsic(StringRef Name, ArrayRef<Type> Types) {
1861c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  // First, look up the name in the intrinsic map.
1862c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  assert_with_loc(IntrinsicMap.find(Name.str()) != IntrinsicMap.end(),
1863c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines                  ("Intrinsic '" + Name + "' not found!").str());
186487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  auto &V = IntrinsicMap.find(Name.str())->second;
1865c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  std::vector<Intrinsic *> GoodVec;
1866c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
1867c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  // Create a string to print if we end up failing.
1868c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  std::string ErrMsg = "looking up intrinsic '" + Name.str() + "(";
1869c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  for (unsigned I = 0; I < Types.size(); ++I) {
1870c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    if (I != 0)
1871c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      ErrMsg += ", ";
1872c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    ErrMsg += Types[I].str();
1873c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  }
1874c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  ErrMsg += ")'\n";
1875c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  ErrMsg += "Available overloads:\n";
1876c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
1877c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  // Now, look through each intrinsic implementation and see if the types are
1878c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  // compatible.
187987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  for (auto &I : V) {
188087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    ErrMsg += "  - " + I.getReturnType().str() + " " + I.getMangledName();
1881c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    ErrMsg += "(";
188287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    for (unsigned A = 0; A < I.getNumParams(); ++A) {
1883c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      if (A != 0)
1884c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        ErrMsg += ", ";
188587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      ErrMsg += I.getParamType(A).str();
1886c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    }
1887c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    ErrMsg += ")\n";
1888315007b1d459846fcc8fd842a63fbcaad6008ec2Jiangning Liu
188987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    if (I.getNumParams() != Types.size())
1890c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      continue;
1891b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
1892c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    bool Good = true;
1893c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    for (unsigned Arg = 0; Arg < Types.size(); ++Arg) {
189487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      if (I.getParamType(Arg) != Types[Arg]) {
1895c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        Good = false;
1896c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        break;
1897c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      }
1898c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    }
1899c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    if (Good)
190087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      GoodVec.push_back(&I);
1901651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  }
1902b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
1903c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  assert_with_loc(GoodVec.size() > 0,
1904c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines                  "No compatible intrinsic found - " + ErrMsg);
1905c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  assert_with_loc(GoodVec.size() == 1, "Multiple overloads found - " + ErrMsg);
1906c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
190787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  return *GoodVec.front();
190851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
190951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
1910c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesvoid NeonEmitter::createIntrinsic(Record *R,
1911c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines                                  SmallVectorImpl<Intrinsic *> &Out) {
1912c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  std::string Name = R->getValueAsString("Name");
191351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string Proto = R->getValueAsString("Prototype");
191451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string Types = R->getValueAsString("Types");
1915c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  Record *OperationRec = R->getValueAsDef("Operation");
1916c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  bool CartesianProductOfTypes = R->getValueAsBit("CartesianProductOfTypes");
1917c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  bool BigEndianSafe  = R->getValueAsBit("BigEndianSafe");
1918c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  std::string Guard = R->getValueAsString("ArchGuard");
1919c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  bool IsUnavailable = OperationRec->getValueAsBit("Unavailable");
1920c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
1921c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  // Set the global current record. This allows assert_with_loc to produce
1922c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  // decent location information even when highly nested.
1923c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  CurrentRecord = R;
192451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
1925c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  ListInit *Body = OperationRec->getValueAsListInit("Ops");
192651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
1927c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  std::vector<TypeSpec> TypeSpecs = TypeSpec::fromTypeSpecs(Types);
192851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
1929c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  ClassKind CK = ClassNone;
193051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (R->getSuperClasses().size() >= 2)
19314967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar    CK = ClassMap[R->getSuperClasses()[1].first];
1932c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
1933c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  std::vector<std::pair<TypeSpec, TypeSpec>> NewTypeSpecs;
1934c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  for (auto TS : TypeSpecs) {
1935c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    if (CartesianProductOfTypes) {
1936c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      Type DefaultT(TS, 'd');
1937c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      for (auto SrcTS : TypeSpecs) {
1938c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        Type DefaultSrcT(SrcTS, 'd');
1939c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        if (TS == SrcTS ||
1940c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines            DefaultSrcT.getSizeInBits() != DefaultT.getSizeInBits())
194151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne          continue;
1942c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        NewTypeSpecs.push_back(std::make_pair(TS, SrcTS));
194351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      }
194451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    } else {
1945c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      NewTypeSpecs.push_back(std::make_pair(TS, TS));
194651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
194751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
194851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
1949c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  std::sort(NewTypeSpecs.begin(), NewTypeSpecs.end());
195058878f85ab89b13e9eea4af3ccf055e42c557bc8Pirama Arumuga Nainar  NewTypeSpecs.erase(std::unique(NewTypeSpecs.begin(), NewTypeSpecs.end()),
195158878f85ab89b13e9eea4af3ccf055e42c557bc8Pirama Arumuga Nainar		     NewTypeSpecs.end());
195287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  auto &Entry = IntrinsicMap[Name];
195351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
1954c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  for (auto &I : NewTypeSpecs) {
195587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    Entry.emplace_back(R, Name, Proto, I.first, I.second, CK, Body, *this,
195687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar                       Guard, IsUnavailable, BigEndianSafe);
195787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    Out.push_back(&Entry.back());
1958f42727215f9fa38175d2e84a938c84122cd1e811Chad Rosier  }
1959f42727215f9fa38175d2e84a938c84122cd1e811Chad Rosier
1960c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  CurrentRecord = nullptr;
1961c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines}
196251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
1963c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines/// genBuiltinsDef: Generate the BuiltinsARM.def and  BuiltinsAArch64.def
1964c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines/// declaration of builtins, checking for unique builtin declarations.
1965c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesvoid NeonEmitter::genBuiltinsDef(raw_ostream &OS,
1966c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines                                 SmallVectorImpl<Intrinsic *> &Defs) {
1967c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  OS << "#ifdef GET_NEON_BUILTINS\n";
1968b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
1969c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  // We only want to emit a builtin once, and we want to emit them in
1970c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  // alphabetical order, so use a std::set.
1971c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  std::set<std::string> Builtins;
1972b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
1973c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  for (auto *Def : Defs) {
1974c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    if (Def->hasBody())
197551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      continue;
197651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // Functions with 'a' (the splat code) in the type prototype should not get
197751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // their own builtin as they use the non-splat variant.
1978c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    if (Def->hasSplat())
197951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      continue;
198051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
1981c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    std::string S = "BUILTIN(__builtin_neon_" + Def->getMangledName() + ", \"";
1982b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
1983c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    S += Def->getBuiltinTypeStr();
1984c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    S += "\", \"n\")";
1985c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
1986c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    Builtins.insert(S);
198751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
1988c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
1989c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  for (auto &S : Builtins)
1990c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    OS << S << "\n";
199151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#endif\n\n";
1992b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover}
1993b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
1994b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover/// Generate the ARM and AArch64 overloaded type checking code for
1995b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover/// SemaChecking.cpp, checking for unique builtin declarations.
1996c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesvoid NeonEmitter::genOverloadTypeCheckCode(raw_ostream &OS,
1997c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines                                           SmallVectorImpl<Intrinsic *> &Defs) {
1998651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  OS << "#ifdef GET_NEON_OVERLOAD_CHECK\n";
1999651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
2000651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // We record each overload check line before emitting because subsequent Inst
2001651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // definitions may extend the number of permitted types (i.e. augment the
2002651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // Mask). Use std::map to avoid sorting the table by hash number.
2003c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  struct OverloadInfo {
2004c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    uint64_t Mask;
2005c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    int PtrArgNum;
2006c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    bool HasConstPtr;
2007c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    OverloadInfo() : Mask(0ULL), PtrArgNum(0), HasConstPtr(false) {}
2008c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  };
2009651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  std::map<std::string, OverloadInfo> OverloadMap;
2010b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
2011c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  for (auto *Def : Defs) {
2012c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    // If the def has a body (that is, it has Operation DAGs), it won't call
2013c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    // __builtin_neon_* so we don't need to generate a definition for it.
2014c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    if (Def->hasBody())
201551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      continue;
201651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // Functions with 'a' (the splat code) in the type prototype should not get
201751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // their own builtin as they use the non-splat variant.
2018c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    if (Def->hasSplat())
201951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      continue;
202051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // Functions which have a scalar argument cannot be overloaded, no need to
202151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // check them if we are emitting the type checking code.
2022c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    if (Def->protoHasScalar())
202351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      continue;
202451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
2025c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    uint64_t Mask = 0ULL;
2026c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    Type Ty = Def->getReturnType();
202787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    if (Def->getProto()[0] == 'v' ||
202887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar        isFloatingPointProtoModifier(Def->getProto()[0]))
2029c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      Ty = Def->getParamType(0);
2030c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    if (Ty.isPointer())
2031c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      Ty = Def->getParamType(1);
203251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
2033c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    Mask |= 1ULL << Ty.getNeonEnum();
20344648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson
2035c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    // Check if the function has a pointer or const pointer argument.
2036c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    std::string Proto = Def->getProto();
20374648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson    int PtrArgNum = -1;
20384648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson    bool HasConstPtr = false;
2039c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    for (unsigned I = 0; I < Def->getNumParams(); ++I) {
2040c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      char ArgType = Proto[I + 1];
20414648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson      if (ArgType == 'c') {
20424648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson        HasConstPtr = true;
2043c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        PtrArgNum = I;
20444648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson        break;
20454648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson      }
20464648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson      if (ArgType == 'p') {
2047c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        PtrArgNum = I;
20484648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson        break;
20494648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson      }
20504648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson    }
20514648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson    // For sret builtins, adjust the pointer argument index.
2052c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    if (PtrArgNum >= 0 && Def->getReturnType().getNumVectors() > 1)
20534648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson      PtrArgNum += 1;
20544648255cebd2fc7c18293c1f93afd6e9add9ccccBob Wilson
2055c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    std::string Name = Def->getName();
20569082cddf28e03c2f718e92457e2d9c7390056b2dBob Wilson    // Omit type checking for the pointer arguments of vld1_lane, vld1_dup,
20579082cddf28e03c2f718e92457e2d9c7390056b2dBob Wilson    // and vst1_lane intrinsics.  Using a pointer to the vector element
20589082cddf28e03c2f718e92457e2d9c7390056b2dBob Wilson    // type with one of those operations causes codegen to select an aligned
20599082cddf28e03c2f718e92457e2d9c7390056b2dBob Wilson    // load/store instruction.  If you want an unaligned operation,
20609082cddf28e03c2f718e92457e2d9c7390056b2dBob Wilson    // the pointer argument needs to have less alignment than element type,
20619082cddf28e03c2f718e92457e2d9c7390056b2dBob Wilson    // so just accept any pointer type.
2062c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    if (Name == "vld1_lane" || Name == "vld1_dup" || Name == "vst1_lane") {
20639082cddf28e03c2f718e92457e2d9c7390056b2dBob Wilson      PtrArgNum = -1;
20649082cddf28e03c2f718e92457e2d9c7390056b2dBob Wilson      HasConstPtr = false;
20659082cddf28e03c2f718e92457e2d9c7390056b2dBob Wilson    }
20669082cddf28e03c2f718e92457e2d9c7390056b2dBob Wilson
2067c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    if (Mask) {
2068c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      std::string Name = Def->getMangledName();
2069c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      OverloadMap.insert(std::make_pair(Name, OverloadInfo()));
2070c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      OverloadInfo &OI = OverloadMap[Name];
2071c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      OI.Mask |= Mask;
2072c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      OI.PtrArgNum |= PtrArgNum;
2073c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      OI.HasConstPtr = HasConstPtr;
20746f9f03ef370ad48ece0c5d10edda28f39ccadb5dBob Wilson    }
207551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
2076651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
2077c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  for (auto &I : OverloadMap) {
2078c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    OverloadInfo &OI = I.second;
2079c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
2080c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    OS << "case NEON::BI__builtin_neon_" << I.first << ": ";
2081c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    OS << "mask = 0x" << utohexstr(OI.Mask) << "ULL";
2082c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    if (OI.PtrArgNum >= 0)
2083c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      OS << "; PtrArgNum = " << OI.PtrArgNum;
2084c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    if (OI.HasConstPtr)
2085651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      OS << "; HasConstPtr = true";
2086651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    OS << "; break;\n";
2087651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  }
208851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#endif\n\n";
2089b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover}
2090b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
2091c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesvoid
2092c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen HinesNeonEmitter::genIntrinsicRangeCheckCode(raw_ostream &OS,
2093c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines                                        SmallVectorImpl<Intrinsic *> &Defs) {
2094c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  OS << "#ifdef GET_NEON_IMMEDIATE_CHECK\n";
2095b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
2096c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  std::set<std::string> Emitted;
209751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
2098c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  for (auto *Def : Defs) {
2099c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    if (Def->hasBody())
210051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      continue;
210151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // Functions with 'a' (the splat code) in the type prototype should not get
210251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // their own builtin as they use the non-splat variant.
2103c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    if (Def->hasSplat())
2104c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      continue;
2105176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    // Functions which do not have an immediate do not need to have range
2106176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    // checking code emitted.
2107c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    if (!Def->hasImmediate())
2108c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      continue;
2109c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    if (Emitted.find(Def->getMangledName()) != Emitted.end())
211051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      continue;
211151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
2112c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    std::string LowerBound, UpperBound;
211351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
2114c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    Record *R = Def->getRecord();
2115c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    if (R->getValueAsBit("isVCVT_N")) {
2116c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      // VCVT between floating- and fixed-point values takes an immediate
2117c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      // in the range [1, 32) for f32 or [1, 64) for f64.
2118c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      LowerBound = "1";
2119c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      if (Def->getBaseType().getElementSizeInBits() == 32)
2120c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        UpperBound = "31";
2121c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      else
2122c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        UpperBound = "63";
2123c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    } else if (R->getValueAsBit("isScalarShift")) {
2124c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      // Right shifts have an 'r' in the name, left shifts do not. Convert
2125c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      // instructions have the same bounds and right shifts.
2126c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      if (Def->getName().find('r') != std::string::npos ||
2127c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines          Def->getName().find("cvt") != std::string::npos)
2128c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        LowerBound = "1";
2129c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
2130c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      UpperBound = utostr(Def->getReturnType().getElementSizeInBits() - 1);
2131c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    } else if (R->getValueAsBit("isShift")) {
2132176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      // Builtins which are overloaded by type will need to have their upper
2133c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      // bound computed at Sema time based on the type constant.
2134c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
2135c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      // Right shifts have an 'r' in the name, left shifts do not.
2136c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      if (Def->getName().find('r') != std::string::npos)
2137c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        LowerBound = "1";
2138c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      UpperBound = "RFT(TV, true)";
2139c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    } else if (Def->getClassKind(true) == ClassB) {
2140c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      // ClassB intrinsics have a type (and hence lane number) that is only
2141c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      // known at runtime.
2142c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      if (R->getValueAsBit("isLaneQ"))
2143c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        UpperBound = "RFT(TV, false, true)";
2144c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      else
2145c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        UpperBound = "RFT(TV, false, false)";
2146c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    } else {
2147c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      // The immediate generally refers to a lane in the preceding argument.
2148c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      assert(Def->getImmediateIdx() > 0);
2149c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      Type T = Def->getParamType(Def->getImmediateIdx() - 1);
2150c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      UpperBound = utostr(T.getNumElements() - 1);
2151c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    }
215251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
2153c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    // Calculate the index of the immediate that should be range checked.
2154c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    unsigned Idx = Def->getNumParams();
2155c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    if (Def->hasImmediate())
2156c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      Idx = Def->getGeneratedParamIdx(Def->getImmediateIdx());
215751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
2158c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    OS << "case NEON::BI__builtin_neon_" << Def->getMangledName() << ": "
2159c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines       << "i = " << Idx << ";";
2160c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    if (LowerBound.size())
2161c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      OS << " l = " << LowerBound << ";";
2162c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    if (UpperBound.size())
2163c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      OS << " u = " << UpperBound << ";";
2164c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    OS << " break;\n";
216551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
2166c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    Emitted.insert(Def->getMangledName());
216751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
2168651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
216951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#endif\n\n";
217051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
217151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
2172b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover/// runHeader - Emit a file with sections defining:
2173b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover/// 1. the NEON section of BuiltinsARM.def and BuiltinsAArch64.def.
2174b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover/// 2. the SemaChecking code for the type overload checking.
2175b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover/// 3. the SemaChecking code for validation of intrinsic immediate arguments.
2176b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northovervoid NeonEmitter::runHeader(raw_ostream &OS) {
2177b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  std::vector<Record *> RV = Records.getAllDerivedDefinitions("Inst");
2178b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
2179c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  SmallVector<Intrinsic *, 128> Defs;
2180c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  for (auto *R : RV)
2181c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    createIntrinsic(R, Defs);
2182c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
2183651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // Generate shared BuiltinsXXX.def
2184c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  genBuiltinsDef(OS, Defs);
2185b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
2186b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  // Generate ARM overloaded type checking code for SemaChecking.cpp
2187c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  genOverloadTypeCheckCode(OS, Defs);
2188b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
2189b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  // Generate ARM range checking code for shift/lane immediates.
2190c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  genIntrinsicRangeCheckCode(OS, Defs);
2191b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover}
2192b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
2193c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines/// run - Read the records in arm_neon.td and output arm_neon.h.  arm_neon.h
2194c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines/// is comprised of type definitions and function declarations.
2195c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesvoid NeonEmitter::run(raw_ostream &OS) {
2196c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  OS << "/*===---- arm_neon.h - ARM Neon intrinsics "
2197c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        "------------------------------"
2198c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        "---===\n"
2199c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        " *\n"
2200c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        " * Permission is hereby granted, free of charge, to any person "
2201c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        "obtaining "
2202c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        "a copy\n"
2203c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        " * of this software and associated documentation files (the "
2204c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        "\"Software\"),"
2205c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        " to deal\n"
2206c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        " * in the Software without restriction, including without limitation "
2207c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        "the "
2208c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        "rights\n"
2209c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        " * to use, copy, modify, merge, publish, distribute, sublicense, "
2210c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        "and/or sell\n"
2211c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        " * copies of the Software, and to permit persons to whom the Software "
2212c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        "is\n"
2213c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        " * furnished to do so, subject to the following conditions:\n"
2214c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        " *\n"
2215c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        " * The above copyright notice and this permission notice shall be "
2216c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        "included in\n"
2217c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        " * all copies or substantial portions of the Software.\n"
2218c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        " *\n"
2219c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        " * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, "
2220c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        "EXPRESS OR\n"
2221c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        " * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF "
2222c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        "MERCHANTABILITY,\n"
2223c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        " * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT "
2224c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        "SHALL THE\n"
2225c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        " * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR "
2226c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        "OTHER\n"
2227c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        " * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, "
2228c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        "ARISING FROM,\n"
2229c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        " * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER "
2230c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        "DEALINGS IN\n"
2231c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        " * THE SOFTWARE.\n"
2232c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        " *\n"
2233c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        " *===-----------------------------------------------------------------"
2234c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        "---"
2235c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        "---===\n"
2236c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        " */\n\n";
2237c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
2238c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  OS << "#ifndef __ARM_NEON_H\n";
2239c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  OS << "#define __ARM_NEON_H\n\n";
2240c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
2241c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  OS << "#if !defined(__ARM_NEON)\n";
2242c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  OS << "#error \"NEON support not enabled\"\n";
2243c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  OS << "#endif\n\n";
2244c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
2245c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  OS << "#include <stdint.h>\n\n";
2246c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
2247c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  // Emit NEON-specific scalar typedefs.
2248c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  OS << "typedef float float32_t;\n";
2249c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  OS << "typedef __fp16 float16_t;\n";
2250c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
2251c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  OS << "#ifdef __aarch64__\n";
2252c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  OS << "typedef double float64_t;\n";
2253c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  OS << "#endif\n\n";
2254c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
2255c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  // For now, signedness of polynomial types depends on target
2256c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  OS << "#ifdef __aarch64__\n";
2257c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  OS << "typedef uint8_t poly8_t;\n";
2258c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  OS << "typedef uint16_t poly16_t;\n";
2259c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  OS << "typedef uint64_t poly64_t;\n";
2260c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  OS << "typedef __uint128_t poly128_t;\n";
2261c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  OS << "#else\n";
2262c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  OS << "typedef int8_t poly8_t;\n";
2263c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  OS << "typedef int16_t poly16_t;\n";
2264c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  OS << "#endif\n";
2265c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
2266c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  // Emit Neon vector typedefs.
2267c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  std::string TypedefTypes(
2268c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      "cQcsQsiQilQlUcQUcUsQUsUiQUiUlQUlhQhfQfdQdPcQPcPsQPsPlQPl");
2269c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  std::vector<TypeSpec> TDTypeVec = TypeSpec::fromTypeSpecs(TypedefTypes);
2270c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
2271c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  // Emit vector typedefs.
2272c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  bool InIfdef = false;
2273c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  for (auto &TS : TDTypeVec) {
2274c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    bool IsA64 = false;
2275c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    Type T(TS, 'd');
2276c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    if (T.isDouble() || (T.isPoly() && T.isLong()))
2277c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      IsA64 = true;
2278c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
2279c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    if (InIfdef && !IsA64) {
2280c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      OS << "#endif\n";
2281c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      InIfdef = false;
2282c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    }
2283c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    if (!InIfdef && IsA64) {
2284c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      OS << "#ifdef __aarch64__\n";
2285c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      InIfdef = true;
2286c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman    }
2287c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
2288c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    if (T.isPoly())
2289c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      OS << "typedef __attribute__((neon_polyvector_type(";
2290c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    else
2291c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      OS << "typedef __attribute__((neon_vector_type(";
2292c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
2293c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    Type T2 = T;
2294c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    T2.makeScalar();
2295c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    OS << utostr(T.getNumElements()) << "))) ";
2296c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    OS << T2.str();
2297c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    OS << " " << T.str() << ";\n";
2298c327f8705ecb8753555822d479f899bd2234386dMichael Gottesman  }
2299c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  if (InIfdef)
2300c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    OS << "#endif\n";
2301c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  OS << "\n";
230251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
2303c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  // Emit struct typedefs.
2304c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  InIfdef = false;
2305c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  for (unsigned NumMembers = 2; NumMembers <= 4; ++NumMembers) {
2306c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    for (auto &TS : TDTypeVec) {
2307c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      bool IsA64 = false;
2308c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      Type T(TS, 'd');
2309c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      if (T.isDouble() || (T.isPoly() && T.isLong()))
2310c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        IsA64 = true;
2311c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
2312c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      if (InIfdef && !IsA64) {
2313c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        OS << "#endif\n";
2314c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        InIfdef = false;
2315c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      }
2316c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      if (!InIfdef && IsA64) {
2317c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        OS << "#ifdef __aarch64__\n";
2318c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        InIfdef = true;
2319c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      }
2320b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover
2321c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      char M = '2' + (NumMembers - 2);
2322c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      Type VT(TS, M);
2323c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      OS << "typedef struct " << VT.str() << " {\n";
2324c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      OS << "  " << T.str() << " val";
2325c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      OS << "[" << utostr(NumMembers) << "]";
2326c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      OS << ";\n} ";
2327c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      OS << VT.str() << ";\n";
2328c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      OS << "\n";
232951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
233051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
2331c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  if (InIfdef)
2332c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    OS << "#endif\n";
2333c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  OS << "\n";
233451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
2335c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  OS << "#define __ai static inline __attribute__((__always_inline__, "
2336c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        "__nodebug__))\n\n";
233751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
2338c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  SmallVector<Intrinsic *, 128> Defs;
2339b793f0d3448a15277cd6b6cc4ba558ded39a8084Tim Northover  std::vector<Record *> RV = Records.getAllDerivedDefinitions("Inst");
2340c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  for (auto *R : RV)
2341c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    createIntrinsic(R, Defs);
2342c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
2343c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  for (auto *I : Defs)
2344c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    I->indexBody();
2345c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
2346c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  std::stable_sort(
2347c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      Defs.begin(), Defs.end(),
2348c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      [](const Intrinsic *A, const Intrinsic *B) { return *A < *B; });
2349c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
2350c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  // Only emit a def when its requirements have been met.
2351c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  // FIXME: This loop could be made faster, but it's fast enough for now.
2352c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  bool MadeProgress = true;
2353c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  std::string InGuard = "";
2354c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  while (!Defs.empty() && MadeProgress) {
2355c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    MadeProgress = false;
2356c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
2357c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    for (SmallVector<Intrinsic *, 128>::iterator I = Defs.begin();
2358c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines         I != Defs.end(); /*No step*/) {
2359c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      bool DependenciesSatisfied = true;
2360c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      for (auto *II : (*I)->getDependencies()) {
2361c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        if (std::find(Defs.begin(), Defs.end(), II) != Defs.end())
2362c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines          DependenciesSatisfied = false;
2363c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      }
2364c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      if (!DependenciesSatisfied) {
2365c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        // Try the next one.
2366c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        ++I;
2367c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        continue;
2368c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      }
236951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
2370c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      // Emit #endif/#if pair if needed.
2371c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      if ((*I)->getGuard() != InGuard) {
2372c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        if (!InGuard.empty())
2373c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines          OS << "#endif\n";
2374c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        InGuard = (*I)->getGuard();
2375c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        if (!InGuard.empty())
2376c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines          OS << "#if " << InGuard << "\n";
237751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      }
2378c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
2379c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      // Actually generate the intrinsic code.
2380c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      OS << (*I)->generate();
2381c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
2382c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      MadeProgress = true;
2383c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      I = Defs.erase(I);
238451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
238551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
2386c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  assert(Defs.empty() && "Some requirements were not satisfied!");
2387c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  if (!InGuard.empty())
2388651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    OS << "#endif\n";
2389c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
2390c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  OS << "\n";
2391c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  OS << "#undef __ai\n\n";
2392c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  OS << "#endif /* __ARM_NEON_H */\n";
239351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
239451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
23953cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesennamespace clang {
23963cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesenvoid EmitNeon(RecordKeeper &Records, raw_ostream &OS) {
23973cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  NeonEmitter(Records).run(OS);
23983cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen}
23993cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesenvoid EmitNeonSema(RecordKeeper &Records, raw_ostream &OS) {
24003cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen  NeonEmitter(Records).runHeader(OS);
24013cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen}
24023cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesenvoid EmitNeonTest(RecordKeeper &Records, raw_ostream &OS) {
2403c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  llvm_unreachable("Neon test generation no longer implemented!");
24043cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen}
24053cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen} // End namespace clang
2406