xref: /freebsd-src/contrib/llvm-project/clang/utils/TableGen/SveEmitter.cpp (revision 5ffd83dbcc34f10e07f6d3e968ae6365869615f4)
1*5ffd83dbSDimitry Andric //===- SveEmitter.cpp - Generate arm_sve.h for use with clang -*- C++ -*-===//
2*5ffd83dbSDimitry Andric //
3*5ffd83dbSDimitry Andric //  Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*5ffd83dbSDimitry Andric //  See https://llvm.org/LICENSE.txt for license information.
5*5ffd83dbSDimitry Andric //  SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*5ffd83dbSDimitry Andric //
7*5ffd83dbSDimitry Andric //===----------------------------------------------------------------------===//
8*5ffd83dbSDimitry Andric //
9*5ffd83dbSDimitry Andric // This tablegen backend is responsible for emitting arm_sve.h, which includes
10*5ffd83dbSDimitry Andric // a declaration and definition of each function specified by the ARM C/C++
11*5ffd83dbSDimitry Andric // Language Extensions (ACLE).
12*5ffd83dbSDimitry Andric //
13*5ffd83dbSDimitry Andric // For details, visit:
14*5ffd83dbSDimitry Andric //  https://developer.arm.com/architectures/system-architectures/software-standards/acle
15*5ffd83dbSDimitry Andric //
16*5ffd83dbSDimitry Andric // Each SVE instruction is implemented in terms of 1 or more functions which
17*5ffd83dbSDimitry Andric // are suffixed with the element type of the input vectors.  Functions may be
18*5ffd83dbSDimitry Andric // implemented in terms of generic vector operations such as +, *, -, etc. or
19*5ffd83dbSDimitry Andric // by calling a __builtin_-prefixed function which will be handled by clang's
20*5ffd83dbSDimitry Andric // CodeGen library.
21*5ffd83dbSDimitry Andric //
22*5ffd83dbSDimitry Andric // See also the documentation in include/clang/Basic/arm_sve.td.
23*5ffd83dbSDimitry Andric //
24*5ffd83dbSDimitry Andric //===----------------------------------------------------------------------===//
25*5ffd83dbSDimitry Andric 
26*5ffd83dbSDimitry Andric #include "llvm/ADT/STLExtras.h"
27*5ffd83dbSDimitry Andric #include "llvm/ADT/StringMap.h"
28*5ffd83dbSDimitry Andric #include "llvm/ADT/ArrayRef.h"
29*5ffd83dbSDimitry Andric #include "llvm/ADT/StringExtras.h"
30*5ffd83dbSDimitry Andric #include "llvm/TableGen/Record.h"
31*5ffd83dbSDimitry Andric #include "llvm/TableGen/Error.h"
32*5ffd83dbSDimitry Andric #include <string>
33*5ffd83dbSDimitry Andric #include <sstream>
34*5ffd83dbSDimitry Andric #include <set>
35*5ffd83dbSDimitry Andric #include <cctype>
36*5ffd83dbSDimitry Andric #include <tuple>
37*5ffd83dbSDimitry Andric 
38*5ffd83dbSDimitry Andric using namespace llvm;
39*5ffd83dbSDimitry Andric 
40*5ffd83dbSDimitry Andric enum ClassKind {
41*5ffd83dbSDimitry Andric   ClassNone,
42*5ffd83dbSDimitry Andric   ClassS,     // signed/unsigned, e.g., "_s8", "_u8" suffix
43*5ffd83dbSDimitry Andric   ClassG,     // Overloaded name without type suffix
44*5ffd83dbSDimitry Andric };
45*5ffd83dbSDimitry Andric 
46*5ffd83dbSDimitry Andric using TypeSpec = std::string;
47*5ffd83dbSDimitry Andric 
48*5ffd83dbSDimitry Andric namespace {
49*5ffd83dbSDimitry Andric 
50*5ffd83dbSDimitry Andric class ImmCheck {
51*5ffd83dbSDimitry Andric   unsigned Arg;
52*5ffd83dbSDimitry Andric   unsigned Kind;
53*5ffd83dbSDimitry Andric   unsigned ElementSizeInBits;
54*5ffd83dbSDimitry Andric 
55*5ffd83dbSDimitry Andric public:
56*5ffd83dbSDimitry Andric   ImmCheck(unsigned Arg, unsigned Kind, unsigned ElementSizeInBits = 0)
57*5ffd83dbSDimitry Andric       : Arg(Arg), Kind(Kind), ElementSizeInBits(ElementSizeInBits) {}
58*5ffd83dbSDimitry Andric   ImmCheck(const ImmCheck &Other) = default;
59*5ffd83dbSDimitry Andric   ~ImmCheck() = default;
60*5ffd83dbSDimitry Andric 
61*5ffd83dbSDimitry Andric   unsigned getArg() const { return Arg; }
62*5ffd83dbSDimitry Andric   unsigned getKind() const { return Kind; }
63*5ffd83dbSDimitry Andric   unsigned getElementSizeInBits() const { return ElementSizeInBits; }
64*5ffd83dbSDimitry Andric };
65*5ffd83dbSDimitry Andric 
66*5ffd83dbSDimitry Andric class SVEType {
67*5ffd83dbSDimitry Andric   TypeSpec TS;
68*5ffd83dbSDimitry Andric   bool Float, Signed, Immediate, Void, Constant, Pointer, BFloat;
69*5ffd83dbSDimitry Andric   bool DefaultType, IsScalable, Predicate, PredicatePattern, PrefetchOp;
70*5ffd83dbSDimitry Andric   unsigned Bitwidth, ElementBitwidth, NumVectors;
71*5ffd83dbSDimitry Andric 
72*5ffd83dbSDimitry Andric public:
73*5ffd83dbSDimitry Andric   SVEType() : SVEType(TypeSpec(), 'v') {}
74*5ffd83dbSDimitry Andric 
75*5ffd83dbSDimitry Andric   SVEType(TypeSpec TS, char CharMod)
76*5ffd83dbSDimitry Andric       : TS(TS), Float(false), Signed(true), Immediate(false), Void(false),
77*5ffd83dbSDimitry Andric         Constant(false), Pointer(false), BFloat(false), DefaultType(false),
78*5ffd83dbSDimitry Andric         IsScalable(true), Predicate(false), PredicatePattern(false),
79*5ffd83dbSDimitry Andric         PrefetchOp(false), Bitwidth(128), ElementBitwidth(~0U), NumVectors(1) {
80*5ffd83dbSDimitry Andric     if (!TS.empty())
81*5ffd83dbSDimitry Andric       applyTypespec();
82*5ffd83dbSDimitry Andric     applyModifier(CharMod);
83*5ffd83dbSDimitry Andric   }
84*5ffd83dbSDimitry Andric 
85*5ffd83dbSDimitry Andric   bool isPointer() const { return Pointer; }
86*5ffd83dbSDimitry Andric   bool isVoidPointer() const { return Pointer && Void; }
87*5ffd83dbSDimitry Andric   bool isSigned() const { return Signed; }
88*5ffd83dbSDimitry Andric   bool isImmediate() const { return Immediate; }
89*5ffd83dbSDimitry Andric   bool isScalar() const { return NumVectors == 0; }
90*5ffd83dbSDimitry Andric   bool isVector() const { return NumVectors > 0; }
91*5ffd83dbSDimitry Andric   bool isScalableVector() const { return isVector() && IsScalable; }
92*5ffd83dbSDimitry Andric   bool isChar() const { return ElementBitwidth == 8; }
93*5ffd83dbSDimitry Andric   bool isVoid() const { return Void & !Pointer; }
94*5ffd83dbSDimitry Andric   bool isDefault() const { return DefaultType; }
95*5ffd83dbSDimitry Andric   bool isFloat() const { return Float && !BFloat; }
96*5ffd83dbSDimitry Andric   bool isBFloat() const { return BFloat && !Float; }
97*5ffd83dbSDimitry Andric   bool isFloatingPoint() const { return Float || BFloat; }
98*5ffd83dbSDimitry Andric   bool isInteger() const { return !isFloatingPoint() && !Predicate; }
99*5ffd83dbSDimitry Andric   bool isScalarPredicate() const {
100*5ffd83dbSDimitry Andric     return !isFloatingPoint() && Predicate && NumVectors == 0;
101*5ffd83dbSDimitry Andric   }
102*5ffd83dbSDimitry Andric   bool isPredicateVector() const { return Predicate; }
103*5ffd83dbSDimitry Andric   bool isPredicatePattern() const { return PredicatePattern; }
104*5ffd83dbSDimitry Andric   bool isPrefetchOp() const { return PrefetchOp; }
105*5ffd83dbSDimitry Andric   bool isConstant() const { return Constant; }
106*5ffd83dbSDimitry Andric   unsigned getElementSizeInBits() const { return ElementBitwidth; }
107*5ffd83dbSDimitry Andric   unsigned getNumVectors() const { return NumVectors; }
108*5ffd83dbSDimitry Andric 
109*5ffd83dbSDimitry Andric   unsigned getNumElements() const {
110*5ffd83dbSDimitry Andric     assert(ElementBitwidth != ~0U);
111*5ffd83dbSDimitry Andric     return Bitwidth / ElementBitwidth;
112*5ffd83dbSDimitry Andric   }
113*5ffd83dbSDimitry Andric   unsigned getSizeInBits() const {
114*5ffd83dbSDimitry Andric     return Bitwidth;
115*5ffd83dbSDimitry Andric   }
116*5ffd83dbSDimitry Andric 
117*5ffd83dbSDimitry Andric   /// Return the string representation of a type, which is an encoded
118*5ffd83dbSDimitry Andric   /// string for passing to the BUILTIN() macro in Builtins.def.
119*5ffd83dbSDimitry Andric   std::string builtin_str() const;
120*5ffd83dbSDimitry Andric 
121*5ffd83dbSDimitry Andric   /// Return the C/C++ string representation of a type for use in the
122*5ffd83dbSDimitry Andric   /// arm_sve.h header file.
123*5ffd83dbSDimitry Andric   std::string str() const;
124*5ffd83dbSDimitry Andric 
125*5ffd83dbSDimitry Andric private:
126*5ffd83dbSDimitry Andric   /// Creates the type based on the typespec string in TS.
127*5ffd83dbSDimitry Andric   void applyTypespec();
128*5ffd83dbSDimitry Andric 
129*5ffd83dbSDimitry Andric   /// Applies a prototype modifier to the type.
130*5ffd83dbSDimitry Andric   void applyModifier(char Mod);
131*5ffd83dbSDimitry Andric };
132*5ffd83dbSDimitry Andric 
133*5ffd83dbSDimitry Andric 
134*5ffd83dbSDimitry Andric class SVEEmitter;
135*5ffd83dbSDimitry Andric 
136*5ffd83dbSDimitry Andric /// The main grunt class. This represents an instantiation of an intrinsic with
137*5ffd83dbSDimitry Andric /// a particular typespec and prototype.
138*5ffd83dbSDimitry Andric class Intrinsic {
139*5ffd83dbSDimitry Andric   /// The unmangled name.
140*5ffd83dbSDimitry Andric   std::string Name;
141*5ffd83dbSDimitry Andric 
142*5ffd83dbSDimitry Andric   /// The name of the corresponding LLVM IR intrinsic.
143*5ffd83dbSDimitry Andric   std::string LLVMName;
144*5ffd83dbSDimitry Andric 
145*5ffd83dbSDimitry Andric   /// Intrinsic prototype.
146*5ffd83dbSDimitry Andric   std::string Proto;
147*5ffd83dbSDimitry Andric 
148*5ffd83dbSDimitry Andric   /// The base type spec for this intrinsic.
149*5ffd83dbSDimitry Andric   TypeSpec BaseTypeSpec;
150*5ffd83dbSDimitry Andric 
151*5ffd83dbSDimitry Andric   /// The base class kind. Most intrinsics use ClassS, which has full type
152*5ffd83dbSDimitry Andric   /// info for integers (_s32/_u32), or ClassG which is used for overloaded
153*5ffd83dbSDimitry Andric   /// intrinsics.
154*5ffd83dbSDimitry Andric   ClassKind Class;
155*5ffd83dbSDimitry Andric 
156*5ffd83dbSDimitry Andric   /// The architectural #ifdef guard.
157*5ffd83dbSDimitry Andric   std::string Guard;
158*5ffd83dbSDimitry Andric 
159*5ffd83dbSDimitry Andric   // The merge suffix such as _m, _x or _z.
160*5ffd83dbSDimitry Andric   std::string MergeSuffix;
161*5ffd83dbSDimitry Andric 
162*5ffd83dbSDimitry Andric   /// The types of return value [0] and parameters [1..].
163*5ffd83dbSDimitry Andric   std::vector<SVEType> Types;
164*5ffd83dbSDimitry Andric 
165*5ffd83dbSDimitry Andric   /// The "base type", which is VarType('d', BaseTypeSpec).
166*5ffd83dbSDimitry Andric   SVEType BaseType;
167*5ffd83dbSDimitry Andric 
168*5ffd83dbSDimitry Andric   uint64_t Flags;
169*5ffd83dbSDimitry Andric 
170*5ffd83dbSDimitry Andric   SmallVector<ImmCheck, 2> ImmChecks;
171*5ffd83dbSDimitry Andric 
172*5ffd83dbSDimitry Andric public:
173*5ffd83dbSDimitry Andric   Intrinsic(StringRef Name, StringRef Proto, uint64_t MergeTy,
174*5ffd83dbSDimitry Andric             StringRef MergeSuffix, uint64_t MemoryElementTy, StringRef LLVMName,
175*5ffd83dbSDimitry Andric             uint64_t Flags, ArrayRef<ImmCheck> ImmChecks, TypeSpec BT,
176*5ffd83dbSDimitry Andric             ClassKind Class, SVEEmitter &Emitter, StringRef Guard);
177*5ffd83dbSDimitry Andric 
178*5ffd83dbSDimitry Andric   ~Intrinsic()=default;
179*5ffd83dbSDimitry Andric 
180*5ffd83dbSDimitry Andric   std::string getName() const { return Name; }
181*5ffd83dbSDimitry Andric   std::string getLLVMName() const { return LLVMName; }
182*5ffd83dbSDimitry Andric   std::string getProto() const { return Proto; }
183*5ffd83dbSDimitry Andric   TypeSpec getBaseTypeSpec() const { return BaseTypeSpec; }
184*5ffd83dbSDimitry Andric   SVEType getBaseType() const { return BaseType; }
185*5ffd83dbSDimitry Andric 
186*5ffd83dbSDimitry Andric   StringRef getGuard() const { return Guard; }
187*5ffd83dbSDimitry Andric   ClassKind getClassKind() const { return Class; }
188*5ffd83dbSDimitry Andric 
189*5ffd83dbSDimitry Andric   SVEType getReturnType() const { return Types[0]; }
190*5ffd83dbSDimitry Andric   ArrayRef<SVEType> getTypes() const { return Types; }
191*5ffd83dbSDimitry Andric   SVEType getParamType(unsigned I) const { return Types[I + 1]; }
192*5ffd83dbSDimitry Andric   unsigned getNumParams() const { return Proto.size() - 1; }
193*5ffd83dbSDimitry Andric 
194*5ffd83dbSDimitry Andric   uint64_t getFlags() const { return Flags; }
195*5ffd83dbSDimitry Andric   bool isFlagSet(uint64_t Flag) const { return Flags & Flag;}
196*5ffd83dbSDimitry Andric 
197*5ffd83dbSDimitry Andric   ArrayRef<ImmCheck> getImmChecks() const { return ImmChecks; }
198*5ffd83dbSDimitry Andric 
199*5ffd83dbSDimitry Andric   /// Return the type string for a BUILTIN() macro in Builtins.def.
200*5ffd83dbSDimitry Andric   std::string getBuiltinTypeStr();
201*5ffd83dbSDimitry Andric 
202*5ffd83dbSDimitry Andric   /// Return the name, mangled with type information. The name is mangled for
203*5ffd83dbSDimitry Andric   /// ClassS, so will add type suffixes such as _u32/_s32.
204*5ffd83dbSDimitry Andric   std::string getMangledName() const { return mangleName(ClassS); }
205*5ffd83dbSDimitry Andric 
206*5ffd83dbSDimitry Andric   /// Returns true if the intrinsic is overloaded, in that it should also generate
207*5ffd83dbSDimitry Andric   /// a short form without the type-specifiers, e.g. 'svld1(..)' instead of
208*5ffd83dbSDimitry Andric   /// 'svld1_u32(..)'.
209*5ffd83dbSDimitry Andric   static bool isOverloadedIntrinsic(StringRef Name) {
210*5ffd83dbSDimitry Andric     auto BrOpen = Name.find("[");
211*5ffd83dbSDimitry Andric     auto BrClose = Name.find(']');
212*5ffd83dbSDimitry Andric     return BrOpen != std::string::npos && BrClose != std::string::npos;
213*5ffd83dbSDimitry Andric   }
214*5ffd83dbSDimitry Andric 
215*5ffd83dbSDimitry Andric   /// Return true if the intrinsic takes a splat operand.
216*5ffd83dbSDimitry Andric   bool hasSplat() const {
217*5ffd83dbSDimitry Andric     // These prototype modifiers are described in arm_sve.td.
218*5ffd83dbSDimitry Andric     return Proto.find_first_of("ajfrKLR@") != std::string::npos;
219*5ffd83dbSDimitry Andric   }
220*5ffd83dbSDimitry Andric 
221*5ffd83dbSDimitry Andric   /// Return the parameter index of the splat operand.
222*5ffd83dbSDimitry Andric   unsigned getSplatIdx() const {
223*5ffd83dbSDimitry Andric     // These prototype modifiers are described in arm_sve.td.
224*5ffd83dbSDimitry Andric     auto Idx = Proto.find_first_of("ajfrKLR@");
225*5ffd83dbSDimitry Andric     assert(Idx != std::string::npos && Idx > 0 &&
226*5ffd83dbSDimitry Andric            "Prototype has no splat operand");
227*5ffd83dbSDimitry Andric     return Idx - 1;
228*5ffd83dbSDimitry Andric   }
229*5ffd83dbSDimitry Andric 
230*5ffd83dbSDimitry Andric   /// Emits the intrinsic declaration to the ostream.
231*5ffd83dbSDimitry Andric   void emitIntrinsic(raw_ostream &OS) const;
232*5ffd83dbSDimitry Andric 
233*5ffd83dbSDimitry Andric private:
234*5ffd83dbSDimitry Andric   std::string getMergeSuffix() const { return MergeSuffix; }
235*5ffd83dbSDimitry Andric   std::string mangleName(ClassKind LocalCK) const;
236*5ffd83dbSDimitry Andric   std::string replaceTemplatedArgs(std::string Name, TypeSpec TS,
237*5ffd83dbSDimitry Andric                                    std::string Proto) const;
238*5ffd83dbSDimitry Andric };
239*5ffd83dbSDimitry Andric 
240*5ffd83dbSDimitry Andric class SVEEmitter {
241*5ffd83dbSDimitry Andric private:
242*5ffd83dbSDimitry Andric   // The reinterpret builtins are generated separately because they
243*5ffd83dbSDimitry Andric   // need the cross product of all types (121 functions in total),
244*5ffd83dbSDimitry Andric   // which is inconvenient to specify in the arm_sve.td file or
245*5ffd83dbSDimitry Andric   // generate in CGBuiltin.cpp.
246*5ffd83dbSDimitry Andric   struct ReinterpretTypeInfo {
247*5ffd83dbSDimitry Andric     const char *Suffix;
248*5ffd83dbSDimitry Andric     const char *Type;
249*5ffd83dbSDimitry Andric     const char *BuiltinType;
250*5ffd83dbSDimitry Andric   };
251*5ffd83dbSDimitry Andric   SmallVector<ReinterpretTypeInfo, 12> Reinterprets = {
252*5ffd83dbSDimitry Andric       {"s8", "svint8_t", "q16Sc"},   {"s16", "svint16_t", "q8Ss"},
253*5ffd83dbSDimitry Andric       {"s32", "svint32_t", "q4Si"},  {"s64", "svint64_t", "q2SWi"},
254*5ffd83dbSDimitry Andric       {"u8", "svuint8_t", "q16Uc"},  {"u16", "svuint16_t", "q8Us"},
255*5ffd83dbSDimitry Andric       {"u32", "svuint32_t", "q4Ui"}, {"u64", "svuint64_t", "q2UWi"},
256*5ffd83dbSDimitry Andric       {"f16", "svfloat16_t", "q8h"}, {"bf16", "svbfloat16_t", "q8y"},
257*5ffd83dbSDimitry Andric       {"f32", "svfloat32_t", "q4f"}, {"f64", "svfloat64_t", "q2d"}};
258*5ffd83dbSDimitry Andric 
259*5ffd83dbSDimitry Andric   RecordKeeper &Records;
260*5ffd83dbSDimitry Andric   llvm::StringMap<uint64_t> EltTypes;
261*5ffd83dbSDimitry Andric   llvm::StringMap<uint64_t> MemEltTypes;
262*5ffd83dbSDimitry Andric   llvm::StringMap<uint64_t> FlagTypes;
263*5ffd83dbSDimitry Andric   llvm::StringMap<uint64_t> MergeTypes;
264*5ffd83dbSDimitry Andric   llvm::StringMap<uint64_t> ImmCheckTypes;
265*5ffd83dbSDimitry Andric 
266*5ffd83dbSDimitry Andric public:
267*5ffd83dbSDimitry Andric   SVEEmitter(RecordKeeper &R) : Records(R) {
268*5ffd83dbSDimitry Andric     for (auto *RV : Records.getAllDerivedDefinitions("EltType"))
269*5ffd83dbSDimitry Andric       EltTypes[RV->getNameInitAsString()] = RV->getValueAsInt("Value");
270*5ffd83dbSDimitry Andric     for (auto *RV : Records.getAllDerivedDefinitions("MemEltType"))
271*5ffd83dbSDimitry Andric       MemEltTypes[RV->getNameInitAsString()] = RV->getValueAsInt("Value");
272*5ffd83dbSDimitry Andric     for (auto *RV : Records.getAllDerivedDefinitions("FlagType"))
273*5ffd83dbSDimitry Andric       FlagTypes[RV->getNameInitAsString()] = RV->getValueAsInt("Value");
274*5ffd83dbSDimitry Andric     for (auto *RV : Records.getAllDerivedDefinitions("MergeType"))
275*5ffd83dbSDimitry Andric       MergeTypes[RV->getNameInitAsString()] = RV->getValueAsInt("Value");
276*5ffd83dbSDimitry Andric     for (auto *RV : Records.getAllDerivedDefinitions("ImmCheckType"))
277*5ffd83dbSDimitry Andric       ImmCheckTypes[RV->getNameInitAsString()] = RV->getValueAsInt("Value");
278*5ffd83dbSDimitry Andric   }
279*5ffd83dbSDimitry Andric 
280*5ffd83dbSDimitry Andric   /// Returns the enum value for the immcheck type
281*5ffd83dbSDimitry Andric   unsigned getEnumValueForImmCheck(StringRef C) const {
282*5ffd83dbSDimitry Andric     auto It = ImmCheckTypes.find(C);
283*5ffd83dbSDimitry Andric     if (It != ImmCheckTypes.end())
284*5ffd83dbSDimitry Andric       return It->getValue();
285*5ffd83dbSDimitry Andric     llvm_unreachable("Unsupported imm check");
286*5ffd83dbSDimitry Andric   }
287*5ffd83dbSDimitry Andric 
288*5ffd83dbSDimitry Andric   /// Returns the enum value for the flag type
289*5ffd83dbSDimitry Andric   uint64_t getEnumValueForFlag(StringRef C) const {
290*5ffd83dbSDimitry Andric     auto Res = FlagTypes.find(C);
291*5ffd83dbSDimitry Andric     if (Res != FlagTypes.end())
292*5ffd83dbSDimitry Andric       return Res->getValue();
293*5ffd83dbSDimitry Andric     llvm_unreachable("Unsupported flag");
294*5ffd83dbSDimitry Andric   }
295*5ffd83dbSDimitry Andric 
296*5ffd83dbSDimitry Andric   // Returns the SVETypeFlags for a given value and mask.
297*5ffd83dbSDimitry Andric   uint64_t encodeFlag(uint64_t V, StringRef MaskName) const {
298*5ffd83dbSDimitry Andric     auto It = FlagTypes.find(MaskName);
299*5ffd83dbSDimitry Andric     if (It != FlagTypes.end()) {
300*5ffd83dbSDimitry Andric       uint64_t Mask = It->getValue();
301*5ffd83dbSDimitry Andric       unsigned Shift = llvm::countTrailingZeros(Mask);
302*5ffd83dbSDimitry Andric       return (V << Shift) & Mask;
303*5ffd83dbSDimitry Andric     }
304*5ffd83dbSDimitry Andric     llvm_unreachable("Unsupported flag");
305*5ffd83dbSDimitry Andric   }
306*5ffd83dbSDimitry Andric 
307*5ffd83dbSDimitry Andric   // Returns the SVETypeFlags for the given element type.
308*5ffd83dbSDimitry Andric   uint64_t encodeEltType(StringRef EltName) {
309*5ffd83dbSDimitry Andric     auto It = EltTypes.find(EltName);
310*5ffd83dbSDimitry Andric     if (It != EltTypes.end())
311*5ffd83dbSDimitry Andric       return encodeFlag(It->getValue(), "EltTypeMask");
312*5ffd83dbSDimitry Andric     llvm_unreachable("Unsupported EltType");
313*5ffd83dbSDimitry Andric   }
314*5ffd83dbSDimitry Andric 
315*5ffd83dbSDimitry Andric   // Returns the SVETypeFlags for the given memory element type.
316*5ffd83dbSDimitry Andric   uint64_t encodeMemoryElementType(uint64_t MT) {
317*5ffd83dbSDimitry Andric     return encodeFlag(MT, "MemEltTypeMask");
318*5ffd83dbSDimitry Andric   }
319*5ffd83dbSDimitry Andric 
320*5ffd83dbSDimitry Andric   // Returns the SVETypeFlags for the given merge type.
321*5ffd83dbSDimitry Andric   uint64_t encodeMergeType(uint64_t MT) {
322*5ffd83dbSDimitry Andric     return encodeFlag(MT, "MergeTypeMask");
323*5ffd83dbSDimitry Andric   }
324*5ffd83dbSDimitry Andric 
325*5ffd83dbSDimitry Andric   // Returns the SVETypeFlags for the given splat operand.
326*5ffd83dbSDimitry Andric   unsigned encodeSplatOperand(unsigned SplatIdx) {
327*5ffd83dbSDimitry Andric     assert(SplatIdx < 7 && "SplatIdx out of encodable range");
328*5ffd83dbSDimitry Andric     return encodeFlag(SplatIdx + 1, "SplatOperandMask");
329*5ffd83dbSDimitry Andric   }
330*5ffd83dbSDimitry Andric 
331*5ffd83dbSDimitry Andric   // Returns the SVETypeFlags value for the given SVEType.
332*5ffd83dbSDimitry Andric   uint64_t encodeTypeFlags(const SVEType &T);
333*5ffd83dbSDimitry Andric 
334*5ffd83dbSDimitry Andric   /// Emit arm_sve.h.
335*5ffd83dbSDimitry Andric   void createHeader(raw_ostream &o);
336*5ffd83dbSDimitry Andric 
337*5ffd83dbSDimitry Andric   /// Emit all the __builtin prototypes and code needed by Sema.
338*5ffd83dbSDimitry Andric   void createBuiltins(raw_ostream &o);
339*5ffd83dbSDimitry Andric 
340*5ffd83dbSDimitry Andric   /// Emit all the information needed to map builtin -> LLVM IR intrinsic.
341*5ffd83dbSDimitry Andric   void createCodeGenMap(raw_ostream &o);
342*5ffd83dbSDimitry Andric 
343*5ffd83dbSDimitry Andric   /// Emit all the range checks for the immediates.
344*5ffd83dbSDimitry Andric   void createRangeChecks(raw_ostream &o);
345*5ffd83dbSDimitry Andric 
346*5ffd83dbSDimitry Andric   /// Create the SVETypeFlags used in CGBuiltins
347*5ffd83dbSDimitry Andric   void createTypeFlags(raw_ostream &o);
348*5ffd83dbSDimitry Andric 
349*5ffd83dbSDimitry Andric   /// Create intrinsic and add it to \p Out
350*5ffd83dbSDimitry Andric   void createIntrinsic(Record *R, SmallVectorImpl<std::unique_ptr<Intrinsic>> &Out);
351*5ffd83dbSDimitry Andric };
352*5ffd83dbSDimitry Andric 
353*5ffd83dbSDimitry Andric } // end anonymous namespace
354*5ffd83dbSDimitry Andric 
355*5ffd83dbSDimitry Andric 
356*5ffd83dbSDimitry Andric //===----------------------------------------------------------------------===//
357*5ffd83dbSDimitry Andric // Type implementation
358*5ffd83dbSDimitry Andric //===----------------------------------------------------------------------===//
359*5ffd83dbSDimitry Andric 
360*5ffd83dbSDimitry Andric std::string SVEType::builtin_str() const {
361*5ffd83dbSDimitry Andric   std::string S;
362*5ffd83dbSDimitry Andric   if (isVoid())
363*5ffd83dbSDimitry Andric     return "v";
364*5ffd83dbSDimitry Andric 
365*5ffd83dbSDimitry Andric   if (isVoidPointer())
366*5ffd83dbSDimitry Andric     S += "v";
367*5ffd83dbSDimitry Andric   else if (!isFloatingPoint())
368*5ffd83dbSDimitry Andric     switch (ElementBitwidth) {
369*5ffd83dbSDimitry Andric     case 1: S += "b"; break;
370*5ffd83dbSDimitry Andric     case 8: S += "c"; break;
371*5ffd83dbSDimitry Andric     case 16: S += "s"; break;
372*5ffd83dbSDimitry Andric     case 32: S += "i"; break;
373*5ffd83dbSDimitry Andric     case 64: S += "Wi"; break;
374*5ffd83dbSDimitry Andric     case 128: S += "LLLi"; break;
375*5ffd83dbSDimitry Andric     default: llvm_unreachable("Unhandled case!");
376*5ffd83dbSDimitry Andric     }
377*5ffd83dbSDimitry Andric   else if (isFloat())
378*5ffd83dbSDimitry Andric     switch (ElementBitwidth) {
379*5ffd83dbSDimitry Andric     case 16: S += "h"; break;
380*5ffd83dbSDimitry Andric     case 32: S += "f"; break;
381*5ffd83dbSDimitry Andric     case 64: S += "d"; break;
382*5ffd83dbSDimitry Andric     default: llvm_unreachable("Unhandled case!");
383*5ffd83dbSDimitry Andric     }
384*5ffd83dbSDimitry Andric   else if (isBFloat()) {
385*5ffd83dbSDimitry Andric     assert(ElementBitwidth == 16 && "Not a valid BFloat.");
386*5ffd83dbSDimitry Andric     S += "y";
387*5ffd83dbSDimitry Andric   }
388*5ffd83dbSDimitry Andric 
389*5ffd83dbSDimitry Andric   if (!isFloatingPoint()) {
390*5ffd83dbSDimitry Andric     if ((isChar() || isPointer()) && !isVoidPointer()) {
391*5ffd83dbSDimitry Andric       // Make chars and typed pointers explicitly signed.
392*5ffd83dbSDimitry Andric       if (Signed)
393*5ffd83dbSDimitry Andric         S = "S" + S;
394*5ffd83dbSDimitry Andric       else if (!Signed)
395*5ffd83dbSDimitry Andric         S = "U" + S;
396*5ffd83dbSDimitry Andric     } else if (!isVoidPointer() && !Signed) {
397*5ffd83dbSDimitry Andric       S = "U" + S;
398*5ffd83dbSDimitry Andric     }
399*5ffd83dbSDimitry Andric   }
400*5ffd83dbSDimitry Andric 
401*5ffd83dbSDimitry Andric   // Constant indices are "int", but have the "constant expression" modifier.
402*5ffd83dbSDimitry Andric   if (isImmediate()) {
403*5ffd83dbSDimitry Andric     assert(!isFloat() && "fp immediates are not supported");
404*5ffd83dbSDimitry Andric     S = "I" + S;
405*5ffd83dbSDimitry Andric   }
406*5ffd83dbSDimitry Andric 
407*5ffd83dbSDimitry Andric   if (isScalar()) {
408*5ffd83dbSDimitry Andric     if (Constant) S += "C";
409*5ffd83dbSDimitry Andric     if (Pointer) S += "*";
410*5ffd83dbSDimitry Andric     return S;
411*5ffd83dbSDimitry Andric   }
412*5ffd83dbSDimitry Andric 
413*5ffd83dbSDimitry Andric   assert(isScalableVector() && "Unsupported type");
414*5ffd83dbSDimitry Andric   return "q" + utostr(getNumElements() * NumVectors) + S;
415*5ffd83dbSDimitry Andric }
416*5ffd83dbSDimitry Andric 
417*5ffd83dbSDimitry Andric std::string SVEType::str() const {
418*5ffd83dbSDimitry Andric   if (isPredicatePattern())
419*5ffd83dbSDimitry Andric     return "sv_pattern";
420*5ffd83dbSDimitry Andric 
421*5ffd83dbSDimitry Andric   if (isPrefetchOp())
422*5ffd83dbSDimitry Andric     return "sv_prfop";
423*5ffd83dbSDimitry Andric 
424*5ffd83dbSDimitry Andric   std::string S;
425*5ffd83dbSDimitry Andric   if (Void)
426*5ffd83dbSDimitry Andric     S += "void";
427*5ffd83dbSDimitry Andric   else {
428*5ffd83dbSDimitry Andric     if (isScalableVector())
429*5ffd83dbSDimitry Andric       S += "sv";
430*5ffd83dbSDimitry Andric     if (!Signed && !isFloatingPoint())
431*5ffd83dbSDimitry Andric       S += "u";
432*5ffd83dbSDimitry Andric 
433*5ffd83dbSDimitry Andric     if (Float)
434*5ffd83dbSDimitry Andric       S += "float";
435*5ffd83dbSDimitry Andric     else if (isScalarPredicate() || isPredicateVector())
436*5ffd83dbSDimitry Andric       S += "bool";
437*5ffd83dbSDimitry Andric     else if (isBFloat())
438*5ffd83dbSDimitry Andric       S += "bfloat";
439*5ffd83dbSDimitry Andric     else
440*5ffd83dbSDimitry Andric       S += "int";
441*5ffd83dbSDimitry Andric 
442*5ffd83dbSDimitry Andric     if (!isScalarPredicate() && !isPredicateVector())
443*5ffd83dbSDimitry Andric       S += utostr(ElementBitwidth);
444*5ffd83dbSDimitry Andric     if (!isScalableVector() && isVector())
445*5ffd83dbSDimitry Andric       S += "x" + utostr(getNumElements());
446*5ffd83dbSDimitry Andric     if (NumVectors > 1)
447*5ffd83dbSDimitry Andric       S += "x" + utostr(NumVectors);
448*5ffd83dbSDimitry Andric     if (!isScalarPredicate())
449*5ffd83dbSDimitry Andric       S += "_t";
450*5ffd83dbSDimitry Andric   }
451*5ffd83dbSDimitry Andric 
452*5ffd83dbSDimitry Andric   if (Constant)
453*5ffd83dbSDimitry Andric     S += " const";
454*5ffd83dbSDimitry Andric   if (Pointer)
455*5ffd83dbSDimitry Andric     S += " *";
456*5ffd83dbSDimitry Andric 
457*5ffd83dbSDimitry Andric   return S;
458*5ffd83dbSDimitry Andric }
459*5ffd83dbSDimitry Andric void SVEType::applyTypespec() {
460*5ffd83dbSDimitry Andric   for (char I : TS) {
461*5ffd83dbSDimitry Andric     switch (I) {
462*5ffd83dbSDimitry Andric     case 'P':
463*5ffd83dbSDimitry Andric       Predicate = true;
464*5ffd83dbSDimitry Andric       break;
465*5ffd83dbSDimitry Andric     case 'U':
466*5ffd83dbSDimitry Andric       Signed = false;
467*5ffd83dbSDimitry Andric       break;
468*5ffd83dbSDimitry Andric     case 'c':
469*5ffd83dbSDimitry Andric       ElementBitwidth = 8;
470*5ffd83dbSDimitry Andric       break;
471*5ffd83dbSDimitry Andric     case 's':
472*5ffd83dbSDimitry Andric       ElementBitwidth = 16;
473*5ffd83dbSDimitry Andric       break;
474*5ffd83dbSDimitry Andric     case 'i':
475*5ffd83dbSDimitry Andric       ElementBitwidth = 32;
476*5ffd83dbSDimitry Andric       break;
477*5ffd83dbSDimitry Andric     case 'l':
478*5ffd83dbSDimitry Andric       ElementBitwidth = 64;
479*5ffd83dbSDimitry Andric       break;
480*5ffd83dbSDimitry Andric     case 'h':
481*5ffd83dbSDimitry Andric       Float = true;
482*5ffd83dbSDimitry Andric       ElementBitwidth = 16;
483*5ffd83dbSDimitry Andric       break;
484*5ffd83dbSDimitry Andric     case 'f':
485*5ffd83dbSDimitry Andric       Float = true;
486*5ffd83dbSDimitry Andric       ElementBitwidth = 32;
487*5ffd83dbSDimitry Andric       break;
488*5ffd83dbSDimitry Andric     case 'd':
489*5ffd83dbSDimitry Andric       Float = true;
490*5ffd83dbSDimitry Andric       ElementBitwidth = 64;
491*5ffd83dbSDimitry Andric       break;
492*5ffd83dbSDimitry Andric     case 'b':
493*5ffd83dbSDimitry Andric       BFloat = true;
494*5ffd83dbSDimitry Andric       Float = false;
495*5ffd83dbSDimitry Andric       ElementBitwidth = 16;
496*5ffd83dbSDimitry Andric       break;
497*5ffd83dbSDimitry Andric     default:
498*5ffd83dbSDimitry Andric       llvm_unreachable("Unhandled type code!");
499*5ffd83dbSDimitry Andric     }
500*5ffd83dbSDimitry Andric   }
501*5ffd83dbSDimitry Andric   assert(ElementBitwidth != ~0U && "Bad element bitwidth!");
502*5ffd83dbSDimitry Andric }
503*5ffd83dbSDimitry Andric 
504*5ffd83dbSDimitry Andric void SVEType::applyModifier(char Mod) {
505*5ffd83dbSDimitry Andric   switch (Mod) {
506*5ffd83dbSDimitry Andric   case '2':
507*5ffd83dbSDimitry Andric     NumVectors = 2;
508*5ffd83dbSDimitry Andric     break;
509*5ffd83dbSDimitry Andric   case '3':
510*5ffd83dbSDimitry Andric     NumVectors = 3;
511*5ffd83dbSDimitry Andric     break;
512*5ffd83dbSDimitry Andric   case '4':
513*5ffd83dbSDimitry Andric     NumVectors = 4;
514*5ffd83dbSDimitry Andric     break;
515*5ffd83dbSDimitry Andric   case 'v':
516*5ffd83dbSDimitry Andric     Void = true;
517*5ffd83dbSDimitry Andric     break;
518*5ffd83dbSDimitry Andric   case 'd':
519*5ffd83dbSDimitry Andric     DefaultType = true;
520*5ffd83dbSDimitry Andric     break;
521*5ffd83dbSDimitry Andric   case 'c':
522*5ffd83dbSDimitry Andric     Constant = true;
523*5ffd83dbSDimitry Andric     LLVM_FALLTHROUGH;
524*5ffd83dbSDimitry Andric   case 'p':
525*5ffd83dbSDimitry Andric     Pointer = true;
526*5ffd83dbSDimitry Andric     Bitwidth = ElementBitwidth;
527*5ffd83dbSDimitry Andric     NumVectors = 0;
528*5ffd83dbSDimitry Andric     break;
529*5ffd83dbSDimitry Andric   case 'e':
530*5ffd83dbSDimitry Andric     Signed = false;
531*5ffd83dbSDimitry Andric     ElementBitwidth /= 2;
532*5ffd83dbSDimitry Andric     break;
533*5ffd83dbSDimitry Andric   case 'h':
534*5ffd83dbSDimitry Andric     ElementBitwidth /= 2;
535*5ffd83dbSDimitry Andric     break;
536*5ffd83dbSDimitry Andric   case 'q':
537*5ffd83dbSDimitry Andric     ElementBitwidth /= 4;
538*5ffd83dbSDimitry Andric     break;
539*5ffd83dbSDimitry Andric   case 'b':
540*5ffd83dbSDimitry Andric     Signed = false;
541*5ffd83dbSDimitry Andric     Float = false;
542*5ffd83dbSDimitry Andric     BFloat = false;
543*5ffd83dbSDimitry Andric     ElementBitwidth /= 4;
544*5ffd83dbSDimitry Andric     break;
545*5ffd83dbSDimitry Andric   case 'o':
546*5ffd83dbSDimitry Andric     ElementBitwidth *= 4;
547*5ffd83dbSDimitry Andric     break;
548*5ffd83dbSDimitry Andric   case 'P':
549*5ffd83dbSDimitry Andric     Signed = true;
550*5ffd83dbSDimitry Andric     Float = false;
551*5ffd83dbSDimitry Andric     BFloat = false;
552*5ffd83dbSDimitry Andric     Predicate = true;
553*5ffd83dbSDimitry Andric     Bitwidth = 16;
554*5ffd83dbSDimitry Andric     ElementBitwidth = 1;
555*5ffd83dbSDimitry Andric     break;
556*5ffd83dbSDimitry Andric   case 's':
557*5ffd83dbSDimitry Andric   case 'a':
558*5ffd83dbSDimitry Andric     Bitwidth = ElementBitwidth;
559*5ffd83dbSDimitry Andric     NumVectors = 0;
560*5ffd83dbSDimitry Andric     break;
561*5ffd83dbSDimitry Andric   case 'R':
562*5ffd83dbSDimitry Andric     ElementBitwidth /= 2;
563*5ffd83dbSDimitry Andric     NumVectors = 0;
564*5ffd83dbSDimitry Andric     break;
565*5ffd83dbSDimitry Andric   case 'r':
566*5ffd83dbSDimitry Andric     ElementBitwidth /= 4;
567*5ffd83dbSDimitry Andric     NumVectors = 0;
568*5ffd83dbSDimitry Andric     break;
569*5ffd83dbSDimitry Andric   case '@':
570*5ffd83dbSDimitry Andric     Signed = false;
571*5ffd83dbSDimitry Andric     Float = false;
572*5ffd83dbSDimitry Andric     BFloat = false;
573*5ffd83dbSDimitry Andric     ElementBitwidth /= 4;
574*5ffd83dbSDimitry Andric     NumVectors = 0;
575*5ffd83dbSDimitry Andric     break;
576*5ffd83dbSDimitry Andric   case 'K':
577*5ffd83dbSDimitry Andric     Signed = true;
578*5ffd83dbSDimitry Andric     Float = false;
579*5ffd83dbSDimitry Andric     BFloat = false;
580*5ffd83dbSDimitry Andric     Bitwidth = ElementBitwidth;
581*5ffd83dbSDimitry Andric     NumVectors = 0;
582*5ffd83dbSDimitry Andric     break;
583*5ffd83dbSDimitry Andric   case 'L':
584*5ffd83dbSDimitry Andric     Signed = false;
585*5ffd83dbSDimitry Andric     Float = false;
586*5ffd83dbSDimitry Andric     BFloat = false;
587*5ffd83dbSDimitry Andric     Bitwidth = ElementBitwidth;
588*5ffd83dbSDimitry Andric     NumVectors = 0;
589*5ffd83dbSDimitry Andric     break;
590*5ffd83dbSDimitry Andric   case 'u':
591*5ffd83dbSDimitry Andric     Predicate = false;
592*5ffd83dbSDimitry Andric     Signed = false;
593*5ffd83dbSDimitry Andric     Float = false;
594*5ffd83dbSDimitry Andric     BFloat = false;
595*5ffd83dbSDimitry Andric     break;
596*5ffd83dbSDimitry Andric   case 'x':
597*5ffd83dbSDimitry Andric     Predicate = false;
598*5ffd83dbSDimitry Andric     Signed = true;
599*5ffd83dbSDimitry Andric     Float = false;
600*5ffd83dbSDimitry Andric     BFloat = false;
601*5ffd83dbSDimitry Andric     break;
602*5ffd83dbSDimitry Andric   case 'i':
603*5ffd83dbSDimitry Andric     Predicate = false;
604*5ffd83dbSDimitry Andric     Float = false;
605*5ffd83dbSDimitry Andric     BFloat = false;
606*5ffd83dbSDimitry Andric     ElementBitwidth = Bitwidth = 64;
607*5ffd83dbSDimitry Andric     NumVectors = 0;
608*5ffd83dbSDimitry Andric     Signed = false;
609*5ffd83dbSDimitry Andric     Immediate = true;
610*5ffd83dbSDimitry Andric     break;
611*5ffd83dbSDimitry Andric   case 'I':
612*5ffd83dbSDimitry Andric     Predicate = false;
613*5ffd83dbSDimitry Andric     Float = false;
614*5ffd83dbSDimitry Andric     BFloat = false;
615*5ffd83dbSDimitry Andric     ElementBitwidth = Bitwidth = 32;
616*5ffd83dbSDimitry Andric     NumVectors = 0;
617*5ffd83dbSDimitry Andric     Signed = true;
618*5ffd83dbSDimitry Andric     Immediate = true;
619*5ffd83dbSDimitry Andric     PredicatePattern = true;
620*5ffd83dbSDimitry Andric     break;
621*5ffd83dbSDimitry Andric   case 'J':
622*5ffd83dbSDimitry Andric     Predicate = false;
623*5ffd83dbSDimitry Andric     Float = false;
624*5ffd83dbSDimitry Andric     BFloat = false;
625*5ffd83dbSDimitry Andric     ElementBitwidth = Bitwidth = 32;
626*5ffd83dbSDimitry Andric     NumVectors = 0;
627*5ffd83dbSDimitry Andric     Signed = true;
628*5ffd83dbSDimitry Andric     Immediate = true;
629*5ffd83dbSDimitry Andric     PrefetchOp = true;
630*5ffd83dbSDimitry Andric     break;
631*5ffd83dbSDimitry Andric   case 'k':
632*5ffd83dbSDimitry Andric     Predicate = false;
633*5ffd83dbSDimitry Andric     Signed = true;
634*5ffd83dbSDimitry Andric     Float = false;
635*5ffd83dbSDimitry Andric     BFloat = false;
636*5ffd83dbSDimitry Andric     ElementBitwidth = Bitwidth = 32;
637*5ffd83dbSDimitry Andric     NumVectors = 0;
638*5ffd83dbSDimitry Andric     break;
639*5ffd83dbSDimitry Andric   case 'l':
640*5ffd83dbSDimitry Andric     Predicate = false;
641*5ffd83dbSDimitry Andric     Signed = true;
642*5ffd83dbSDimitry Andric     Float = false;
643*5ffd83dbSDimitry Andric     BFloat = false;
644*5ffd83dbSDimitry Andric     ElementBitwidth = Bitwidth = 64;
645*5ffd83dbSDimitry Andric     NumVectors = 0;
646*5ffd83dbSDimitry Andric     break;
647*5ffd83dbSDimitry Andric   case 'm':
648*5ffd83dbSDimitry Andric     Predicate = false;
649*5ffd83dbSDimitry Andric     Signed = false;
650*5ffd83dbSDimitry Andric     Float = false;
651*5ffd83dbSDimitry Andric     BFloat = false;
652*5ffd83dbSDimitry Andric     ElementBitwidth = Bitwidth = 32;
653*5ffd83dbSDimitry Andric     NumVectors = 0;
654*5ffd83dbSDimitry Andric     break;
655*5ffd83dbSDimitry Andric   case 'n':
656*5ffd83dbSDimitry Andric     Predicate = false;
657*5ffd83dbSDimitry Andric     Signed = false;
658*5ffd83dbSDimitry Andric     Float = false;
659*5ffd83dbSDimitry Andric     BFloat = false;
660*5ffd83dbSDimitry Andric     ElementBitwidth = Bitwidth = 64;
661*5ffd83dbSDimitry Andric     NumVectors = 0;
662*5ffd83dbSDimitry Andric     break;
663*5ffd83dbSDimitry Andric   case 'w':
664*5ffd83dbSDimitry Andric     ElementBitwidth = 64;
665*5ffd83dbSDimitry Andric     break;
666*5ffd83dbSDimitry Andric   case 'j':
667*5ffd83dbSDimitry Andric     ElementBitwidth = Bitwidth = 64;
668*5ffd83dbSDimitry Andric     NumVectors = 0;
669*5ffd83dbSDimitry Andric     break;
670*5ffd83dbSDimitry Andric   case 'f':
671*5ffd83dbSDimitry Andric     Signed = false;
672*5ffd83dbSDimitry Andric     ElementBitwidth = Bitwidth = 64;
673*5ffd83dbSDimitry Andric     NumVectors = 0;
674*5ffd83dbSDimitry Andric     break;
675*5ffd83dbSDimitry Andric   case 'g':
676*5ffd83dbSDimitry Andric     Signed = false;
677*5ffd83dbSDimitry Andric     Float = false;
678*5ffd83dbSDimitry Andric     BFloat = false;
679*5ffd83dbSDimitry Andric     ElementBitwidth = 64;
680*5ffd83dbSDimitry Andric     break;
681*5ffd83dbSDimitry Andric   case 't':
682*5ffd83dbSDimitry Andric     Signed = true;
683*5ffd83dbSDimitry Andric     Float = false;
684*5ffd83dbSDimitry Andric     BFloat = false;
685*5ffd83dbSDimitry Andric     ElementBitwidth = 32;
686*5ffd83dbSDimitry Andric     break;
687*5ffd83dbSDimitry Andric   case 'z':
688*5ffd83dbSDimitry Andric     Signed = false;
689*5ffd83dbSDimitry Andric     Float = false;
690*5ffd83dbSDimitry Andric     BFloat = false;
691*5ffd83dbSDimitry Andric     ElementBitwidth = 32;
692*5ffd83dbSDimitry Andric     break;
693*5ffd83dbSDimitry Andric   case 'O':
694*5ffd83dbSDimitry Andric     Predicate = false;
695*5ffd83dbSDimitry Andric     Float = true;
696*5ffd83dbSDimitry Andric     ElementBitwidth = 16;
697*5ffd83dbSDimitry Andric     break;
698*5ffd83dbSDimitry Andric   case 'M':
699*5ffd83dbSDimitry Andric     Predicate = false;
700*5ffd83dbSDimitry Andric     Float = true;
701*5ffd83dbSDimitry Andric     BFloat = false;
702*5ffd83dbSDimitry Andric     ElementBitwidth = 32;
703*5ffd83dbSDimitry Andric     break;
704*5ffd83dbSDimitry Andric   case 'N':
705*5ffd83dbSDimitry Andric     Predicate = false;
706*5ffd83dbSDimitry Andric     Float = true;
707*5ffd83dbSDimitry Andric     ElementBitwidth = 64;
708*5ffd83dbSDimitry Andric     break;
709*5ffd83dbSDimitry Andric   case 'Q':
710*5ffd83dbSDimitry Andric     Constant = true;
711*5ffd83dbSDimitry Andric     Pointer = true;
712*5ffd83dbSDimitry Andric     Void = true;
713*5ffd83dbSDimitry Andric     NumVectors = 0;
714*5ffd83dbSDimitry Andric     break;
715*5ffd83dbSDimitry Andric   case 'S':
716*5ffd83dbSDimitry Andric     Constant = true;
717*5ffd83dbSDimitry Andric     Pointer = true;
718*5ffd83dbSDimitry Andric     ElementBitwidth = Bitwidth = 8;
719*5ffd83dbSDimitry Andric     NumVectors = 0;
720*5ffd83dbSDimitry Andric     Signed = true;
721*5ffd83dbSDimitry Andric     break;
722*5ffd83dbSDimitry Andric   case 'W':
723*5ffd83dbSDimitry Andric     Constant = true;
724*5ffd83dbSDimitry Andric     Pointer = true;
725*5ffd83dbSDimitry Andric     ElementBitwidth = Bitwidth = 8;
726*5ffd83dbSDimitry Andric     NumVectors = 0;
727*5ffd83dbSDimitry Andric     Signed = false;
728*5ffd83dbSDimitry Andric     break;
729*5ffd83dbSDimitry Andric   case 'T':
730*5ffd83dbSDimitry Andric     Constant = true;
731*5ffd83dbSDimitry Andric     Pointer = true;
732*5ffd83dbSDimitry Andric     ElementBitwidth = Bitwidth = 16;
733*5ffd83dbSDimitry Andric     NumVectors = 0;
734*5ffd83dbSDimitry Andric     Signed = true;
735*5ffd83dbSDimitry Andric     break;
736*5ffd83dbSDimitry Andric   case 'X':
737*5ffd83dbSDimitry Andric     Constant = true;
738*5ffd83dbSDimitry Andric     Pointer = true;
739*5ffd83dbSDimitry Andric     ElementBitwidth = Bitwidth = 16;
740*5ffd83dbSDimitry Andric     NumVectors = 0;
741*5ffd83dbSDimitry Andric     Signed = false;
742*5ffd83dbSDimitry Andric     break;
743*5ffd83dbSDimitry Andric   case 'Y':
744*5ffd83dbSDimitry Andric     Constant = true;
745*5ffd83dbSDimitry Andric     Pointer = true;
746*5ffd83dbSDimitry Andric     ElementBitwidth = Bitwidth = 32;
747*5ffd83dbSDimitry Andric     NumVectors = 0;
748*5ffd83dbSDimitry Andric     Signed = false;
749*5ffd83dbSDimitry Andric     break;
750*5ffd83dbSDimitry Andric   case 'U':
751*5ffd83dbSDimitry Andric     Constant = true;
752*5ffd83dbSDimitry Andric     Pointer = true;
753*5ffd83dbSDimitry Andric     ElementBitwidth = Bitwidth = 32;
754*5ffd83dbSDimitry Andric     NumVectors = 0;
755*5ffd83dbSDimitry Andric     Signed = true;
756*5ffd83dbSDimitry Andric     break;
757*5ffd83dbSDimitry Andric   case 'A':
758*5ffd83dbSDimitry Andric     Pointer = true;
759*5ffd83dbSDimitry Andric     ElementBitwidth = Bitwidth = 8;
760*5ffd83dbSDimitry Andric     NumVectors = 0;
761*5ffd83dbSDimitry Andric     Signed = true;
762*5ffd83dbSDimitry Andric     break;
763*5ffd83dbSDimitry Andric   case 'B':
764*5ffd83dbSDimitry Andric     Pointer = true;
765*5ffd83dbSDimitry Andric     ElementBitwidth = Bitwidth = 16;
766*5ffd83dbSDimitry Andric     NumVectors = 0;
767*5ffd83dbSDimitry Andric     Signed = true;
768*5ffd83dbSDimitry Andric     break;
769*5ffd83dbSDimitry Andric   case 'C':
770*5ffd83dbSDimitry Andric     Pointer = true;
771*5ffd83dbSDimitry Andric     ElementBitwidth = Bitwidth = 32;
772*5ffd83dbSDimitry Andric     NumVectors = 0;
773*5ffd83dbSDimitry Andric     Signed = true;
774*5ffd83dbSDimitry Andric     break;
775*5ffd83dbSDimitry Andric   case 'D':
776*5ffd83dbSDimitry Andric     Pointer = true;
777*5ffd83dbSDimitry Andric     ElementBitwidth = Bitwidth = 64;
778*5ffd83dbSDimitry Andric     NumVectors = 0;
779*5ffd83dbSDimitry Andric     Signed = true;
780*5ffd83dbSDimitry Andric     break;
781*5ffd83dbSDimitry Andric   case 'E':
782*5ffd83dbSDimitry Andric     Pointer = true;
783*5ffd83dbSDimitry Andric     ElementBitwidth = Bitwidth = 8;
784*5ffd83dbSDimitry Andric     NumVectors = 0;
785*5ffd83dbSDimitry Andric     Signed = false;
786*5ffd83dbSDimitry Andric     break;
787*5ffd83dbSDimitry Andric   case 'F':
788*5ffd83dbSDimitry Andric     Pointer = true;
789*5ffd83dbSDimitry Andric     ElementBitwidth = Bitwidth = 16;
790*5ffd83dbSDimitry Andric     NumVectors = 0;
791*5ffd83dbSDimitry Andric     Signed = false;
792*5ffd83dbSDimitry Andric     break;
793*5ffd83dbSDimitry Andric   case 'G':
794*5ffd83dbSDimitry Andric     Pointer = true;
795*5ffd83dbSDimitry Andric     ElementBitwidth = Bitwidth = 32;
796*5ffd83dbSDimitry Andric     NumVectors = 0;
797*5ffd83dbSDimitry Andric     Signed = false;
798*5ffd83dbSDimitry Andric     break;
799*5ffd83dbSDimitry Andric   default:
800*5ffd83dbSDimitry Andric     llvm_unreachable("Unhandled character!");
801*5ffd83dbSDimitry Andric   }
802*5ffd83dbSDimitry Andric }
803*5ffd83dbSDimitry Andric 
804*5ffd83dbSDimitry Andric 
805*5ffd83dbSDimitry Andric //===----------------------------------------------------------------------===//
806*5ffd83dbSDimitry Andric // Intrinsic implementation
807*5ffd83dbSDimitry Andric //===----------------------------------------------------------------------===//
808*5ffd83dbSDimitry Andric 
809*5ffd83dbSDimitry Andric Intrinsic::Intrinsic(StringRef Name, StringRef Proto, uint64_t MergeTy,
810*5ffd83dbSDimitry Andric                      StringRef MergeSuffix, uint64_t MemoryElementTy,
811*5ffd83dbSDimitry Andric                      StringRef LLVMName, uint64_t Flags,
812*5ffd83dbSDimitry Andric                      ArrayRef<ImmCheck> Checks, TypeSpec BT, ClassKind Class,
813*5ffd83dbSDimitry Andric                      SVEEmitter &Emitter, StringRef Guard)
814*5ffd83dbSDimitry Andric     : Name(Name.str()), LLVMName(LLVMName), Proto(Proto.str()),
815*5ffd83dbSDimitry Andric       BaseTypeSpec(BT), Class(Class), Guard(Guard.str()),
816*5ffd83dbSDimitry Andric       MergeSuffix(MergeSuffix.str()), BaseType(BT, 'd'), Flags(Flags),
817*5ffd83dbSDimitry Andric       ImmChecks(Checks.begin(), Checks.end()) {
818*5ffd83dbSDimitry Andric   // Types[0] is the return value.
819*5ffd83dbSDimitry Andric   for (unsigned I = 0; I < Proto.size(); ++I) {
820*5ffd83dbSDimitry Andric     SVEType T(BaseTypeSpec, Proto[I]);
821*5ffd83dbSDimitry Andric     Types.push_back(T);
822*5ffd83dbSDimitry Andric 
823*5ffd83dbSDimitry Andric     // Add range checks for immediates
824*5ffd83dbSDimitry Andric     if (I > 0) {
825*5ffd83dbSDimitry Andric       if (T.isPredicatePattern())
826*5ffd83dbSDimitry Andric         ImmChecks.emplace_back(
827*5ffd83dbSDimitry Andric             I - 1, Emitter.getEnumValueForImmCheck("ImmCheck0_31"));
828*5ffd83dbSDimitry Andric       else if (T.isPrefetchOp())
829*5ffd83dbSDimitry Andric         ImmChecks.emplace_back(
830*5ffd83dbSDimitry Andric             I - 1, Emitter.getEnumValueForImmCheck("ImmCheck0_13"));
831*5ffd83dbSDimitry Andric     }
832*5ffd83dbSDimitry Andric   }
833*5ffd83dbSDimitry Andric 
834*5ffd83dbSDimitry Andric   // Set flags based on properties
835*5ffd83dbSDimitry Andric   this->Flags |= Emitter.encodeTypeFlags(BaseType);
836*5ffd83dbSDimitry Andric   this->Flags |= Emitter.encodeMemoryElementType(MemoryElementTy);
837*5ffd83dbSDimitry Andric   this->Flags |= Emitter.encodeMergeType(MergeTy);
838*5ffd83dbSDimitry Andric   if (hasSplat())
839*5ffd83dbSDimitry Andric     this->Flags |= Emitter.encodeSplatOperand(getSplatIdx());
840*5ffd83dbSDimitry Andric }
841*5ffd83dbSDimitry Andric 
842*5ffd83dbSDimitry Andric std::string Intrinsic::getBuiltinTypeStr() {
843*5ffd83dbSDimitry Andric   std::string S = getReturnType().builtin_str();
844*5ffd83dbSDimitry Andric   for (unsigned I = 0; I < getNumParams(); ++I)
845*5ffd83dbSDimitry Andric     S += getParamType(I).builtin_str();
846*5ffd83dbSDimitry Andric 
847*5ffd83dbSDimitry Andric   return S;
848*5ffd83dbSDimitry Andric }
849*5ffd83dbSDimitry Andric 
850*5ffd83dbSDimitry Andric std::string Intrinsic::replaceTemplatedArgs(std::string Name, TypeSpec TS,
851*5ffd83dbSDimitry Andric                                             std::string Proto) const {
852*5ffd83dbSDimitry Andric   std::string Ret = Name;
853*5ffd83dbSDimitry Andric   while (Ret.find('{') != std::string::npos) {
854*5ffd83dbSDimitry Andric     size_t Pos = Ret.find('{');
855*5ffd83dbSDimitry Andric     size_t End = Ret.find('}');
856*5ffd83dbSDimitry Andric     unsigned NumChars = End - Pos + 1;
857*5ffd83dbSDimitry Andric     assert(NumChars == 3 && "Unexpected template argument");
858*5ffd83dbSDimitry Andric 
859*5ffd83dbSDimitry Andric     SVEType T;
860*5ffd83dbSDimitry Andric     char C = Ret[Pos+1];
861*5ffd83dbSDimitry Andric     switch(C) {
862*5ffd83dbSDimitry Andric     default:
863*5ffd83dbSDimitry Andric       llvm_unreachable("Unknown predication specifier");
864*5ffd83dbSDimitry Andric     case 'd':
865*5ffd83dbSDimitry Andric       T = SVEType(TS, 'd');
866*5ffd83dbSDimitry Andric       break;
867*5ffd83dbSDimitry Andric     case '0':
868*5ffd83dbSDimitry Andric     case '1':
869*5ffd83dbSDimitry Andric     case '2':
870*5ffd83dbSDimitry Andric     case '3':
871*5ffd83dbSDimitry Andric       T = SVEType(TS, Proto[C - '0']);
872*5ffd83dbSDimitry Andric       break;
873*5ffd83dbSDimitry Andric     }
874*5ffd83dbSDimitry Andric 
875*5ffd83dbSDimitry Andric     // Replace templated arg with the right suffix (e.g. u32)
876*5ffd83dbSDimitry Andric     std::string TypeCode;
877*5ffd83dbSDimitry Andric     if (T.isInteger())
878*5ffd83dbSDimitry Andric       TypeCode = T.isSigned() ? 's' : 'u';
879*5ffd83dbSDimitry Andric     else if (T.isPredicateVector())
880*5ffd83dbSDimitry Andric       TypeCode = 'b';
881*5ffd83dbSDimitry Andric     else if (T.isBFloat())
882*5ffd83dbSDimitry Andric       TypeCode = "bf";
883*5ffd83dbSDimitry Andric     else
884*5ffd83dbSDimitry Andric       TypeCode = 'f';
885*5ffd83dbSDimitry Andric     Ret.replace(Pos, NumChars, TypeCode + utostr(T.getElementSizeInBits()));
886*5ffd83dbSDimitry Andric   }
887*5ffd83dbSDimitry Andric 
888*5ffd83dbSDimitry Andric   return Ret;
889*5ffd83dbSDimitry Andric }
890*5ffd83dbSDimitry Andric 
891*5ffd83dbSDimitry Andric std::string Intrinsic::mangleName(ClassKind LocalCK) const {
892*5ffd83dbSDimitry Andric   std::string S = getName();
893*5ffd83dbSDimitry Andric 
894*5ffd83dbSDimitry Andric   if (LocalCK == ClassG) {
895*5ffd83dbSDimitry Andric     // Remove the square brackets and everything in between.
896*5ffd83dbSDimitry Andric     while (S.find("[") != std::string::npos) {
897*5ffd83dbSDimitry Andric       auto Start = S.find("[");
898*5ffd83dbSDimitry Andric       auto End = S.find(']');
899*5ffd83dbSDimitry Andric       S.erase(Start, (End-Start)+1);
900*5ffd83dbSDimitry Andric     }
901*5ffd83dbSDimitry Andric   } else {
902*5ffd83dbSDimitry Andric     // Remove the square brackets.
903*5ffd83dbSDimitry Andric     while (S.find("[") != std::string::npos) {
904*5ffd83dbSDimitry Andric       auto BrPos = S.find('[');
905*5ffd83dbSDimitry Andric       if (BrPos != std::string::npos)
906*5ffd83dbSDimitry Andric         S.erase(BrPos, 1);
907*5ffd83dbSDimitry Andric       BrPos = S.find(']');
908*5ffd83dbSDimitry Andric       if (BrPos != std::string::npos)
909*5ffd83dbSDimitry Andric         S.erase(BrPos, 1);
910*5ffd83dbSDimitry Andric     }
911*5ffd83dbSDimitry Andric   }
912*5ffd83dbSDimitry Andric 
913*5ffd83dbSDimitry Andric   // Replace all {d} like expressions with e.g. 'u32'
914*5ffd83dbSDimitry Andric   return replaceTemplatedArgs(S, getBaseTypeSpec(), getProto()) +
915*5ffd83dbSDimitry Andric          getMergeSuffix();
916*5ffd83dbSDimitry Andric }
917*5ffd83dbSDimitry Andric 
918*5ffd83dbSDimitry Andric void Intrinsic::emitIntrinsic(raw_ostream &OS) const {
919*5ffd83dbSDimitry Andric   // Use the preprocessor to
920*5ffd83dbSDimitry Andric   if (getClassKind() != ClassG || getProto().size() <= 1) {
921*5ffd83dbSDimitry Andric     OS << "#define " << mangleName(getClassKind())
922*5ffd83dbSDimitry Andric        << "(...) __builtin_sve_" << mangleName(ClassS)
923*5ffd83dbSDimitry Andric        << "(__VA_ARGS__)\n";
924*5ffd83dbSDimitry Andric   } else {
925*5ffd83dbSDimitry Andric     std::string FullName = mangleName(ClassS);
926*5ffd83dbSDimitry Andric     std::string ProtoName = mangleName(ClassG);
927*5ffd83dbSDimitry Andric 
928*5ffd83dbSDimitry Andric     OS << "__aio __attribute__((__clang_arm_builtin_alias("
929*5ffd83dbSDimitry Andric        << "__builtin_sve_" << FullName << ")))\n";
930*5ffd83dbSDimitry Andric 
931*5ffd83dbSDimitry Andric     OS << getTypes()[0].str() << " " << ProtoName << "(";
932*5ffd83dbSDimitry Andric     for (unsigned I = 0; I < getTypes().size() - 1; ++I) {
933*5ffd83dbSDimitry Andric       if (I != 0)
934*5ffd83dbSDimitry Andric         OS << ", ";
935*5ffd83dbSDimitry Andric       OS << getTypes()[I + 1].str();
936*5ffd83dbSDimitry Andric     }
937*5ffd83dbSDimitry Andric     OS << ");\n";
938*5ffd83dbSDimitry Andric   }
939*5ffd83dbSDimitry Andric }
940*5ffd83dbSDimitry Andric 
941*5ffd83dbSDimitry Andric //===----------------------------------------------------------------------===//
942*5ffd83dbSDimitry Andric // SVEEmitter implementation
943*5ffd83dbSDimitry Andric //===----------------------------------------------------------------------===//
944*5ffd83dbSDimitry Andric uint64_t SVEEmitter::encodeTypeFlags(const SVEType &T) {
945*5ffd83dbSDimitry Andric   if (T.isFloat()) {
946*5ffd83dbSDimitry Andric     switch (T.getElementSizeInBits()) {
947*5ffd83dbSDimitry Andric     case 16:
948*5ffd83dbSDimitry Andric       return encodeEltType("EltTyFloat16");
949*5ffd83dbSDimitry Andric     case 32:
950*5ffd83dbSDimitry Andric       return encodeEltType("EltTyFloat32");
951*5ffd83dbSDimitry Andric     case 64:
952*5ffd83dbSDimitry Andric       return encodeEltType("EltTyFloat64");
953*5ffd83dbSDimitry Andric     default:
954*5ffd83dbSDimitry Andric       llvm_unreachable("Unhandled float element bitwidth!");
955*5ffd83dbSDimitry Andric     }
956*5ffd83dbSDimitry Andric   }
957*5ffd83dbSDimitry Andric 
958*5ffd83dbSDimitry Andric   if (T.isBFloat()) {
959*5ffd83dbSDimitry Andric     assert(T.getElementSizeInBits() == 16 && "Not a valid BFloat.");
960*5ffd83dbSDimitry Andric     return encodeEltType("EltTyBFloat16");
961*5ffd83dbSDimitry Andric   }
962*5ffd83dbSDimitry Andric 
963*5ffd83dbSDimitry Andric   if (T.isPredicateVector()) {
964*5ffd83dbSDimitry Andric     switch (T.getElementSizeInBits()) {
965*5ffd83dbSDimitry Andric     case 8:
966*5ffd83dbSDimitry Andric       return encodeEltType("EltTyBool8");
967*5ffd83dbSDimitry Andric     case 16:
968*5ffd83dbSDimitry Andric       return encodeEltType("EltTyBool16");
969*5ffd83dbSDimitry Andric     case 32:
970*5ffd83dbSDimitry Andric       return encodeEltType("EltTyBool32");
971*5ffd83dbSDimitry Andric     case 64:
972*5ffd83dbSDimitry Andric       return encodeEltType("EltTyBool64");
973*5ffd83dbSDimitry Andric     default:
974*5ffd83dbSDimitry Andric       llvm_unreachable("Unhandled predicate element bitwidth!");
975*5ffd83dbSDimitry Andric     }
976*5ffd83dbSDimitry Andric   }
977*5ffd83dbSDimitry Andric 
978*5ffd83dbSDimitry Andric   switch (T.getElementSizeInBits()) {
979*5ffd83dbSDimitry Andric   case 8:
980*5ffd83dbSDimitry Andric     return encodeEltType("EltTyInt8");
981*5ffd83dbSDimitry Andric   case 16:
982*5ffd83dbSDimitry Andric     return encodeEltType("EltTyInt16");
983*5ffd83dbSDimitry Andric   case 32:
984*5ffd83dbSDimitry Andric     return encodeEltType("EltTyInt32");
985*5ffd83dbSDimitry Andric   case 64:
986*5ffd83dbSDimitry Andric     return encodeEltType("EltTyInt64");
987*5ffd83dbSDimitry Andric   default:
988*5ffd83dbSDimitry Andric     llvm_unreachable("Unhandled integer element bitwidth!");
989*5ffd83dbSDimitry Andric   }
990*5ffd83dbSDimitry Andric }
991*5ffd83dbSDimitry Andric 
992*5ffd83dbSDimitry Andric void SVEEmitter::createIntrinsic(
993*5ffd83dbSDimitry Andric     Record *R, SmallVectorImpl<std::unique_ptr<Intrinsic>> &Out) {
994*5ffd83dbSDimitry Andric   StringRef Name = R->getValueAsString("Name");
995*5ffd83dbSDimitry Andric   StringRef Proto = R->getValueAsString("Prototype");
996*5ffd83dbSDimitry Andric   StringRef Types = R->getValueAsString("Types");
997*5ffd83dbSDimitry Andric   StringRef Guard = R->getValueAsString("ArchGuard");
998*5ffd83dbSDimitry Andric   StringRef LLVMName = R->getValueAsString("LLVMIntrinsic");
999*5ffd83dbSDimitry Andric   uint64_t Merge = R->getValueAsInt("Merge");
1000*5ffd83dbSDimitry Andric   StringRef MergeSuffix = R->getValueAsString("MergeSuffix");
1001*5ffd83dbSDimitry Andric   uint64_t MemEltType = R->getValueAsInt("MemEltType");
1002*5ffd83dbSDimitry Andric   std::vector<Record*> FlagsList = R->getValueAsListOfDefs("Flags");
1003*5ffd83dbSDimitry Andric   std::vector<Record*> ImmCheckList = R->getValueAsListOfDefs("ImmChecks");
1004*5ffd83dbSDimitry Andric 
1005*5ffd83dbSDimitry Andric   int64_t Flags = 0;
1006*5ffd83dbSDimitry Andric   for (auto FlagRec : FlagsList)
1007*5ffd83dbSDimitry Andric     Flags |= FlagRec->getValueAsInt("Value");
1008*5ffd83dbSDimitry Andric 
1009*5ffd83dbSDimitry Andric   // Create a dummy TypeSpec for non-overloaded builtins.
1010*5ffd83dbSDimitry Andric   if (Types.empty()) {
1011*5ffd83dbSDimitry Andric     assert((Flags & getEnumValueForFlag("IsOverloadNone")) &&
1012*5ffd83dbSDimitry Andric            "Expect TypeSpec for overloaded builtin!");
1013*5ffd83dbSDimitry Andric     Types = "i";
1014*5ffd83dbSDimitry Andric   }
1015*5ffd83dbSDimitry Andric 
1016*5ffd83dbSDimitry Andric   // Extract type specs from string
1017*5ffd83dbSDimitry Andric   SmallVector<TypeSpec, 8> TypeSpecs;
1018*5ffd83dbSDimitry Andric   TypeSpec Acc;
1019*5ffd83dbSDimitry Andric   for (char I : Types) {
1020*5ffd83dbSDimitry Andric     Acc.push_back(I);
1021*5ffd83dbSDimitry Andric     if (islower(I)) {
1022*5ffd83dbSDimitry Andric       TypeSpecs.push_back(TypeSpec(Acc));
1023*5ffd83dbSDimitry Andric       Acc.clear();
1024*5ffd83dbSDimitry Andric     }
1025*5ffd83dbSDimitry Andric   }
1026*5ffd83dbSDimitry Andric 
1027*5ffd83dbSDimitry Andric   // Remove duplicate type specs.
1028*5ffd83dbSDimitry Andric   llvm::sort(TypeSpecs);
1029*5ffd83dbSDimitry Andric   TypeSpecs.erase(std::unique(TypeSpecs.begin(), TypeSpecs.end()),
1030*5ffd83dbSDimitry Andric                   TypeSpecs.end());
1031*5ffd83dbSDimitry Andric 
1032*5ffd83dbSDimitry Andric   // Create an Intrinsic for each type spec.
1033*5ffd83dbSDimitry Andric   for (auto TS : TypeSpecs) {
1034*5ffd83dbSDimitry Andric     // Collate a list of range/option checks for the immediates.
1035*5ffd83dbSDimitry Andric     SmallVector<ImmCheck, 2> ImmChecks;
1036*5ffd83dbSDimitry Andric     for (auto *R : ImmCheckList) {
1037*5ffd83dbSDimitry Andric       int64_t Arg = R->getValueAsInt("Arg");
1038*5ffd83dbSDimitry Andric       int64_t EltSizeArg = R->getValueAsInt("EltSizeArg");
1039*5ffd83dbSDimitry Andric       int64_t Kind = R->getValueAsDef("Kind")->getValueAsInt("Value");
1040*5ffd83dbSDimitry Andric       assert(Arg >= 0 && Kind >= 0 && "Arg and Kind must be nonnegative");
1041*5ffd83dbSDimitry Andric 
1042*5ffd83dbSDimitry Andric       unsigned ElementSizeInBits = 0;
1043*5ffd83dbSDimitry Andric       if (EltSizeArg >= 0)
1044*5ffd83dbSDimitry Andric         ElementSizeInBits =
1045*5ffd83dbSDimitry Andric             SVEType(TS, Proto[EltSizeArg + /* offset by return arg */ 1])
1046*5ffd83dbSDimitry Andric                 .getElementSizeInBits();
1047*5ffd83dbSDimitry Andric       ImmChecks.push_back(ImmCheck(Arg, Kind, ElementSizeInBits));
1048*5ffd83dbSDimitry Andric     }
1049*5ffd83dbSDimitry Andric 
1050*5ffd83dbSDimitry Andric     Out.push_back(std::make_unique<Intrinsic>(
1051*5ffd83dbSDimitry Andric         Name, Proto, Merge, MergeSuffix, MemEltType, LLVMName, Flags, ImmChecks,
1052*5ffd83dbSDimitry Andric         TS, ClassS, *this, Guard));
1053*5ffd83dbSDimitry Andric 
1054*5ffd83dbSDimitry Andric     // Also generate the short-form (e.g. svadd_m) for the given type-spec.
1055*5ffd83dbSDimitry Andric     if (Intrinsic::isOverloadedIntrinsic(Name))
1056*5ffd83dbSDimitry Andric       Out.push_back(std::make_unique<Intrinsic>(
1057*5ffd83dbSDimitry Andric           Name, Proto, Merge, MergeSuffix, MemEltType, LLVMName, Flags,
1058*5ffd83dbSDimitry Andric           ImmChecks, TS, ClassG, *this, Guard));
1059*5ffd83dbSDimitry Andric   }
1060*5ffd83dbSDimitry Andric }
1061*5ffd83dbSDimitry Andric 
1062*5ffd83dbSDimitry Andric void SVEEmitter::createHeader(raw_ostream &OS) {
1063*5ffd83dbSDimitry Andric   OS << "/*===---- arm_sve.h - ARM SVE intrinsics "
1064*5ffd83dbSDimitry Andric         "-----------------------------------===\n"
1065*5ffd83dbSDimitry Andric         " *\n"
1066*5ffd83dbSDimitry Andric         " *\n"
1067*5ffd83dbSDimitry Andric         " * Part of the LLVM Project, under the Apache License v2.0 with LLVM "
1068*5ffd83dbSDimitry Andric         "Exceptions.\n"
1069*5ffd83dbSDimitry Andric         " * See https://llvm.org/LICENSE.txt for license information.\n"
1070*5ffd83dbSDimitry Andric         " * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n"
1071*5ffd83dbSDimitry Andric         " *\n"
1072*5ffd83dbSDimitry Andric         " *===-----------------------------------------------------------------"
1073*5ffd83dbSDimitry Andric         "------===\n"
1074*5ffd83dbSDimitry Andric         " */\n\n";
1075*5ffd83dbSDimitry Andric 
1076*5ffd83dbSDimitry Andric   OS << "#ifndef __ARM_SVE_H\n";
1077*5ffd83dbSDimitry Andric   OS << "#define __ARM_SVE_H\n\n";
1078*5ffd83dbSDimitry Andric 
1079*5ffd83dbSDimitry Andric   OS << "#if !defined(__ARM_FEATURE_SVE)\n";
1080*5ffd83dbSDimitry Andric   OS << "#error \"SVE support not enabled\"\n";
1081*5ffd83dbSDimitry Andric   OS << "#else\n\n";
1082*5ffd83dbSDimitry Andric 
1083*5ffd83dbSDimitry Andric   OS << "#if !defined(__LITTLE_ENDIAN__)\n";
1084*5ffd83dbSDimitry Andric   OS << "#error \"Big endian is currently not supported for arm_sve.h\"\n";
1085*5ffd83dbSDimitry Andric   OS << "#endif\n";
1086*5ffd83dbSDimitry Andric 
1087*5ffd83dbSDimitry Andric   OS << "#include <stdint.h>\n\n";
1088*5ffd83dbSDimitry Andric   OS << "#ifdef  __cplusplus\n";
1089*5ffd83dbSDimitry Andric   OS << "extern \"C\" {\n";
1090*5ffd83dbSDimitry Andric   OS << "#else\n";
1091*5ffd83dbSDimitry Andric   OS << "#include <stdbool.h>\n";
1092*5ffd83dbSDimitry Andric   OS << "#endif\n\n";
1093*5ffd83dbSDimitry Andric 
1094*5ffd83dbSDimitry Andric   OS << "typedef __fp16 float16_t;\n";
1095*5ffd83dbSDimitry Andric   OS << "typedef float float32_t;\n";
1096*5ffd83dbSDimitry Andric   OS << "typedef double float64_t;\n";
1097*5ffd83dbSDimitry Andric 
1098*5ffd83dbSDimitry Andric   OS << "typedef __SVInt8_t svint8_t;\n";
1099*5ffd83dbSDimitry Andric   OS << "typedef __SVInt16_t svint16_t;\n";
1100*5ffd83dbSDimitry Andric   OS << "typedef __SVInt32_t svint32_t;\n";
1101*5ffd83dbSDimitry Andric   OS << "typedef __SVInt64_t svint64_t;\n";
1102*5ffd83dbSDimitry Andric   OS << "typedef __SVUint8_t svuint8_t;\n";
1103*5ffd83dbSDimitry Andric   OS << "typedef __SVUint16_t svuint16_t;\n";
1104*5ffd83dbSDimitry Andric   OS << "typedef __SVUint32_t svuint32_t;\n";
1105*5ffd83dbSDimitry Andric   OS << "typedef __SVUint64_t svuint64_t;\n";
1106*5ffd83dbSDimitry Andric   OS << "typedef __SVFloat16_t svfloat16_t;\n\n";
1107*5ffd83dbSDimitry Andric 
1108*5ffd83dbSDimitry Andric   OS << "#if defined(__ARM_FEATURE_SVE_BF16) && "
1109*5ffd83dbSDimitry Andric         "!defined(__ARM_FEATURE_BF16_SCALAR_ARITHMETIC)\n";
1110*5ffd83dbSDimitry Andric   OS << "#error \"__ARM_FEATURE_BF16_SCALAR_ARITHMETIC must be defined when "
1111*5ffd83dbSDimitry Andric         "__ARM_FEATURE_SVE_BF16 is defined\"\n";
1112*5ffd83dbSDimitry Andric   OS << "#endif\n\n";
1113*5ffd83dbSDimitry Andric 
1114*5ffd83dbSDimitry Andric   OS << "#if defined(__ARM_FEATURE_SVE_BF16)\n";
1115*5ffd83dbSDimitry Andric   OS << "typedef __SVBFloat16_t svbfloat16_t;\n";
1116*5ffd83dbSDimitry Andric   OS << "#endif\n\n";
1117*5ffd83dbSDimitry Andric 
1118*5ffd83dbSDimitry Andric   OS << "#if defined(__ARM_FEATURE_BF16_SCALAR_ARITHMETIC)\n";
1119*5ffd83dbSDimitry Andric   OS << "#include <arm_bf16.h>\n";
1120*5ffd83dbSDimitry Andric   OS << "typedef __bf16 bfloat16_t;\n";
1121*5ffd83dbSDimitry Andric   OS << "#endif\n\n";
1122*5ffd83dbSDimitry Andric 
1123*5ffd83dbSDimitry Andric   OS << "typedef __SVFloat32_t svfloat32_t;\n";
1124*5ffd83dbSDimitry Andric   OS << "typedef __SVFloat64_t svfloat64_t;\n";
1125*5ffd83dbSDimitry Andric   OS << "typedef __clang_svint8x2_t svint8x2_t;\n";
1126*5ffd83dbSDimitry Andric   OS << "typedef __clang_svint16x2_t svint16x2_t;\n";
1127*5ffd83dbSDimitry Andric   OS << "typedef __clang_svint32x2_t svint32x2_t;\n";
1128*5ffd83dbSDimitry Andric   OS << "typedef __clang_svint64x2_t svint64x2_t;\n";
1129*5ffd83dbSDimitry Andric   OS << "typedef __clang_svuint8x2_t svuint8x2_t;\n";
1130*5ffd83dbSDimitry Andric   OS << "typedef __clang_svuint16x2_t svuint16x2_t;\n";
1131*5ffd83dbSDimitry Andric   OS << "typedef __clang_svuint32x2_t svuint32x2_t;\n";
1132*5ffd83dbSDimitry Andric   OS << "typedef __clang_svuint64x2_t svuint64x2_t;\n";
1133*5ffd83dbSDimitry Andric   OS << "typedef __clang_svfloat16x2_t svfloat16x2_t;\n";
1134*5ffd83dbSDimitry Andric   OS << "typedef __clang_svfloat32x2_t svfloat32x2_t;\n";
1135*5ffd83dbSDimitry Andric   OS << "typedef __clang_svfloat64x2_t svfloat64x2_t;\n";
1136*5ffd83dbSDimitry Andric   OS << "typedef __clang_svint8x3_t svint8x3_t;\n";
1137*5ffd83dbSDimitry Andric   OS << "typedef __clang_svint16x3_t svint16x3_t;\n";
1138*5ffd83dbSDimitry Andric   OS << "typedef __clang_svint32x3_t svint32x3_t;\n";
1139*5ffd83dbSDimitry Andric   OS << "typedef __clang_svint64x3_t svint64x3_t;\n";
1140*5ffd83dbSDimitry Andric   OS << "typedef __clang_svuint8x3_t svuint8x3_t;\n";
1141*5ffd83dbSDimitry Andric   OS << "typedef __clang_svuint16x3_t svuint16x3_t;\n";
1142*5ffd83dbSDimitry Andric   OS << "typedef __clang_svuint32x3_t svuint32x3_t;\n";
1143*5ffd83dbSDimitry Andric   OS << "typedef __clang_svuint64x3_t svuint64x3_t;\n";
1144*5ffd83dbSDimitry Andric   OS << "typedef __clang_svfloat16x3_t svfloat16x3_t;\n";
1145*5ffd83dbSDimitry Andric   OS << "typedef __clang_svfloat32x3_t svfloat32x3_t;\n";
1146*5ffd83dbSDimitry Andric   OS << "typedef __clang_svfloat64x3_t svfloat64x3_t;\n";
1147*5ffd83dbSDimitry Andric   OS << "typedef __clang_svint8x4_t svint8x4_t;\n";
1148*5ffd83dbSDimitry Andric   OS << "typedef __clang_svint16x4_t svint16x4_t;\n";
1149*5ffd83dbSDimitry Andric   OS << "typedef __clang_svint32x4_t svint32x4_t;\n";
1150*5ffd83dbSDimitry Andric   OS << "typedef __clang_svint64x4_t svint64x4_t;\n";
1151*5ffd83dbSDimitry Andric   OS << "typedef __clang_svuint8x4_t svuint8x4_t;\n";
1152*5ffd83dbSDimitry Andric   OS << "typedef __clang_svuint16x4_t svuint16x4_t;\n";
1153*5ffd83dbSDimitry Andric   OS << "typedef __clang_svuint32x4_t svuint32x4_t;\n";
1154*5ffd83dbSDimitry Andric   OS << "typedef __clang_svuint64x4_t svuint64x4_t;\n";
1155*5ffd83dbSDimitry Andric   OS << "typedef __clang_svfloat16x4_t svfloat16x4_t;\n";
1156*5ffd83dbSDimitry Andric   OS << "typedef __clang_svfloat32x4_t svfloat32x4_t;\n";
1157*5ffd83dbSDimitry Andric   OS << "typedef __clang_svfloat64x4_t svfloat64x4_t;\n";
1158*5ffd83dbSDimitry Andric   OS << "typedef __SVBool_t  svbool_t;\n\n";
1159*5ffd83dbSDimitry Andric 
1160*5ffd83dbSDimitry Andric   OS << "#ifdef __ARM_FEATURE_SVE_BF16\n";
1161*5ffd83dbSDimitry Andric   OS << "typedef __clang_svbfloat16x2_t svbfloat16x2_t;\n";
1162*5ffd83dbSDimitry Andric   OS << "typedef __clang_svbfloat16x3_t svbfloat16x3_t;\n";
1163*5ffd83dbSDimitry Andric   OS << "typedef __clang_svbfloat16x4_t svbfloat16x4_t;\n";
1164*5ffd83dbSDimitry Andric   OS << "#endif\n";
1165*5ffd83dbSDimitry Andric 
1166*5ffd83dbSDimitry Andric   OS << "typedef enum\n";
1167*5ffd83dbSDimitry Andric   OS << "{\n";
1168*5ffd83dbSDimitry Andric   OS << "  SV_POW2 = 0,\n";
1169*5ffd83dbSDimitry Andric   OS << "  SV_VL1 = 1,\n";
1170*5ffd83dbSDimitry Andric   OS << "  SV_VL2 = 2,\n";
1171*5ffd83dbSDimitry Andric   OS << "  SV_VL3 = 3,\n";
1172*5ffd83dbSDimitry Andric   OS << "  SV_VL4 = 4,\n";
1173*5ffd83dbSDimitry Andric   OS << "  SV_VL5 = 5,\n";
1174*5ffd83dbSDimitry Andric   OS << "  SV_VL6 = 6,\n";
1175*5ffd83dbSDimitry Andric   OS << "  SV_VL7 = 7,\n";
1176*5ffd83dbSDimitry Andric   OS << "  SV_VL8 = 8,\n";
1177*5ffd83dbSDimitry Andric   OS << "  SV_VL16 = 9,\n";
1178*5ffd83dbSDimitry Andric   OS << "  SV_VL32 = 10,\n";
1179*5ffd83dbSDimitry Andric   OS << "  SV_VL64 = 11,\n";
1180*5ffd83dbSDimitry Andric   OS << "  SV_VL128 = 12,\n";
1181*5ffd83dbSDimitry Andric   OS << "  SV_VL256 = 13,\n";
1182*5ffd83dbSDimitry Andric   OS << "  SV_MUL4 = 29,\n";
1183*5ffd83dbSDimitry Andric   OS << "  SV_MUL3 = 30,\n";
1184*5ffd83dbSDimitry Andric   OS << "  SV_ALL = 31\n";
1185*5ffd83dbSDimitry Andric   OS << "} sv_pattern;\n\n";
1186*5ffd83dbSDimitry Andric 
1187*5ffd83dbSDimitry Andric   OS << "typedef enum\n";
1188*5ffd83dbSDimitry Andric   OS << "{\n";
1189*5ffd83dbSDimitry Andric   OS << "  SV_PLDL1KEEP = 0,\n";
1190*5ffd83dbSDimitry Andric   OS << "  SV_PLDL1STRM = 1,\n";
1191*5ffd83dbSDimitry Andric   OS << "  SV_PLDL2KEEP = 2,\n";
1192*5ffd83dbSDimitry Andric   OS << "  SV_PLDL2STRM = 3,\n";
1193*5ffd83dbSDimitry Andric   OS << "  SV_PLDL3KEEP = 4,\n";
1194*5ffd83dbSDimitry Andric   OS << "  SV_PLDL3STRM = 5,\n";
1195*5ffd83dbSDimitry Andric   OS << "  SV_PSTL1KEEP = 8,\n";
1196*5ffd83dbSDimitry Andric   OS << "  SV_PSTL1STRM = 9,\n";
1197*5ffd83dbSDimitry Andric   OS << "  SV_PSTL2KEEP = 10,\n";
1198*5ffd83dbSDimitry Andric   OS << "  SV_PSTL2STRM = 11,\n";
1199*5ffd83dbSDimitry Andric   OS << "  SV_PSTL3KEEP = 12,\n";
1200*5ffd83dbSDimitry Andric   OS << "  SV_PSTL3STRM = 13\n";
1201*5ffd83dbSDimitry Andric   OS << "} sv_prfop;\n\n";
1202*5ffd83dbSDimitry Andric 
1203*5ffd83dbSDimitry Andric   OS << "/* Function attributes */\n";
1204*5ffd83dbSDimitry Andric   OS << "#define __aio static inline __attribute__((__always_inline__, "
1205*5ffd83dbSDimitry Andric         "__nodebug__, __overloadable__))\n\n";
1206*5ffd83dbSDimitry Andric 
1207*5ffd83dbSDimitry Andric   // Add reinterpret functions.
1208*5ffd83dbSDimitry Andric   for (auto ShortForm : { false, true } )
1209*5ffd83dbSDimitry Andric     for (const ReinterpretTypeInfo &From : Reinterprets)
1210*5ffd83dbSDimitry Andric       for (const ReinterpretTypeInfo &To : Reinterprets) {
1211*5ffd83dbSDimitry Andric         const bool IsBFloat = StringRef(From.Suffix).equals("bf16") ||
1212*5ffd83dbSDimitry Andric                               StringRef(To.Suffix).equals("bf16");
1213*5ffd83dbSDimitry Andric         if (IsBFloat)
1214*5ffd83dbSDimitry Andric           OS << "#if defined(__ARM_FEATURE_SVE_BF16)\n";
1215*5ffd83dbSDimitry Andric         if (ShortForm) {
1216*5ffd83dbSDimitry Andric           OS << "__aio " << From.Type << " svreinterpret_" << From.Suffix;
1217*5ffd83dbSDimitry Andric           OS << "(" << To.Type << " op) {\n";
1218*5ffd83dbSDimitry Andric           OS << "  return __builtin_sve_reinterpret_" << From.Suffix << "_"
1219*5ffd83dbSDimitry Andric              << To.Suffix << "(op);\n";
1220*5ffd83dbSDimitry Andric           OS << "}\n\n";
1221*5ffd83dbSDimitry Andric         } else
1222*5ffd83dbSDimitry Andric           OS << "#define svreinterpret_" << From.Suffix << "_" << To.Suffix
1223*5ffd83dbSDimitry Andric              << "(...) __builtin_sve_reinterpret_" << From.Suffix << "_"
1224*5ffd83dbSDimitry Andric              << To.Suffix << "(__VA_ARGS__)\n";
1225*5ffd83dbSDimitry Andric         if (IsBFloat)
1226*5ffd83dbSDimitry Andric           OS << "#endif /* #if defined(__ARM_FEATURE_SVE_BF16) */\n";
1227*5ffd83dbSDimitry Andric       }
1228*5ffd83dbSDimitry Andric 
1229*5ffd83dbSDimitry Andric   SmallVector<std::unique_ptr<Intrinsic>, 128> Defs;
1230*5ffd83dbSDimitry Andric   std::vector<Record *> RV = Records.getAllDerivedDefinitions("Inst");
1231*5ffd83dbSDimitry Andric   for (auto *R : RV)
1232*5ffd83dbSDimitry Andric     createIntrinsic(R, Defs);
1233*5ffd83dbSDimitry Andric 
1234*5ffd83dbSDimitry Andric   // Sort intrinsics in header file by following order/priority:
1235*5ffd83dbSDimitry Andric   // - Architectural guard (i.e. does it require SVE2 or SVE2_AES)
1236*5ffd83dbSDimitry Andric   // - Class (is intrinsic overloaded or not)
1237*5ffd83dbSDimitry Andric   // - Intrinsic name
1238*5ffd83dbSDimitry Andric   std::stable_sort(
1239*5ffd83dbSDimitry Andric       Defs.begin(), Defs.end(), [](const std::unique_ptr<Intrinsic> &A,
1240*5ffd83dbSDimitry Andric                                    const std::unique_ptr<Intrinsic> &B) {
1241*5ffd83dbSDimitry Andric         auto ToTuple = [](const std::unique_ptr<Intrinsic> &I) {
1242*5ffd83dbSDimitry Andric           return std::make_tuple(I->getGuard(), (unsigned)I->getClassKind(), I->getName());
1243*5ffd83dbSDimitry Andric         };
1244*5ffd83dbSDimitry Andric         return ToTuple(A) < ToTuple(B);
1245*5ffd83dbSDimitry Andric       });
1246*5ffd83dbSDimitry Andric 
1247*5ffd83dbSDimitry Andric   StringRef InGuard = "";
1248*5ffd83dbSDimitry Andric   for (auto &I : Defs) {
1249*5ffd83dbSDimitry Andric     // Emit #endif/#if pair if needed.
1250*5ffd83dbSDimitry Andric     if (I->getGuard() != InGuard) {
1251*5ffd83dbSDimitry Andric       if (!InGuard.empty())
1252*5ffd83dbSDimitry Andric         OS << "#endif  //" << InGuard << "\n";
1253*5ffd83dbSDimitry Andric       InGuard = I->getGuard();
1254*5ffd83dbSDimitry Andric       if (!InGuard.empty())
1255*5ffd83dbSDimitry Andric         OS << "\n#if " << InGuard << "\n";
1256*5ffd83dbSDimitry Andric     }
1257*5ffd83dbSDimitry Andric 
1258*5ffd83dbSDimitry Andric     // Actually emit the intrinsic declaration.
1259*5ffd83dbSDimitry Andric     I->emitIntrinsic(OS);
1260*5ffd83dbSDimitry Andric   }
1261*5ffd83dbSDimitry Andric 
1262*5ffd83dbSDimitry Andric   if (!InGuard.empty())
1263*5ffd83dbSDimitry Andric     OS << "#endif  //" << InGuard << "\n";
1264*5ffd83dbSDimitry Andric 
1265*5ffd83dbSDimitry Andric   OS << "#if defined(__ARM_FEATURE_SVE_BF16)\n";
1266*5ffd83dbSDimitry Andric   OS << "#define svcvtnt_bf16_x      svcvtnt_bf16_m\n";
1267*5ffd83dbSDimitry Andric   OS << "#define svcvtnt_bf16_f32_x  svcvtnt_bf16_f32_m\n";
1268*5ffd83dbSDimitry Andric   OS << "#endif /*__ARM_FEATURE_SVE_BF16 */\n\n";
1269*5ffd83dbSDimitry Andric 
1270*5ffd83dbSDimitry Andric   OS << "#if defined(__ARM_FEATURE_SVE2)\n";
1271*5ffd83dbSDimitry Andric   OS << "#define svcvtnt_f16_x      svcvtnt_f16_m\n";
1272*5ffd83dbSDimitry Andric   OS << "#define svcvtnt_f16_f32_x  svcvtnt_f16_f32_m\n";
1273*5ffd83dbSDimitry Andric   OS << "#define svcvtnt_f32_x      svcvtnt_f32_m\n";
1274*5ffd83dbSDimitry Andric   OS << "#define svcvtnt_f32_f64_x  svcvtnt_f32_f64_m\n\n";
1275*5ffd83dbSDimitry Andric 
1276*5ffd83dbSDimitry Andric   OS << "#define svcvtxnt_f32_x     svcvtxnt_f32_m\n";
1277*5ffd83dbSDimitry Andric   OS << "#define svcvtxnt_f32_f64_x svcvtxnt_f32_f64_m\n\n";
1278*5ffd83dbSDimitry Andric 
1279*5ffd83dbSDimitry Andric   OS << "#endif /*__ARM_FEATURE_SVE2 */\n\n";
1280*5ffd83dbSDimitry Andric 
1281*5ffd83dbSDimitry Andric   OS << "#ifdef __cplusplus\n";
1282*5ffd83dbSDimitry Andric   OS << "} // extern \"C\"\n";
1283*5ffd83dbSDimitry Andric   OS << "#endif\n\n";
1284*5ffd83dbSDimitry Andric   OS << "#endif /*__ARM_FEATURE_SVE */\n\n";
1285*5ffd83dbSDimitry Andric   OS << "#endif /* __ARM_SVE_H */\n";
1286*5ffd83dbSDimitry Andric }
1287*5ffd83dbSDimitry Andric 
1288*5ffd83dbSDimitry Andric void SVEEmitter::createBuiltins(raw_ostream &OS) {
1289*5ffd83dbSDimitry Andric   std::vector<Record *> RV = Records.getAllDerivedDefinitions("Inst");
1290*5ffd83dbSDimitry Andric   SmallVector<std::unique_ptr<Intrinsic>, 128> Defs;
1291*5ffd83dbSDimitry Andric   for (auto *R : RV)
1292*5ffd83dbSDimitry Andric     createIntrinsic(R, Defs);
1293*5ffd83dbSDimitry Andric 
1294*5ffd83dbSDimitry Andric   // The mappings must be sorted based on BuiltinID.
1295*5ffd83dbSDimitry Andric   llvm::sort(Defs, [](const std::unique_ptr<Intrinsic> &A,
1296*5ffd83dbSDimitry Andric                       const std::unique_ptr<Intrinsic> &B) {
1297*5ffd83dbSDimitry Andric     return A->getMangledName() < B->getMangledName();
1298*5ffd83dbSDimitry Andric   });
1299*5ffd83dbSDimitry Andric 
1300*5ffd83dbSDimitry Andric   OS << "#ifdef GET_SVE_BUILTINS\n";
1301*5ffd83dbSDimitry Andric   for (auto &Def : Defs) {
1302*5ffd83dbSDimitry Andric     // Only create BUILTINs for non-overloaded intrinsics, as overloaded
1303*5ffd83dbSDimitry Andric     // declarations only live in the header file.
1304*5ffd83dbSDimitry Andric     if (Def->getClassKind() != ClassG)
1305*5ffd83dbSDimitry Andric       OS << "BUILTIN(__builtin_sve_" << Def->getMangledName() << ", \""
1306*5ffd83dbSDimitry Andric          << Def->getBuiltinTypeStr() << "\", \"n\")\n";
1307*5ffd83dbSDimitry Andric   }
1308*5ffd83dbSDimitry Andric 
1309*5ffd83dbSDimitry Andric   // Add reinterpret builtins
1310*5ffd83dbSDimitry Andric   for (const ReinterpretTypeInfo &From : Reinterprets)
1311*5ffd83dbSDimitry Andric     for (const ReinterpretTypeInfo &To : Reinterprets)
1312*5ffd83dbSDimitry Andric       OS << "BUILTIN(__builtin_sve_reinterpret_" << From.Suffix << "_"
1313*5ffd83dbSDimitry Andric          << To.Suffix << +", \"" << From.BuiltinType << To.BuiltinType
1314*5ffd83dbSDimitry Andric          << "\", \"n\")\n";
1315*5ffd83dbSDimitry Andric 
1316*5ffd83dbSDimitry Andric   OS << "#endif\n\n";
1317*5ffd83dbSDimitry Andric   }
1318*5ffd83dbSDimitry Andric 
1319*5ffd83dbSDimitry Andric void SVEEmitter::createCodeGenMap(raw_ostream &OS) {
1320*5ffd83dbSDimitry Andric   std::vector<Record *> RV = Records.getAllDerivedDefinitions("Inst");
1321*5ffd83dbSDimitry Andric   SmallVector<std::unique_ptr<Intrinsic>, 128> Defs;
1322*5ffd83dbSDimitry Andric   for (auto *R : RV)
1323*5ffd83dbSDimitry Andric     createIntrinsic(R, Defs);
1324*5ffd83dbSDimitry Andric 
1325*5ffd83dbSDimitry Andric   // The mappings must be sorted based on BuiltinID.
1326*5ffd83dbSDimitry Andric   llvm::sort(Defs, [](const std::unique_ptr<Intrinsic> &A,
1327*5ffd83dbSDimitry Andric                       const std::unique_ptr<Intrinsic> &B) {
1328*5ffd83dbSDimitry Andric     return A->getMangledName() < B->getMangledName();
1329*5ffd83dbSDimitry Andric   });
1330*5ffd83dbSDimitry Andric 
1331*5ffd83dbSDimitry Andric   OS << "#ifdef GET_SVE_LLVM_INTRINSIC_MAP\n";
1332*5ffd83dbSDimitry Andric   for (auto &Def : Defs) {
1333*5ffd83dbSDimitry Andric     // Builtins only exist for non-overloaded intrinsics, overloaded
1334*5ffd83dbSDimitry Andric     // declarations only live in the header file.
1335*5ffd83dbSDimitry Andric     if (Def->getClassKind() == ClassG)
1336*5ffd83dbSDimitry Andric       continue;
1337*5ffd83dbSDimitry Andric 
1338*5ffd83dbSDimitry Andric     uint64_t Flags = Def->getFlags();
1339*5ffd83dbSDimitry Andric     auto FlagString = std::to_string(Flags);
1340*5ffd83dbSDimitry Andric 
1341*5ffd83dbSDimitry Andric     std::string LLVMName = Def->getLLVMName();
1342*5ffd83dbSDimitry Andric     std::string Builtin = Def->getMangledName();
1343*5ffd83dbSDimitry Andric     if (!LLVMName.empty())
1344*5ffd83dbSDimitry Andric       OS << "SVEMAP1(" << Builtin << ", " << LLVMName << ", " << FlagString
1345*5ffd83dbSDimitry Andric          << "),\n";
1346*5ffd83dbSDimitry Andric     else
1347*5ffd83dbSDimitry Andric       OS << "SVEMAP2(" << Builtin << ", " << FlagString << "),\n";
1348*5ffd83dbSDimitry Andric   }
1349*5ffd83dbSDimitry Andric   OS << "#endif\n\n";
1350*5ffd83dbSDimitry Andric }
1351*5ffd83dbSDimitry Andric 
1352*5ffd83dbSDimitry Andric void SVEEmitter::createRangeChecks(raw_ostream &OS) {
1353*5ffd83dbSDimitry Andric   std::vector<Record *> RV = Records.getAllDerivedDefinitions("Inst");
1354*5ffd83dbSDimitry Andric   SmallVector<std::unique_ptr<Intrinsic>, 128> Defs;
1355*5ffd83dbSDimitry Andric   for (auto *R : RV)
1356*5ffd83dbSDimitry Andric     createIntrinsic(R, Defs);
1357*5ffd83dbSDimitry Andric 
1358*5ffd83dbSDimitry Andric   // The mappings must be sorted based on BuiltinID.
1359*5ffd83dbSDimitry Andric   llvm::sort(Defs, [](const std::unique_ptr<Intrinsic> &A,
1360*5ffd83dbSDimitry Andric                       const std::unique_ptr<Intrinsic> &B) {
1361*5ffd83dbSDimitry Andric     return A->getMangledName() < B->getMangledName();
1362*5ffd83dbSDimitry Andric   });
1363*5ffd83dbSDimitry Andric 
1364*5ffd83dbSDimitry Andric 
1365*5ffd83dbSDimitry Andric   OS << "#ifdef GET_SVE_IMMEDIATE_CHECK\n";
1366*5ffd83dbSDimitry Andric 
1367*5ffd83dbSDimitry Andric   // Ensure these are only emitted once.
1368*5ffd83dbSDimitry Andric   std::set<std::string> Emitted;
1369*5ffd83dbSDimitry Andric 
1370*5ffd83dbSDimitry Andric   for (auto &Def : Defs) {
1371*5ffd83dbSDimitry Andric     if (Emitted.find(Def->getMangledName()) != Emitted.end() ||
1372*5ffd83dbSDimitry Andric         Def->getImmChecks().empty())
1373*5ffd83dbSDimitry Andric       continue;
1374*5ffd83dbSDimitry Andric 
1375*5ffd83dbSDimitry Andric     OS << "case SVE::BI__builtin_sve_" << Def->getMangledName() << ":\n";
1376*5ffd83dbSDimitry Andric     for (auto &Check : Def->getImmChecks())
1377*5ffd83dbSDimitry Andric       OS << "ImmChecks.push_back(std::make_tuple(" << Check.getArg() << ", "
1378*5ffd83dbSDimitry Andric          << Check.getKind() << ", " << Check.getElementSizeInBits() << "));\n";
1379*5ffd83dbSDimitry Andric     OS << "  break;\n";
1380*5ffd83dbSDimitry Andric 
1381*5ffd83dbSDimitry Andric     Emitted.insert(Def->getMangledName());
1382*5ffd83dbSDimitry Andric   }
1383*5ffd83dbSDimitry Andric 
1384*5ffd83dbSDimitry Andric   OS << "#endif\n\n";
1385*5ffd83dbSDimitry Andric }
1386*5ffd83dbSDimitry Andric 
1387*5ffd83dbSDimitry Andric /// Create the SVETypeFlags used in CGBuiltins
1388*5ffd83dbSDimitry Andric void SVEEmitter::createTypeFlags(raw_ostream &OS) {
1389*5ffd83dbSDimitry Andric   OS << "#ifdef LLVM_GET_SVE_TYPEFLAGS\n";
1390*5ffd83dbSDimitry Andric   for (auto &KV : FlagTypes)
1391*5ffd83dbSDimitry Andric     OS << "const uint64_t " << KV.getKey() << " = " << KV.getValue() << ";\n";
1392*5ffd83dbSDimitry Andric   OS << "#endif\n\n";
1393*5ffd83dbSDimitry Andric 
1394*5ffd83dbSDimitry Andric   OS << "#ifdef LLVM_GET_SVE_ELTTYPES\n";
1395*5ffd83dbSDimitry Andric   for (auto &KV : EltTypes)
1396*5ffd83dbSDimitry Andric     OS << "  " << KV.getKey() << " = " << KV.getValue() << ",\n";
1397*5ffd83dbSDimitry Andric   OS << "#endif\n\n";
1398*5ffd83dbSDimitry Andric 
1399*5ffd83dbSDimitry Andric   OS << "#ifdef LLVM_GET_SVE_MEMELTTYPES\n";
1400*5ffd83dbSDimitry Andric   for (auto &KV : MemEltTypes)
1401*5ffd83dbSDimitry Andric     OS << "  " << KV.getKey() << " = " << KV.getValue() << ",\n";
1402*5ffd83dbSDimitry Andric   OS << "#endif\n\n";
1403*5ffd83dbSDimitry Andric 
1404*5ffd83dbSDimitry Andric   OS << "#ifdef LLVM_GET_SVE_MERGETYPES\n";
1405*5ffd83dbSDimitry Andric   for (auto &KV : MergeTypes)
1406*5ffd83dbSDimitry Andric     OS << "  " << KV.getKey() << " = " << KV.getValue() << ",\n";
1407*5ffd83dbSDimitry Andric   OS << "#endif\n\n";
1408*5ffd83dbSDimitry Andric 
1409*5ffd83dbSDimitry Andric   OS << "#ifdef LLVM_GET_SVE_IMMCHECKTYPES\n";
1410*5ffd83dbSDimitry Andric   for (auto &KV : ImmCheckTypes)
1411*5ffd83dbSDimitry Andric     OS << "  " << KV.getKey() << " = " << KV.getValue() << ",\n";
1412*5ffd83dbSDimitry Andric   OS << "#endif\n\n";
1413*5ffd83dbSDimitry Andric }
1414*5ffd83dbSDimitry Andric 
1415*5ffd83dbSDimitry Andric namespace clang {
1416*5ffd83dbSDimitry Andric void EmitSveHeader(RecordKeeper &Records, raw_ostream &OS) {
1417*5ffd83dbSDimitry Andric   SVEEmitter(Records).createHeader(OS);
1418*5ffd83dbSDimitry Andric }
1419*5ffd83dbSDimitry Andric 
1420*5ffd83dbSDimitry Andric void EmitSveBuiltins(RecordKeeper &Records, raw_ostream &OS) {
1421*5ffd83dbSDimitry Andric   SVEEmitter(Records).createBuiltins(OS);
1422*5ffd83dbSDimitry Andric }
1423*5ffd83dbSDimitry Andric 
1424*5ffd83dbSDimitry Andric void EmitSveBuiltinCG(RecordKeeper &Records, raw_ostream &OS) {
1425*5ffd83dbSDimitry Andric   SVEEmitter(Records).createCodeGenMap(OS);
1426*5ffd83dbSDimitry Andric }
1427*5ffd83dbSDimitry Andric 
1428*5ffd83dbSDimitry Andric void EmitSveRangeChecks(RecordKeeper &Records, raw_ostream &OS) {
1429*5ffd83dbSDimitry Andric   SVEEmitter(Records).createRangeChecks(OS);
1430*5ffd83dbSDimitry Andric }
1431*5ffd83dbSDimitry Andric 
1432*5ffd83dbSDimitry Andric void EmitSveTypeFlags(RecordKeeper &Records, raw_ostream &OS) {
1433*5ffd83dbSDimitry Andric   SVEEmitter(Records).createTypeFlags(OS);
1434*5ffd83dbSDimitry Andric }
1435*5ffd83dbSDimitry Andric 
1436*5ffd83dbSDimitry Andric } // End namespace clang
1437