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