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