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