xref: /freebsd/contrib/llvm-project/clang/utils/TableGen/RISCVVEmitter.cpp (revision ebacd8013fe5f7fdf9f6a5b286f6680dd2891036)
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 "clang/Support/RISCVVIntrinsicUtils.h"
18 #include "llvm/ADT/ArrayRef.h"
19 #include "llvm/ADT/SmallSet.h"
20 #include "llvm/ADT/StringExtras.h"
21 #include "llvm/ADT/StringMap.h"
22 #include "llvm/ADT/StringSet.h"
23 #include "llvm/ADT/StringSwitch.h"
24 #include "llvm/ADT/Twine.h"
25 #include "llvm/TableGen/Error.h"
26 #include "llvm/TableGen/Record.h"
27 #include <numeric>
28 
29 using namespace llvm;
30 using namespace clang::RISCV;
31 
32 namespace {
33 struct SemaRecord {
34   // Intrinsic name, e.g. vadd_vv
35   std::string Name;
36 
37   // Overloaded intrinsic name, could be empty if can be computed from Name
38   // e.g. vadd
39   std::string OverloadedName;
40 
41   // Supported type, mask of BasicType.
42   unsigned TypeRangeMask;
43 
44   // Supported LMUL.
45   unsigned Log2LMULMask;
46 
47   // Required extensions for this intrinsic.
48   unsigned RequiredExtensions;
49 
50   // Prototype for this intrinsic.
51   SmallVector<PrototypeDescriptor> Prototype;
52 
53   // Suffix of intrinsic name.
54   SmallVector<PrototypeDescriptor> Suffix;
55 
56   // Suffix of overloaded intrinsic name.
57   SmallVector<PrototypeDescriptor> OverloadedSuffix;
58 
59   // Number of field, large than 1 if it's segment load/store.
60   unsigned NF;
61 
62   bool HasMasked :1;
63   bool HasVL :1;
64   bool HasMaskedOffOperand :1;
65 };
66 
67 // Compressed function signature table.
68 class SemaSignatureTable {
69 private:
70   std::vector<PrototypeDescriptor> SignatureTable;
71 
72   void insert(ArrayRef<PrototypeDescriptor> Signature);
73 
74 public:
75   static constexpr unsigned INVALID_INDEX = ~0U;
76 
77   // Create compressed signature table from SemaRecords.
78   void init(ArrayRef<SemaRecord> SemaRecords);
79 
80   // Query the Signature, return INVALID_INDEX if not found.
81   unsigned getIndex(ArrayRef<PrototypeDescriptor> Signature);
82 
83   /// Print signature table in RVVHeader Record to \p OS
84   void print(raw_ostream &OS);
85 };
86 
87 class RVVEmitter {
88 private:
89   RecordKeeper &Records;
90 
91 public:
92   RVVEmitter(RecordKeeper &R) : Records(R) {}
93 
94   /// Emit riscv_vector.h
95   void createHeader(raw_ostream &o);
96 
97   /// Emit all the __builtin prototypes and code needed by Sema.
98   void createBuiltins(raw_ostream &o);
99 
100   /// Emit all the information needed to map builtin -> LLVM IR intrinsic.
101   void createCodeGen(raw_ostream &o);
102 
103   /// Emit all the information needed by SemaRISCVVectorLookup.cpp.
104   /// We've large number of intrinsic function for RVV, creating a customized
105   /// could speed up the compilation time.
106   void createSema(raw_ostream &o);
107 
108 private:
109   /// Create all intrinsics and add them to \p Out and SemaRecords.
110   void createRVVIntrinsics(std::vector<std::unique_ptr<RVVIntrinsic>> &Out,
111                            std::vector<SemaRecord> *SemaRecords = nullptr);
112   /// Create all intrinsic records and SemaSignatureTable from SemaRecords.
113   void createRVVIntrinsicRecords(std::vector<RVVIntrinsicRecord> &Out,
114                                  SemaSignatureTable &SST,
115                                  ArrayRef<SemaRecord> SemaRecords);
116 
117   /// Print HeaderCode in RVVHeader Record to \p Out
118   void printHeaderCode(raw_ostream &OS);
119 };
120 
121 } // namespace
122 
123 static BasicType ParseBasicType(char c) {
124   switch (c) {
125   case 'c':
126     return BasicType::Int8;
127     break;
128   case 's':
129     return BasicType::Int16;
130     break;
131   case 'i':
132     return BasicType::Int32;
133     break;
134   case 'l':
135     return BasicType::Int64;
136     break;
137   case 'x':
138     return BasicType::Float16;
139     break;
140   case 'f':
141     return BasicType::Float32;
142     break;
143   case 'd':
144     return BasicType::Float64;
145     break;
146 
147   default:
148     return BasicType::Unknown;
149   }
150 }
151 
152 void emitCodeGenSwitchBody(const RVVIntrinsic *RVVI, raw_ostream &OS) {
153   if (!RVVI->getIRName().empty())
154     OS << "  ID = Intrinsic::riscv_" + RVVI->getIRName() + ";\n";
155   if (RVVI->getNF() >= 2)
156     OS << "  NF = " + utostr(RVVI->getNF()) + ";\n";
157   if (RVVI->hasManualCodegen()) {
158     OS << RVVI->getManualCodegen();
159     OS << "break;\n";
160     return;
161   }
162 
163   // Cast pointer operand of vector load intrinsic.
164   for (const auto &I : enumerate(RVVI->getInputTypes())) {
165     if (I.value()->isPointer()) {
166       assert(RVVI->getIntrinsicTypes().front() == -1 &&
167              "RVVI should be vector load intrinsic.");
168       OS << "  Ops[" << I.index() << "] = Builder.CreateBitCast(Ops[";
169       OS << I.index() << "], ResultType->getPointerTo());\n";
170     }
171   }
172 
173   if (RVVI->isMasked()) {
174     if (RVVI->hasVL()) {
175       OS << "  std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1);\n";
176       if (RVVI->hasPolicyOperand())
177         OS << "  Ops.push_back(ConstantInt::get(Ops.back()->getType(),"
178               " TAIL_UNDISTURBED));\n";
179     } else {
180       OS << "  std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end());\n";
181     }
182   } else {
183     if (RVVI->hasPolicyOperand())
184       OS << "  Ops.push_back(ConstantInt::get(Ops.back()->getType(), "
185             "TAIL_UNDISTURBED));\n";
186     else if (RVVI->hasPassthruOperand()) {
187       OS << "  Ops.push_back(llvm::UndefValue::get(ResultType));\n";
188       OS << "  std::rotate(Ops.rbegin(), Ops.rbegin() + 1,  Ops.rend());\n";
189     }
190   }
191 
192   OS << "  IntrinsicTypes = {";
193   ListSeparator LS;
194   for (const auto &Idx : RVVI->getIntrinsicTypes()) {
195     if (Idx == -1)
196       OS << LS << "ResultType";
197     else
198       OS << LS << "Ops[" << Idx << "]->getType()";
199   }
200 
201   // VL could be i64 or i32, need to encode it in IntrinsicTypes. VL is
202   // always last operand.
203   if (RVVI->hasVL())
204     OS << ", Ops.back()->getType()";
205   OS << "};\n";
206   OS << "  break;\n";
207 }
208 
209 //===----------------------------------------------------------------------===//
210 // SemaSignatureTable implementation
211 //===----------------------------------------------------------------------===//
212 void SemaSignatureTable::init(ArrayRef<SemaRecord> SemaRecords) {
213   // Sort signature entries by length, let longer signature insert first, to
214   // make it more possible to reuse table entries, that can reduce ~10% table
215   // size.
216   struct Compare {
217     bool operator()(const SmallVector<PrototypeDescriptor> &A,
218                     const SmallVector<PrototypeDescriptor> &B) const {
219       if (A.size() != B.size())
220         return A.size() > B.size();
221 
222       size_t Len = A.size();
223       for (size_t i = 0; i < Len; ++i) {
224         if (A[i] != B[i])
225           return A[i] < B[i];
226       }
227 
228       return false;
229     }
230   };
231 
232   std::set<SmallVector<PrototypeDescriptor>, Compare> Signatures;
233   auto InsertToSignatureSet =
234       [&](const SmallVector<PrototypeDescriptor> &Signature) {
235         if (Signature.empty())
236           return;
237 
238         Signatures.insert(Signature);
239       };
240 
241   assert(!SemaRecords.empty());
242 
243   llvm::for_each(SemaRecords, [&](const SemaRecord &SR) {
244     InsertToSignatureSet(SR.Prototype);
245     InsertToSignatureSet(SR.Suffix);
246     InsertToSignatureSet(SR.OverloadedSuffix);
247   });
248 
249   llvm::for_each(Signatures, [this](auto &Sig) { insert(Sig); });
250 }
251 
252 void SemaSignatureTable::insert(ArrayRef<PrototypeDescriptor> Signature) {
253   if (getIndex(Signature) != INVALID_INDEX)
254     return;
255 
256   // Insert Signature into SignatureTable if not found in the table.
257   SignatureTable.insert(SignatureTable.begin(), Signature.begin(),
258                         Signature.end());
259 }
260 
261 unsigned SemaSignatureTable::getIndex(ArrayRef<PrototypeDescriptor> Signature) {
262   // Empty signature could be point into any index since there is length
263   // field when we use, so just always point it to 0.
264   if (Signature.empty())
265     return 0;
266 
267   // Checking Signature already in table or not.
268   if (Signature.size() < SignatureTable.size()) {
269     size_t Bound = SignatureTable.size() - Signature.size() + 1;
270     for (size_t Index = 0; Index < Bound; ++Index) {
271       if (equal(Signature.begin(), Signature.end(),
272                 SignatureTable.begin() + Index))
273         return Index;
274     }
275   }
276 
277   return INVALID_INDEX;
278 }
279 
280 void SemaSignatureTable::print(raw_ostream &OS) {
281   for (const auto &Sig : SignatureTable)
282     OS << "PrototypeDescriptor(" << static_cast<int>(Sig.PT) << ", "
283        << static_cast<int>(Sig.VTM) << ", " << static_cast<int>(Sig.TM)
284        << "),\n";
285 }
286 
287 //===----------------------------------------------------------------------===//
288 // RVVEmitter implementation
289 //===----------------------------------------------------------------------===//
290 void RVVEmitter::createHeader(raw_ostream &OS) {
291 
292   OS << "/*===---- riscv_vector.h - RISC-V V-extension RVVIntrinsics "
293         "-------------------===\n"
294         " *\n"
295         " *\n"
296         " * Part of the LLVM Project, under the Apache License v2.0 with LLVM "
297         "Exceptions.\n"
298         " * See https://llvm.org/LICENSE.txt for license information.\n"
299         " * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n"
300         " *\n"
301         " *===-----------------------------------------------------------------"
302         "------===\n"
303         " */\n\n";
304 
305   OS << "#ifndef __RISCV_VECTOR_H\n";
306   OS << "#define __RISCV_VECTOR_H\n\n";
307 
308   OS << "#include <stdint.h>\n";
309   OS << "#include <stddef.h>\n\n";
310 
311   OS << "#ifndef __riscv_vector\n";
312   OS << "#error \"Vector intrinsics require the vector extension.\"\n";
313   OS << "#endif\n\n";
314 
315   OS << "#ifdef __cplusplus\n";
316   OS << "extern \"C\" {\n";
317   OS << "#endif\n\n";
318 
319   OS << "#pragma clang riscv intrinsic vector\n\n";
320 
321   printHeaderCode(OS);
322 
323   auto printType = [&](auto T) {
324     OS << "typedef " << T->getClangBuiltinStr() << " " << T->getTypeStr()
325        << ";\n";
326   };
327 
328   constexpr int Log2LMULs[] = {-3, -2, -1, 0, 1, 2, 3};
329   // Print RVV boolean types.
330   for (int Log2LMUL : Log2LMULs) {
331     auto T = RVVType::computeType(BasicType::Int8, Log2LMUL,
332                                   PrototypeDescriptor::Mask);
333     if (T)
334       printType(T.value());
335   }
336   // Print RVV int/float types.
337   for (char I : StringRef("csil")) {
338     BasicType BT = ParseBasicType(I);
339     for (int Log2LMUL : Log2LMULs) {
340       auto T = RVVType::computeType(BT, Log2LMUL, PrototypeDescriptor::Vector);
341       if (T) {
342         printType(T.value());
343         auto UT = RVVType::computeType(
344             BT, Log2LMUL,
345             PrototypeDescriptor(BaseTypeModifier::Vector,
346                                 VectorTypeModifier::NoModifier,
347                                 TypeModifier::UnsignedInteger));
348         printType(UT.value());
349       }
350     }
351   }
352   OS << "#if defined(__riscv_zvfh)\n";
353   for (int Log2LMUL : Log2LMULs) {
354     auto T = RVVType::computeType(BasicType::Float16, Log2LMUL,
355                                   PrototypeDescriptor::Vector);
356     if (T)
357       printType(T.value());
358   }
359   OS << "#endif\n";
360 
361   OS << "#if (__riscv_v_elen_fp >= 32)\n";
362   for (int Log2LMUL : Log2LMULs) {
363     auto T = RVVType::computeType(BasicType::Float32, Log2LMUL,
364                                   PrototypeDescriptor::Vector);
365     if (T)
366       printType(T.value());
367   }
368   OS << "#endif\n";
369 
370   OS << "#if (__riscv_v_elen_fp >= 64)\n";
371   for (int Log2LMUL : Log2LMULs) {
372     auto T = RVVType::computeType(BasicType::Float64, Log2LMUL,
373                                   PrototypeDescriptor::Vector);
374     if (T)
375       printType(T.value());
376   }
377   OS << "#endif\n\n";
378 
379   OS << "#define __riscv_v_intrinsic_overloading 1\n";
380 
381   OS << "\n#ifdef __cplusplus\n";
382   OS << "}\n";
383   OS << "#endif // __cplusplus\n";
384   OS << "#endif // __RISCV_VECTOR_H\n";
385 }
386 
387 void RVVEmitter::createBuiltins(raw_ostream &OS) {
388   std::vector<std::unique_ptr<RVVIntrinsic>> Defs;
389   createRVVIntrinsics(Defs);
390 
391   // Map to keep track of which builtin names have already been emitted.
392   StringMap<RVVIntrinsic *> BuiltinMap;
393 
394   OS << "#if defined(TARGET_BUILTIN) && !defined(RISCVV_BUILTIN)\n";
395   OS << "#define RISCVV_BUILTIN(ID, TYPE, ATTRS) TARGET_BUILTIN(ID, TYPE, "
396         "ATTRS, \"zve32x\")\n";
397   OS << "#endif\n";
398   for (auto &Def : Defs) {
399     auto P =
400         BuiltinMap.insert(std::make_pair(Def->getBuiltinName(), Def.get()));
401     if (!P.second) {
402       // Verf that this would have produced the same builtin definition.
403       if (P.first->second->hasBuiltinAlias() != Def->hasBuiltinAlias())
404         PrintFatalError("Builtin with same name has different hasAutoDef");
405       else if (!Def->hasBuiltinAlias() &&
406                P.first->second->getBuiltinTypeStr() != Def->getBuiltinTypeStr())
407         PrintFatalError("Builtin with same name has different type string");
408       continue;
409     }
410     OS << "RISCVV_BUILTIN(__builtin_rvv_" << Def->getBuiltinName() << ",\"";
411     if (!Def->hasBuiltinAlias())
412       OS << Def->getBuiltinTypeStr();
413     OS << "\", \"n\")\n";
414   }
415   OS << "#undef RISCVV_BUILTIN\n";
416 }
417 
418 void RVVEmitter::createCodeGen(raw_ostream &OS) {
419   std::vector<std::unique_ptr<RVVIntrinsic>> Defs;
420   createRVVIntrinsics(Defs);
421   // IR name could be empty, use the stable sort preserves the relative order.
422   llvm::stable_sort(Defs, [](const std::unique_ptr<RVVIntrinsic> &A,
423                              const std::unique_ptr<RVVIntrinsic> &B) {
424     return A->getIRName() < B->getIRName();
425   });
426 
427   // Map to keep track of which builtin names have already been emitted.
428   StringMap<RVVIntrinsic *> BuiltinMap;
429 
430   // Print switch body when the ir name or ManualCodegen changes from previous
431   // iteration.
432   RVVIntrinsic *PrevDef = Defs.begin()->get();
433   for (auto &Def : Defs) {
434     StringRef CurIRName = Def->getIRName();
435     if (CurIRName != PrevDef->getIRName() ||
436         (Def->getManualCodegen() != PrevDef->getManualCodegen())) {
437       emitCodeGenSwitchBody(PrevDef, OS);
438     }
439     PrevDef = Def.get();
440 
441     auto P =
442         BuiltinMap.insert(std::make_pair(Def->getBuiltinName(), Def.get()));
443     if (P.second) {
444       OS << "case RISCVVector::BI__builtin_rvv_" << Def->getBuiltinName()
445          << ":\n";
446       continue;
447     }
448 
449     if (P.first->second->getIRName() != Def->getIRName())
450       PrintFatalError("Builtin with same name has different IRName");
451     else if (P.first->second->getManualCodegen() != Def->getManualCodegen())
452       PrintFatalError("Builtin with same name has different ManualCodegen");
453     else if (P.first->second->getNF() != Def->getNF())
454       PrintFatalError("Builtin with same name has different NF");
455     else if (P.first->second->isMasked() != Def->isMasked())
456       PrintFatalError("Builtin with same name has different isMasked");
457     else if (P.first->second->hasVL() != Def->hasVL())
458       PrintFatalError("Builtin with same name has different hasVL");
459     else if (P.first->second->getPolicyScheme() != Def->getPolicyScheme())
460       PrintFatalError("Builtin with same name has different getPolicyScheme");
461     else if (P.first->second->getIntrinsicTypes() != Def->getIntrinsicTypes())
462       PrintFatalError("Builtin with same name has different IntrinsicTypes");
463   }
464   emitCodeGenSwitchBody(Defs.back().get(), OS);
465   OS << "\n";
466 }
467 
468 void RVVEmitter::createRVVIntrinsics(
469     std::vector<std::unique_ptr<RVVIntrinsic>> &Out,
470     std::vector<SemaRecord> *SemaRecords) {
471   std::vector<Record *> RV = Records.getAllDerivedDefinitions("RVVBuiltin");
472   for (auto *R : RV) {
473     StringRef Name = R->getValueAsString("Name");
474     StringRef SuffixProto = R->getValueAsString("Suffix");
475     StringRef OverloadedName = R->getValueAsString("OverloadedName");
476     StringRef OverloadedSuffixProto = R->getValueAsString("OverloadedSuffix");
477     StringRef Prototypes = R->getValueAsString("Prototype");
478     StringRef TypeRange = R->getValueAsString("TypeRange");
479     bool HasMasked = R->getValueAsBit("HasMasked");
480     bool HasMaskedOffOperand = R->getValueAsBit("HasMaskedOffOperand");
481     bool HasVL = R->getValueAsBit("HasVL");
482     Record *MPSRecord = R->getValueAsDef("MaskedPolicyScheme");
483     auto MaskedPolicyScheme =
484         static_cast<PolicyScheme>(MPSRecord->getValueAsInt("Value"));
485     Record *UMPSRecord = R->getValueAsDef("UnMaskedPolicyScheme");
486     auto UnMaskedPolicyScheme =
487         static_cast<PolicyScheme>(UMPSRecord->getValueAsInt("Value"));
488     bool HasUnMaskedOverloaded = R->getValueAsBit("HasUnMaskedOverloaded");
489     std::vector<int64_t> Log2LMULList = R->getValueAsListOfInts("Log2LMUL");
490     bool HasBuiltinAlias = R->getValueAsBit("HasBuiltinAlias");
491     StringRef ManualCodegen = R->getValueAsString("ManualCodegen");
492     StringRef MaskedManualCodegen = R->getValueAsString("MaskedManualCodegen");
493     std::vector<int64_t> IntrinsicTypes =
494         R->getValueAsListOfInts("IntrinsicTypes");
495     std::vector<StringRef> RequiredFeatures =
496         R->getValueAsListOfStrings("RequiredFeatures");
497     StringRef IRName = R->getValueAsString("IRName");
498     StringRef MaskedIRName = R->getValueAsString("MaskedIRName");
499     unsigned NF = R->getValueAsInt("NF");
500 
501     // Parse prototype and create a list of primitive type with transformers
502     // (operand) in Prototype. Prototype[0] is output operand.
503     SmallVector<PrototypeDescriptor> BasicPrototype =
504         parsePrototypes(Prototypes);
505 
506     SmallVector<PrototypeDescriptor> SuffixDesc = parsePrototypes(SuffixProto);
507     SmallVector<PrototypeDescriptor> OverloadedSuffixDesc =
508         parsePrototypes(OverloadedSuffixProto);
509 
510     // Compute Builtin types
511     auto Prototype = RVVIntrinsic::computeBuiltinTypes(
512         BasicPrototype, /*IsMasked=*/false, /*HasMaskedOffOperand=*/false,
513         HasVL, NF);
514     auto MaskedPrototype = RVVIntrinsic::computeBuiltinTypes(
515         BasicPrototype, /*IsMasked=*/true, HasMaskedOffOperand, HasVL, NF);
516 
517     // Create Intrinsics for each type and LMUL.
518     for (char I : TypeRange) {
519       for (int Log2LMUL : Log2LMULList) {
520         BasicType BT = ParseBasicType(I);
521         Optional<RVVTypes> Types =
522             RVVType::computeTypes(BT, Log2LMUL, NF, Prototype);
523         // Ignored to create new intrinsic if there are any illegal types.
524         if (!Types)
525           continue;
526 
527         auto SuffixStr = RVVIntrinsic::getSuffixStr(BT, Log2LMUL, SuffixDesc);
528         auto OverloadedSuffixStr =
529             RVVIntrinsic::getSuffixStr(BT, Log2LMUL, OverloadedSuffixDesc);
530         // Create a unmasked intrinsic
531         Out.push_back(std::make_unique<RVVIntrinsic>(
532             Name, SuffixStr, OverloadedName, OverloadedSuffixStr, IRName,
533             /*IsMasked=*/false, /*HasMaskedOffOperand=*/false, HasVL,
534             UnMaskedPolicyScheme, HasUnMaskedOverloaded, HasBuiltinAlias,
535             ManualCodegen, *Types, IntrinsicTypes, RequiredFeatures, NF));
536         if (HasMasked) {
537           // Create a masked intrinsic
538           Optional<RVVTypes> MaskTypes =
539               RVVType::computeTypes(BT, Log2LMUL, NF, MaskedPrototype);
540           Out.push_back(std::make_unique<RVVIntrinsic>(
541               Name, SuffixStr, OverloadedName, OverloadedSuffixStr,
542               MaskedIRName,
543               /*IsMasked=*/true, HasMaskedOffOperand, HasVL, MaskedPolicyScheme,
544               HasUnMaskedOverloaded, HasBuiltinAlias, MaskedManualCodegen,
545               *MaskTypes, IntrinsicTypes, RequiredFeatures, NF));
546         }
547       } // end for Log2LMULList
548     }   // end for TypeRange
549 
550     // We don't emit vsetvli and vsetvlimax for SemaRecord.
551     // They are written in riscv_vector.td and will emit those marco define in
552     // riscv_vector.h
553     if (Name == "vsetvli" || Name == "vsetvlimax")
554       continue;
555 
556     if (!SemaRecords)
557       continue;
558 
559     // Create SemaRecord
560     SemaRecord SR;
561     SR.Name = Name.str();
562     SR.OverloadedName = OverloadedName.str();
563     BasicType TypeRangeMask = BasicType::Unknown;
564     for (char I : TypeRange)
565       TypeRangeMask |= ParseBasicType(I);
566 
567     SR.TypeRangeMask = static_cast<unsigned>(TypeRangeMask);
568 
569     unsigned Log2LMULMask = 0;
570     for (int Log2LMUL : Log2LMULList)
571       Log2LMULMask |= 1 << (Log2LMUL + 3);
572 
573     SR.Log2LMULMask = Log2LMULMask;
574 
575     SR.RequiredExtensions = 0;
576     for (auto RequiredFeature : RequiredFeatures) {
577       RVVRequire RequireExt = StringSwitch<RVVRequire>(RequiredFeature)
578                                   .Case("RV64", RVV_REQ_RV64)
579                                   .Case("FullMultiply", RVV_REQ_FullMultiply)
580                                   .Default(RVV_REQ_None);
581       assert(RequireExt != RVV_REQ_None && "Unrecognized required feature?");
582       SR.RequiredExtensions |= RequireExt;
583     }
584 
585     SR.NF = NF;
586     SR.HasMasked = HasMasked;
587     SR.HasVL = HasVL;
588     SR.HasMaskedOffOperand = HasMaskedOffOperand;
589     SR.Prototype = std::move(BasicPrototype);
590     SR.Suffix = parsePrototypes(SuffixProto);
591     SR.OverloadedSuffix = parsePrototypes(OverloadedSuffixProto);
592 
593     SemaRecords->push_back(SR);
594   }
595 }
596 
597 void RVVEmitter::printHeaderCode(raw_ostream &OS) {
598   std::vector<Record *> RVVHeaders =
599       Records.getAllDerivedDefinitions("RVVHeader");
600   for (auto *R : RVVHeaders) {
601     StringRef HeaderCodeStr = R->getValueAsString("HeaderCode");
602     OS << HeaderCodeStr.str();
603   }
604 }
605 
606 void RVVEmitter::createRVVIntrinsicRecords(std::vector<RVVIntrinsicRecord> &Out,
607                                            SemaSignatureTable &SST,
608                                            ArrayRef<SemaRecord> SemaRecords) {
609   SST.init(SemaRecords);
610 
611   for (const auto &SR : SemaRecords) {
612     Out.emplace_back(RVVIntrinsicRecord());
613     RVVIntrinsicRecord &R = Out.back();
614     R.Name = SR.Name.c_str();
615     R.OverloadedName = SR.OverloadedName.c_str();
616     R.PrototypeIndex = SST.getIndex(SR.Prototype);
617     R.SuffixIndex = SST.getIndex(SR.Suffix);
618     R.OverloadedSuffixIndex = SST.getIndex(SR.OverloadedSuffix);
619     R.PrototypeLength = SR.Prototype.size();
620     R.SuffixLength = SR.Suffix.size();
621     R.OverloadedSuffixSize = SR.OverloadedSuffix.size();
622     R.RequiredExtensions = SR.RequiredExtensions;
623     R.TypeRangeMask = SR.TypeRangeMask;
624     R.Log2LMULMask = SR.Log2LMULMask;
625     R.NF = SR.NF;
626     R.HasMasked = SR.HasMasked;
627     R.HasVL = SR.HasVL;
628     R.HasMaskedOffOperand = SR.HasMaskedOffOperand;
629 
630     assert(R.PrototypeIndex !=
631            static_cast<uint16_t>(SemaSignatureTable::INVALID_INDEX));
632     assert(R.SuffixIndex !=
633            static_cast<uint16_t>(SemaSignatureTable::INVALID_INDEX));
634     assert(R.OverloadedSuffixIndex !=
635            static_cast<uint16_t>(SemaSignatureTable::INVALID_INDEX));
636   }
637 }
638 
639 void RVVEmitter::createSema(raw_ostream &OS) {
640   std::vector<std::unique_ptr<RVVIntrinsic>> Defs;
641   std::vector<RVVIntrinsicRecord> RVVIntrinsicRecords;
642   SemaSignatureTable SST;
643   std::vector<SemaRecord> SemaRecords;
644 
645   createRVVIntrinsics(Defs, &SemaRecords);
646 
647   createRVVIntrinsicRecords(RVVIntrinsicRecords, SST, SemaRecords);
648 
649   // Emit signature table for SemaRISCVVectorLookup.cpp.
650   OS << "#ifdef DECL_SIGNATURE_TABLE\n";
651   SST.print(OS);
652   OS << "#endif\n";
653 
654   // Emit RVVIntrinsicRecords for SemaRISCVVectorLookup.cpp.
655   OS << "#ifdef DECL_INTRINSIC_RECORDS\n";
656   for (const RVVIntrinsicRecord &Record : RVVIntrinsicRecords)
657     OS << Record;
658   OS << "#endif\n";
659 }
660 
661 namespace clang {
662 void EmitRVVHeader(RecordKeeper &Records, raw_ostream &OS) {
663   RVVEmitter(Records).createHeader(OS);
664 }
665 
666 void EmitRVVBuiltins(RecordKeeper &Records, raw_ostream &OS) {
667   RVVEmitter(Records).createBuiltins(OS);
668 }
669 
670 void EmitRVVBuiltinCG(RecordKeeper &Records, raw_ostream &OS) {
671   RVVEmitter(Records).createCodeGen(OS);
672 }
673 
674 void EmitRVVBuiltinSema(RecordKeeper &Records, raw_ostream &OS) {
675   RVVEmitter(Records).createSema(OS);
676 }
677 
678 } // End namespace clang
679