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