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