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