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