xref: /llvm-project/clang/utils/TableGen/SveEmitter.cpp (revision f95a8bde3425ada0ef004186eb8ccda6e723241c)
1 //===-- SveEmitter.cpp - Generate arm_sve.h for use with clang ------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This tablegen backend is responsible for emitting arm_sve.h, which includes
10 // a declaration and definition of each function specified by the ARM C/C++
11 // Language Extensions (ACLE).
12 //
13 // For details, visit:
14 //  https://developer.arm.com/architectures/system-architectures/software-standards/acle
15 //
16 // Each SVE instruction is implemented in terms of 1 or more functions which
17 // are suffixed with the element type of the input vectors.  Functions may be
18 // implemented in terms of generic vector operations such as +, *, -, etc. or
19 // by calling a __builtin_-prefixed function which will be handled by clang's
20 // CodeGen library.
21 //
22 // See also the documentation in include/clang/Basic/arm_sve.td.
23 //
24 //===----------------------------------------------------------------------===//
25 
26 #include "llvm/ADT/ArrayRef.h"
27 #include "llvm/ADT/STLExtras.h"
28 #include "llvm/ADT/StringExtras.h"
29 #include "llvm/ADT/StringMap.h"
30 #include "llvm/TableGen/AArch64ImmCheck.h"
31 #include "llvm/TableGen/Error.h"
32 #include "llvm/TableGen/Record.h"
33 #include <array>
34 #include <cctype>
35 #include <set>
36 #include <string>
37 #include <tuple>
38 
39 using namespace llvm;
40 
41 enum ClassKind {
42   ClassNone,
43   ClassS,     // signed/unsigned, e.g., "_s8", "_u8" suffix
44   ClassG,     // Overloaded name without type suffix
45 };
46 
47 enum class ACLEKind { SVE, SME };
48 
49 using TypeSpec = std::string;
50 
51 namespace {
52 class SVEType {
53 
54   enum TypeKind {
55     Invalid,
56     Void,
57     Float,
58     SInt,
59     UInt,
60     BFloat16,
61     MFloat8,
62     Svcount,
63     PrefetchOp,
64     PredicatePattern,
65     Predicate,
66     Fpm
67   };
68   TypeKind Kind;
69   bool Immediate, Constant, Pointer, DefaultType, IsScalable;
70   unsigned Bitwidth, ElementBitwidth, NumVectors;
71 
72 public:
73   SVEType() : SVEType("", 'v') {}
74 
75   SVEType(StringRef TS, char CharMod, unsigned NumVectors = 1)
76       : Kind(Invalid), Immediate(false), Constant(false), Pointer(false),
77         DefaultType(false), IsScalable(true), Bitwidth(128),
78         ElementBitwidth(~0U), NumVectors(NumVectors) {
79     if (!TS.empty())
80       applyTypespec(TS);
81     applyModifier(CharMod);
82   }
83 
84   SVEType(const SVEType &Base, unsigned NumV) : SVEType(Base) {
85     NumVectors = NumV;
86   }
87 
88   bool isPointer() const { return Pointer; }
89   bool isConstant() const { return Constant; }
90   bool isImmediate() const { return Immediate; }
91   bool isScalar() const { return NumVectors == 0; }
92   bool isVector() const { return NumVectors > 0; }
93   bool isScalableVector() const { return isVector() && IsScalable; }
94   bool isFixedLengthVector() const { return isVector() && !IsScalable; }
95   bool isChar() const { return ElementBitwidth == 8 && isInteger(); }
96   bool isVoid() const { return Kind == Void; }
97   bool isDefault() const { return DefaultType; }
98   bool isFloat() const { return Kind == Float; }
99   bool isBFloat() const { return Kind == BFloat16; }
100   bool isMFloat() const { return Kind == MFloat8; }
101   bool isFloatingPoint() const {
102     return Kind == Float || Kind == BFloat16 || Kind == MFloat8;
103   }
104   bool isInteger() const { return Kind == SInt || Kind == UInt; }
105   bool isSignedInteger() const { return Kind == SInt; }
106   bool isUnsignedInteger() const { return Kind == UInt; }
107   bool isScalarPredicate() const {
108     return Kind == Predicate && NumVectors == 0;
109   }
110   bool isPredicate() const { return Kind == Predicate; }
111   bool isPredicatePattern() const { return Kind == PredicatePattern; }
112   bool isPrefetchOp() const { return Kind == PrefetchOp; }
113   bool isSvcount() const { return Kind == Svcount; }
114   bool isFpm() const { return Kind == Fpm; }
115   bool isInvalid() const { return Kind == Invalid; }
116   unsigned getElementSizeInBits() const { return ElementBitwidth; }
117   unsigned getNumVectors() const { return NumVectors; }
118 
119   unsigned getNumElements() const {
120     assert(ElementBitwidth != ~0U);
121     return isPredicate() ? 16 : (Bitwidth / ElementBitwidth);
122   }
123   unsigned getSizeInBits() const {
124     return Bitwidth;
125   }
126 
127   /// Return the string representation of a type, which is an encoded
128   /// string for passing to the BUILTIN() macro in Builtins.def.
129   std::string builtin_str() const;
130 
131   /// Return the C/C++ string representation of a type for use in the
132   /// arm_sve.h header file.
133   std::string str() const;
134 
135 private:
136   /// Creates the type based on the typespec string in TS.
137   void applyTypespec(StringRef TS);
138 
139   /// Applies a prototype modifier to the type.
140   void applyModifier(char Mod);
141 
142   /// Get the builtin base for this SVEType, e.g. 'Wi' for svint64_t.
143   std::string builtinBaseType() const;
144 };
145 
146 class SVEEmitter;
147 
148 /// The main grunt class. This represents an instantiation of an intrinsic with
149 /// a particular typespec and prototype.
150 class Intrinsic {
151   /// The unmangled name.
152   std::string Name;
153 
154   /// The name of the corresponding LLVM IR intrinsic.
155   std::string LLVMName;
156 
157   /// Intrinsic prototype.
158   std::string Proto;
159 
160   /// The base type spec for this intrinsic.
161   TypeSpec BaseTypeSpec;
162 
163   /// The base class kind. Most intrinsics use ClassS, which has full type
164   /// info for integers (_s32/_u32), or ClassG which is used for overloaded
165   /// intrinsics.
166   ClassKind Class;
167 
168   /// The architectural #ifdef guard.
169   std::string SVEGuard, SMEGuard;
170 
171   // The merge suffix such as _m, _x or _z.
172   std::string MergeSuffix;
173 
174   /// The types of return value [0] and parameters [1..].
175   std::vector<SVEType> Types;
176 
177   /// The "base type", which is VarType('d', BaseTypeSpec).
178   SVEType BaseType;
179 
180   uint64_t Flags;
181 
182   SmallVector<ImmCheck, 2> ImmChecks;
183 
184 public:
185   Intrinsic(StringRef Name, StringRef Proto, uint64_t MergeTy,
186             StringRef MergeSuffix, uint64_t MemoryElementTy, StringRef LLVMName,
187             uint64_t Flags, ArrayRef<ImmCheck> ImmChecks, TypeSpec BT,
188             ClassKind Class, SVEEmitter &Emitter, StringRef SVEGuard,
189             StringRef SMEGuard);
190 
191   ~Intrinsic()=default;
192 
193   std::string getName() const { return Name; }
194   std::string getLLVMName() const { return LLVMName; }
195   std::string getProto() const { return Proto; }
196   TypeSpec getBaseTypeSpec() const { return BaseTypeSpec; }
197   SVEType getBaseType() const { return BaseType; }
198 
199   StringRef getSVEGuard() const { return SVEGuard; }
200   StringRef getSMEGuard() const { return SMEGuard; }
201   void printGuard(raw_ostream &OS) const {
202     if (!SVEGuard.empty() && SMEGuard.empty())
203       OS << SVEGuard;
204     else if (SVEGuard.empty() && !SMEGuard.empty())
205       OS << SMEGuard;
206     else {
207       if (SVEGuard.find(",") != std::string::npos ||
208           SVEGuard.find("|") != std::string::npos)
209         OS << "(" << SVEGuard << ")";
210       else
211         OS << SVEGuard;
212       OS << "|";
213       if (SMEGuard.find(",") != std::string::npos ||
214           SMEGuard.find("|") != std::string::npos)
215         OS << "(" << SMEGuard << ")";
216       else
217         OS << SMEGuard;
218     }
219   }
220   ClassKind getClassKind() const { return Class; }
221 
222   SVEType getReturnType() const { return Types[0]; }
223   ArrayRef<SVEType> getTypes() const { return Types; }
224   SVEType getParamType(unsigned I) const { return Types[I + 1]; }
225   unsigned getNumParams() const {
226     return Proto.size() - (2 * count(Proto, '.')) - 1;
227   }
228 
229   uint64_t getFlags() const { return Flags; }
230   bool isFlagSet(uint64_t Flag) const { return Flags & Flag;}
231 
232   ArrayRef<ImmCheck> getImmChecks() const { return ImmChecks; }
233 
234   /// Return the type string for a BUILTIN() macro in Builtins.def.
235   std::string getBuiltinTypeStr();
236 
237   /// Return the name, mangled with type information. The name is mangled for
238   /// ClassS, so will add type suffixes such as _u32/_s32.
239   std::string getMangledName() const { return mangleName(ClassS); }
240 
241   /// As above, but mangles the LLVM name instead.
242   std::string getMangledLLVMName() const { return mangleLLVMName(); }
243 
244   /// Returns true if the intrinsic is overloaded, in that it should also generate
245   /// a short form without the type-specifiers, e.g. 'svld1(..)' instead of
246   /// 'svld1_u32(..)'.
247   static bool isOverloadedIntrinsic(StringRef Name) {
248     auto BrOpen = Name.find('[');
249     auto BrClose = Name.find(']');
250     return BrOpen != std::string::npos && BrClose != std::string::npos;
251   }
252 
253   /// Return true if the intrinsic takes a splat operand.
254   bool hasSplat() const {
255     // These prototype modifiers are described in arm_sve.td.
256     return Proto.find_first_of("ajfrKLR@!") != std::string::npos;
257   }
258 
259   /// Return the parameter index of the splat operand.
260   unsigned getSplatIdx() const {
261     unsigned I = 1, Param = 0;
262     for (; I < Proto.size(); ++I, ++Param) {
263       if (Proto[I] == 'a' || Proto[I] == 'j' || Proto[I] == 'f' ||
264           Proto[I] == 'r' || Proto[I] == 'K' || Proto[I] == 'L' ||
265           Proto[I] == 'R' || Proto[I] == '@' || Proto[I] == '!')
266         break;
267 
268       // Multivector modifier can be skipped
269       if (Proto[I] == '.')
270         I += 2;
271     }
272     assert(I != Proto.size() && "Prototype has no splat operand");
273     return Param;
274   }
275 
276   /// Emits the intrinsic declaration to the ostream.
277   void emitIntrinsic(raw_ostream &OS, SVEEmitter &Emitter, ACLEKind Kind) const;
278 
279 private:
280   std::string getMergeSuffix() const { return MergeSuffix; }
281   std::string mangleName(ClassKind LocalCK) const;
282   std::string mangleLLVMName() const;
283   std::string replaceTemplatedArgs(std::string Name, TypeSpec TS,
284                                    std::string Proto) const;
285 };
286 
287 class SVEEmitter {
288 private:
289   // The reinterpret builtins are generated separately because they
290   // need the cross product of all types (121 functions in total),
291   // which is inconvenient to specify in the arm_sve.td file or
292   // generate in CGBuiltin.cpp.
293   struct ReinterpretTypeInfo {
294     SVEType BaseType;
295     const char *Suffix;
296   };
297 
298   static const std::array<ReinterpretTypeInfo, 13> Reinterprets;
299 
300   const RecordKeeper &Records;
301   StringMap<uint64_t> EltTypes;
302   StringMap<uint64_t> MemEltTypes;
303   StringMap<uint64_t> FlagTypes;
304   StringMap<uint64_t> MergeTypes;
305   StringMap<uint64_t> ImmCheckTypes;
306 
307 public:
308   SVEEmitter(const RecordKeeper &R) : Records(R) {
309     for (auto *RV : Records.getAllDerivedDefinitions("EltType"))
310       EltTypes[RV->getNameInitAsString()] = RV->getValueAsInt("Value");
311     for (auto *RV : Records.getAllDerivedDefinitions("MemEltType"))
312       MemEltTypes[RV->getNameInitAsString()] = RV->getValueAsInt("Value");
313     for (auto *RV : Records.getAllDerivedDefinitions("FlagType"))
314       FlagTypes[RV->getNameInitAsString()] = RV->getValueAsInt("Value");
315     for (auto *RV : Records.getAllDerivedDefinitions("MergeType"))
316       MergeTypes[RV->getNameInitAsString()] = RV->getValueAsInt("Value");
317     for (auto *RV : Records.getAllDerivedDefinitions("ImmCheckType"))
318       ImmCheckTypes[RV->getNameInitAsString()] = RV->getValueAsInt("Value");
319   }
320 
321   /// Returns the enum value for the immcheck type
322   unsigned getEnumValueForImmCheck(StringRef C) const {
323     auto It = ImmCheckTypes.find(C);
324     if (It != ImmCheckTypes.end())
325       return It->getValue();
326     llvm_unreachable("Unsupported imm check");
327   }
328 
329   /// Returns the enum value for the flag type
330   uint64_t getEnumValueForFlag(StringRef C) const {
331     auto Res = FlagTypes.find(C);
332     if (Res != FlagTypes.end())
333       return Res->getValue();
334     llvm_unreachable("Unsupported flag");
335   }
336 
337   // Returns the SVETypeFlags for a given value and mask.
338   uint64_t encodeFlag(uint64_t V, StringRef MaskName) const {
339     auto It = FlagTypes.find(MaskName);
340     if (It != FlagTypes.end()) {
341       uint64_t Mask = It->getValue();
342       unsigned Shift = countr_zero(Mask);
343       assert(Shift < 64 && "Mask value produced an invalid shift value");
344       return (V << Shift) & Mask;
345     }
346     llvm_unreachable("Unsupported flag");
347   }
348 
349   // Returns the SVETypeFlags for the given element type.
350   uint64_t encodeEltType(StringRef EltName) {
351     auto It = EltTypes.find(EltName);
352     if (It != EltTypes.end())
353       return encodeFlag(It->getValue(), "EltTypeMask");
354     llvm_unreachable("Unsupported EltType");
355   }
356 
357   // Returns the SVETypeFlags for the given memory element type.
358   uint64_t encodeMemoryElementType(uint64_t MT) {
359     return encodeFlag(MT, "MemEltTypeMask");
360   }
361 
362   // Returns the SVETypeFlags for the given merge type.
363   uint64_t encodeMergeType(uint64_t MT) {
364     return encodeFlag(MT, "MergeTypeMask");
365   }
366 
367   // Returns the SVETypeFlags for the given splat operand.
368   unsigned encodeSplatOperand(unsigned SplatIdx) {
369     assert(SplatIdx < 7 && "SplatIdx out of encodable range");
370     return encodeFlag(SplatIdx + 1, "SplatOperandMask");
371   }
372 
373   // Returns the SVETypeFlags value for the given SVEType.
374   uint64_t encodeTypeFlags(const SVEType &T);
375 
376   /// Emit arm_sve.h.
377   void createHeader(raw_ostream &o);
378 
379   // Emits core intrinsics in both arm_sme.h and arm_sve.h
380   void createCoreHeaderIntrinsics(raw_ostream &o, SVEEmitter &Emitter,
381                                   ACLEKind Kind);
382 
383   /// Emit all the __builtin prototypes and code needed by Sema.
384   void createBuiltins(raw_ostream &o);
385 
386   /// Emit all the information needed to map builtin -> LLVM IR intrinsic.
387   void createCodeGenMap(raw_ostream &o);
388 
389   /// Emit all the range checks for the immediates.
390   void createRangeChecks(raw_ostream &o);
391 
392   // Emit all the ImmCheckTypes to arm_immcheck_types.inc
393   void createImmCheckTypes(raw_ostream &OS);
394 
395   /// Create the SVETypeFlags used in CGBuiltins
396   void createTypeFlags(raw_ostream &o);
397 
398   /// Emit arm_sme.h.
399   void createSMEHeader(raw_ostream &o);
400 
401   /// Emit all the SME __builtin prototypes and code needed by Sema.
402   void createSMEBuiltins(raw_ostream &o);
403 
404   /// Emit all the information needed to map builtin -> LLVM IR intrinsic.
405   void createSMECodeGenMap(raw_ostream &o);
406 
407   /// Create a table for a builtin's requirement for PSTATE.SM.
408   void createStreamingAttrs(raw_ostream &o, ACLEKind Kind);
409 
410   /// Emit all the range checks for the immediates.
411   void createSMERangeChecks(raw_ostream &o);
412 
413   /// Create a table for a builtin's requirement for PSTATE.ZA.
414   void createBuiltinZAState(raw_ostream &OS);
415 
416   /// Create intrinsic and add it to \p Out
417   void createIntrinsic(const Record *R,
418                        SmallVectorImpl<std::unique_ptr<Intrinsic>> &Out);
419 };
420 
421 const std::array<SVEEmitter::ReinterpretTypeInfo, 13> SVEEmitter::Reinterprets =
422     {{{SVEType("c", 'd'), "s8"},
423       {SVEType("Uc", 'd'), "u8"},
424       {SVEType("m", 'd'), "mf8"},
425       {SVEType("s", 'd'), "s16"},
426       {SVEType("Us", 'd'), "u16"},
427       {SVEType("i", 'd'), "s32"},
428       {SVEType("Ui", 'd'), "u32"},
429       {SVEType("l", 'd'), "s64"},
430       {SVEType("Ul", 'd'), "u64"},
431       {SVEType("h", 'd'), "f16"},
432       {SVEType("b", 'd'), "bf16"},
433       {SVEType("f", 'd'), "f32"},
434       {SVEType("d", 'd'), "f64"}}};
435 
436 } // end anonymous namespace
437 
438 //===----------------------------------------------------------------------===//
439 // Type implementation
440 //===----------------------------------------------------------------------===//
441 
442 std::string SVEType::builtinBaseType() const {
443   switch (Kind) {
444   case TypeKind::Void:
445     return "v";
446   case TypeKind::Svcount:
447     return "Qa";
448   case TypeKind::PrefetchOp:
449   case TypeKind::PredicatePattern:
450     return "i";
451   case TypeKind::Fpm:
452     return "UWi";
453   case TypeKind::Predicate:
454     return "b";
455   case TypeKind::BFloat16:
456     assert(ElementBitwidth == 16 && "Invalid BFloat16!");
457     return "y";
458   case TypeKind::MFloat8:
459     assert(ElementBitwidth == 8 && "Invalid MFloat8!");
460     return "m";
461   case TypeKind::Float:
462     switch (ElementBitwidth) {
463     case 16:
464       return "h";
465     case 32:
466       return "f";
467     case 64:
468       return "d";
469     default:
470       llvm_unreachable("Unhandled float width!");
471     }
472   case TypeKind::SInt:
473   case TypeKind::UInt:
474     switch (ElementBitwidth) {
475     case 1:
476       return "b";
477     case 8:
478       return "c";
479     case 16:
480       return "s";
481     case 32:
482       return "i";
483     case 64:
484       return "Wi";
485     case 128:
486       return "LLLi";
487     default:
488       llvm_unreachable("Unhandled bitwidth!");
489     }
490   case TypeKind::Invalid:
491     llvm_unreachable("Attempting to resolve builtin string from Invalid type!");
492   }
493   llvm_unreachable("Unhandled TypeKind!");
494 }
495 
496 std::string SVEType::builtin_str() const {
497   std::string Prefix;
498 
499   if (isScalableVector())
500     Prefix = "q" + llvm::utostr(getNumElements() * NumVectors);
501   else if (isFixedLengthVector())
502     Prefix = "V" + llvm::utostr(getNumElements() * NumVectors);
503   else if (isImmediate()) {
504     assert(!isFloatingPoint() && "fp immediates are not supported");
505     Prefix = "I";
506   }
507 
508   // Make chars and integer pointers explicitly signed.
509   if ((ElementBitwidth == 8 || isPointer()) && isSignedInteger())
510     Prefix += "S";
511   else if (isUnsignedInteger())
512     Prefix += "U";
513 
514   std::string BuiltinStr = Prefix + builtinBaseType();
515   if (isConstant())
516     BuiltinStr += "C";
517   if (isPointer())
518     BuiltinStr += "*";
519 
520   return BuiltinStr;
521 }
522 
523 std::string SVEType::str() const {
524   std::string TypeStr;
525 
526   switch (Kind) {
527   case TypeKind::PrefetchOp:
528     return "enum svprfop";
529   case TypeKind::PredicatePattern:
530     return "enum svpattern";
531   case TypeKind::Fpm:
532     TypeStr += "fpm";
533     break;
534   case TypeKind::Void:
535     TypeStr += "void";
536     break;
537   case TypeKind::Float:
538     TypeStr += "float" + llvm::utostr(ElementBitwidth);
539     break;
540   case TypeKind::Svcount:
541     TypeStr += "svcount";
542     break;
543   case TypeKind::Predicate:
544     TypeStr += "bool";
545     break;
546   case TypeKind::BFloat16:
547     TypeStr += "bfloat16";
548     break;
549   case TypeKind::MFloat8:
550     TypeStr += "mfloat8";
551     break;
552   case TypeKind::SInt:
553     TypeStr += "int" + llvm::utostr(ElementBitwidth);
554     break;
555   case TypeKind::UInt:
556     TypeStr += "uint" + llvm::utostr(ElementBitwidth);
557     break;
558   case TypeKind::Invalid:
559     llvm_unreachable("Attempting to resolve type name from Invalid type!");
560   }
561 
562   if (isFixedLengthVector())
563     TypeStr += "x" + llvm::utostr(getNumElements());
564   else if (isScalableVector())
565     TypeStr = "sv" + TypeStr;
566 
567   if (NumVectors > 1)
568     TypeStr += "x" + llvm::utostr(NumVectors);
569   if (!isScalarPredicate() && !isVoid())
570     TypeStr += "_t";
571   if (isConstant())
572     TypeStr += " const";
573   if (isPointer())
574     TypeStr += " *";
575 
576   return TypeStr;
577 }
578 
579 void SVEType::applyTypespec(StringRef TS) {
580   for (char I : TS) {
581     switch (I) {
582     case 'Q':
583       assert(isInvalid() && "Unexpected use of typespec modifier");
584       Kind = Svcount;
585       break;
586     case 'P':
587       assert(isInvalid() && "Unexpected use of typespec modifier");
588       Kind = Predicate;
589       break;
590     case 'U':
591       assert(isInvalid() && "Unexpected use of typespec modifier");
592       Kind = UInt;
593       break;
594     case 'c':
595       Kind = isInvalid() ? SInt : Kind;
596       ElementBitwidth = 8;
597       break;
598     case 's':
599       Kind = isInvalid() ? SInt : Kind;
600       ElementBitwidth = 16;
601       break;
602     case 'i':
603       Kind = isInvalid() ? SInt : Kind;
604       ElementBitwidth = 32;
605       break;
606     case 'l':
607       Kind = isInvalid() ? SInt : Kind;
608       ElementBitwidth = 64;
609       break;
610     case 'q':
611       Kind = isInvalid() ? SInt : Kind;
612       ElementBitwidth = 128;
613       break;
614     case 'h':
615       assert(isInvalid() && "Unexpected use of typespec modifier");
616       Kind = Float;
617       ElementBitwidth = 16;
618       break;
619     case 'f':
620       assert(isInvalid() && "Unexpected use of typespec modifier");
621       Kind = Float;
622       ElementBitwidth = 32;
623       break;
624     case 'd':
625       assert(isInvalid() && "Unexpected use of typespec modifier");
626       Kind = Float;
627       ElementBitwidth = 64;
628       break;
629     case 'b':
630       assert(isInvalid() && "Unexpected use of typespec modifier");
631       Kind = BFloat16;
632       ElementBitwidth = 16;
633       break;
634     case 'm':
635       assert(isInvalid() && "Unexpected use of typespec modifier");
636       Kind = MFloat8;
637       ElementBitwidth = 8;
638       break;
639     default:
640       llvm_unreachable("Unhandled type code!");
641     }
642   }
643   assert(ElementBitwidth != ~0U && "Bad element bitwidth!");
644 }
645 
646 void SVEType::applyModifier(char Mod) {
647   switch (Mod) {
648   case 'v':
649     Kind = Void;
650     NumVectors = 0;
651     break;
652   case 'd':
653     DefaultType = true;
654     break;
655   case 'c':
656     Constant = true;
657     [[fallthrough]];
658   case 'p':
659     Pointer = true;
660     Bitwidth = ElementBitwidth;
661     NumVectors = 0;
662     break;
663   case 'e':
664     Kind = UInt;
665     ElementBitwidth /= 2;
666     break;
667   case 'h':
668     ElementBitwidth /= 2;
669     break;
670   case 'q':
671     ElementBitwidth /= 4;
672     break;
673   case 'b':
674     Kind = UInt;
675     ElementBitwidth /= 4;
676     break;
677   case 'o':
678     ElementBitwidth *= 4;
679     break;
680   case 'P':
681     Kind = Predicate;
682     Bitwidth = 16;
683     ElementBitwidth = 1;
684     break;
685   case '{':
686     IsScalable = false;
687     Bitwidth = 128;
688     NumVectors = 1;
689     break;
690   case 's':
691   case 'a':
692     Bitwidth = ElementBitwidth;
693     NumVectors = 0;
694     break;
695   case 'R':
696     ElementBitwidth /= 2;
697     NumVectors = 0;
698     break;
699   case 'r':
700     ElementBitwidth /= 4;
701     NumVectors = 0;
702     break;
703   case '@':
704     Kind = UInt;
705     ElementBitwidth /= 4;
706     NumVectors = 0;
707     break;
708   case 'K':
709     Kind = SInt;
710     Bitwidth = ElementBitwidth;
711     NumVectors = 0;
712     break;
713   case 'L':
714     Kind = UInt;
715     Bitwidth = ElementBitwidth;
716     NumVectors = 0;
717     break;
718   case 'u':
719     Kind = UInt;
720     break;
721   case 'x':
722     Kind = SInt;
723     break;
724   case 'i':
725     Kind = UInt;
726     ElementBitwidth = Bitwidth = 64;
727     NumVectors = 0;
728     Immediate = true;
729     break;
730   case 'I':
731     Kind = PredicatePattern;
732     ElementBitwidth = Bitwidth = 32;
733     NumVectors = 0;
734     Immediate = true;
735     break;
736   case 'J':
737     Kind = PrefetchOp;
738     ElementBitwidth = Bitwidth = 32;
739     NumVectors = 0;
740     Immediate = true;
741     break;
742   case 'k':
743     Kind = SInt;
744     ElementBitwidth = Bitwidth = 32;
745     NumVectors = 0;
746     break;
747   case 'l':
748     Kind = SInt;
749     ElementBitwidth = Bitwidth = 64;
750     NumVectors = 0;
751     break;
752   case 'm':
753     Kind = UInt;
754     ElementBitwidth = Bitwidth = 32;
755     NumVectors = 0;
756     break;
757   case '>':
758     Kind = Fpm;
759     ElementBitwidth = Bitwidth = 64;
760     NumVectors = 0;
761     break;
762   case 'n':
763     Kind = UInt;
764     ElementBitwidth = Bitwidth = 64;
765     NumVectors = 0;
766     break;
767   case 'w':
768     ElementBitwidth = 64;
769     break;
770   case 'j':
771     ElementBitwidth = Bitwidth = 64;
772     NumVectors = 0;
773     break;
774   case 'f':
775     Kind = UInt;
776     ElementBitwidth = Bitwidth = 64;
777     NumVectors = 0;
778     break;
779   case 'g':
780     Kind = UInt;
781     ElementBitwidth = 64;
782     break;
783   case '#':
784     Kind = SInt;
785     ElementBitwidth = 64;
786     break;
787   case '[':
788     Kind = UInt;
789     ElementBitwidth = 8;
790     break;
791   case 't':
792     Kind = SInt;
793     ElementBitwidth = 32;
794     break;
795   case 'z':
796     Kind = UInt;
797     ElementBitwidth = 32;
798     break;
799   case 'O':
800     Kind = Float;
801     ElementBitwidth = 16;
802     break;
803   case 'M':
804     Kind = Float;
805     ElementBitwidth = 32;
806     break;
807   case 'N':
808     Kind = Float;
809     ElementBitwidth = 64;
810     break;
811   case 'Q':
812     Kind = Void;
813     Constant = true;
814     Pointer = true;
815     NumVectors = 0;
816     break;
817   case 'S':
818     Kind = SInt;
819     Constant = true;
820     Pointer = true;
821     ElementBitwidth = Bitwidth = 8;
822     NumVectors = 0;
823     break;
824   case 'W':
825     Kind = UInt;
826     Constant = true;
827     Pointer = true;
828     ElementBitwidth = Bitwidth = 8;
829     NumVectors = 0;
830     break;
831   case 'T':
832     Kind = SInt;
833     Constant = true;
834     Pointer = true;
835     ElementBitwidth = Bitwidth = 16;
836     NumVectors = 0;
837     break;
838   case 'X':
839     Kind = UInt;
840     Constant = true;
841     Pointer = true;
842     ElementBitwidth = Bitwidth = 16;
843     NumVectors = 0;
844     break;
845   case 'Y':
846     Kind = UInt;
847     Constant = true;
848     Pointer = true;
849     ElementBitwidth = Bitwidth = 32;
850     NumVectors = 0;
851     break;
852   case 'U':
853     Kind = SInt;
854     Constant = true;
855     Pointer = true;
856     ElementBitwidth = Bitwidth = 32;
857     NumVectors = 0;
858     break;
859   case '%':
860     Kind = Void;
861     Pointer = true;
862     NumVectors = 0;
863     break;
864   case 'A':
865     Kind = SInt;
866     Pointer = true;
867     ElementBitwidth = Bitwidth = 8;
868     NumVectors = 0;
869     break;
870   case 'B':
871     Kind = SInt;
872     Pointer = true;
873     ElementBitwidth = Bitwidth = 16;
874     NumVectors = 0;
875     break;
876   case 'C':
877     Kind = SInt;
878     Pointer = true;
879     ElementBitwidth = Bitwidth = 32;
880     NumVectors = 0;
881     break;
882   case 'D':
883     Kind = SInt;
884     Pointer = true;
885     ElementBitwidth = Bitwidth = 64;
886     NumVectors = 0;
887     break;
888   case 'E':
889     Kind = UInt;
890     Pointer = true;
891     ElementBitwidth = Bitwidth = 8;
892     NumVectors = 0;
893     break;
894   case 'F':
895     Kind = UInt;
896     Pointer = true;
897     ElementBitwidth = Bitwidth = 16;
898     NumVectors = 0;
899     break;
900   case 'G':
901     Kind = UInt;
902     Pointer = true;
903     ElementBitwidth = Bitwidth = 32;
904     NumVectors = 0;
905     break;
906   case '$':
907     Kind = BFloat16;
908     ElementBitwidth = 16;
909     break;
910   case '}':
911     Kind = Svcount;
912     NumVectors = 0;
913     break;
914   case '~':
915     Kind = MFloat8;
916     ElementBitwidth = 8;
917     break;
918   case '!':
919     Kind = MFloat8;
920     Bitwidth = ElementBitwidth = 8;
921     NumVectors = 0;
922     break;
923   case '.':
924     llvm_unreachable(". is never a type in itself");
925     break;
926   default:
927     llvm_unreachable("Unhandled character!");
928   }
929 }
930 
931 /// Returns the modifier and number of vectors for the given operand \p Op.
932 std::pair<char, unsigned> getProtoModifier(StringRef Proto, unsigned Op) {
933   for (unsigned P = 0; !Proto.empty(); ++P) {
934     unsigned NumVectors = 1;
935     unsigned CharsToSkip = 1;
936     char Mod = Proto[0];
937     if (Mod == '2' || Mod == '3' || Mod == '4') {
938       NumVectors = Mod - '0';
939       Mod = 'd';
940       if (Proto.size() > 1 && Proto[1] == '.') {
941         Mod = Proto[2];
942         CharsToSkip = 3;
943       }
944     }
945 
946     if (P == Op)
947       return {Mod, NumVectors};
948 
949     Proto = Proto.drop_front(CharsToSkip);
950   }
951   llvm_unreachable("Unexpected Op");
952 }
953 
954 //===----------------------------------------------------------------------===//
955 // Intrinsic implementation
956 //===----------------------------------------------------------------------===//
957 
958 Intrinsic::Intrinsic(StringRef Name, StringRef Proto, uint64_t MergeTy,
959                      StringRef MergeSuffix, uint64_t MemoryElementTy,
960                      StringRef LLVMName, uint64_t Flags,
961                      ArrayRef<ImmCheck> Checks, TypeSpec BT, ClassKind Class,
962                      SVEEmitter &Emitter, StringRef SVEGuard,
963                      StringRef SMEGuard)
964     : Name(Name.str()), LLVMName(LLVMName), Proto(Proto.str()),
965       BaseTypeSpec(BT), Class(Class), MergeSuffix(MergeSuffix.str()),
966       BaseType(BT, 'd'), Flags(Flags), ImmChecks(Checks) {
967 
968   auto FormatGuard = [](StringRef Guard, StringRef Base) -> std::string {
969     if (Guard.contains('|'))
970       return Base.str() + ",(" + Guard.str() + ")";
971     if (Guard.empty() || Guard == Base || Guard.starts_with(Base.str() + ","))
972       return Guard.str();
973     return Base.str() + "," + Guard.str();
974   };
975 
976   this->SVEGuard = FormatGuard(SVEGuard, "sve");
977   this->SMEGuard = FormatGuard(SMEGuard, "sme");
978 
979   // Types[0] is the return value.
980   for (unsigned I = 0; I < (getNumParams() + 1); ++I) {
981     char Mod;
982     unsigned NumVectors;
983     std::tie(Mod, NumVectors) = getProtoModifier(Proto, I);
984     SVEType T(BaseTypeSpec, Mod, NumVectors);
985     Types.push_back(T);
986 
987     // Add range checks for immediates
988     if (I > 0) {
989       if (T.isPredicatePattern())
990         ImmChecks.emplace_back(
991             I - 1, Emitter.getEnumValueForImmCheck("ImmCheck0_31"));
992       else if (T.isPrefetchOp())
993         ImmChecks.emplace_back(
994             I - 1, Emitter.getEnumValueForImmCheck("ImmCheck0_13"));
995     }
996   }
997 
998   // Set flags based on properties
999   this->Flags |= Emitter.encodeTypeFlags(BaseType);
1000   this->Flags |= Emitter.encodeMemoryElementType(MemoryElementTy);
1001   this->Flags |= Emitter.encodeMergeType(MergeTy);
1002   if (hasSplat())
1003     this->Flags |= Emitter.encodeSplatOperand(getSplatIdx());
1004 }
1005 
1006 std::string Intrinsic::getBuiltinTypeStr() {
1007   std::string S = getReturnType().builtin_str();
1008   for (unsigned I = 0; I < getNumParams(); ++I)
1009     S += getParamType(I).builtin_str();
1010 
1011   return S;
1012 }
1013 
1014 std::string Intrinsic::replaceTemplatedArgs(std::string Name, TypeSpec TS,
1015                                             std::string Proto) const {
1016   std::string Ret = Name;
1017   while (Ret.find('{') != std::string::npos) {
1018     size_t Pos = Ret.find('{');
1019     size_t End = Ret.find('}');
1020     unsigned NumChars = End - Pos + 1;
1021     assert(NumChars == 3 && "Unexpected template argument");
1022 
1023     SVEType T;
1024     char C = Ret[Pos+1];
1025     switch(C) {
1026     default:
1027       llvm_unreachable("Unknown predication specifier");
1028     case 'd':
1029       T = SVEType(TS, 'd');
1030       break;
1031     case '0':
1032     case '1':
1033     case '2':
1034     case '3':
1035       T = SVEType(TS, Proto[C - '0']);
1036       break;
1037     }
1038 
1039     // Replace templated arg with the right suffix (e.g. u32)
1040     std::string TypeCode;
1041 
1042     if (T.isSignedInteger())
1043       TypeCode = 's';
1044     else if (T.isUnsignedInteger())
1045       TypeCode = 'u';
1046     else if (T.isSvcount())
1047       TypeCode = 'c';
1048     else if (T.isPredicate())
1049       TypeCode = 'b';
1050     else if (T.isBFloat())
1051       TypeCode = "bf";
1052     else if (T.isMFloat())
1053       TypeCode = "mf";
1054     else
1055       TypeCode = 'f';
1056     Ret.replace(Pos, NumChars, TypeCode + utostr(T.getElementSizeInBits()));
1057   }
1058 
1059   return Ret;
1060 }
1061 
1062 std::string Intrinsic::mangleLLVMName() const {
1063   std::string S = getLLVMName();
1064 
1065   // Replace all {d} like expressions with e.g. 'u32'
1066   return replaceTemplatedArgs(S, getBaseTypeSpec(), getProto());
1067 }
1068 
1069 std::string Intrinsic::mangleName(ClassKind LocalCK) const {
1070   std::string S = getName();
1071 
1072   if (LocalCK == ClassG) {
1073     // Remove the square brackets and everything in between.
1074     while (S.find('[') != std::string::npos) {
1075       auto Start = S.find('[');
1076       auto End = S.find(']');
1077       S.erase(Start, (End-Start)+1);
1078     }
1079   } else {
1080     // Remove the square brackets.
1081     while (S.find('[') != std::string::npos) {
1082       auto BrPos = S.find('[');
1083       if (BrPos != std::string::npos)
1084         S.erase(BrPos, 1);
1085       BrPos = S.find(']');
1086       if (BrPos != std::string::npos)
1087         S.erase(BrPos, 1);
1088     }
1089   }
1090 
1091   // Replace all {d} like expressions with e.g. 'u32'
1092   return replaceTemplatedArgs(S, getBaseTypeSpec(), getProto()) +
1093          getMergeSuffix();
1094 }
1095 
1096 void Intrinsic::emitIntrinsic(raw_ostream &OS, SVEEmitter &Emitter,
1097                               ACLEKind Kind) const {
1098   bool IsOverloaded = getClassKind() == ClassG && getProto().size() > 1;
1099 
1100   std::string FullName = mangleName(ClassS);
1101   std::string ProtoName = mangleName(getClassKind());
1102   OS << (IsOverloaded ? "__aio " : "__ai ")
1103      << "__attribute__((__clang_arm_builtin_alias(";
1104 
1105   switch (Kind) {
1106   case ACLEKind::SME:
1107     OS << "__builtin_sme_" << FullName << ")";
1108     break;
1109   case ACLEKind::SVE:
1110     OS << "__builtin_sve_" << FullName << ")";
1111     break;
1112   }
1113 
1114   OS << "))\n";
1115 
1116   OS << getTypes()[0].str() << " " << ProtoName << "(";
1117   for (unsigned I = 0; I < getTypes().size() - 1; ++I) {
1118     if (I != 0)
1119       OS << ", ";
1120     OS << getTypes()[I + 1].str();
1121   }
1122   OS << ");\n";
1123 }
1124 
1125 //===----------------------------------------------------------------------===//
1126 // SVEEmitter implementation
1127 //===----------------------------------------------------------------------===//
1128 uint64_t SVEEmitter::encodeTypeFlags(const SVEType &T) {
1129   if (T.isFloat()) {
1130     switch (T.getElementSizeInBits()) {
1131     case 16:
1132       return encodeEltType("EltTyFloat16");
1133     case 32:
1134       return encodeEltType("EltTyFloat32");
1135     case 64:
1136       return encodeEltType("EltTyFloat64");
1137     default:
1138       llvm_unreachable("Unhandled float element bitwidth!");
1139     }
1140   }
1141 
1142   if (T.isBFloat()) {
1143     assert(T.getElementSizeInBits() == 16 && "Not a valid BFloat.");
1144     return encodeEltType("EltTyBFloat16");
1145   }
1146 
1147   if (T.isMFloat()) {
1148     assert(T.getElementSizeInBits() == 8 && "Not a valid MFloat.");
1149     return encodeEltType("EltTyMFloat8");
1150   }
1151 
1152   if (T.isPredicate() || T.isSvcount()) {
1153     switch (T.getElementSizeInBits()) {
1154     case 8:
1155       return encodeEltType("EltTyBool8");
1156     case 16:
1157       return encodeEltType("EltTyBool16");
1158     case 32:
1159       return encodeEltType("EltTyBool32");
1160     case 64:
1161       return encodeEltType("EltTyBool64");
1162     default:
1163       llvm_unreachable("Unhandled predicate element bitwidth!");
1164     }
1165   }
1166 
1167   switch (T.getElementSizeInBits()) {
1168   case 8:
1169     return encodeEltType("EltTyInt8");
1170   case 16:
1171     return encodeEltType("EltTyInt16");
1172   case 32:
1173     return encodeEltType("EltTyInt32");
1174   case 64:
1175     return encodeEltType("EltTyInt64");
1176   case 128:
1177     return encodeEltType("EltTyInt128");
1178   default:
1179     llvm_unreachable("Unhandled integer element bitwidth!");
1180   }
1181 }
1182 
1183 void SVEEmitter::createIntrinsic(
1184     const Record *R, SmallVectorImpl<std::unique_ptr<Intrinsic>> &Out) {
1185   StringRef Name = R->getValueAsString("Name");
1186   StringRef Proto = R->getValueAsString("Prototype");
1187   StringRef Types = R->getValueAsString("Types");
1188   StringRef SVEGuard = R->getValueAsString("SVETargetGuard");
1189   StringRef SMEGuard = R->getValueAsString("SMETargetGuard");
1190   StringRef LLVMName = R->getValueAsString("LLVMIntrinsic");
1191   uint64_t Merge = R->getValueAsInt("Merge");
1192   StringRef MergeSuffix = R->getValueAsString("MergeSuffix");
1193   uint64_t MemEltType = R->getValueAsInt("MemEltType");
1194 
1195   int64_t Flags = 0;
1196   for (const Record *FlagRec : R->getValueAsListOfDefs("Flags"))
1197     Flags |= FlagRec->getValueAsInt("Value");
1198 
1199   // Create a dummy TypeSpec for non-overloaded builtins.
1200   if (Types.empty()) {
1201     assert((Flags & getEnumValueForFlag("IsOverloadNone")) &&
1202            "Expect TypeSpec for overloaded builtin!");
1203     Types = "i";
1204   }
1205 
1206   // Extract type specs from string
1207   SmallVector<TypeSpec, 8> TypeSpecs;
1208   TypeSpec Acc;
1209   for (char I : Types) {
1210     Acc.push_back(I);
1211     if (islower(I)) {
1212       TypeSpecs.push_back(TypeSpec(Acc));
1213       Acc.clear();
1214     }
1215   }
1216 
1217   // Remove duplicate type specs.
1218   sort(TypeSpecs);
1219   TypeSpecs.erase(std::unique(TypeSpecs.begin(), TypeSpecs.end()),
1220                   TypeSpecs.end());
1221 
1222   // Create an Intrinsic for each type spec.
1223   for (auto TS : TypeSpecs) {
1224     // Collate a list of range/option checks for the immediates.
1225     SmallVector<ImmCheck, 2> ImmChecks;
1226     for (const Record *ImmR : R->getValueAsListOfDefs("ImmChecks")) {
1227       int64_t ArgIdx = ImmR->getValueAsInt("ImmArgIdx");
1228       int64_t EltSizeArgIdx = ImmR->getValueAsInt("TypeContextArgIdx");
1229       int64_t Kind = ImmR->getValueAsDef("Kind")->getValueAsInt("Value");
1230       assert(ArgIdx >= 0 && Kind >= 0 &&
1231              "ImmArgIdx and Kind must be nonnegative");
1232 
1233       unsigned ElementSizeInBits = 0;
1234       auto [Mod, NumVectors] = getProtoModifier(Proto, EltSizeArgIdx + 1);
1235       if (EltSizeArgIdx >= 0)
1236         ElementSizeInBits = SVEType(TS, Mod, NumVectors).getElementSizeInBits();
1237       ImmChecks.push_back(ImmCheck(ArgIdx, Kind, ElementSizeInBits));
1238     }
1239 
1240     Out.push_back(std::make_unique<Intrinsic>(
1241         Name, Proto, Merge, MergeSuffix, MemEltType, LLVMName, Flags, ImmChecks,
1242         TS, ClassS, *this, SVEGuard, SMEGuard));
1243 
1244     // Also generate the short-form (e.g. svadd_m) for the given type-spec.
1245     if (Intrinsic::isOverloadedIntrinsic(Name))
1246       Out.push_back(std::make_unique<Intrinsic>(
1247           Name, Proto, Merge, MergeSuffix, MemEltType, LLVMName, Flags,
1248           ImmChecks, TS, ClassG, *this, SVEGuard, SMEGuard));
1249   }
1250 }
1251 
1252 void SVEEmitter::createCoreHeaderIntrinsics(raw_ostream &OS,
1253                                             SVEEmitter &Emitter,
1254                                             ACLEKind Kind) {
1255   SmallVector<std::unique_ptr<Intrinsic>, 128> Defs;
1256   std::vector<const Record *> RV = Records.getAllDerivedDefinitions("Inst");
1257   for (auto *R : RV)
1258     createIntrinsic(R, Defs);
1259 
1260   // Sort intrinsics in header file by following order/priority:
1261   // - Architectural guard (i.e. does it require SVE2 or SVE2_AES)
1262   // - Class (is intrinsic overloaded or not)
1263   // - Intrinsic name
1264   std::stable_sort(Defs.begin(), Defs.end(),
1265                    [](const std::unique_ptr<Intrinsic> &A,
1266                       const std::unique_ptr<Intrinsic> &B) {
1267                      auto ToTuple = [](const std::unique_ptr<Intrinsic> &I) {
1268                        return std::make_tuple(
1269                            I->getSVEGuard().str() + I->getSMEGuard().str(),
1270                            (unsigned)I->getClassKind(), I->getName());
1271                      };
1272                      return ToTuple(A) < ToTuple(B);
1273                    });
1274 
1275   // Actually emit the intrinsic declarations.
1276   for (auto &I : Defs)
1277     I->emitIntrinsic(OS, Emitter, Kind);
1278 }
1279 
1280 void SVEEmitter::createHeader(raw_ostream &OS) {
1281   OS << "/*===---- arm_sve.h - ARM SVE intrinsics "
1282         "-----------------------------------===\n"
1283         " *\n"
1284         " *\n"
1285         " * Part of the LLVM Project, under the Apache License v2.0 with LLVM "
1286         "Exceptions.\n"
1287         " * See https://llvm.org/LICENSE.txt for license information.\n"
1288         " * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n"
1289         " *\n"
1290         " *===-----------------------------------------------------------------"
1291         "------===\n"
1292         " */\n\n";
1293 
1294   OS << "#ifndef __ARM_SVE_H\n";
1295   OS << "#define __ARM_SVE_H\n\n";
1296 
1297   OS << "#if !defined(__LITTLE_ENDIAN__)\n";
1298   OS << "#error \"Big endian is currently not supported for arm_sve.h\"\n";
1299   OS << "#endif\n";
1300 
1301   OS << "#include <stdint.h>\n\n";
1302   OS << "#ifdef  __cplusplus\n";
1303   OS << "extern \"C\" {\n";
1304   OS << "#else\n";
1305   OS << "#include <stdbool.h>\n";
1306   OS << "#endif\n\n";
1307 
1308   OS << "typedef __fp16 float16_t;\n";
1309   OS << "typedef float float32_t;\n";
1310   OS << "typedef double float64_t;\n";
1311 
1312   OS << "typedef __SVInt8_t svint8_t;\n";
1313   OS << "typedef __SVInt16_t svint16_t;\n";
1314   OS << "typedef __SVInt32_t svint32_t;\n";
1315   OS << "typedef __SVInt64_t svint64_t;\n";
1316   OS << "typedef __SVUint8_t svuint8_t;\n";
1317   OS << "typedef __SVUint16_t svuint16_t;\n";
1318   OS << "typedef __SVUint32_t svuint32_t;\n";
1319   OS << "typedef __SVUint64_t svuint64_t;\n";
1320   OS << "typedef __SVFloat16_t svfloat16_t;\n\n";
1321 
1322   OS << "typedef __SVBfloat16_t svbfloat16_t;\n";
1323 
1324   OS << "#include <arm_bf16.h>\n";
1325   OS << "#include <arm_vector_types.h>\n";
1326 
1327   OS << "typedef __SVMfloat8_t svmfloat8_t;\n\n";
1328 
1329   OS << "typedef __SVFloat32_t svfloat32_t;\n";
1330   OS << "typedef __SVFloat64_t svfloat64_t;\n";
1331   OS << "typedef __clang_svint8x2_t svint8x2_t;\n";
1332   OS << "typedef __clang_svint16x2_t svint16x2_t;\n";
1333   OS << "typedef __clang_svint32x2_t svint32x2_t;\n";
1334   OS << "typedef __clang_svint64x2_t svint64x2_t;\n";
1335   OS << "typedef __clang_svuint8x2_t svuint8x2_t;\n";
1336   OS << "typedef __clang_svuint16x2_t svuint16x2_t;\n";
1337   OS << "typedef __clang_svuint32x2_t svuint32x2_t;\n";
1338   OS << "typedef __clang_svuint64x2_t svuint64x2_t;\n";
1339   OS << "typedef __clang_svfloat16x2_t svfloat16x2_t;\n";
1340   OS << "typedef __clang_svfloat32x2_t svfloat32x2_t;\n";
1341   OS << "typedef __clang_svfloat64x2_t svfloat64x2_t;\n";
1342   OS << "typedef __clang_svint8x3_t svint8x3_t;\n";
1343   OS << "typedef __clang_svint16x3_t svint16x3_t;\n";
1344   OS << "typedef __clang_svint32x3_t svint32x3_t;\n";
1345   OS << "typedef __clang_svint64x3_t svint64x3_t;\n";
1346   OS << "typedef __clang_svuint8x3_t svuint8x3_t;\n";
1347   OS << "typedef __clang_svuint16x3_t svuint16x3_t;\n";
1348   OS << "typedef __clang_svuint32x3_t svuint32x3_t;\n";
1349   OS << "typedef __clang_svuint64x3_t svuint64x3_t;\n";
1350   OS << "typedef __clang_svfloat16x3_t svfloat16x3_t;\n";
1351   OS << "typedef __clang_svfloat32x3_t svfloat32x3_t;\n";
1352   OS << "typedef __clang_svfloat64x3_t svfloat64x3_t;\n";
1353   OS << "typedef __clang_svint8x4_t svint8x4_t;\n";
1354   OS << "typedef __clang_svint16x4_t svint16x4_t;\n";
1355   OS << "typedef __clang_svint32x4_t svint32x4_t;\n";
1356   OS << "typedef __clang_svint64x4_t svint64x4_t;\n";
1357   OS << "typedef __clang_svuint8x4_t svuint8x4_t;\n";
1358   OS << "typedef __clang_svuint16x4_t svuint16x4_t;\n";
1359   OS << "typedef __clang_svuint32x4_t svuint32x4_t;\n";
1360   OS << "typedef __clang_svuint64x4_t svuint64x4_t;\n";
1361   OS << "typedef __clang_svfloat16x4_t svfloat16x4_t;\n";
1362   OS << "typedef __clang_svfloat32x4_t svfloat32x4_t;\n";
1363   OS << "typedef __clang_svfloat64x4_t svfloat64x4_t;\n";
1364   OS << "typedef __SVBool_t  svbool_t;\n";
1365   OS << "typedef __clang_svboolx2_t  svboolx2_t;\n";
1366   OS << "typedef __clang_svboolx4_t  svboolx4_t;\n\n";
1367 
1368   OS << "typedef __clang_svbfloat16x2_t svbfloat16x2_t;\n";
1369   OS << "typedef __clang_svbfloat16x3_t svbfloat16x3_t;\n";
1370   OS << "typedef __clang_svbfloat16x4_t svbfloat16x4_t;\n";
1371 
1372   OS << "typedef __clang_svmfloat8x2_t svmfloat8x2_t;\n";
1373   OS << "typedef __clang_svmfloat8x3_t svmfloat8x3_t;\n";
1374   OS << "typedef __clang_svmfloat8x4_t svmfloat8x4_t;\n";
1375 
1376   OS << "typedef __SVCount_t svcount_t;\n\n";
1377 
1378   OS << "enum svpattern\n";
1379   OS << "{\n";
1380   OS << "  SV_POW2 = 0,\n";
1381   OS << "  SV_VL1 = 1,\n";
1382   OS << "  SV_VL2 = 2,\n";
1383   OS << "  SV_VL3 = 3,\n";
1384   OS << "  SV_VL4 = 4,\n";
1385   OS << "  SV_VL5 = 5,\n";
1386   OS << "  SV_VL6 = 6,\n";
1387   OS << "  SV_VL7 = 7,\n";
1388   OS << "  SV_VL8 = 8,\n";
1389   OS << "  SV_VL16 = 9,\n";
1390   OS << "  SV_VL32 = 10,\n";
1391   OS << "  SV_VL64 = 11,\n";
1392   OS << "  SV_VL128 = 12,\n";
1393   OS << "  SV_VL256 = 13,\n";
1394   OS << "  SV_MUL4 = 29,\n";
1395   OS << "  SV_MUL3 = 30,\n";
1396   OS << "  SV_ALL = 31\n";
1397   OS << "};\n\n";
1398 
1399   OS << "enum svprfop\n";
1400   OS << "{\n";
1401   OS << "  SV_PLDL1KEEP = 0,\n";
1402   OS << "  SV_PLDL1STRM = 1,\n";
1403   OS << "  SV_PLDL2KEEP = 2,\n";
1404   OS << "  SV_PLDL2STRM = 3,\n";
1405   OS << "  SV_PLDL3KEEP = 4,\n";
1406   OS << "  SV_PLDL3STRM = 5,\n";
1407   OS << "  SV_PSTL1KEEP = 8,\n";
1408   OS << "  SV_PSTL1STRM = 9,\n";
1409   OS << "  SV_PSTL2KEEP = 10,\n";
1410   OS << "  SV_PSTL2STRM = 11,\n";
1411   OS << "  SV_PSTL3KEEP = 12,\n";
1412   OS << "  SV_PSTL3STRM = 13\n";
1413   OS << "};\n\n";
1414 
1415   OS << "/* Function attributes */\n";
1416   OS << "#define __ai static __inline__ __attribute__((__always_inline__, "
1417         "__nodebug__))\n\n";
1418   OS << "#define __aio static __inline__ __attribute__((__always_inline__, "
1419         "__nodebug__, __overloadable__))\n\n";
1420 
1421   // Add reinterpret functions.
1422   for (auto [N, Suffix] :
1423        std::initializer_list<std::pair<unsigned, const char *>>{
1424            {1, ""}, {2, "_x2"}, {3, "_x3"}, {4, "_x4"}}) {
1425     for (auto ShortForm : {false, true})
1426       for (const ReinterpretTypeInfo &To : Reinterprets) {
1427         SVEType ToV(To.BaseType, N);
1428         for (const ReinterpretTypeInfo &From : Reinterprets) {
1429           SVEType FromV(From.BaseType, N);
1430           OS << "__aio "
1431                 "__attribute__((__clang_arm_builtin_alias(__builtin_sve_"
1432                 "reinterpret_"
1433              << To.Suffix << "_" << From.Suffix << Suffix << ")))\n"
1434              << ToV.str() << " svreinterpret_" << To.Suffix;
1435           if (!ShortForm)
1436             OS << "_" << From.Suffix << Suffix;
1437           OS << "(" << FromV.str() << " op);\n";
1438         }
1439       }
1440   }
1441 
1442   createCoreHeaderIntrinsics(OS, *this, ACLEKind::SVE);
1443 
1444   OS << "#define svcvtnt_bf16_x      svcvtnt_bf16_m\n";
1445   OS << "#define svcvtnt_bf16_f32_x  svcvtnt_bf16_f32_m\n";
1446 
1447   OS << "#define svcvtnt_f16_x      svcvtnt_f16_m\n";
1448   OS << "#define svcvtnt_f16_f32_x  svcvtnt_f16_f32_m\n";
1449   OS << "#define svcvtnt_f32_x      svcvtnt_f32_m\n";
1450   OS << "#define svcvtnt_f32_f64_x  svcvtnt_f32_f64_m\n\n";
1451 
1452   OS << "#define svcvtxnt_f32_x     svcvtxnt_f32_m\n";
1453   OS << "#define svcvtxnt_f32_f64_x svcvtxnt_f32_f64_m\n\n";
1454 
1455   OS << "#ifdef __cplusplus\n";
1456   OS << "} // extern \"C\"\n";
1457   OS << "#endif\n\n";
1458   OS << "#undef __ai\n\n";
1459   OS << "#undef __aio\n\n";
1460   OS << "#endif /* __ARM_SVE_H */\n";
1461 }
1462 
1463 void SVEEmitter::createBuiltins(raw_ostream &OS) {
1464   std::vector<const Record *> RV = Records.getAllDerivedDefinitions("Inst");
1465   SmallVector<std::unique_ptr<Intrinsic>, 128> Defs;
1466   for (auto *R : RV)
1467     createIntrinsic(R, Defs);
1468 
1469   // The mappings must be sorted based on BuiltinID.
1470   sort(Defs, [](const std::unique_ptr<Intrinsic> &A,
1471                 const std::unique_ptr<Intrinsic> &B) {
1472     return A->getMangledName() < B->getMangledName();
1473   });
1474 
1475   OS << "#ifdef GET_SVE_BUILTINS\n";
1476   for (auto &Def : Defs) {
1477     // Only create BUILTINs for non-overloaded intrinsics, as overloaded
1478     // declarations only live in the header file.
1479     if (Def->getClassKind() != ClassG) {
1480       OS << "TARGET_BUILTIN(__builtin_sve_" << Def->getMangledName() << ", \""
1481          << Def->getBuiltinTypeStr() << "\", \"n\", \"";
1482       Def->printGuard(OS);
1483       OS << "\")\n";
1484     }
1485   }
1486 
1487   // Add reinterpret functions.
1488   for (auto [N, Suffix] :
1489        std::initializer_list<std::pair<unsigned, const char *>>{
1490            {1, ""}, {2, "_x2"}, {3, "_x3"}, {4, "_x4"}}) {
1491     for (const ReinterpretTypeInfo &To : Reinterprets) {
1492       SVEType ToV(To.BaseType, N);
1493       for (const ReinterpretTypeInfo &From : Reinterprets) {
1494         SVEType FromV(From.BaseType, N);
1495         OS << "TARGET_BUILTIN(__builtin_sve_reinterpret_" << To.Suffix << "_"
1496            << From.Suffix << Suffix << +", \"" << ToV.builtin_str()
1497            << FromV.builtin_str() << "\", \"n\", \"sme|sve\")\n";
1498       }
1499     }
1500   }
1501 
1502   OS << "#endif\n\n";
1503 }
1504 
1505 void SVEEmitter::createCodeGenMap(raw_ostream &OS) {
1506   std::vector<const Record *> RV = Records.getAllDerivedDefinitions("Inst");
1507   SmallVector<std::unique_ptr<Intrinsic>, 128> Defs;
1508   for (auto *R : RV)
1509     createIntrinsic(R, Defs);
1510 
1511   // The mappings must be sorted based on BuiltinID.
1512   sort(Defs, [](const std::unique_ptr<Intrinsic> &A,
1513                 const std::unique_ptr<Intrinsic> &B) {
1514     return A->getMangledName() < B->getMangledName();
1515   });
1516 
1517   OS << "#ifdef GET_SVE_LLVM_INTRINSIC_MAP\n";
1518   for (auto &Def : Defs) {
1519     // Builtins only exist for non-overloaded intrinsics, overloaded
1520     // declarations only live in the header file.
1521     if (Def->getClassKind() == ClassG)
1522       continue;
1523 
1524     uint64_t Flags = Def->getFlags();
1525     auto FlagString = std::to_string(Flags);
1526 
1527     std::string LLVMName = Def->getMangledLLVMName();
1528     std::string Builtin = Def->getMangledName();
1529     if (!LLVMName.empty())
1530       OS << "SVEMAP1(" << Builtin << ", " << LLVMName << ", " << FlagString
1531          << "),\n";
1532     else
1533       OS << "SVEMAP2(" << Builtin << ", " << FlagString << "),\n";
1534   }
1535   OS << "#endif\n\n";
1536 }
1537 
1538 void SVEEmitter::createRangeChecks(raw_ostream &OS) {
1539   std::vector<const Record *> RV = Records.getAllDerivedDefinitions("Inst");
1540   SmallVector<std::unique_ptr<Intrinsic>, 128> Defs;
1541   for (auto *R : RV)
1542     createIntrinsic(R, Defs);
1543 
1544   // The mappings must be sorted based on BuiltinID.
1545   sort(Defs, [](const std::unique_ptr<Intrinsic> &A,
1546                 const std::unique_ptr<Intrinsic> &B) {
1547     return A->getMangledName() < B->getMangledName();
1548   });
1549 
1550   OS << "#ifdef GET_SVE_IMMEDIATE_CHECK\n";
1551 
1552   // Ensure these are only emitted once.
1553   std::set<std::string> Emitted;
1554 
1555   for (auto &Def : Defs) {
1556     if (Emitted.find(Def->getMangledName()) != Emitted.end() ||
1557         Def->getImmChecks().empty())
1558       continue;
1559 
1560     OS << "case SVE::BI__builtin_sve_" << Def->getMangledName() << ":\n";
1561     for (auto &Check : Def->getImmChecks())
1562       OS << "ImmChecks.emplace_back(" << Check.getImmArgIdx() << ", "
1563          << Check.getKind() << ", " << Check.getElementSizeInBits() << ");\n";
1564     OS << "  break;\n";
1565 
1566     Emitted.insert(Def->getMangledName());
1567   }
1568 
1569   OS << "#endif\n\n";
1570 }
1571 
1572 /// Create the SVETypeFlags used in CGBuiltins
1573 void SVEEmitter::createTypeFlags(raw_ostream &OS) {
1574   OS << "#ifdef LLVM_GET_SVE_TYPEFLAGS\n";
1575   for (auto &KV : FlagTypes)
1576     OS << "const uint64_t " << KV.getKey() << " = " << KV.getValue() << ";\n";
1577   OS << "#endif\n\n";
1578 
1579   OS << "#ifdef LLVM_GET_SVE_ELTTYPES\n";
1580   for (auto &KV : EltTypes)
1581     OS << "  " << KV.getKey() << " = " << KV.getValue() << ",\n";
1582   OS << "#endif\n\n";
1583 
1584   OS << "#ifdef LLVM_GET_SVE_MEMELTTYPES\n";
1585   for (auto &KV : MemEltTypes)
1586     OS << "  " << KV.getKey() << " = " << KV.getValue() << ",\n";
1587   OS << "#endif\n\n";
1588 
1589   OS << "#ifdef LLVM_GET_SVE_MERGETYPES\n";
1590   for (auto &KV : MergeTypes)
1591     OS << "  " << KV.getKey() << " = " << KV.getValue() << ",\n";
1592   OS << "#endif\n\n";
1593 }
1594 
1595 void SVEEmitter::createImmCheckTypes(raw_ostream &OS) {
1596   OS << "#ifdef LLVM_GET_ARM_INTRIN_IMMCHECKTYPES\n";
1597   for (auto &KV : ImmCheckTypes)
1598     OS << "  " << KV.getKey() << " = " << KV.getValue() << ",\n";
1599   OS << "#endif\n\n";
1600 }
1601 
1602 void SVEEmitter::createSMEHeader(raw_ostream &OS) {
1603   OS << "/*===---- arm_sme.h - ARM SME intrinsics "
1604         "------===\n"
1605         " *\n"
1606         " *\n"
1607         " * Part of the LLVM Project, under the Apache License v2.0 with LLVM "
1608         "Exceptions.\n"
1609         " * See https://llvm.org/LICENSE.txt for license information.\n"
1610         " * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n"
1611         " *\n"
1612         " *===-----------------------------------------------------------------"
1613         "------===\n"
1614         " */\n\n";
1615 
1616   OS << "#ifndef __ARM_SME_H\n";
1617   OS << "#define __ARM_SME_H\n\n";
1618 
1619   OS << "#if !defined(__LITTLE_ENDIAN__)\n";
1620   OS << "#error \"Big endian is currently not supported for arm_sme.h\"\n";
1621   OS << "#endif\n";
1622 
1623   OS << "#include <arm_sve.h>\n\n";
1624   OS << "#include <stddef.h>\n\n";
1625 
1626   OS << "/* Function attributes */\n";
1627   OS << "#define __ai static __inline__ __attribute__((__always_inline__, "
1628         "__nodebug__))\n\n";
1629   OS << "#define __aio static __inline__ __attribute__((__always_inline__, "
1630         "__nodebug__, __overloadable__))\n\n";
1631 
1632   OS << "#ifdef  __cplusplus\n";
1633   OS << "extern \"C\" {\n";
1634   OS << "#endif\n\n";
1635 
1636   OS << "void __arm_za_disable(void) __arm_streaming_compatible;\n\n";
1637 
1638   OS << "__ai bool __arm_has_sme(void) __arm_streaming_compatible {\n";
1639   OS << "  uint64_t x0, x1;\n";
1640   OS << "  __builtin_arm_get_sme_state(&x0, &x1);\n";
1641   OS << "  return x0 & (1ULL << 63);\n";
1642   OS << "}\n\n";
1643 
1644   OS << "void *__arm_sc_memcpy(void *dest, const void *src, size_t n) __arm_streaming_compatible;\n";
1645   OS << "void *__arm_sc_memmove(void *dest, const void *src, size_t n) __arm_streaming_compatible;\n";
1646   OS << "void *__arm_sc_memset(void *s, int c, size_t n) __arm_streaming_compatible;\n";
1647   OS << "void *__arm_sc_memchr(void *s, int c, size_t n) __arm_streaming_compatible;\n\n";
1648 
1649   OS << "__ai __attribute__((target(\"sme\"))) void svundef_za(void) "
1650         "__arm_streaming_compatible __arm_out(\"za\") "
1651         "{ }\n\n";
1652 
1653   createCoreHeaderIntrinsics(OS, *this, ACLEKind::SME);
1654 
1655   OS << "#ifdef __cplusplus\n";
1656   OS << "} // extern \"C\"\n";
1657   OS << "#endif\n\n";
1658   OS << "#undef __ai\n\n";
1659   OS << "#endif /* __ARM_SME_H */\n";
1660 }
1661 
1662 void SVEEmitter::createSMEBuiltins(raw_ostream &OS) {
1663   std::vector<const Record *> RV = Records.getAllDerivedDefinitions("Inst");
1664   SmallVector<std::unique_ptr<Intrinsic>, 128> Defs;
1665   for (auto *R : RV) {
1666     createIntrinsic(R, Defs);
1667   }
1668 
1669   // The mappings must be sorted based on BuiltinID.
1670   sort(Defs, [](const std::unique_ptr<Intrinsic> &A,
1671                 const std::unique_ptr<Intrinsic> &B) {
1672     return A->getMangledName() < B->getMangledName();
1673   });
1674 
1675   OS << "#ifdef GET_SME_BUILTINS\n";
1676   for (auto &Def : Defs) {
1677     // Only create BUILTINs for non-overloaded intrinsics, as overloaded
1678     // declarations only live in the header file.
1679     if (Def->getClassKind() != ClassG) {
1680       OS << "TARGET_BUILTIN(__builtin_sme_" << Def->getMangledName() << ", \""
1681          << Def->getBuiltinTypeStr() << "\", \"n\", \"";
1682       Def->printGuard(OS);
1683       OS << "\")\n";
1684     }
1685   }
1686 
1687   OS << "#endif\n\n";
1688 }
1689 
1690 void SVEEmitter::createSMECodeGenMap(raw_ostream &OS) {
1691   std::vector<const Record *> RV = Records.getAllDerivedDefinitions("Inst");
1692   SmallVector<std::unique_ptr<Intrinsic>, 128> Defs;
1693   for (auto *R : RV) {
1694     createIntrinsic(R, Defs);
1695   }
1696 
1697   // The mappings must be sorted based on BuiltinID.
1698   sort(Defs, [](const std::unique_ptr<Intrinsic> &A,
1699                 const std::unique_ptr<Intrinsic> &B) {
1700     return A->getMangledName() < B->getMangledName();
1701   });
1702 
1703   OS << "#ifdef GET_SME_LLVM_INTRINSIC_MAP\n";
1704   for (auto &Def : Defs) {
1705     // Builtins only exist for non-overloaded intrinsics, overloaded
1706     // declarations only live in the header file.
1707     if (Def->getClassKind() == ClassG)
1708       continue;
1709 
1710     uint64_t Flags = Def->getFlags();
1711     auto FlagString = std::to_string(Flags);
1712 
1713     std::string LLVMName = Def->getLLVMName();
1714     std::string Builtin = Def->getMangledName();
1715     if (!LLVMName.empty())
1716       OS << "SMEMAP1(" << Builtin << ", " << LLVMName << ", " << FlagString
1717          << "),\n";
1718     else
1719       OS << "SMEMAP2(" << Builtin << ", " << FlagString << "),\n";
1720   }
1721   OS << "#endif\n\n";
1722 }
1723 
1724 void SVEEmitter::createSMERangeChecks(raw_ostream &OS) {
1725   std::vector<const Record *> RV = Records.getAllDerivedDefinitions("Inst");
1726   SmallVector<std::unique_ptr<Intrinsic>, 128> Defs;
1727   for (auto *R : RV) {
1728     createIntrinsic(R, Defs);
1729   }
1730 
1731   // The mappings must be sorted based on BuiltinID.
1732   sort(Defs, [](const std::unique_ptr<Intrinsic> &A,
1733                 const std::unique_ptr<Intrinsic> &B) {
1734     return A->getMangledName() < B->getMangledName();
1735   });
1736 
1737   OS << "#ifdef GET_SME_IMMEDIATE_CHECK\n";
1738 
1739   // Ensure these are only emitted once.
1740   std::set<std::string> Emitted;
1741 
1742   for (auto &Def : Defs) {
1743     if (Emitted.find(Def->getMangledName()) != Emitted.end() ||
1744         Def->getImmChecks().empty())
1745       continue;
1746 
1747     OS << "case SME::BI__builtin_sme_" << Def->getMangledName() << ":\n";
1748     for (auto &Check : Def->getImmChecks())
1749       OS << "ImmChecks.push_back(std::make_tuple(" << Check.getImmArgIdx()
1750          << ", " << Check.getKind() << ", " << Check.getElementSizeInBits()
1751          << "));\n";
1752     OS << "  break;\n";
1753 
1754     Emitted.insert(Def->getMangledName());
1755   }
1756 
1757   OS << "#endif\n\n";
1758 }
1759 
1760 void SVEEmitter::createBuiltinZAState(raw_ostream &OS) {
1761   std::vector<const Record *> RV = Records.getAllDerivedDefinitions("Inst");
1762   SmallVector<std::unique_ptr<Intrinsic>, 128> Defs;
1763   for (auto *R : RV)
1764     createIntrinsic(R, Defs);
1765 
1766   std::map<std::string, std::set<std::string>> IntrinsicsPerState;
1767   for (auto &Def : Defs) {
1768     std::string Key;
1769     auto AddToKey = [&Key](const std::string &S) -> void {
1770       Key = Key.empty() ? S : (Key + " | " + S);
1771     };
1772 
1773     if (Def->isFlagSet(getEnumValueForFlag("IsInZA")))
1774       AddToKey("ArmInZA");
1775     else if (Def->isFlagSet(getEnumValueForFlag("IsOutZA")))
1776       AddToKey("ArmOutZA");
1777     else if (Def->isFlagSet(getEnumValueForFlag("IsInOutZA")))
1778       AddToKey("ArmInOutZA");
1779 
1780     if (Def->isFlagSet(getEnumValueForFlag("IsInZT0")))
1781       AddToKey("ArmInZT0");
1782     else if (Def->isFlagSet(getEnumValueForFlag("IsOutZT0")))
1783       AddToKey("ArmOutZT0");
1784     else if (Def->isFlagSet(getEnumValueForFlag("IsInOutZT0")))
1785       AddToKey("ArmInOutZT0");
1786 
1787     if (!Key.empty())
1788       IntrinsicsPerState[Key].insert(Def->getMangledName());
1789   }
1790 
1791   OS << "#ifdef GET_SME_BUILTIN_GET_STATE\n";
1792   for (auto &KV : IntrinsicsPerState) {
1793     for (StringRef Name : KV.second)
1794       OS << "case SME::BI__builtin_sme_" << Name << ":\n";
1795     OS << "  return " << KV.first << ";\n";
1796   }
1797   OS << "#endif\n\n";
1798 }
1799 
1800 void SVEEmitter::createStreamingAttrs(raw_ostream &OS, ACLEKind Kind) {
1801   std::vector<const Record *> RV = Records.getAllDerivedDefinitions("Inst");
1802   SmallVector<std::unique_ptr<Intrinsic>, 128> Defs;
1803   for (auto *R : RV)
1804     createIntrinsic(R, Defs);
1805 
1806   StringRef ExtensionKind;
1807   switch (Kind) {
1808   case ACLEKind::SME:
1809     ExtensionKind = "SME";
1810     break;
1811   case ACLEKind::SVE:
1812     ExtensionKind = "SVE";
1813     break;
1814   }
1815 
1816   OS << "#ifdef GET_" << ExtensionKind << "_STREAMING_ATTRS\n";
1817 
1818   StringMap<std::set<std::string>> StreamingMap;
1819 
1820   uint64_t IsStreamingFlag = getEnumValueForFlag("IsStreaming");
1821   uint64_t VerifyRuntimeMode = getEnumValueForFlag("VerifyRuntimeMode");
1822   uint64_t IsStreamingCompatibleFlag =
1823       getEnumValueForFlag("IsStreamingCompatible");
1824 
1825   for (auto &Def : Defs) {
1826     if (!Def->isFlagSet(VerifyRuntimeMode) && !Def->getSVEGuard().empty() &&
1827         !Def->getSMEGuard().empty())
1828       report_fatal_error("Missing VerifyRuntimeMode flag");
1829 
1830     if (Def->isFlagSet(IsStreamingFlag))
1831       StreamingMap["ArmStreaming"].insert(Def->getMangledName());
1832     else if (Def->isFlagSet(VerifyRuntimeMode))
1833       StreamingMap["VerifyRuntimeMode"].insert(Def->getMangledName());
1834     else if (Def->isFlagSet(IsStreamingCompatibleFlag))
1835       StreamingMap["ArmStreamingCompatible"].insert(Def->getMangledName());
1836     else
1837       StreamingMap["ArmNonStreaming"].insert(Def->getMangledName());
1838   }
1839 
1840   for (auto BuiltinType : StreamingMap.keys()) {
1841     for (auto Name : StreamingMap[BuiltinType]) {
1842       OS << "case " << ExtensionKind << "::BI__builtin_"
1843          << ExtensionKind.lower() << "_";
1844       OS << Name << ":\n";
1845     }
1846     OS << "  BuiltinType = " << BuiltinType << ";\n";
1847     OS << "  break;\n";
1848   }
1849 
1850   OS << "#endif\n\n";
1851 }
1852 
1853 namespace clang {
1854 void EmitSveHeader(const RecordKeeper &Records, raw_ostream &OS) {
1855   SVEEmitter(Records).createHeader(OS);
1856 }
1857 
1858 void EmitSveBuiltins(const RecordKeeper &Records, raw_ostream &OS) {
1859   SVEEmitter(Records).createBuiltins(OS);
1860 }
1861 
1862 void EmitSveBuiltinCG(const RecordKeeper &Records, raw_ostream &OS) {
1863   SVEEmitter(Records).createCodeGenMap(OS);
1864 }
1865 
1866 void EmitSveRangeChecks(const RecordKeeper &Records, raw_ostream &OS) {
1867   SVEEmitter(Records).createRangeChecks(OS);
1868 }
1869 
1870 void EmitSveTypeFlags(const RecordKeeper &Records, raw_ostream &OS) {
1871   SVEEmitter(Records).createTypeFlags(OS);
1872 }
1873 
1874 void EmitImmCheckTypes(const RecordKeeper &Records, raw_ostream &OS) {
1875   SVEEmitter(Records).createImmCheckTypes(OS);
1876 }
1877 
1878 void EmitSveStreamingAttrs(const RecordKeeper &Records, raw_ostream &OS) {
1879   SVEEmitter(Records).createStreamingAttrs(OS, ACLEKind::SVE);
1880 }
1881 
1882 void EmitSmeHeader(const RecordKeeper &Records, raw_ostream &OS) {
1883   SVEEmitter(Records).createSMEHeader(OS);
1884 }
1885 
1886 void EmitSmeBuiltins(const RecordKeeper &Records, raw_ostream &OS) {
1887   SVEEmitter(Records).createSMEBuiltins(OS);
1888 }
1889 
1890 void EmitSmeBuiltinCG(const RecordKeeper &Records, raw_ostream &OS) {
1891   SVEEmitter(Records).createSMECodeGenMap(OS);
1892 }
1893 
1894 void EmitSmeRangeChecks(const RecordKeeper &Records, raw_ostream &OS) {
1895   SVEEmitter(Records).createSMERangeChecks(OS);
1896 }
1897 
1898 void EmitSmeStreamingAttrs(const RecordKeeper &Records, raw_ostream &OS) {
1899   SVEEmitter(Records).createStreamingAttrs(OS, ACLEKind::SME);
1900 }
1901 
1902 void EmitSmeBuiltinZAState(const RecordKeeper &Records, raw_ostream &OS) {
1903   SVEEmitter(Records).createBuiltinZAState(OS);
1904 }
1905 } // End namespace clang
1906