1 //===- RISCVVEmitter.cpp - Generate riscv_vector.h for use with clang -----===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This tablegen backend is responsible for emitting riscv_vector.h which
10 // includes a declaration and definition of each intrinsic functions specified
11 // in https://github.com/riscv/rvv-intrinsic-doc.
12 //
13 // See also the documentation in include/clang/Basic/riscv_vector.td.
14 //
15 //===----------------------------------------------------------------------===//
16 
17 #include "llvm/ADT/ArrayRef.h"
18 #include "llvm/ADT/SmallSet.h"
19 #include "llvm/ADT/StringExtras.h"
20 #include "llvm/ADT/StringMap.h"
21 #include "llvm/ADT/StringSet.h"
22 #include "llvm/ADT/Twine.h"
23 #include "llvm/TableGen/Error.h"
24 #include "llvm/TableGen/Record.h"
25 #include <numeric>
26 
27 using namespace llvm;
28 using BasicType = char;
29 using VScaleVal = Optional<unsigned>;
30 
31 namespace {
32 
33 // Exponential LMUL
34 struct LMULType {
35   int Log2LMUL;
36   LMULType(int Log2LMUL);
37   // Return the C/C++ string representation of LMUL
38   std::string str() const;
39   Optional<unsigned> getScale(unsigned ElementBitwidth) const;
40   void MulLog2LMUL(int Log2LMUL);
41   LMULType &operator*=(uint32_t RHS);
42 };
43 
44 // This class is compact representation of a valid and invalid RVVType.
45 class RVVType {
46   enum ScalarTypeKind : uint32_t {
47     Void,
48     Size_t,
49     Ptrdiff_t,
50     UnsignedLong,
51     SignedLong,
52     Boolean,
53     SignedInteger,
54     UnsignedInteger,
55     Float,
56     Invalid,
57   };
58   BasicType BT;
59   ScalarTypeKind ScalarType = Invalid;
60   LMULType LMUL;
61   bool IsPointer = false;
62   // IsConstant indices are "int", but have the constant expression.
63   bool IsImmediate = false;
64   // Const qualifier for pointer to const object or object of const type.
65   bool IsConstant = false;
66   unsigned ElementBitwidth = 0;
67   VScaleVal Scale = 0;
68   bool Valid;
69 
70   std::string BuiltinStr;
71   std::string ClangBuiltinStr;
72   std::string Str;
73   std::string ShortStr;
74 
75 public:
76   RVVType() : RVVType(BasicType(), 0, StringRef()) {}
77   RVVType(BasicType BT, int Log2LMUL, StringRef prototype);
78 
79   // Return the string representation of a type, which is an encoded string for
80   // passing to the BUILTIN() macro in Builtins.def.
81   const std::string &getBuiltinStr() const { return BuiltinStr; }
82 
83   // Return the clang builtin type for RVV vector type which are used in the
84   // riscv_vector.h header file.
85   const std::string &getClangBuiltinStr() const { return ClangBuiltinStr; }
86 
87   // Return the C/C++ string representation of a type for use in the
88   // riscv_vector.h header file.
89   const std::string &getTypeStr() const { return Str; }
90 
91   // Return the short name of a type for C/C++ name suffix.
92   const std::string &getShortStr() {
93     // Not all types are used in short name, so compute the short name by
94     // demanded.
95     if (ShortStr.empty())
96       initShortStr();
97     return ShortStr;
98   }
99 
100   bool isValid() const { return Valid; }
101   bool isScalar() const { return Scale.hasValue() && Scale.getValue() == 0; }
102   bool isVector() const { return Scale.hasValue() && Scale.getValue() != 0; }
103   bool isFloat() const { return ScalarType == ScalarTypeKind::Float; }
104   bool isSignedInteger() const {
105     return ScalarType == ScalarTypeKind::SignedInteger;
106   }
107   bool isFloatVector(unsigned Width) const {
108     return isVector() && isFloat() && ElementBitwidth == Width;
109   }
110   bool isFloat(unsigned Width) const {
111     return isFloat() && ElementBitwidth == Width;
112   }
113 
114 private:
115   // Verify RVV vector type and set Valid.
116   bool verifyType() const;
117 
118   // Creates a type based on basic types of TypeRange
119   void applyBasicType();
120 
121   // Applies a prototype modifier to the current type. The result maybe an
122   // invalid type.
123   void applyModifier(StringRef prototype);
124 
125   // Compute and record a string for legal type.
126   void initBuiltinStr();
127   // Compute and record a builtin RVV vector type string.
128   void initClangBuiltinStr();
129   // Compute and record a type string for used in the header.
130   void initTypeStr();
131   // Compute and record a short name of a type for C/C++ name suffix.
132   void initShortStr();
133 };
134 
135 using RVVTypePtr = RVVType *;
136 using RVVTypes = std::vector<RVVTypePtr>;
137 
138 enum RISCVExtension : uint8_t {
139   Basic = 0,
140   F = 1 << 1,
141   D = 1 << 2,
142   Zfh = 1 << 3,
143   Zvlsseg = 1 << 4,
144 };
145 
146 // TODO refactor RVVIntrinsic class design after support all intrinsic
147 // combination. This represents an instantiation of an intrinsic with a
148 // particular type and prototype
149 class RVVIntrinsic {
150 
151 private:
152   std::string Name; // Builtin name
153   std::string MangledName;
154   std::string IRName;
155   bool IsMask;
156   bool HasVL;
157   bool HasPolicy;
158   bool HasNoMaskedOverloaded;
159   bool HasAutoDef; // There is automiatic definition in header
160   std::string ManualCodegen;
161   RVVTypePtr OutputType; // Builtin output type
162   RVVTypes InputTypes;   // Builtin input types
163   // The types we use to obtain the specific LLVM intrinsic. They are index of
164   // InputTypes. -1 means the return type.
165   std::vector<int64_t> IntrinsicTypes;
166   uint8_t RISCVExtensions = 0;
167   unsigned NF = 1;
168 
169 public:
170   RVVIntrinsic(StringRef Name, StringRef Suffix, StringRef MangledName,
171                StringRef MangledSuffix, StringRef IRName, bool IsMask,
172                bool HasMaskedOffOperand, bool HasVL, bool HasPolicy,
173                bool HasNoMaskedOverloaded, bool HasAutoDef,
174                StringRef ManualCodegen, const RVVTypes &Types,
175                const std::vector<int64_t> &IntrinsicTypes,
176                StringRef RequiredExtension, unsigned NF);
177   ~RVVIntrinsic() = default;
178 
179   StringRef getName() const { return Name; }
180   StringRef getMangledName() const { return MangledName; }
181   bool hasVL() const { return HasVL; }
182   bool hasPolicy() const { return HasPolicy; }
183   bool hasNoMaskedOverloaded() const { return HasNoMaskedOverloaded; }
184   bool hasManualCodegen() const { return !ManualCodegen.empty(); }
185   bool hasAutoDef() const { return HasAutoDef; }
186   bool isMask() const { return IsMask; }
187   StringRef getIRName() const { return IRName; }
188   StringRef getManualCodegen() const { return ManualCodegen; }
189   uint8_t getRISCVExtensions() const { return RISCVExtensions; }
190   unsigned getNF() const { return NF; }
191 
192   // Return the type string for a BUILTIN() macro in Builtins.def.
193   std::string getBuiltinTypeStr() const;
194 
195   // Emit the code block for switch body in EmitRISCVBuiltinExpr, it should
196   // init the RVVIntrinsic ID and IntrinsicTypes.
197   void emitCodeGenSwitchBody(raw_ostream &o) const;
198 
199   // Emit the macros for mapping C/C++ intrinsic function to builtin functions.
200   void emitIntrinsicFuncDef(raw_ostream &o) const;
201 
202   // Emit the mangled function definition.
203   void emitMangledFuncDef(raw_ostream &o) const;
204 };
205 
206 class RVVEmitter {
207 private:
208   RecordKeeper &Records;
209   std::string HeaderCode;
210   // Concat BasicType, LMUL and Proto as key
211   StringMap<RVVType> LegalTypes;
212   StringSet<> IllegalTypes;
213 
214 public:
215   RVVEmitter(RecordKeeper &R) : Records(R) {}
216 
217   /// Emit riscv_vector.h
218   void createHeader(raw_ostream &o);
219 
220   /// Emit all the __builtin prototypes and code needed by Sema.
221   void createBuiltins(raw_ostream &o);
222 
223   /// Emit all the information needed to map builtin -> LLVM IR intrinsic.
224   void createCodeGen(raw_ostream &o);
225 
226   std::string getSuffixStr(char Type, int Log2LMUL, StringRef Prototypes);
227 
228 private:
229   /// Create all intrinsics and add them to \p Out
230   void createRVVIntrinsics(std::vector<std::unique_ptr<RVVIntrinsic>> &Out);
231   /// Create Headers and add them to \p Out
232   void createRVVHeaders(raw_ostream &OS);
233   /// Compute output and input types by applying different config (basic type
234   /// and LMUL with type transformers). It also record result of type in legal
235   /// or illegal set to avoid compute the  same config again. The result maybe
236   /// have illegal RVVType.
237   Optional<RVVTypes> computeTypes(BasicType BT, int Log2LMUL, unsigned NF,
238                                   ArrayRef<std::string> PrototypeSeq);
239   Optional<RVVTypePtr> computeType(BasicType BT, int Log2LMUL, StringRef Proto);
240 
241   /// Emit Acrh predecessor definitions and body, assume the element of Defs are
242   /// sorted by extension.
243   void emitArchMacroAndBody(
244       std::vector<std::unique_ptr<RVVIntrinsic>> &Defs, raw_ostream &o,
245       std::function<void(raw_ostream &, const RVVIntrinsic &)>);
246 
247   // Emit the architecture preprocessor definitions. Return true when emits
248   // non-empty string.
249   bool emitExtDefStr(uint8_t Extensions, raw_ostream &o);
250   // Slice Prototypes string into sub prototype string and process each sub
251   // prototype string individually in the Handler.
252   void parsePrototypes(StringRef Prototypes,
253                        std::function<void(StringRef)> Handler);
254 };
255 
256 } // namespace
257 
258 //===----------------------------------------------------------------------===//
259 // Type implementation
260 //===----------------------------------------------------------------------===//
261 
262 LMULType::LMULType(int NewLog2LMUL) {
263   // Check Log2LMUL is -3, -2, -1, 0, 1, 2, 3
264   assert(NewLog2LMUL <= 3 && NewLog2LMUL >= -3 && "Bad LMUL number!");
265   Log2LMUL = NewLog2LMUL;
266 }
267 
268 std::string LMULType::str() const {
269   if (Log2LMUL < 0)
270     return "mf" + utostr(1ULL << (-Log2LMUL));
271   return "m" + utostr(1ULL << Log2LMUL);
272 }
273 
274 VScaleVal LMULType::getScale(unsigned ElementBitwidth) const {
275   int Log2ScaleResult = 0;
276   switch (ElementBitwidth) {
277   default:
278     break;
279   case 8:
280     Log2ScaleResult = Log2LMUL + 3;
281     break;
282   case 16:
283     Log2ScaleResult = Log2LMUL + 2;
284     break;
285   case 32:
286     Log2ScaleResult = Log2LMUL + 1;
287     break;
288   case 64:
289     Log2ScaleResult = Log2LMUL;
290     break;
291   }
292   // Illegal vscale result would be less than 1
293   if (Log2ScaleResult < 0)
294     return None;
295   return 1 << Log2ScaleResult;
296 }
297 
298 void LMULType::MulLog2LMUL(int log2LMUL) { Log2LMUL += log2LMUL; }
299 
300 LMULType &LMULType::operator*=(uint32_t RHS) {
301   assert(isPowerOf2_32(RHS));
302   this->Log2LMUL = this->Log2LMUL + Log2_32(RHS);
303   return *this;
304 }
305 
306 RVVType::RVVType(BasicType BT, int Log2LMUL, StringRef prototype)
307     : BT(BT), LMUL(LMULType(Log2LMUL)) {
308   applyBasicType();
309   applyModifier(prototype);
310   Valid = verifyType();
311   if (Valid) {
312     initBuiltinStr();
313     initTypeStr();
314     if (isVector()) {
315       initClangBuiltinStr();
316     }
317   }
318 }
319 
320 // clang-format off
321 // boolean type are encoded the ratio of n (SEW/LMUL)
322 // SEW/LMUL | 1         | 2         | 4         | 8        | 16        | 32        | 64
323 // c type   | vbool64_t | vbool32_t | vbool16_t | vbool8_t | vbool4_t  | vbool2_t  | vbool1_t
324 // IR type  | nxv1i1    | nxv2i1    | nxv4i1    | nxv8i1   | nxv16i1   | nxv32i1   | nxv64i1
325 
326 // type\lmul | 1/8    | 1/4      | 1/2     | 1       | 2        | 4        | 8
327 // --------  |------  | -------- | ------- | ------- | -------- | -------- | --------
328 // i64       | N/A    | N/A      | N/A     | nxv1i64 | nxv2i64  | nxv4i64  | nxv8i64
329 // i32       | N/A    | N/A      | nxv1i32 | nxv2i32 | nxv4i32  | nxv8i32  | nxv16i32
330 // i16       | N/A    | nxv1i16  | nxv2i16 | nxv4i16 | nxv8i16  | nxv16i16 | nxv32i16
331 // i8        | nxv1i8 | nxv2i8   | nxv4i8  | nxv8i8  | nxv16i8  | nxv32i8  | nxv64i8
332 // double    | N/A    | N/A      | N/A     | nxv1f64 | nxv2f64  | nxv4f64  | nxv8f64
333 // float     | N/A    | N/A      | nxv1f32 | nxv2f32 | nxv4f32  | nxv8f32  | nxv16f32
334 // half      | N/A    | nxv1f16  | nxv2f16 | nxv4f16 | nxv8f16  | nxv16f16 | nxv32f16
335 // clang-format on
336 
337 bool RVVType::verifyType() const {
338   if (ScalarType == Invalid)
339     return false;
340   if (isScalar())
341     return true;
342   if (!Scale.hasValue())
343     return false;
344   if (isFloat() && ElementBitwidth == 8)
345     return false;
346   unsigned V = Scale.getValue();
347   switch (ElementBitwidth) {
348   case 1:
349   case 8:
350     // Check Scale is 1,2,4,8,16,32,64
351     return (V <= 64 && isPowerOf2_32(V));
352   case 16:
353     // Check Scale is 1,2,4,8,16,32
354     return (V <= 32 && isPowerOf2_32(V));
355   case 32:
356     // Check Scale is 1,2,4,8,16
357     return (V <= 16 && isPowerOf2_32(V));
358   case 64:
359     // Check Scale is 1,2,4,8
360     return (V <= 8 && isPowerOf2_32(V));
361   }
362   return false;
363 }
364 
365 void RVVType::initBuiltinStr() {
366   assert(isValid() && "RVVType is invalid");
367   switch (ScalarType) {
368   case ScalarTypeKind::Void:
369     BuiltinStr = "v";
370     return;
371   case ScalarTypeKind::Size_t:
372     BuiltinStr = "z";
373     if (IsImmediate)
374       BuiltinStr = "I" + BuiltinStr;
375     if (IsPointer)
376       BuiltinStr += "*";
377     return;
378   case ScalarTypeKind::Ptrdiff_t:
379     BuiltinStr = "Y";
380     return;
381   case ScalarTypeKind::UnsignedLong:
382     BuiltinStr = "ULi";
383     return;
384   case ScalarTypeKind::SignedLong:
385     BuiltinStr = "Li";
386     return;
387   case ScalarTypeKind::Boolean:
388     assert(ElementBitwidth == 1);
389     BuiltinStr += "b";
390     break;
391   case ScalarTypeKind::SignedInteger:
392   case ScalarTypeKind::UnsignedInteger:
393     switch (ElementBitwidth) {
394     case 8:
395       BuiltinStr += "c";
396       break;
397     case 16:
398       BuiltinStr += "s";
399       break;
400     case 32:
401       BuiltinStr += "i";
402       break;
403     case 64:
404       BuiltinStr += "Wi";
405       break;
406     default:
407       llvm_unreachable("Unhandled ElementBitwidth!");
408     }
409     if (isSignedInteger())
410       BuiltinStr = "S" + BuiltinStr;
411     else
412       BuiltinStr = "U" + BuiltinStr;
413     break;
414   case ScalarTypeKind::Float:
415     switch (ElementBitwidth) {
416     case 16:
417       BuiltinStr += "x";
418       break;
419     case 32:
420       BuiltinStr += "f";
421       break;
422     case 64:
423       BuiltinStr += "d";
424       break;
425     default:
426       llvm_unreachable("Unhandled ElementBitwidth!");
427     }
428     break;
429   default:
430     llvm_unreachable("ScalarType is invalid!");
431   }
432   if (IsImmediate)
433     BuiltinStr = "I" + BuiltinStr;
434   if (isScalar()) {
435     if (IsConstant)
436       BuiltinStr += "C";
437     if (IsPointer)
438       BuiltinStr += "*";
439     return;
440   }
441   BuiltinStr = "q" + utostr(Scale.getValue()) + BuiltinStr;
442   // Pointer to vector types. Defined for Zvlsseg load intrinsics.
443   // Zvlsseg load intrinsics have pointer type arguments to store the loaded
444   // vector values.
445   if (IsPointer)
446     BuiltinStr += "*";
447 }
448 
449 void RVVType::initClangBuiltinStr() {
450   assert(isValid() && "RVVType is invalid");
451   assert(isVector() && "Handle Vector type only");
452 
453   ClangBuiltinStr = "__rvv_";
454   switch (ScalarType) {
455   case ScalarTypeKind::Boolean:
456     ClangBuiltinStr += "bool" + utostr(64 / Scale.getValue()) + "_t";
457     return;
458   case ScalarTypeKind::Float:
459     ClangBuiltinStr += "float";
460     break;
461   case ScalarTypeKind::SignedInteger:
462     ClangBuiltinStr += "int";
463     break;
464   case ScalarTypeKind::UnsignedInteger:
465     ClangBuiltinStr += "uint";
466     break;
467   default:
468     llvm_unreachable("ScalarTypeKind is invalid");
469   }
470   ClangBuiltinStr += utostr(ElementBitwidth) + LMUL.str() + "_t";
471 }
472 
473 void RVVType::initTypeStr() {
474   assert(isValid() && "RVVType is invalid");
475 
476   if (IsConstant)
477     Str += "const ";
478 
479   auto getTypeString = [&](StringRef TypeStr) {
480     if (isScalar())
481       return Twine(TypeStr + Twine(ElementBitwidth) + "_t").str();
482     return Twine("v" + TypeStr + Twine(ElementBitwidth) + LMUL.str() + "_t")
483         .str();
484   };
485 
486   switch (ScalarType) {
487   case ScalarTypeKind::Void:
488     Str = "void";
489     return;
490   case ScalarTypeKind::Size_t:
491     Str = "size_t";
492     if (IsPointer)
493       Str += " *";
494     return;
495   case ScalarTypeKind::Ptrdiff_t:
496     Str = "ptrdiff_t";
497     return;
498   case ScalarTypeKind::UnsignedLong:
499     Str = "unsigned long";
500     return;
501   case ScalarTypeKind::SignedLong:
502     Str = "long";
503     return;
504   case ScalarTypeKind::Boolean:
505     if (isScalar())
506       Str += "bool";
507     else
508       // Vector bool is special case, the formulate is
509       // `vbool<N>_t = MVT::nxv<64/N>i1` ex. vbool16_t = MVT::4i1
510       Str += "vbool" + utostr(64 / Scale.getValue()) + "_t";
511     break;
512   case ScalarTypeKind::Float:
513     if (isScalar()) {
514       if (ElementBitwidth == 64)
515         Str += "double";
516       else if (ElementBitwidth == 32)
517         Str += "float";
518       else if (ElementBitwidth == 16)
519         Str += "_Float16";
520       else
521         llvm_unreachable("Unhandled floating type.");
522     } else
523       Str += getTypeString("float");
524     break;
525   case ScalarTypeKind::SignedInteger:
526     Str += getTypeString("int");
527     break;
528   case ScalarTypeKind::UnsignedInteger:
529     Str += getTypeString("uint");
530     break;
531   default:
532     llvm_unreachable("ScalarType is invalid!");
533   }
534   if (IsPointer)
535     Str += " *";
536 }
537 
538 void RVVType::initShortStr() {
539   switch (ScalarType) {
540   case ScalarTypeKind::Boolean:
541     assert(isVector());
542     ShortStr = "b" + utostr(64 / Scale.getValue());
543     return;
544   case ScalarTypeKind::Float:
545     ShortStr = "f" + utostr(ElementBitwidth);
546     break;
547   case ScalarTypeKind::SignedInteger:
548     ShortStr = "i" + utostr(ElementBitwidth);
549     break;
550   case ScalarTypeKind::UnsignedInteger:
551     ShortStr = "u" + utostr(ElementBitwidth);
552     break;
553   default:
554     PrintFatalError("Unhandled case!");
555   }
556   if (isVector())
557     ShortStr += LMUL.str();
558 }
559 
560 void RVVType::applyBasicType() {
561   switch (BT) {
562   case 'c':
563     ElementBitwidth = 8;
564     ScalarType = ScalarTypeKind::SignedInteger;
565     break;
566   case 's':
567     ElementBitwidth = 16;
568     ScalarType = ScalarTypeKind::SignedInteger;
569     break;
570   case 'i':
571     ElementBitwidth = 32;
572     ScalarType = ScalarTypeKind::SignedInteger;
573     break;
574   case 'l':
575     ElementBitwidth = 64;
576     ScalarType = ScalarTypeKind::SignedInteger;
577     break;
578   case 'x':
579     ElementBitwidth = 16;
580     ScalarType = ScalarTypeKind::Float;
581     break;
582   case 'f':
583     ElementBitwidth = 32;
584     ScalarType = ScalarTypeKind::Float;
585     break;
586   case 'd':
587     ElementBitwidth = 64;
588     ScalarType = ScalarTypeKind::Float;
589     break;
590   default:
591     PrintFatalError("Unhandled type code!");
592   }
593   assert(ElementBitwidth != 0 && "Bad element bitwidth!");
594 }
595 
596 void RVVType::applyModifier(StringRef Transformer) {
597   if (Transformer.empty())
598     return;
599   // Handle primitive type transformer
600   auto PType = Transformer.back();
601   switch (PType) {
602   case 'e':
603     Scale = 0;
604     break;
605   case 'v':
606     Scale = LMUL.getScale(ElementBitwidth);
607     break;
608   case 'w':
609     ElementBitwidth *= 2;
610     LMUL *= 2;
611     Scale = LMUL.getScale(ElementBitwidth);
612     break;
613   case 'q':
614     ElementBitwidth *= 4;
615     LMUL *= 4;
616     Scale = LMUL.getScale(ElementBitwidth);
617     break;
618   case 'o':
619     ElementBitwidth *= 8;
620     LMUL *= 8;
621     Scale = LMUL.getScale(ElementBitwidth);
622     break;
623   case 'm':
624     ScalarType = ScalarTypeKind::Boolean;
625     Scale = LMUL.getScale(ElementBitwidth);
626     ElementBitwidth = 1;
627     break;
628   case '0':
629     ScalarType = ScalarTypeKind::Void;
630     break;
631   case 'z':
632     ScalarType = ScalarTypeKind::Size_t;
633     break;
634   case 't':
635     ScalarType = ScalarTypeKind::Ptrdiff_t;
636     break;
637   case 'u':
638     ScalarType = ScalarTypeKind::UnsignedLong;
639     break;
640   case 'l':
641     ScalarType = ScalarTypeKind::SignedLong;
642     break;
643   default:
644     PrintFatalError("Illegal primitive type transformers!");
645   }
646   Transformer = Transformer.drop_back();
647 
648   // Extract and compute complex type transformer. It can only appear one time.
649   if (Transformer.startswith("(")) {
650     size_t Idx = Transformer.find(')');
651     assert(Idx != StringRef::npos);
652     StringRef ComplexType = Transformer.slice(1, Idx);
653     Transformer = Transformer.drop_front(Idx + 1);
654     assert(!Transformer.contains('(') &&
655            "Only allow one complex type transformer");
656 
657     auto UpdateAndCheckComplexProto = [&]() {
658       Scale = LMUL.getScale(ElementBitwidth);
659       const StringRef VectorPrototypes("vwqom");
660       if (!VectorPrototypes.contains(PType))
661         PrintFatalError("Complex type transformer only supports vector type!");
662       if (Transformer.find_first_of("PCKWS") != StringRef::npos)
663         PrintFatalError(
664             "Illegal type transformer for Complex type transformer");
665     };
666     auto ComputeFixedLog2LMUL =
667         [&](StringRef Value,
668             std::function<bool(const int32_t &, const int32_t &)> Compare) {
669           int32_t Log2LMUL;
670           Value.getAsInteger(10, Log2LMUL);
671           if (!Compare(Log2LMUL, LMUL.Log2LMUL)) {
672             ScalarType = Invalid;
673             return false;
674           }
675           // Update new LMUL
676           LMUL = LMULType(Log2LMUL);
677           UpdateAndCheckComplexProto();
678           return true;
679         };
680     auto ComplexTT = ComplexType.split(":");
681     if (ComplexTT.first == "Log2EEW") {
682       uint32_t Log2EEW;
683       ComplexTT.second.getAsInteger(10, Log2EEW);
684       // update new elmul = (eew/sew) * lmul
685       LMUL.MulLog2LMUL(Log2EEW - Log2_32(ElementBitwidth));
686       // update new eew
687       ElementBitwidth = 1 << Log2EEW;
688       ScalarType = ScalarTypeKind::SignedInteger;
689       UpdateAndCheckComplexProto();
690     } else if (ComplexTT.first == "FixedSEW") {
691       uint32_t NewSEW;
692       ComplexTT.second.getAsInteger(10, NewSEW);
693       // Set invalid type if src and dst SEW are same.
694       if (ElementBitwidth == NewSEW) {
695         ScalarType = Invalid;
696         return;
697       }
698       // Update new SEW
699       ElementBitwidth = NewSEW;
700       UpdateAndCheckComplexProto();
701     } else if (ComplexTT.first == "LFixedLog2LMUL") {
702       // New LMUL should be larger than old
703       if (!ComputeFixedLog2LMUL(ComplexTT.second, std::greater<int32_t>()))
704         return;
705     } else if (ComplexTT.first == "SFixedLog2LMUL") {
706       // New LMUL should be smaller than old
707       if (!ComputeFixedLog2LMUL(ComplexTT.second, std::less<int32_t>()))
708         return;
709     } else {
710       PrintFatalError("Illegal complex type transformers!");
711     }
712   }
713 
714   // Compute the remain type transformers
715   for (char I : Transformer) {
716     switch (I) {
717     case 'P':
718       if (IsConstant)
719         PrintFatalError("'P' transformer cannot be used after 'C'");
720       if (IsPointer)
721         PrintFatalError("'P' transformer cannot be used twice");
722       IsPointer = true;
723       break;
724     case 'C':
725       if (IsConstant)
726         PrintFatalError("'C' transformer cannot be used twice");
727       IsConstant = true;
728       break;
729     case 'K':
730       IsImmediate = true;
731       break;
732     case 'U':
733       ScalarType = ScalarTypeKind::UnsignedInteger;
734       break;
735     case 'I':
736       ScalarType = ScalarTypeKind::SignedInteger;
737       break;
738     case 'F':
739       ScalarType = ScalarTypeKind::Float;
740       break;
741     case 'S':
742       LMUL = LMULType(0);
743       // Update ElementBitwidth need to update Scale too.
744       Scale = LMUL.getScale(ElementBitwidth);
745       break;
746     default:
747       PrintFatalError("Illegal non-primitive type transformer!");
748     }
749   }
750 }
751 
752 //===----------------------------------------------------------------------===//
753 // RVVIntrinsic implementation
754 //===----------------------------------------------------------------------===//
755 RVVIntrinsic::RVVIntrinsic(StringRef NewName, StringRef Suffix,
756                            StringRef NewMangledName, StringRef MangledSuffix,
757                            StringRef IRName, bool IsMask,
758                            bool HasMaskedOffOperand, bool HasVL, bool HasPolicy,
759                            bool HasNoMaskedOverloaded, bool HasAutoDef,
760                            StringRef ManualCodegen, const RVVTypes &OutInTypes,
761                            const std::vector<int64_t> &NewIntrinsicTypes,
762                            StringRef RequiredExtension, unsigned NF)
763     : IRName(IRName), IsMask(IsMask), HasVL(HasVL), HasPolicy(HasPolicy),
764       HasNoMaskedOverloaded(HasNoMaskedOverloaded), HasAutoDef(HasAutoDef),
765       ManualCodegen(ManualCodegen.str()), NF(NF) {
766 
767   // Init Name and MangledName
768   Name = NewName.str();
769   if (NewMangledName.empty())
770     MangledName = NewName.split("_").first.str();
771   else
772     MangledName = NewMangledName.str();
773   if (!Suffix.empty())
774     Name += "_" + Suffix.str();
775   if (!MangledSuffix.empty())
776     MangledName += "_" + MangledSuffix.str();
777   if (IsMask) {
778     Name += "_m";
779   }
780   // Init RISC-V extensions
781   for (const auto &T : OutInTypes) {
782     if (T->isFloatVector(16) || T->isFloat(16))
783       RISCVExtensions |= RISCVExtension::Zfh;
784     else if (T->isFloatVector(32) || T->isFloat(32))
785       RISCVExtensions |= RISCVExtension::F;
786     else if (T->isFloatVector(64) || T->isFloat(64))
787       RISCVExtensions |= RISCVExtension::D;
788   }
789   if (RequiredExtension == "Zvlsseg")
790     RISCVExtensions |= RISCVExtension::Zvlsseg;
791 
792   // Init OutputType and InputTypes
793   OutputType = OutInTypes[0];
794   InputTypes.assign(OutInTypes.begin() + 1, OutInTypes.end());
795 
796   // IntrinsicTypes is nonmasked version index. Need to update it
797   // if there is maskedoff operand (It is always in first operand).
798   IntrinsicTypes = NewIntrinsicTypes;
799   if (IsMask && HasMaskedOffOperand) {
800     for (auto &I : IntrinsicTypes) {
801       if (I >= 0)
802         I += NF;
803     }
804   }
805 }
806 
807 std::string RVVIntrinsic::getBuiltinTypeStr() const {
808   std::string S;
809   S += OutputType->getBuiltinStr();
810   for (const auto &T : InputTypes) {
811     S += T->getBuiltinStr();
812   }
813   return S;
814 }
815 
816 void RVVIntrinsic::emitCodeGenSwitchBody(raw_ostream &OS) const {
817   if (!getIRName().empty())
818     OS << "  ID = Intrinsic::riscv_" + getIRName() + ";\n";
819   if (NF >= 2)
820     OS << "  NF = " + utostr(getNF()) + ";\n";
821   if (hasManualCodegen()) {
822     OS << ManualCodegen;
823     OS << "break;\n";
824     return;
825   }
826 
827   if (isMask()) {
828     if (hasVL()) {
829       OS << "  std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1);\n";
830       if (hasPolicy())
831         OS << "  Ops.push_back(ConstantInt::get(Ops.back()->getType(),"
832                                " TAIL_UNDISTURBED));\n";
833     } else {
834       OS << "  std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end());\n";
835     }
836   }
837 
838   OS << "  IntrinsicTypes = {";
839   ListSeparator LS;
840   for (const auto &Idx : IntrinsicTypes) {
841     if (Idx == -1)
842       OS << LS << "ResultType";
843     else
844       OS << LS << "Ops[" << Idx << "]->getType()";
845   }
846 
847   // VL could be i64 or i32, need to encode it in IntrinsicTypes. VL is
848   // always last operand.
849   if (hasVL())
850     OS << ", Ops.back()->getType()";
851   OS << "};\n";
852   OS << "  break;\n";
853 }
854 
855 void RVVIntrinsic::emitIntrinsicFuncDef(raw_ostream &OS) const {
856   OS << "__attribute__((__clang_builtin_alias__(";
857   OS << "__builtin_rvv_" << getName() << ")))\n";
858   OS << OutputType->getTypeStr() << " " << getName() << "(";
859   // Emit function arguments
860   if (!InputTypes.empty()) {
861     ListSeparator LS;
862     for (unsigned i = 0; i < InputTypes.size(); ++i)
863       OS << LS << InputTypes[i]->getTypeStr();
864   }
865   OS << ");\n";
866 }
867 
868 void RVVIntrinsic::emitMangledFuncDef(raw_ostream &OS) const {
869   OS << "__attribute__((__clang_builtin_alias__(";
870   OS << "__builtin_rvv_" << getName() << ")))\n";
871   OS << OutputType->getTypeStr() << " " << getMangledName() << "(";
872   // Emit function arguments
873   if (!InputTypes.empty()) {
874     ListSeparator LS;
875     for (unsigned i = 0; i < InputTypes.size(); ++i)
876       OS << LS << InputTypes[i]->getTypeStr();
877   }
878   OS << ");\n";
879 }
880 
881 //===----------------------------------------------------------------------===//
882 // RVVEmitter implementation
883 //===----------------------------------------------------------------------===//
884 void RVVEmitter::createHeader(raw_ostream &OS) {
885 
886   OS << "/*===---- riscv_vector.h - RISC-V V-extension RVVIntrinsics "
887         "-------------------===\n"
888         " *\n"
889         " *\n"
890         " * Part of the LLVM Project, under the Apache License v2.0 with LLVM "
891         "Exceptions.\n"
892         " * See https://llvm.org/LICENSE.txt for license information.\n"
893         " * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n"
894         " *\n"
895         " *===-----------------------------------------------------------------"
896         "------===\n"
897         " */\n\n";
898 
899   OS << "#ifndef __RISCV_VECTOR_H\n";
900   OS << "#define __RISCV_VECTOR_H\n\n";
901 
902   OS << "#include <stdint.h>\n";
903   OS << "#include <stddef.h>\n\n";
904 
905   OS << "#ifndef __riscv_vector\n";
906   OS << "#error \"Vector intrinsics require the vector extension.\"\n";
907   OS << "#endif\n\n";
908 
909   OS << "#ifdef __cplusplus\n";
910   OS << "extern \"C\" {\n";
911   OS << "#endif\n\n";
912 
913   createRVVHeaders(OS);
914 
915   std::vector<std::unique_ptr<RVVIntrinsic>> Defs;
916   createRVVIntrinsics(Defs);
917 
918   // Print header code
919   if (!HeaderCode.empty()) {
920     OS << HeaderCode;
921   }
922 
923   auto printType = [&](auto T) {
924     OS << "typedef " << T->getClangBuiltinStr() << " " << T->getTypeStr()
925        << ";\n";
926   };
927 
928   constexpr int Log2LMULs[] = {-3, -2, -1, 0, 1, 2, 3};
929   // Print RVV boolean types.
930   for (int Log2LMUL : Log2LMULs) {
931     auto T = computeType('c', Log2LMUL, "m");
932     if (T.hasValue())
933       printType(T.getValue());
934   }
935   // Print RVV int/float types.
936   for (char I : StringRef("csil")) {
937     for (int Log2LMUL : Log2LMULs) {
938       auto T = computeType(I, Log2LMUL, "v");
939       if (T.hasValue()) {
940         printType(T.getValue());
941         auto UT = computeType(I, Log2LMUL, "Uv");
942         printType(UT.getValue());
943       }
944     }
945   }
946   OS << "#if defined(__riscv_zfh)\n";
947   for (int Log2LMUL : Log2LMULs) {
948     auto T = computeType('x', Log2LMUL, "v");
949     if (T.hasValue())
950       printType(T.getValue());
951   }
952   OS << "#endif\n";
953 
954   OS << "#if defined(__riscv_f)\n";
955   for (int Log2LMUL : Log2LMULs) {
956     auto T = computeType('f', Log2LMUL, "v");
957     if (T.hasValue())
958       printType(T.getValue());
959   }
960   OS << "#endif\n";
961 
962   OS << "#if defined(__riscv_d)\n";
963   for (int Log2LMUL : Log2LMULs) {
964     auto T = computeType('d', Log2LMUL, "v");
965     if (T.hasValue())
966       printType(T.getValue());
967   }
968   OS << "#endif\n\n";
969 
970   // The same extension include in the same arch guard marco.
971   llvm::stable_sort(Defs, [](const std::unique_ptr<RVVIntrinsic> &A,
972                              const std::unique_ptr<RVVIntrinsic> &B) {
973     return A->getRISCVExtensions() < B->getRISCVExtensions();
974   });
975 
976   OS << "#define __rvv_ai static __inline__ "
977         "__attribute__((__always_inline__, __nodebug__))\n";
978 
979   // Print intrinsic functions with macro
980   emitArchMacroAndBody(Defs, OS, [](raw_ostream &OS, const RVVIntrinsic &Inst) {
981     OS << "__rvv_ai ";
982     Inst.emitIntrinsicFuncDef(OS);
983   });
984 
985   OS << "#undef __rvv_ai\n\n";
986 
987   OS << "#define __riscv_v_intrinsic_overloading 1\n";
988 
989   // Print Overloaded APIs
990   OS << "#define __rvv_aio static __inline__ "
991         "__attribute__((__always_inline__, __nodebug__, __overloadable__))\n";
992 
993   emitArchMacroAndBody(Defs, OS, [](raw_ostream &OS, const RVVIntrinsic &Inst) {
994     if (!Inst.isMask() && !Inst.hasNoMaskedOverloaded())
995       return;
996     OS << "__rvv_aio ";
997     Inst.emitMangledFuncDef(OS);
998   });
999 
1000   OS << "#undef __rvv_aio\n";
1001 
1002   OS << "\n#ifdef __cplusplus\n";
1003   OS << "}\n";
1004   OS << "#endif // __cplusplus\n";
1005   OS << "#endif // __RISCV_VECTOR_H\n";
1006 }
1007 
1008 void RVVEmitter::createBuiltins(raw_ostream &OS) {
1009   std::vector<std::unique_ptr<RVVIntrinsic>> Defs;
1010   createRVVIntrinsics(Defs);
1011 
1012   OS << "#if defined(TARGET_BUILTIN) && !defined(RISCVV_BUILTIN)\n";
1013   OS << "#define RISCVV_BUILTIN(ID, TYPE, ATTRS) TARGET_BUILTIN(ID, TYPE, "
1014         "ATTRS, \"experimental-v\")\n";
1015   OS << "#endif\n";
1016   for (auto &Def : Defs) {
1017     OS << "RISCVV_BUILTIN(__builtin_rvv_" << Def->getName() << ",\""
1018        << Def->getBuiltinTypeStr() << "\", \"n\")\n";
1019   }
1020   OS << "#undef RISCVV_BUILTIN\n";
1021 }
1022 
1023 void RVVEmitter::createCodeGen(raw_ostream &OS) {
1024   std::vector<std::unique_ptr<RVVIntrinsic>> Defs;
1025   createRVVIntrinsics(Defs);
1026   // IR name could be empty, use the stable sort preserves the relative order.
1027   llvm::stable_sort(Defs, [](const std::unique_ptr<RVVIntrinsic> &A,
1028                              const std::unique_ptr<RVVIntrinsic> &B) {
1029     return A->getIRName() < B->getIRName();
1030   });
1031   // Print switch body when the ir name or ManualCodegen changes from previous
1032   // iteration.
1033   RVVIntrinsic *PrevDef = Defs.begin()->get();
1034   for (auto &Def : Defs) {
1035     StringRef CurIRName = Def->getIRName();
1036     if (CurIRName != PrevDef->getIRName() ||
1037         (Def->getManualCodegen() != PrevDef->getManualCodegen())) {
1038       PrevDef->emitCodeGenSwitchBody(OS);
1039     }
1040     PrevDef = Def.get();
1041     OS << "case RISCVVector::BI__builtin_rvv_" << Def->getName() << ":\n";
1042   }
1043   Defs.back()->emitCodeGenSwitchBody(OS);
1044   OS << "\n";
1045 }
1046 
1047 void RVVEmitter::parsePrototypes(StringRef Prototypes,
1048                                  std::function<void(StringRef)> Handler) {
1049   const StringRef Primaries("evwqom0ztul");
1050   while (!Prototypes.empty()) {
1051     size_t Idx = 0;
1052     // Skip over complex prototype because it could contain primitive type
1053     // character.
1054     if (Prototypes[0] == '(')
1055       Idx = Prototypes.find_first_of(')');
1056     Idx = Prototypes.find_first_of(Primaries, Idx);
1057     assert(Idx != StringRef::npos);
1058     Handler(Prototypes.slice(0, Idx + 1));
1059     Prototypes = Prototypes.drop_front(Idx + 1);
1060   }
1061 }
1062 
1063 std::string RVVEmitter::getSuffixStr(char Type, int Log2LMUL,
1064                                      StringRef Prototypes) {
1065   SmallVector<std::string> SuffixStrs;
1066   parsePrototypes(Prototypes, [&](StringRef Proto) {
1067     auto T = computeType(Type, Log2LMUL, Proto);
1068     SuffixStrs.push_back(T.getValue()->getShortStr());
1069   });
1070   return join(SuffixStrs, "_");
1071 }
1072 
1073 void RVVEmitter::createRVVIntrinsics(
1074     std::vector<std::unique_ptr<RVVIntrinsic>> &Out) {
1075   std::vector<Record *> RV = Records.getAllDerivedDefinitions("RVVBuiltin");
1076   for (auto *R : RV) {
1077     StringRef Name = R->getValueAsString("Name");
1078     StringRef SuffixProto = R->getValueAsString("Suffix");
1079     StringRef MangledName = R->getValueAsString("MangledName");
1080     StringRef MangledSuffixProto = R->getValueAsString("MangledSuffix");
1081     StringRef Prototypes = R->getValueAsString("Prototype");
1082     StringRef TypeRange = R->getValueAsString("TypeRange");
1083     bool HasMask = R->getValueAsBit("HasMask");
1084     bool HasMaskedOffOperand = R->getValueAsBit("HasMaskedOffOperand");
1085     bool HasVL = R->getValueAsBit("HasVL");
1086     bool HasPolicy = R->getValueAsBit("HasPolicy");
1087     bool HasNoMaskedOverloaded = R->getValueAsBit("HasNoMaskedOverloaded");
1088     std::vector<int64_t> Log2LMULList = R->getValueAsListOfInts("Log2LMUL");
1089     StringRef ManualCodegen = R->getValueAsString("ManualCodegen");
1090     StringRef ManualCodegenMask = R->getValueAsString("ManualCodegenMask");
1091     std::vector<int64_t> IntrinsicTypes =
1092         R->getValueAsListOfInts("IntrinsicTypes");
1093     StringRef RequiredExtension = R->getValueAsString("RequiredExtension");
1094     StringRef IRName = R->getValueAsString("IRName");
1095     StringRef IRNameMask = R->getValueAsString("IRNameMask");
1096     unsigned NF = R->getValueAsInt("NF");
1097 
1098     StringRef HeaderCodeStr = R->getValueAsString("HeaderCode");
1099     bool HasAutoDef = HeaderCodeStr.empty();
1100     if (!HeaderCodeStr.empty()) {
1101       HeaderCode += HeaderCodeStr.str();
1102     }
1103     // Parse prototype and create a list of primitive type with transformers
1104     // (operand) in ProtoSeq. ProtoSeq[0] is output operand.
1105     SmallVector<std::string> ProtoSeq;
1106     parsePrototypes(Prototypes, [&ProtoSeq](StringRef Proto) {
1107       ProtoSeq.push_back(Proto.str());
1108     });
1109 
1110     // Compute Builtin types
1111     SmallVector<std::string> ProtoMaskSeq = ProtoSeq;
1112     if (HasMask) {
1113       // If HasMaskedOffOperand, insert result type as first input operand.
1114       if (HasMaskedOffOperand) {
1115         if (NF == 1) {
1116           ProtoMaskSeq.insert(ProtoMaskSeq.begin() + 1, ProtoSeq[0]);
1117         } else {
1118           // Convert
1119           // (void, op0 address, op1 address, ...)
1120           // to
1121           // (void, op0 address, op1 address, ..., maskedoff0, maskedoff1, ...)
1122           for (unsigned I = 0; I < NF; ++I)
1123             ProtoMaskSeq.insert(
1124                 ProtoMaskSeq.begin() + NF + 1,
1125                 ProtoSeq[1].substr(1)); // Use substr(1) to skip '*'
1126         }
1127       }
1128       if (HasMaskedOffOperand && NF > 1) {
1129         // Convert
1130         // (void, op0 address, op1 address, ..., maskedoff0, maskedoff1, ...)
1131         // to
1132         // (void, op0 address, op1 address, ..., mask, maskedoff0, maskedoff1,
1133         // ...)
1134         ProtoMaskSeq.insert(ProtoMaskSeq.begin() + NF + 1, "m");
1135       } else {
1136         // If HasMask, insert 'm' as first input operand.
1137         ProtoMaskSeq.insert(ProtoMaskSeq.begin() + 1, "m");
1138       }
1139     }
1140     // If HasVL, append 'z' to last operand
1141     if (HasVL) {
1142       ProtoSeq.push_back("z");
1143       ProtoMaskSeq.push_back("z");
1144     }
1145 
1146     // Create Intrinsics for each type and LMUL.
1147     for (char I : TypeRange) {
1148       for (int Log2LMUL : Log2LMULList) {
1149         Optional<RVVTypes> Types = computeTypes(I, Log2LMUL, NF, ProtoSeq);
1150         // Ignored to create new intrinsic if there are any illegal types.
1151         if (!Types.hasValue())
1152           continue;
1153 
1154         auto SuffixStr = getSuffixStr(I, Log2LMUL, SuffixProto);
1155         auto MangledSuffixStr = getSuffixStr(I, Log2LMUL, MangledSuffixProto);
1156         // Create a non-mask intrinsic
1157         Out.push_back(std::make_unique<RVVIntrinsic>(
1158             Name, SuffixStr, MangledName, MangledSuffixStr, IRName,
1159             /*IsMask=*/false, /*HasMaskedOffOperand=*/false, HasVL, HasPolicy,
1160             HasNoMaskedOverloaded, HasAutoDef, ManualCodegen, Types.getValue(),
1161             IntrinsicTypes, RequiredExtension, NF));
1162         if (HasMask) {
1163           // Create a mask intrinsic
1164           Optional<RVVTypes> MaskTypes =
1165               computeTypes(I, Log2LMUL, NF, ProtoMaskSeq);
1166           Out.push_back(std::make_unique<RVVIntrinsic>(
1167               Name, SuffixStr, MangledName, MangledSuffixStr, IRNameMask,
1168               /*IsMask=*/true, HasMaskedOffOperand, HasVL, HasPolicy,
1169               HasNoMaskedOverloaded, HasAutoDef, ManualCodegenMask,
1170               MaskTypes.getValue(), IntrinsicTypes, RequiredExtension, NF));
1171         }
1172       } // end for Log2LMULList
1173     }   // end for TypeRange
1174   }
1175 }
1176 
1177 void RVVEmitter::createRVVHeaders(raw_ostream &OS) {
1178   std::vector<Record *> RVVHeaders =
1179       Records.getAllDerivedDefinitions("RVVHeader");
1180   for (auto *R : RVVHeaders) {
1181     StringRef HeaderCodeStr = R->getValueAsString("HeaderCode");
1182     OS << HeaderCodeStr.str();
1183   }
1184 }
1185 
1186 Optional<RVVTypes>
1187 RVVEmitter::computeTypes(BasicType BT, int Log2LMUL, unsigned NF,
1188                          ArrayRef<std::string> PrototypeSeq) {
1189   // LMUL x NF must be less than or equal to 8.
1190   if ((Log2LMUL >= 1) && (1 << Log2LMUL) * NF > 8)
1191     return llvm::None;
1192 
1193   RVVTypes Types;
1194   for (const std::string &Proto : PrototypeSeq) {
1195     auto T = computeType(BT, Log2LMUL, Proto);
1196     if (!T.hasValue())
1197       return llvm::None;
1198     // Record legal type index
1199     Types.push_back(T.getValue());
1200   }
1201   return Types;
1202 }
1203 
1204 Optional<RVVTypePtr> RVVEmitter::computeType(BasicType BT, int Log2LMUL,
1205                                              StringRef Proto) {
1206   std::string Idx = Twine(Twine(BT) + Twine(Log2LMUL) + Proto).str();
1207   // Search first
1208   auto It = LegalTypes.find(Idx);
1209   if (It != LegalTypes.end())
1210     return &(It->second);
1211   if (IllegalTypes.count(Idx))
1212     return llvm::None;
1213   // Compute type and record the result.
1214   RVVType T(BT, Log2LMUL, Proto);
1215   if (T.isValid()) {
1216     // Record legal type index and value.
1217     LegalTypes.insert({Idx, T});
1218     return &(LegalTypes[Idx]);
1219   }
1220   // Record illegal type index.
1221   IllegalTypes.insert(Idx);
1222   return llvm::None;
1223 }
1224 
1225 void RVVEmitter::emitArchMacroAndBody(
1226     std::vector<std::unique_ptr<RVVIntrinsic>> &Defs, raw_ostream &OS,
1227     std::function<void(raw_ostream &, const RVVIntrinsic &)> PrintBody) {
1228   uint8_t PrevExt = (*Defs.begin())->getRISCVExtensions();
1229   bool NeedEndif = emitExtDefStr(PrevExt, OS);
1230   for (auto &Def : Defs) {
1231     uint8_t CurExt = Def->getRISCVExtensions();
1232     if (CurExt != PrevExt) {
1233       if (NeedEndif)
1234         OS << "#endif\n\n";
1235       NeedEndif = emitExtDefStr(CurExt, OS);
1236       PrevExt = CurExt;
1237     }
1238     if (Def->hasAutoDef())
1239       PrintBody(OS, *Def);
1240   }
1241   if (NeedEndif)
1242     OS << "#endif\n\n";
1243 }
1244 
1245 bool RVVEmitter::emitExtDefStr(uint8_t Extents, raw_ostream &OS) {
1246   if (Extents == RISCVExtension::Basic)
1247     return false;
1248   OS << "#if ";
1249   ListSeparator LS(" && ");
1250   if (Extents & RISCVExtension::F)
1251     OS << LS << "defined(__riscv_f)";
1252   if (Extents & RISCVExtension::D)
1253     OS << LS << "defined(__riscv_d)";
1254   if (Extents & RISCVExtension::Zfh)
1255     OS << LS << "defined(__riscv_zfh)";
1256   if (Extents & RISCVExtension::Zvlsseg)
1257     OS << LS << "defined(__riscv_zvlsseg)";
1258   OS << "\n";
1259   return true;
1260 }
1261 
1262 namespace clang {
1263 void EmitRVVHeader(RecordKeeper &Records, raw_ostream &OS) {
1264   RVVEmitter(Records).createHeader(OS);
1265 }
1266 
1267 void EmitRVVBuiltins(RecordKeeper &Records, raw_ostream &OS) {
1268   RVVEmitter(Records).createBuiltins(OS);
1269 }
1270 
1271 void EmitRVVBuiltinCG(RecordKeeper &Records, raw_ostream &OS) {
1272   RVVEmitter(Records).createCodeGen(OS);
1273 }
1274 
1275 } // End namespace clang
1276