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/Twine.h"
24 #include "llvm/TableGen/Error.h"
25 #include "llvm/TableGen/Record.h"
26 #include <numeric>
27 
28 using namespace llvm;
29 using namespace clang::RISCV;
30 
31 namespace {
32 class RVVEmitter {
33 private:
34   RecordKeeper &Records;
35 
36 public:
37   RVVEmitter(RecordKeeper &R) : Records(R) {}
38 
39   /// Emit riscv_vector.h
40   void createHeader(raw_ostream &o);
41 
42   /// Emit all the __builtin prototypes and code needed by Sema.
43   void createBuiltins(raw_ostream &o);
44 
45   /// Emit all the information needed to map builtin -> LLVM IR intrinsic.
46   void createCodeGen(raw_ostream &o);
47 
48 private:
49   /// Create all intrinsics and add them to \p Out
50   void createRVVIntrinsics(std::vector<std::unique_ptr<RVVIntrinsic>> &Out);
51   /// Print HeaderCode in RVVHeader Record to \p Out
52   void printHeaderCode(raw_ostream &OS);
53 
54   /// Emit Acrh predecessor definitions and body, assume the element of Defs are
55   /// sorted by extension.
56   void emitArchMacroAndBody(
57       std::vector<std::unique_ptr<RVVIntrinsic>> &Defs, raw_ostream &o,
58       std::function<void(raw_ostream &, const RVVIntrinsic &)>);
59 
60   // Emit the architecture preprocessor definitions. Return true when emits
61   // non-empty string.
62   bool emitMacroRestrictionStr(RISCVPredefinedMacroT PredefinedMacros,
63                                raw_ostream &o);
64 };
65 
66 } // namespace
67 
68 static BasicType ParseBasicType(char c) {
69   switch (c) {
70   case 'c':
71     return BasicType::Int8;
72     break;
73   case 's':
74     return BasicType::Int16;
75     break;
76   case 'i':
77     return BasicType::Int32;
78     break;
79   case 'l':
80     return BasicType::Int64;
81     break;
82   case 'x':
83     return BasicType::Float16;
84     break;
85   case 'f':
86     return BasicType::Float32;
87     break;
88   case 'd':
89     return BasicType::Float64;
90     break;
91 
92   default:
93     return BasicType::Unknown;
94   }
95 }
96 
97 void emitCodeGenSwitchBody(const RVVIntrinsic *RVVI, raw_ostream &OS) {
98   if (!RVVI->getIRName().empty())
99     OS << "  ID = Intrinsic::riscv_" + RVVI->getIRName() + ";\n";
100   if (RVVI->getNF() >= 2)
101     OS << "  NF = " + utostr(RVVI->getNF()) + ";\n";
102   if (RVVI->hasManualCodegen()) {
103     OS << RVVI->getManualCodegen();
104     OS << "break;\n";
105     return;
106   }
107 
108   // Cast pointer operand of vector load intrinsic.
109   for (const auto &I : enumerate(RVVI->getInputTypes())) {
110     if (I.value()->isPointer()) {
111       assert(RVVI->getIntrinsicTypes().front() == -1 &&
112              "RVVI should be vector load intrinsic.");
113       OS << "  Ops[" << I.index() << "] = Builder.CreateBitCast(Ops[";
114       OS << I.index() << "], ResultType->getPointerTo());\n";
115     }
116   }
117 
118   if (RVVI->isMasked()) {
119     if (RVVI->hasVL()) {
120       OS << "  std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1);\n";
121       if (RVVI->hasPolicyOperand())
122         OS << "  Ops.push_back(ConstantInt::get(Ops.back()->getType(),"
123               " TAIL_UNDISTURBED));\n";
124     } else {
125       OS << "  std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end());\n";
126     }
127   } else {
128     if (RVVI->hasPolicyOperand())
129       OS << "  Ops.push_back(ConstantInt::get(Ops.back()->getType(), "
130             "TAIL_UNDISTURBED));\n";
131     else if (RVVI->hasPassthruOperand()) {
132       OS << "  Ops.push_back(llvm::UndefValue::get(ResultType));\n";
133       OS << "  std::rotate(Ops.rbegin(), Ops.rbegin() + 1,  Ops.rend());\n";
134     }
135   }
136 
137   OS << "  IntrinsicTypes = {";
138   ListSeparator LS;
139   for (const auto &Idx : RVVI->getIntrinsicTypes()) {
140     if (Idx == -1)
141       OS << LS << "ResultType";
142     else
143       OS << LS << "Ops[" << Idx << "]->getType()";
144   }
145 
146   // VL could be i64 or i32, need to encode it in IntrinsicTypes. VL is
147   // always last operand.
148   if (RVVI->hasVL())
149     OS << ", Ops.back()->getType()";
150   OS << "};\n";
151   OS << "  break;\n";
152 }
153 
154 void emitIntrinsicFuncDef(const RVVIntrinsic &RVVI, raw_ostream &OS) {
155   OS << "__attribute__((__clang_builtin_alias__(";
156   OS << "__builtin_rvv_" << RVVI.getBuiltinName() << ")))\n";
157   OS << RVVI.getOutputType()->getTypeStr() << " " << RVVI.getName() << "(";
158   // Emit function arguments
159   const RVVTypes &InputTypes = RVVI.getInputTypes();
160   if (!InputTypes.empty()) {
161     ListSeparator LS;
162     for (unsigned i = 0; i < InputTypes.size(); ++i)
163       OS << LS << InputTypes[i]->getTypeStr();
164   }
165   OS << ");\n";
166 }
167 
168 void emitOverloadedFuncDef(const RVVIntrinsic &RVVI, raw_ostream &OS) {
169   OS << "__attribute__((__clang_builtin_alias__(";
170   OS << "__builtin_rvv_" << RVVI.getBuiltinName() << ")))\n";
171   OS << RVVI.getOutputType()->getTypeStr() << " " << RVVI.getOverloadedName()
172      << "(";
173   // Emit function arguments
174   const RVVTypes &InputTypes = RVVI.getInputTypes();
175   if (!InputTypes.empty()) {
176     ListSeparator LS;
177     for (unsigned i = 0; i < InputTypes.size(); ++i)
178       OS << LS << InputTypes[i]->getTypeStr();
179   }
180   OS << ");\n";
181 }
182 
183 //===----------------------------------------------------------------------===//
184 // RVVEmitter implementation
185 //===----------------------------------------------------------------------===//
186 void RVVEmitter::createHeader(raw_ostream &OS) {
187 
188   OS << "/*===---- riscv_vector.h - RISC-V V-extension RVVIntrinsics "
189         "-------------------===\n"
190         " *\n"
191         " *\n"
192         " * Part of the LLVM Project, under the Apache License v2.0 with LLVM "
193         "Exceptions.\n"
194         " * See https://llvm.org/LICENSE.txt for license information.\n"
195         " * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n"
196         " *\n"
197         " *===-----------------------------------------------------------------"
198         "------===\n"
199         " */\n\n";
200 
201   OS << "#ifndef __RISCV_VECTOR_H\n";
202   OS << "#define __RISCV_VECTOR_H\n\n";
203 
204   OS << "#include <stdint.h>\n";
205   OS << "#include <stddef.h>\n\n";
206 
207   OS << "#ifndef __riscv_vector\n";
208   OS << "#error \"Vector intrinsics require the vector extension.\"\n";
209   OS << "#endif\n\n";
210 
211   OS << "#ifdef __cplusplus\n";
212   OS << "extern \"C\" {\n";
213   OS << "#endif\n\n";
214 
215   printHeaderCode(OS);
216 
217   std::vector<std::unique_ptr<RVVIntrinsic>> Defs;
218   createRVVIntrinsics(Defs);
219 
220   auto printType = [&](auto T) {
221     OS << "typedef " << T->getClangBuiltinStr() << " " << T->getTypeStr()
222        << ";\n";
223   };
224 
225   constexpr int Log2LMULs[] = {-3, -2, -1, 0, 1, 2, 3};
226   // Print RVV boolean types.
227   for (int Log2LMUL : Log2LMULs) {
228     auto T = RVVType::computeType(BasicType::Int8, Log2LMUL,
229                                   PrototypeDescriptor::Mask);
230     if (T)
231       printType(T.getValue());
232   }
233   // Print RVV int/float types.
234   for (char I : StringRef("csil")) {
235     BasicType BT = ParseBasicType(I);
236     for (int Log2LMUL : Log2LMULs) {
237       auto T = RVVType::computeType(BT, Log2LMUL, PrototypeDescriptor::Vector);
238       if (T) {
239         printType(T.getValue());
240         auto UT = RVVType::computeType(
241             BT, Log2LMUL,
242             PrototypeDescriptor(BaseTypeModifier::Vector,
243                                 VectorTypeModifier::NoModifier,
244                                 TypeModifier::UnsignedInteger));
245         printType(UT.getValue());
246       }
247     }
248   }
249   OS << "#if defined(__riscv_zvfh)\n";
250   for (int Log2LMUL : Log2LMULs) {
251     auto T = RVVType::computeType(BasicType::Float16, Log2LMUL,
252                                   PrototypeDescriptor::Vector);
253     if (T)
254       printType(T.getValue());
255   }
256   OS << "#endif\n";
257 
258   OS << "#if defined(__riscv_f)\n";
259   for (int Log2LMUL : Log2LMULs) {
260     auto T = RVVType::computeType(BasicType::Float32, Log2LMUL,
261                                   PrototypeDescriptor::Vector);
262     if (T)
263       printType(T.getValue());
264   }
265   OS << "#endif\n";
266 
267   OS << "#if defined(__riscv_d)\n";
268   for (int Log2LMUL : Log2LMULs) {
269     auto T = RVVType::computeType(BasicType::Float64, Log2LMUL,
270                                   PrototypeDescriptor::Vector);
271     if (T)
272       printType(T.getValue());
273   }
274   OS << "#endif\n\n";
275 
276   // The same extension include in the same arch guard marco.
277   llvm::stable_sort(Defs, [](const std::unique_ptr<RVVIntrinsic> &A,
278                              const std::unique_ptr<RVVIntrinsic> &B) {
279     return A->getRISCVPredefinedMacros() < B->getRISCVPredefinedMacros();
280   });
281 
282   OS << "#define __rvv_ai static __inline__\n";
283 
284   // Print intrinsic functions with macro
285   emitArchMacroAndBody(Defs, OS, [](raw_ostream &OS, const RVVIntrinsic &Inst) {
286     OS << "__rvv_ai ";
287     emitIntrinsicFuncDef(Inst, OS);
288   });
289 
290   OS << "#undef __rvv_ai\n\n";
291 
292   OS << "#define __riscv_v_intrinsic_overloading 1\n";
293 
294   // Print Overloaded APIs
295   OS << "#define __rvv_aio static __inline__ "
296         "__attribute__((__overloadable__))\n";
297 
298   emitArchMacroAndBody(Defs, OS, [](raw_ostream &OS, const RVVIntrinsic &Inst) {
299     if (!Inst.isMasked() && !Inst.hasUnMaskedOverloaded())
300       return;
301     OS << "__rvv_aio ";
302     emitOverloadedFuncDef(Inst, OS);
303   });
304 
305   OS << "#undef __rvv_aio\n";
306 
307   OS << "\n#ifdef __cplusplus\n";
308   OS << "}\n";
309   OS << "#endif // __cplusplus\n";
310   OS << "#endif // __RISCV_VECTOR_H\n";
311 }
312 
313 void RVVEmitter::createBuiltins(raw_ostream &OS) {
314   std::vector<std::unique_ptr<RVVIntrinsic>> Defs;
315   createRVVIntrinsics(Defs);
316 
317   // Map to keep track of which builtin names have already been emitted.
318   StringMap<RVVIntrinsic *> BuiltinMap;
319 
320   OS << "#if defined(TARGET_BUILTIN) && !defined(RISCVV_BUILTIN)\n";
321   OS << "#define RISCVV_BUILTIN(ID, TYPE, ATTRS) TARGET_BUILTIN(ID, TYPE, "
322         "ATTRS, \"zve32x\")\n";
323   OS << "#endif\n";
324   for (auto &Def : Defs) {
325     auto P =
326         BuiltinMap.insert(std::make_pair(Def->getBuiltinName(), Def.get()));
327     if (!P.second) {
328       // Verf that this would have produced the same builtin definition.
329       if (P.first->second->hasBuiltinAlias() != Def->hasBuiltinAlias())
330         PrintFatalError("Builtin with same name has different hasAutoDef");
331       else if (!Def->hasBuiltinAlias() &&
332                P.first->second->getBuiltinTypeStr() != Def->getBuiltinTypeStr())
333         PrintFatalError("Builtin with same name has different type string");
334       continue;
335     }
336     OS << "RISCVV_BUILTIN(__builtin_rvv_" << Def->getBuiltinName() << ",\"";
337     if (!Def->hasBuiltinAlias())
338       OS << Def->getBuiltinTypeStr();
339     OS << "\", \"n\")\n";
340   }
341   OS << "#undef RISCVV_BUILTIN\n";
342 }
343 
344 void RVVEmitter::createCodeGen(raw_ostream &OS) {
345   std::vector<std::unique_ptr<RVVIntrinsic>> Defs;
346   createRVVIntrinsics(Defs);
347   // IR name could be empty, use the stable sort preserves the relative order.
348   llvm::stable_sort(Defs, [](const std::unique_ptr<RVVIntrinsic> &A,
349                              const std::unique_ptr<RVVIntrinsic> &B) {
350     return A->getIRName() < B->getIRName();
351   });
352 
353   // Map to keep track of which builtin names have already been emitted.
354   StringMap<RVVIntrinsic *> BuiltinMap;
355 
356   // Print switch body when the ir name or ManualCodegen changes from previous
357   // iteration.
358   RVVIntrinsic *PrevDef = Defs.begin()->get();
359   for (auto &Def : Defs) {
360     StringRef CurIRName = Def->getIRName();
361     if (CurIRName != PrevDef->getIRName() ||
362         (Def->getManualCodegen() != PrevDef->getManualCodegen())) {
363       emitCodeGenSwitchBody(PrevDef, OS);
364     }
365     PrevDef = Def.get();
366 
367     auto P =
368         BuiltinMap.insert(std::make_pair(Def->getBuiltinName(), Def.get()));
369     if (P.second) {
370       OS << "case RISCVVector::BI__builtin_rvv_" << Def->getBuiltinName()
371          << ":\n";
372       continue;
373     }
374 
375     if (P.first->second->getIRName() != Def->getIRName())
376       PrintFatalError("Builtin with same name has different IRName");
377     else if (P.first->second->getManualCodegen() != Def->getManualCodegen())
378       PrintFatalError("Builtin with same name has different ManualCodegen");
379     else if (P.first->second->getNF() != Def->getNF())
380       PrintFatalError("Builtin with same name has different NF");
381     else if (P.first->second->isMasked() != Def->isMasked())
382       PrintFatalError("Builtin with same name has different isMasked");
383     else if (P.first->second->hasVL() != Def->hasVL())
384       PrintFatalError("Builtin with same name has different hasVL");
385     else if (P.first->second->getPolicyScheme() != Def->getPolicyScheme())
386       PrintFatalError("Builtin with same name has different getPolicyScheme");
387     else if (P.first->second->getIntrinsicTypes() != Def->getIntrinsicTypes())
388       PrintFatalError("Builtin with same name has different IntrinsicTypes");
389   }
390   emitCodeGenSwitchBody(Defs.back().get(), OS);
391   OS << "\n";
392 }
393 
394 void RVVEmitter::createRVVIntrinsics(
395     std::vector<std::unique_ptr<RVVIntrinsic>> &Out) {
396   std::vector<Record *> RV = Records.getAllDerivedDefinitions("RVVBuiltin");
397   for (auto *R : RV) {
398     StringRef Name = R->getValueAsString("Name");
399     StringRef SuffixProto = R->getValueAsString("Suffix");
400     StringRef OverloadedName = R->getValueAsString("OverloadedName");
401     StringRef OverloadedSuffixProto = R->getValueAsString("OverloadedSuffix");
402     StringRef Prototypes = R->getValueAsString("Prototype");
403     StringRef TypeRange = R->getValueAsString("TypeRange");
404     bool HasMasked = R->getValueAsBit("HasMasked");
405     bool HasMaskedOffOperand = R->getValueAsBit("HasMaskedOffOperand");
406     bool HasVL = R->getValueAsBit("HasVL");
407     Record *MaskedPolicyRecord = R->getValueAsDef("MaskedPolicy");
408     PolicyScheme MaskedPolicy =
409         static_cast<PolicyScheme>(MaskedPolicyRecord->getValueAsInt("Value"));
410     Record *UnMaskedPolicyRecord = R->getValueAsDef("UnMaskedPolicy");
411     PolicyScheme UnMaskedPolicy =
412         static_cast<PolicyScheme>(UnMaskedPolicyRecord->getValueAsInt("Value"));
413     bool HasUnMaskedOverloaded = R->getValueAsBit("HasUnMaskedOverloaded");
414     std::vector<int64_t> Log2LMULList = R->getValueAsListOfInts("Log2LMUL");
415     bool HasBuiltinAlias = R->getValueAsBit("HasBuiltinAlias");
416     StringRef ManualCodegen = R->getValueAsString("ManualCodegen");
417     StringRef MaskedManualCodegen = R->getValueAsString("MaskedManualCodegen");
418     std::vector<int64_t> IntrinsicTypes =
419         R->getValueAsListOfInts("IntrinsicTypes");
420     std::vector<StringRef> RequiredFeatures =
421         R->getValueAsListOfStrings("RequiredFeatures");
422     StringRef IRName = R->getValueAsString("IRName");
423     StringRef MaskedIRName = R->getValueAsString("MaskedIRName");
424     unsigned NF = R->getValueAsInt("NF");
425 
426     // Parse prototype and create a list of primitive type with transformers
427     // (operand) in Prototype. Prototype[0] is output operand.
428     SmallVector<PrototypeDescriptor> Prototype = parsePrototypes(Prototypes);
429 
430     SmallVector<PrototypeDescriptor> SuffixDesc = parsePrototypes(SuffixProto);
431     SmallVector<PrototypeDescriptor> OverloadedSuffixDesc =
432         parsePrototypes(OverloadedSuffixProto);
433 
434     // Compute Builtin types
435     SmallVector<PrototypeDescriptor> MaskedPrototype = Prototype;
436     if (HasMasked) {
437       // If HasMaskedOffOperand, insert result type as first input operand.
438       if (HasMaskedOffOperand) {
439         if (NF == 1) {
440           MaskedPrototype.insert(MaskedPrototype.begin() + 1, Prototype[0]);
441         } else {
442           // Convert
443           // (void, op0 address, op1 address, ...)
444           // to
445           // (void, op0 address, op1 address, ..., maskedoff0, maskedoff1, ...)
446           PrototypeDescriptor MaskoffType = Prototype[1];
447           MaskoffType.TM &= ~static_cast<uint8_t>(TypeModifier::Pointer);
448           for (unsigned I = 0; I < NF; ++I)
449             MaskedPrototype.insert(MaskedPrototype.begin() + NF + 1,
450                                    MaskoffType);
451         }
452       }
453       if (HasMaskedOffOperand && NF > 1) {
454         // Convert
455         // (void, op0 address, op1 address, ..., maskedoff0, maskedoff1, ...)
456         // to
457         // (void, op0 address, op1 address, ..., mask, maskedoff0, maskedoff1,
458         // ...)
459         MaskedPrototype.insert(MaskedPrototype.begin() + NF + 1,
460                                PrototypeDescriptor::Mask);
461       } else {
462         // If HasMasked, insert PrototypeDescriptor:Mask as first input operand.
463         MaskedPrototype.insert(MaskedPrototype.begin() + 1,
464                                PrototypeDescriptor::Mask);
465       }
466     }
467     // If HasVL, append PrototypeDescriptor:VL to last operand
468     if (HasVL) {
469       Prototype.push_back(PrototypeDescriptor::VL);
470       MaskedPrototype.push_back(PrototypeDescriptor::VL);
471     }
472 
473     // Create Intrinsics for each type and LMUL.
474     for (char I : TypeRange) {
475       for (int Log2LMUL : Log2LMULList) {
476         BasicType BT = ParseBasicType(I);
477         Optional<RVVTypes> Types =
478             RVVType::computeTypes(BT, Log2LMUL, NF, Prototype);
479         // Ignored to create new intrinsic if there are any illegal types.
480         if (!Types)
481           continue;
482 
483         auto SuffixStr = RVVIntrinsic::getSuffixStr(BT, Log2LMUL, SuffixDesc);
484         auto OverloadedSuffixStr =
485             RVVIntrinsic::getSuffixStr(BT, Log2LMUL, OverloadedSuffixDesc);
486         // Create a unmasked intrinsic
487         Out.push_back(std::make_unique<RVVIntrinsic>(
488             Name, SuffixStr, OverloadedName, OverloadedSuffixStr, IRName,
489             /*IsMasked=*/false, /*HasMaskedOffOperand=*/false, HasVL,
490             UnMaskedPolicy, HasUnMaskedOverloaded, HasBuiltinAlias,
491             ManualCodegen, *Types, IntrinsicTypes, RequiredFeatures, NF));
492         if (HasMasked) {
493           // Create a masked intrinsic
494           Optional<RVVTypes> MaskTypes =
495               RVVType::computeTypes(BT, Log2LMUL, NF, MaskedPrototype);
496           Out.push_back(std::make_unique<RVVIntrinsic>(
497               Name, SuffixStr, OverloadedName, OverloadedSuffixStr,
498               MaskedIRName,
499               /*IsMasked=*/true, HasMaskedOffOperand, HasVL, MaskedPolicy,
500               HasUnMaskedOverloaded, HasBuiltinAlias, MaskedManualCodegen,
501               *MaskTypes, IntrinsicTypes, RequiredFeatures, NF));
502         }
503       } // end for Log2LMULList
504     }   // end for TypeRange
505   }
506 }
507 
508 void RVVEmitter::printHeaderCode(raw_ostream &OS) {
509   std::vector<Record *> RVVHeaders =
510       Records.getAllDerivedDefinitions("RVVHeader");
511   for (auto *R : RVVHeaders) {
512     StringRef HeaderCodeStr = R->getValueAsString("HeaderCode");
513     OS << HeaderCodeStr.str();
514   }
515 }
516 
517 void RVVEmitter::emitArchMacroAndBody(
518     std::vector<std::unique_ptr<RVVIntrinsic>> &Defs, raw_ostream &OS,
519     std::function<void(raw_ostream &, const RVVIntrinsic &)> PrintBody) {
520   RISCVPredefinedMacroT PrevMacros =
521       (*Defs.begin())->getRISCVPredefinedMacros();
522   bool NeedEndif = emitMacroRestrictionStr(PrevMacros, OS);
523   for (auto &Def : Defs) {
524     RISCVPredefinedMacroT CurMacros = Def->getRISCVPredefinedMacros();
525     if (CurMacros != PrevMacros) {
526       if (NeedEndif)
527         OS << "#endif\n\n";
528       NeedEndif = emitMacroRestrictionStr(CurMacros, OS);
529       PrevMacros = CurMacros;
530     }
531     if (Def->hasBuiltinAlias())
532       PrintBody(OS, *Def);
533   }
534   if (NeedEndif)
535     OS << "#endif\n\n";
536 }
537 
538 bool RVVEmitter::emitMacroRestrictionStr(RISCVPredefinedMacroT PredefinedMacros,
539                                          raw_ostream &OS) {
540   if (PredefinedMacros == RISCVPredefinedMacro::Basic)
541     return false;
542   OS << "#if ";
543   ListSeparator LS(" && ");
544   if (PredefinedMacros & RISCVPredefinedMacro::V)
545     OS << LS << "defined(__riscv_v)";
546   if (PredefinedMacros & RISCVPredefinedMacro::Zvfh)
547     OS << LS << "defined(__riscv_zvfh)";
548   if (PredefinedMacros & RISCVPredefinedMacro::RV64)
549     OS << LS << "(__riscv_xlen == 64)";
550   if (PredefinedMacros & RISCVPredefinedMacro::VectorMaxELen64)
551     OS << LS << "(__riscv_v_elen >= 64)";
552   if (PredefinedMacros & RISCVPredefinedMacro::VectorMaxELenFp32)
553     OS << LS << "(__riscv_v_elen_fp >= 32)";
554   if (PredefinedMacros & RISCVPredefinedMacro::VectorMaxELenFp64)
555     OS << LS << "(__riscv_v_elen_fp >= 64)";
556   OS << "\n";
557   return true;
558 }
559 
560 namespace clang {
561 void EmitRVVHeader(RecordKeeper &Records, raw_ostream &OS) {
562   RVVEmitter(Records).createHeader(OS);
563 }
564 
565 void EmitRVVBuiltins(RecordKeeper &Records, raw_ostream &OS) {
566   RVVEmitter(Records).createBuiltins(OS);
567 }
568 
569 void EmitRVVBuiltinCG(RecordKeeper &Records, raw_ostream &OS) {
570   RVVEmitter(Records).createCodeGen(OS);
571 }
572 
573 } // End namespace clang
574