xref: /freebsd-src/contrib/llvm-project/clang/utils/TableGen/RISCVVEmitter.cpp (revision cb14a3fe5122c879eae1fb480ed7ce82a699ddb6)
1fe6060f1SDimitry Andric //===- RISCVVEmitter.cpp - Generate riscv_vector.h for use with clang -----===//
2fe6060f1SDimitry Andric //
3fe6060f1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4fe6060f1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5fe6060f1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6fe6060f1SDimitry Andric //
7fe6060f1SDimitry Andric //===----------------------------------------------------------------------===//
8fe6060f1SDimitry Andric //
9fe6060f1SDimitry Andric // This tablegen backend is responsible for emitting riscv_vector.h which
10fe6060f1SDimitry Andric // includes a declaration and definition of each intrinsic functions specified
11fe6060f1SDimitry Andric // in https://github.com/riscv/rvv-intrinsic-doc.
12fe6060f1SDimitry Andric //
13fe6060f1SDimitry Andric // See also the documentation in include/clang/Basic/riscv_vector.td.
14fe6060f1SDimitry Andric //
15fe6060f1SDimitry Andric //===----------------------------------------------------------------------===//
16fe6060f1SDimitry Andric 
1781ad6265SDimitry Andric #include "clang/Support/RISCVVIntrinsicUtils.h"
18fe6060f1SDimitry Andric #include "llvm/ADT/ArrayRef.h"
19fe6060f1SDimitry Andric #include "llvm/ADT/SmallSet.h"
20fe6060f1SDimitry Andric #include "llvm/ADT/StringExtras.h"
21fe6060f1SDimitry Andric #include "llvm/ADT/StringMap.h"
22fe6060f1SDimitry Andric #include "llvm/ADT/StringSet.h"
23972a253aSDimitry Andric #include "llvm/ADT/StringSwitch.h"
24fe6060f1SDimitry Andric #include "llvm/ADT/Twine.h"
25fe6060f1SDimitry Andric #include "llvm/TableGen/Error.h"
26fe6060f1SDimitry Andric #include "llvm/TableGen/Record.h"
27fe6060f1SDimitry Andric #include <numeric>
28bdd1243dSDimitry Andric #include <optional>
29fe6060f1SDimitry Andric 
30fe6060f1SDimitry Andric using namespace llvm;
3181ad6265SDimitry Andric using namespace clang::RISCV;
32fe6060f1SDimitry Andric 
33fe6060f1SDimitry Andric namespace {
34972a253aSDimitry Andric struct SemaRecord {
35972a253aSDimitry Andric   // Intrinsic name, e.g. vadd_vv
36972a253aSDimitry Andric   std::string Name;
37972a253aSDimitry Andric 
38972a253aSDimitry Andric   // Overloaded intrinsic name, could be empty if can be computed from Name
39972a253aSDimitry Andric   // e.g. vadd
40972a253aSDimitry Andric   std::string OverloadedName;
41972a253aSDimitry Andric 
42972a253aSDimitry Andric   // Supported type, mask of BasicType.
43972a253aSDimitry Andric   unsigned TypeRangeMask;
44972a253aSDimitry Andric 
45972a253aSDimitry Andric   // Supported LMUL.
46972a253aSDimitry Andric   unsigned Log2LMULMask;
47972a253aSDimitry Andric 
48972a253aSDimitry Andric   // Required extensions for this intrinsic.
49*cb14a3feSDimitry Andric   uint32_t RequiredExtensions;
50972a253aSDimitry Andric 
51972a253aSDimitry Andric   // Prototype for this intrinsic.
52972a253aSDimitry Andric   SmallVector<PrototypeDescriptor> Prototype;
53972a253aSDimitry Andric 
54972a253aSDimitry Andric   // Suffix of intrinsic name.
55972a253aSDimitry Andric   SmallVector<PrototypeDescriptor> Suffix;
56972a253aSDimitry Andric 
57972a253aSDimitry Andric   // Suffix of overloaded intrinsic name.
58972a253aSDimitry Andric   SmallVector<PrototypeDescriptor> OverloadedSuffix;
59972a253aSDimitry Andric 
60972a253aSDimitry Andric   // Number of field, large than 1 if it's segment load/store.
61972a253aSDimitry Andric   unsigned NF;
62972a253aSDimitry Andric 
63972a253aSDimitry Andric   bool HasMasked :1;
64972a253aSDimitry Andric   bool HasVL :1;
65972a253aSDimitry Andric   bool HasMaskedOffOperand :1;
66bdd1243dSDimitry Andric   bool HasTailPolicy : 1;
67bdd1243dSDimitry Andric   bool HasMaskPolicy : 1;
6806c3fb27SDimitry Andric   bool HasFRMRoundModeOp : 1;
6906c3fb27SDimitry Andric   bool IsTuple : 1;
70bdd1243dSDimitry Andric   uint8_t UnMaskedPolicyScheme : 2;
71bdd1243dSDimitry Andric   uint8_t MaskedPolicyScheme : 2;
72972a253aSDimitry Andric };
73972a253aSDimitry Andric 
74972a253aSDimitry Andric // Compressed function signature table.
75972a253aSDimitry Andric class SemaSignatureTable {
76972a253aSDimitry Andric private:
77972a253aSDimitry Andric   std::vector<PrototypeDescriptor> SignatureTable;
78972a253aSDimitry Andric 
79972a253aSDimitry Andric   void insert(ArrayRef<PrototypeDescriptor> Signature);
80972a253aSDimitry Andric 
81972a253aSDimitry Andric public:
82972a253aSDimitry Andric   static constexpr unsigned INVALID_INDEX = ~0U;
83972a253aSDimitry Andric 
84972a253aSDimitry Andric   // Create compressed signature table from SemaRecords.
85972a253aSDimitry Andric   void init(ArrayRef<SemaRecord> SemaRecords);
86972a253aSDimitry Andric 
87972a253aSDimitry Andric   // Query the Signature, return INVALID_INDEX if not found.
88972a253aSDimitry Andric   unsigned getIndex(ArrayRef<PrototypeDescriptor> Signature);
89972a253aSDimitry Andric 
90972a253aSDimitry Andric   /// Print signature table in RVVHeader Record to \p OS
91972a253aSDimitry Andric   void print(raw_ostream &OS);
92972a253aSDimitry Andric };
93972a253aSDimitry Andric 
94fe6060f1SDimitry Andric class RVVEmitter {
95fe6060f1SDimitry Andric private:
96fe6060f1SDimitry Andric   RecordKeeper &Records;
97bdd1243dSDimitry Andric   RVVTypeCache TypeCache;
98fe6060f1SDimitry Andric 
99fe6060f1SDimitry Andric public:
100fe6060f1SDimitry Andric   RVVEmitter(RecordKeeper &R) : Records(R) {}
101fe6060f1SDimitry Andric 
102fe6060f1SDimitry Andric   /// Emit riscv_vector.h
103fe6060f1SDimitry Andric   void createHeader(raw_ostream &o);
104fe6060f1SDimitry Andric 
105fe6060f1SDimitry Andric   /// Emit all the __builtin prototypes and code needed by Sema.
106fe6060f1SDimitry Andric   void createBuiltins(raw_ostream &o);
107fe6060f1SDimitry Andric 
108fe6060f1SDimitry Andric   /// Emit all the information needed to map builtin -> LLVM IR intrinsic.
109fe6060f1SDimitry Andric   void createCodeGen(raw_ostream &o);
110fe6060f1SDimitry Andric 
111972a253aSDimitry Andric   /// Emit all the information needed by SemaRISCVVectorLookup.cpp.
112972a253aSDimitry Andric   /// We've large number of intrinsic function for RVV, creating a customized
113972a253aSDimitry Andric   /// could speed up the compilation time.
114972a253aSDimitry Andric   void createSema(raw_ostream &o);
115972a253aSDimitry Andric 
116fe6060f1SDimitry Andric private:
117972a253aSDimitry Andric   /// Create all intrinsics and add them to \p Out and SemaRecords.
118972a253aSDimitry Andric   void createRVVIntrinsics(std::vector<std::unique_ptr<RVVIntrinsic>> &Out,
119972a253aSDimitry Andric                            std::vector<SemaRecord> *SemaRecords = nullptr);
120972a253aSDimitry Andric   /// Create all intrinsic records and SemaSignatureTable from SemaRecords.
121972a253aSDimitry Andric   void createRVVIntrinsicRecords(std::vector<RVVIntrinsicRecord> &Out,
122972a253aSDimitry Andric                                  SemaSignatureTable &SST,
123972a253aSDimitry Andric                                  ArrayRef<SemaRecord> SemaRecords);
124972a253aSDimitry Andric 
12581ad6265SDimitry Andric   /// Print HeaderCode in RVVHeader Record to \p Out
12681ad6265SDimitry Andric   void printHeaderCode(raw_ostream &OS);
127fe6060f1SDimitry Andric };
128fe6060f1SDimitry Andric 
129fe6060f1SDimitry Andric } // namespace
130fe6060f1SDimitry Andric 
13181ad6265SDimitry Andric static BasicType ParseBasicType(char c) {
13281ad6265SDimitry Andric   switch (c) {
133fe6060f1SDimitry Andric   case 'c':
13481ad6265SDimitry Andric     return BasicType::Int8;
135fe6060f1SDimitry Andric     break;
136fe6060f1SDimitry Andric   case 's':
13781ad6265SDimitry Andric     return BasicType::Int16;
138fe6060f1SDimitry Andric     break;
139fe6060f1SDimitry Andric   case 'i':
14081ad6265SDimitry Andric     return BasicType::Int32;
141fe6060f1SDimitry Andric     break;
142fe6060f1SDimitry Andric   case 'l':
14381ad6265SDimitry Andric     return BasicType::Int64;
144fe6060f1SDimitry Andric     break;
145fe6060f1SDimitry Andric   case 'x':
14681ad6265SDimitry Andric     return BasicType::Float16;
147fe6060f1SDimitry Andric     break;
148fe6060f1SDimitry Andric   case 'f':
14981ad6265SDimitry Andric     return BasicType::Float32;
150fe6060f1SDimitry Andric     break;
151fe6060f1SDimitry Andric   case 'd':
15281ad6265SDimitry Andric     return BasicType::Float64;
153fe6060f1SDimitry Andric     break;
1545f757f3fSDimitry Andric   case 'b':
1555f757f3fSDimitry Andric     return BasicType::BFloat16;
1565f757f3fSDimitry Andric     break;
157fe6060f1SDimitry Andric   default:
15881ad6265SDimitry Andric     return BasicType::Unknown;
159fe6060f1SDimitry Andric   }
160fe6060f1SDimitry Andric }
161fe6060f1SDimitry Andric 
16206c3fb27SDimitry Andric static VectorTypeModifier getTupleVTM(unsigned NF) {
16306c3fb27SDimitry Andric   assert(2 <= NF && NF <= 8 && "2 <= NF <= 8");
16406c3fb27SDimitry Andric   return static_cast<VectorTypeModifier>(
16506c3fb27SDimitry Andric       static_cast<uint8_t>(VectorTypeModifier::Tuple2) + (NF - 2));
16606c3fb27SDimitry Andric }
16706c3fb27SDimitry Andric 
16881ad6265SDimitry Andric void emitCodeGenSwitchBody(const RVVIntrinsic *RVVI, raw_ostream &OS) {
16981ad6265SDimitry Andric   if (!RVVI->getIRName().empty())
17081ad6265SDimitry Andric     OS << "  ID = Intrinsic::riscv_" + RVVI->getIRName() + ";\n";
17181ad6265SDimitry Andric   if (RVVI->getNF() >= 2)
17281ad6265SDimitry Andric     OS << "  NF = " + utostr(RVVI->getNF()) + ";\n";
173bdd1243dSDimitry Andric 
174bdd1243dSDimitry Andric   OS << "  PolicyAttrs = " << RVVI->getPolicyAttrsBits() << ";\n";
175bdd1243dSDimitry Andric 
17681ad6265SDimitry Andric   if (RVVI->hasManualCodegen()) {
177bdd1243dSDimitry Andric     OS << "IsMasked = " << (RVVI->isMasked() ? "true" : "false") << ";\n";
17881ad6265SDimitry Andric     OS << RVVI->getManualCodegen();
179fe6060f1SDimitry Andric     OS << "break;\n";
180fe6060f1SDimitry Andric     return;
181fe6060f1SDimitry Andric   }
182fe6060f1SDimitry Andric 
183753f127fSDimitry Andric   for (const auto &I : enumerate(RVVI->getInputTypes())) {
184753f127fSDimitry Andric     if (I.value()->isPointer()) {
185753f127fSDimitry Andric       assert(RVVI->getIntrinsicTypes().front() == -1 &&
186753f127fSDimitry Andric              "RVVI should be vector load intrinsic.");
187753f127fSDimitry Andric     }
188753f127fSDimitry Andric   }
189753f127fSDimitry Andric 
19081ad6265SDimitry Andric   if (RVVI->isMasked()) {
19181ad6265SDimitry Andric     if (RVVI->hasVL()) {
192fe6060f1SDimitry Andric       OS << "  std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1);\n";
19381ad6265SDimitry Andric       if (RVVI->hasPolicyOperand())
194349cc55cSDimitry Andric         OS << "  Ops.push_back(ConstantInt::get(Ops.back()->getType(),"
195bdd1243dSDimitry Andric               " PolicyAttrs));\n";
196bdd1243dSDimitry Andric       if (RVVI->hasMaskedOffOperand() && RVVI->getPolicyAttrs().isTAMAPolicy())
197bdd1243dSDimitry Andric         OS << "  Ops.insert(Ops.begin(), "
198bdd1243dSDimitry Andric               "llvm::PoisonValue::get(ResultType));\n";
199bdd1243dSDimitry Andric       // Masked reduction cases.
200bdd1243dSDimitry Andric       if (!RVVI->hasMaskedOffOperand() && RVVI->hasPassthruOperand() &&
201bdd1243dSDimitry Andric           RVVI->getPolicyAttrs().isTAMAPolicy())
202bdd1243dSDimitry Andric         OS << "  Ops.insert(Ops.begin(), "
203bdd1243dSDimitry Andric               "llvm::PoisonValue::get(ResultType));\n";
204fe6060f1SDimitry Andric     } else {
205fe6060f1SDimitry Andric       OS << "  std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end());\n";
206fe6060f1SDimitry Andric     }
20781ad6265SDimitry Andric   } else {
20881ad6265SDimitry Andric     if (RVVI->hasPolicyOperand())
20981ad6265SDimitry Andric       OS << "  Ops.push_back(ConstantInt::get(Ops.back()->getType(), "
210bdd1243dSDimitry Andric             "PolicyAttrs));\n";
211bdd1243dSDimitry Andric     else if (RVVI->hasPassthruOperand() && RVVI->getPolicyAttrs().isTAPolicy())
212bdd1243dSDimitry Andric       OS << "  Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType));\n";
213fe6060f1SDimitry Andric   }
214fe6060f1SDimitry Andric 
215fe6060f1SDimitry Andric   OS << "  IntrinsicTypes = {";
216fe6060f1SDimitry Andric   ListSeparator LS;
21781ad6265SDimitry Andric   for (const auto &Idx : RVVI->getIntrinsicTypes()) {
218fe6060f1SDimitry Andric     if (Idx == -1)
219fe6060f1SDimitry Andric       OS << LS << "ResultType";
220fe6060f1SDimitry Andric     else
221fe6060f1SDimitry Andric       OS << LS << "Ops[" << Idx << "]->getType()";
222fe6060f1SDimitry Andric   }
223fe6060f1SDimitry Andric 
224fe6060f1SDimitry Andric   // VL could be i64 or i32, need to encode it in IntrinsicTypes. VL is
225fe6060f1SDimitry Andric   // always last operand.
22681ad6265SDimitry Andric   if (RVVI->hasVL())
227fe6060f1SDimitry Andric     OS << ", Ops.back()->getType()";
228fe6060f1SDimitry Andric   OS << "};\n";
229fe6060f1SDimitry Andric   OS << "  break;\n";
230fe6060f1SDimitry Andric }
231fe6060f1SDimitry Andric 
232972a253aSDimitry Andric //===----------------------------------------------------------------------===//
233972a253aSDimitry Andric // SemaSignatureTable implementation
234972a253aSDimitry Andric //===----------------------------------------------------------------------===//
235972a253aSDimitry Andric void SemaSignatureTable::init(ArrayRef<SemaRecord> SemaRecords) {
236972a253aSDimitry Andric   // Sort signature entries by length, let longer signature insert first, to
237972a253aSDimitry Andric   // make it more possible to reuse table entries, that can reduce ~10% table
238972a253aSDimitry Andric   // size.
239972a253aSDimitry Andric   struct Compare {
240972a253aSDimitry Andric     bool operator()(const SmallVector<PrototypeDescriptor> &A,
241972a253aSDimitry Andric                     const SmallVector<PrototypeDescriptor> &B) const {
242972a253aSDimitry Andric       if (A.size() != B.size())
243972a253aSDimitry Andric         return A.size() > B.size();
244972a253aSDimitry Andric 
245972a253aSDimitry Andric       size_t Len = A.size();
246972a253aSDimitry Andric       for (size_t i = 0; i < Len; ++i) {
247972a253aSDimitry Andric         if (A[i] != B[i])
248972a253aSDimitry Andric           return A[i] < B[i];
249fe6060f1SDimitry Andric       }
250fe6060f1SDimitry Andric 
251972a253aSDimitry Andric       return false;
252fe6060f1SDimitry Andric     }
253972a253aSDimitry Andric   };
254972a253aSDimitry Andric 
255972a253aSDimitry Andric   std::set<SmallVector<PrototypeDescriptor>, Compare> Signatures;
256972a253aSDimitry Andric   auto InsertToSignatureSet =
257972a253aSDimitry Andric       [&](const SmallVector<PrototypeDescriptor> &Signature) {
258972a253aSDimitry Andric         if (Signature.empty())
259972a253aSDimitry Andric           return;
260972a253aSDimitry Andric 
261972a253aSDimitry Andric         Signatures.insert(Signature);
262972a253aSDimitry Andric       };
263972a253aSDimitry Andric 
264972a253aSDimitry Andric   assert(!SemaRecords.empty());
265972a253aSDimitry Andric 
2665f757f3fSDimitry Andric   for (const SemaRecord &SR : SemaRecords) {
267972a253aSDimitry Andric     InsertToSignatureSet(SR.Prototype);
268972a253aSDimitry Andric     InsertToSignatureSet(SR.Suffix);
269972a253aSDimitry Andric     InsertToSignatureSet(SR.OverloadedSuffix);
2705f757f3fSDimitry Andric   }
271972a253aSDimitry Andric 
2725f757f3fSDimitry Andric   for (auto &Sig : Signatures)
2735f757f3fSDimitry Andric     insert(Sig);
274972a253aSDimitry Andric }
275972a253aSDimitry Andric 
276972a253aSDimitry Andric void SemaSignatureTable::insert(ArrayRef<PrototypeDescriptor> Signature) {
277972a253aSDimitry Andric   if (getIndex(Signature) != INVALID_INDEX)
278972a253aSDimitry Andric     return;
279972a253aSDimitry Andric 
280972a253aSDimitry Andric   // Insert Signature into SignatureTable if not found in the table.
281972a253aSDimitry Andric   SignatureTable.insert(SignatureTable.begin(), Signature.begin(),
282972a253aSDimitry Andric                         Signature.end());
283972a253aSDimitry Andric }
284972a253aSDimitry Andric 
285972a253aSDimitry Andric unsigned SemaSignatureTable::getIndex(ArrayRef<PrototypeDescriptor> Signature) {
286972a253aSDimitry Andric   // Empty signature could be point into any index since there is length
287972a253aSDimitry Andric   // field when we use, so just always point it to 0.
288972a253aSDimitry Andric   if (Signature.empty())
289972a253aSDimitry Andric     return 0;
290972a253aSDimitry Andric 
291972a253aSDimitry Andric   // Checking Signature already in table or not.
2925f757f3fSDimitry Andric   if (Signature.size() <= SignatureTable.size()) {
293972a253aSDimitry Andric     size_t Bound = SignatureTable.size() - Signature.size() + 1;
294972a253aSDimitry Andric     for (size_t Index = 0; Index < Bound; ++Index) {
295972a253aSDimitry Andric       if (equal(Signature.begin(), Signature.end(),
296972a253aSDimitry Andric                 SignatureTable.begin() + Index))
297972a253aSDimitry Andric         return Index;
298972a253aSDimitry Andric     }
299972a253aSDimitry Andric   }
300972a253aSDimitry Andric 
301972a253aSDimitry Andric   return INVALID_INDEX;
302972a253aSDimitry Andric }
303972a253aSDimitry Andric 
304972a253aSDimitry Andric void SemaSignatureTable::print(raw_ostream &OS) {
305972a253aSDimitry Andric   for (const auto &Sig : SignatureTable)
306972a253aSDimitry Andric     OS << "PrototypeDescriptor(" << static_cast<int>(Sig.PT) << ", "
307972a253aSDimitry Andric        << static_cast<int>(Sig.VTM) << ", " << static_cast<int>(Sig.TM)
308972a253aSDimitry Andric        << "),\n";
309fe6060f1SDimitry Andric }
310fe6060f1SDimitry Andric 
311fe6060f1SDimitry Andric //===----------------------------------------------------------------------===//
312fe6060f1SDimitry Andric // RVVEmitter implementation
313fe6060f1SDimitry Andric //===----------------------------------------------------------------------===//
314fe6060f1SDimitry Andric void RVVEmitter::createHeader(raw_ostream &OS) {
315fe6060f1SDimitry Andric 
316fe6060f1SDimitry Andric   OS << "/*===---- riscv_vector.h - RISC-V V-extension RVVIntrinsics "
317fe6060f1SDimitry Andric         "-------------------===\n"
318fe6060f1SDimitry Andric         " *\n"
319fe6060f1SDimitry Andric         " *\n"
320fe6060f1SDimitry Andric         " * Part of the LLVM Project, under the Apache License v2.0 with LLVM "
321fe6060f1SDimitry Andric         "Exceptions.\n"
322fe6060f1SDimitry Andric         " * See https://llvm.org/LICENSE.txt for license information.\n"
323fe6060f1SDimitry Andric         " * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n"
324fe6060f1SDimitry Andric         " *\n"
325fe6060f1SDimitry Andric         " *===-----------------------------------------------------------------"
326fe6060f1SDimitry Andric         "------===\n"
327fe6060f1SDimitry Andric         " */\n\n";
328fe6060f1SDimitry Andric 
329fe6060f1SDimitry Andric   OS << "#ifndef __RISCV_VECTOR_H\n";
330fe6060f1SDimitry Andric   OS << "#define __RISCV_VECTOR_H\n\n";
331fe6060f1SDimitry Andric 
332fe6060f1SDimitry Andric   OS << "#include <stdint.h>\n";
333fe6060f1SDimitry Andric   OS << "#include <stddef.h>\n\n";
334fe6060f1SDimitry Andric 
335fe6060f1SDimitry Andric   OS << "#ifndef __riscv_vector\n";
336fe6060f1SDimitry Andric   OS << "#error \"Vector intrinsics require the vector extension.\"\n";
337fe6060f1SDimitry Andric   OS << "#endif\n\n";
338fe6060f1SDimitry Andric 
339fe6060f1SDimitry Andric   OS << "#ifdef __cplusplus\n";
340fe6060f1SDimitry Andric   OS << "extern \"C\" {\n";
341fe6060f1SDimitry Andric   OS << "#endif\n\n";
342fe6060f1SDimitry Andric 
343972a253aSDimitry Andric   OS << "#pragma clang riscv intrinsic vector\n\n";
344349cc55cSDimitry Andric 
345972a253aSDimitry Andric   printHeaderCode(OS);
346fe6060f1SDimitry Andric 
347fe6060f1SDimitry Andric   auto printType = [&](auto T) {
348fe6060f1SDimitry Andric     OS << "typedef " << T->getClangBuiltinStr() << " " << T->getTypeStr()
349fe6060f1SDimitry Andric        << ";\n";
350fe6060f1SDimitry Andric   };
351fe6060f1SDimitry Andric 
352fe6060f1SDimitry Andric   constexpr int Log2LMULs[] = {-3, -2, -1, 0, 1, 2, 3};
353fe6060f1SDimitry Andric   // Print RVV boolean types.
354fe6060f1SDimitry Andric   for (int Log2LMUL : Log2LMULs) {
355bdd1243dSDimitry Andric     auto T = TypeCache.computeType(BasicType::Int8, Log2LMUL,
35681ad6265SDimitry Andric                                    PrototypeDescriptor::Mask);
35781ad6265SDimitry Andric     if (T)
358bdd1243dSDimitry Andric       printType(*T);
359fe6060f1SDimitry Andric   }
360fe6060f1SDimitry Andric   // Print RVV int/float types.
361fe6060f1SDimitry Andric   for (char I : StringRef("csil")) {
36281ad6265SDimitry Andric     BasicType BT = ParseBasicType(I);
363fe6060f1SDimitry Andric     for (int Log2LMUL : Log2LMULs) {
364bdd1243dSDimitry Andric       auto T = TypeCache.computeType(BT, Log2LMUL, PrototypeDescriptor::Vector);
36581ad6265SDimitry Andric       if (T) {
366bdd1243dSDimitry Andric         printType(*T);
367bdd1243dSDimitry Andric         auto UT = TypeCache.computeType(
36881ad6265SDimitry Andric             BT, Log2LMUL,
36981ad6265SDimitry Andric             PrototypeDescriptor(BaseTypeModifier::Vector,
37081ad6265SDimitry Andric                                 VectorTypeModifier::NoModifier,
37181ad6265SDimitry Andric                                 TypeModifier::UnsignedInteger));
372bdd1243dSDimitry Andric         printType(*UT);
373fe6060f1SDimitry Andric       }
37406c3fb27SDimitry Andric       for (int NF = 2; NF <= 8; ++NF) {
37506c3fb27SDimitry Andric         auto TupleT = TypeCache.computeType(
37606c3fb27SDimitry Andric             BT, Log2LMUL,
37706c3fb27SDimitry Andric             PrototypeDescriptor(BaseTypeModifier::Vector, getTupleVTM(NF),
37806c3fb27SDimitry Andric                                 TypeModifier::SignedInteger));
37906c3fb27SDimitry Andric         auto TupleUT = TypeCache.computeType(
38006c3fb27SDimitry Andric             BT, Log2LMUL,
38106c3fb27SDimitry Andric             PrototypeDescriptor(BaseTypeModifier::Vector, getTupleVTM(NF),
38206c3fb27SDimitry Andric                                 TypeModifier::UnsignedInteger));
38306c3fb27SDimitry Andric         if (TupleT)
38406c3fb27SDimitry Andric           printType(*TupleT);
38506c3fb27SDimitry Andric         if (TupleUT)
38606c3fb27SDimitry Andric           printType(*TupleUT);
387fe6060f1SDimitry Andric       }
388fe6060f1SDimitry Andric     }
389fe6060f1SDimitry Andric   }
390fe6060f1SDimitry Andric 
3915f757f3fSDimitry Andric   for (BasicType BT : {BasicType::Float16, BasicType::Float32,
3925f757f3fSDimitry Andric                        BasicType::Float64, BasicType::BFloat16}) {
393fe6060f1SDimitry Andric     for (int Log2LMUL : Log2LMULs) {
39406c3fb27SDimitry Andric       auto T = TypeCache.computeType(BT, Log2LMUL, PrototypeDescriptor::Vector);
39581ad6265SDimitry Andric       if (T)
396bdd1243dSDimitry Andric         printType(*T);
39706c3fb27SDimitry Andric       for (int NF = 2; NF <= 8; ++NF) {
39806c3fb27SDimitry Andric         auto TupleT = TypeCache.computeType(
39906c3fb27SDimitry Andric             BT, Log2LMUL,
40006c3fb27SDimitry Andric             PrototypeDescriptor(BaseTypeModifier::Vector, getTupleVTM(NF),
4015f757f3fSDimitry Andric                                 (BT == BasicType::BFloat16
4025f757f3fSDimitry Andric                                      ? TypeModifier::BFloat
4035f757f3fSDimitry Andric                                      : TypeModifier::Float)));
40406c3fb27SDimitry Andric         if (TupleT)
40506c3fb27SDimitry Andric           printType(*TupleT);
406fe6060f1SDimitry Andric       }
407fe6060f1SDimitry Andric     }
40806c3fb27SDimitry Andric   }
409fe6060f1SDimitry Andric 
410fe6060f1SDimitry Andric   OS << "#define __riscv_v_intrinsic_overloading 1\n";
411fe6060f1SDimitry Andric 
412fe6060f1SDimitry Andric   OS << "\n#ifdef __cplusplus\n";
413fe6060f1SDimitry Andric   OS << "}\n";
414349cc55cSDimitry Andric   OS << "#endif // __cplusplus\n";
415fe6060f1SDimitry Andric   OS << "#endif // __RISCV_VECTOR_H\n";
416fe6060f1SDimitry Andric }
417fe6060f1SDimitry Andric 
418fe6060f1SDimitry Andric void RVVEmitter::createBuiltins(raw_ostream &OS) {
419fe6060f1SDimitry Andric   std::vector<std::unique_ptr<RVVIntrinsic>> Defs;
420fe6060f1SDimitry Andric   createRVVIntrinsics(Defs);
421fe6060f1SDimitry Andric 
422349cc55cSDimitry Andric   // Map to keep track of which builtin names have already been emitted.
423349cc55cSDimitry Andric   StringMap<RVVIntrinsic *> BuiltinMap;
424349cc55cSDimitry Andric 
425fe6060f1SDimitry Andric   OS << "#if defined(TARGET_BUILTIN) && !defined(RISCVV_BUILTIN)\n";
426fe6060f1SDimitry Andric   OS << "#define RISCVV_BUILTIN(ID, TYPE, ATTRS) TARGET_BUILTIN(ID, TYPE, "
42781ad6265SDimitry Andric         "ATTRS, \"zve32x\")\n";
428fe6060f1SDimitry Andric   OS << "#endif\n";
429fe6060f1SDimitry Andric   for (auto &Def : Defs) {
430349cc55cSDimitry Andric     auto P =
431349cc55cSDimitry Andric         BuiltinMap.insert(std::make_pair(Def->getBuiltinName(), Def.get()));
432349cc55cSDimitry Andric     if (!P.second) {
43381ad6265SDimitry Andric       // Verf that this would have produced the same builtin definition.
43481ad6265SDimitry Andric       if (P.first->second->hasBuiltinAlias() != Def->hasBuiltinAlias())
435349cc55cSDimitry Andric         PrintFatalError("Builtin with same name has different hasAutoDef");
43681ad6265SDimitry Andric       else if (!Def->hasBuiltinAlias() &&
43781ad6265SDimitry Andric                P.first->second->getBuiltinTypeStr() != Def->getBuiltinTypeStr())
438349cc55cSDimitry Andric         PrintFatalError("Builtin with same name has different type string");
439349cc55cSDimitry Andric       continue;
440349cc55cSDimitry Andric     }
441349cc55cSDimitry Andric     OS << "RISCVV_BUILTIN(__builtin_rvv_" << Def->getBuiltinName() << ",\"";
44281ad6265SDimitry Andric     if (!Def->hasBuiltinAlias())
443349cc55cSDimitry Andric       OS << Def->getBuiltinTypeStr();
444349cc55cSDimitry Andric     OS << "\", \"n\")\n";
445fe6060f1SDimitry Andric   }
446fe6060f1SDimitry Andric   OS << "#undef RISCVV_BUILTIN\n";
447fe6060f1SDimitry Andric }
448fe6060f1SDimitry Andric 
449fe6060f1SDimitry Andric void RVVEmitter::createCodeGen(raw_ostream &OS) {
450fe6060f1SDimitry Andric   std::vector<std::unique_ptr<RVVIntrinsic>> Defs;
451fe6060f1SDimitry Andric   createRVVIntrinsics(Defs);
452fe6060f1SDimitry Andric   // IR name could be empty, use the stable sort preserves the relative order.
453349cc55cSDimitry Andric   llvm::stable_sort(Defs, [](const std::unique_ptr<RVVIntrinsic> &A,
454fe6060f1SDimitry Andric                              const std::unique_ptr<RVVIntrinsic> &B) {
455bdd1243dSDimitry Andric     if (A->getIRName() == B->getIRName())
456bdd1243dSDimitry Andric       return (A->getPolicyAttrs() < B->getPolicyAttrs());
457bdd1243dSDimitry Andric     return (A->getIRName() < B->getIRName());
458fe6060f1SDimitry Andric   });
459349cc55cSDimitry Andric 
460349cc55cSDimitry Andric   // Map to keep track of which builtin names have already been emitted.
461349cc55cSDimitry Andric   StringMap<RVVIntrinsic *> BuiltinMap;
462349cc55cSDimitry Andric 
463bdd1243dSDimitry Andric   // Print switch body when the ir name, ManualCodegen or policy changes from
464bdd1243dSDimitry Andric   // previous iteration.
465fe6060f1SDimitry Andric   RVVIntrinsic *PrevDef = Defs.begin()->get();
466fe6060f1SDimitry Andric   for (auto &Def : Defs) {
467fe6060f1SDimitry Andric     StringRef CurIRName = Def->getIRName();
468fe6060f1SDimitry Andric     if (CurIRName != PrevDef->getIRName() ||
469bdd1243dSDimitry Andric         (Def->getManualCodegen() != PrevDef->getManualCodegen()) ||
470bdd1243dSDimitry Andric         (Def->getPolicyAttrs() != PrevDef->getPolicyAttrs())) {
47181ad6265SDimitry Andric       emitCodeGenSwitchBody(PrevDef, OS);
472fe6060f1SDimitry Andric     }
473fe6060f1SDimitry Andric     PrevDef = Def.get();
474349cc55cSDimitry Andric 
475349cc55cSDimitry Andric     auto P =
476349cc55cSDimitry Andric         BuiltinMap.insert(std::make_pair(Def->getBuiltinName(), Def.get()));
477349cc55cSDimitry Andric     if (P.second) {
478349cc55cSDimitry Andric       OS << "case RISCVVector::BI__builtin_rvv_" << Def->getBuiltinName()
479349cc55cSDimitry Andric          << ":\n";
480349cc55cSDimitry Andric       continue;
481349cc55cSDimitry Andric     }
482349cc55cSDimitry Andric 
483349cc55cSDimitry Andric     if (P.first->second->getIRName() != Def->getIRName())
484349cc55cSDimitry Andric       PrintFatalError("Builtin with same name has different IRName");
485349cc55cSDimitry Andric     else if (P.first->second->getManualCodegen() != Def->getManualCodegen())
486349cc55cSDimitry Andric       PrintFatalError("Builtin with same name has different ManualCodegen");
48781ad6265SDimitry Andric     else if (P.first->second->isMasked() != Def->isMasked())
48881ad6265SDimitry Andric       PrintFatalError("Builtin with same name has different isMasked");
489349cc55cSDimitry Andric     else if (P.first->second->hasVL() != Def->hasVL())
49081ad6265SDimitry Andric       PrintFatalError("Builtin with same name has different hasVL");
49181ad6265SDimitry Andric     else if (P.first->second->getPolicyScheme() != Def->getPolicyScheme())
49281ad6265SDimitry Andric       PrintFatalError("Builtin with same name has different getPolicyScheme");
493349cc55cSDimitry Andric     else if (P.first->second->getIntrinsicTypes() != Def->getIntrinsicTypes())
494349cc55cSDimitry Andric       PrintFatalError("Builtin with same name has different IntrinsicTypes");
495fe6060f1SDimitry Andric   }
49681ad6265SDimitry Andric   emitCodeGenSwitchBody(Defs.back().get(), OS);
497fe6060f1SDimitry Andric   OS << "\n";
498fe6060f1SDimitry Andric }
499fe6060f1SDimitry Andric 
500fe6060f1SDimitry Andric void RVVEmitter::createRVVIntrinsics(
501972a253aSDimitry Andric     std::vector<std::unique_ptr<RVVIntrinsic>> &Out,
502972a253aSDimitry Andric     std::vector<SemaRecord> *SemaRecords) {
503fe6060f1SDimitry Andric   std::vector<Record *> RV = Records.getAllDerivedDefinitions("RVVBuiltin");
504fe6060f1SDimitry Andric   for (auto *R : RV) {
505fe6060f1SDimitry Andric     StringRef Name = R->getValueAsString("Name");
506fe6060f1SDimitry Andric     StringRef SuffixProto = R->getValueAsString("Suffix");
50781ad6265SDimitry Andric     StringRef OverloadedName = R->getValueAsString("OverloadedName");
50881ad6265SDimitry Andric     StringRef OverloadedSuffixProto = R->getValueAsString("OverloadedSuffix");
509fe6060f1SDimitry Andric     StringRef Prototypes = R->getValueAsString("Prototype");
510fe6060f1SDimitry Andric     StringRef TypeRange = R->getValueAsString("TypeRange");
51181ad6265SDimitry Andric     bool HasMasked = R->getValueAsBit("HasMasked");
512fe6060f1SDimitry Andric     bool HasMaskedOffOperand = R->getValueAsBit("HasMaskedOffOperand");
513fe6060f1SDimitry Andric     bool HasVL = R->getValueAsBit("HasVL");
514972a253aSDimitry Andric     Record *MPSRecord = R->getValueAsDef("MaskedPolicyScheme");
515972a253aSDimitry Andric     auto MaskedPolicyScheme =
516972a253aSDimitry Andric         static_cast<PolicyScheme>(MPSRecord->getValueAsInt("Value"));
517972a253aSDimitry Andric     Record *UMPSRecord = R->getValueAsDef("UnMaskedPolicyScheme");
518972a253aSDimitry Andric     auto UnMaskedPolicyScheme =
519972a253aSDimitry Andric         static_cast<PolicyScheme>(UMPSRecord->getValueAsInt("Value"));
520fe6060f1SDimitry Andric     std::vector<int64_t> Log2LMULList = R->getValueAsListOfInts("Log2LMUL");
521bdd1243dSDimitry Andric     bool HasTailPolicy = R->getValueAsBit("HasTailPolicy");
522bdd1243dSDimitry Andric     bool HasMaskPolicy = R->getValueAsBit("HasMaskPolicy");
523bdd1243dSDimitry Andric     bool SupportOverloading = R->getValueAsBit("SupportOverloading");
52481ad6265SDimitry Andric     bool HasBuiltinAlias = R->getValueAsBit("HasBuiltinAlias");
525fe6060f1SDimitry Andric     StringRef ManualCodegen = R->getValueAsString("ManualCodegen");
526fe6060f1SDimitry Andric     std::vector<int64_t> IntrinsicTypes =
527fe6060f1SDimitry Andric         R->getValueAsListOfInts("IntrinsicTypes");
52804eeddc0SDimitry Andric     std::vector<StringRef> RequiredFeatures =
52904eeddc0SDimitry Andric         R->getValueAsListOfStrings("RequiredFeatures");
530fe6060f1SDimitry Andric     StringRef IRName = R->getValueAsString("IRName");
53181ad6265SDimitry Andric     StringRef MaskedIRName = R->getValueAsString("MaskedIRName");
532fe6060f1SDimitry Andric     unsigned NF = R->getValueAsInt("NF");
53306c3fb27SDimitry Andric     bool IsTuple = R->getValueAsBit("IsTuple");
53406c3fb27SDimitry Andric     bool HasFRMRoundModeOp = R->getValueAsBit("HasFRMRoundModeOp");
535fe6060f1SDimitry Andric 
5361ac55f4cSDimitry Andric     const Policy DefaultPolicy;
537bdd1243dSDimitry Andric     SmallVector<Policy> SupportedUnMaskedPolicies =
5381ac55f4cSDimitry Andric         RVVIntrinsic::getSupportedUnMaskedPolicies();
539bdd1243dSDimitry Andric     SmallVector<Policy> SupportedMaskedPolicies =
540bdd1243dSDimitry Andric         RVVIntrinsic::getSupportedMaskedPolicies(HasTailPolicy, HasMaskPolicy);
541bdd1243dSDimitry Andric 
542fe6060f1SDimitry Andric     // Parse prototype and create a list of primitive type with transformers
54381ad6265SDimitry Andric     // (operand) in Prototype. Prototype[0] is output operand.
544972a253aSDimitry Andric     SmallVector<PrototypeDescriptor> BasicPrototype =
545972a253aSDimitry Andric         parsePrototypes(Prototypes);
54681ad6265SDimitry Andric 
54781ad6265SDimitry Andric     SmallVector<PrototypeDescriptor> SuffixDesc = parsePrototypes(SuffixProto);
54881ad6265SDimitry Andric     SmallVector<PrototypeDescriptor> OverloadedSuffixDesc =
54981ad6265SDimitry Andric         parsePrototypes(OverloadedSuffixProto);
550fe6060f1SDimitry Andric 
551fe6060f1SDimitry Andric     // Compute Builtin types
552972a253aSDimitry Andric     auto Prototype = RVVIntrinsic::computeBuiltinTypes(
553bdd1243dSDimitry Andric         BasicPrototype, /*IsMasked=*/false,
554bdd1243dSDimitry Andric         /*HasMaskedOffOperand=*/false, HasVL, NF, UnMaskedPolicyScheme,
55506c3fb27SDimitry Andric         DefaultPolicy, IsTuple);
55606c3fb27SDimitry Andric     llvm::SmallVector<PrototypeDescriptor> MaskedPrototype;
55706c3fb27SDimitry Andric     if (HasMasked)
55806c3fb27SDimitry Andric       MaskedPrototype = RVVIntrinsic::computeBuiltinTypes(
559bdd1243dSDimitry Andric           BasicPrototype, /*IsMasked=*/true, HasMaskedOffOperand, HasVL, NF,
56006c3fb27SDimitry Andric           MaskedPolicyScheme, DefaultPolicy, IsTuple);
561fe6060f1SDimitry Andric 
562fe6060f1SDimitry Andric     // Create Intrinsics for each type and LMUL.
563fe6060f1SDimitry Andric     for (char I : TypeRange) {
564fe6060f1SDimitry Andric       for (int Log2LMUL : Log2LMULList) {
56581ad6265SDimitry Andric         BasicType BT = ParseBasicType(I);
566bdd1243dSDimitry Andric         std::optional<RVVTypes> Types =
567bdd1243dSDimitry Andric             TypeCache.computeTypes(BT, Log2LMUL, NF, Prototype);
568fe6060f1SDimitry Andric         // Ignored to create new intrinsic if there are any illegal types.
56981ad6265SDimitry Andric         if (!Types)
570fe6060f1SDimitry Andric           continue;
571fe6060f1SDimitry Andric 
572bdd1243dSDimitry Andric         auto SuffixStr =
573bdd1243dSDimitry Andric             RVVIntrinsic::getSuffixStr(TypeCache, BT, Log2LMUL, SuffixDesc);
574bdd1243dSDimitry Andric         auto OverloadedSuffixStr = RVVIntrinsic::getSuffixStr(
575bdd1243dSDimitry Andric             TypeCache, BT, Log2LMUL, OverloadedSuffixDesc);
57681ad6265SDimitry Andric         // Create a unmasked intrinsic
577fe6060f1SDimitry Andric         Out.push_back(std::make_unique<RVVIntrinsic>(
57881ad6265SDimitry Andric             Name, SuffixStr, OverloadedName, OverloadedSuffixStr, IRName,
57981ad6265SDimitry Andric             /*IsMasked=*/false, /*HasMaskedOffOperand=*/false, HasVL,
580bdd1243dSDimitry Andric             UnMaskedPolicyScheme, SupportOverloading, HasBuiltinAlias,
581bdd1243dSDimitry Andric             ManualCodegen, *Types, IntrinsicTypes, RequiredFeatures, NF,
58206c3fb27SDimitry Andric             DefaultPolicy, HasFRMRoundModeOp));
583bdd1243dSDimitry Andric         if (UnMaskedPolicyScheme != PolicyScheme::SchemeNone)
584bdd1243dSDimitry Andric           for (auto P : SupportedUnMaskedPolicies) {
585bdd1243dSDimitry Andric             SmallVector<PrototypeDescriptor> PolicyPrototype =
586bdd1243dSDimitry Andric                 RVVIntrinsic::computeBuiltinTypes(
587bdd1243dSDimitry Andric                     BasicPrototype, /*IsMasked=*/false,
588bdd1243dSDimitry Andric                     /*HasMaskedOffOperand=*/false, HasVL, NF,
58906c3fb27SDimitry Andric                     UnMaskedPolicyScheme, P, IsTuple);
590bdd1243dSDimitry Andric             std::optional<RVVTypes> PolicyTypes =
591bdd1243dSDimitry Andric                 TypeCache.computeTypes(BT, Log2LMUL, NF, PolicyPrototype);
592bdd1243dSDimitry Andric             Out.push_back(std::make_unique<RVVIntrinsic>(
593bdd1243dSDimitry Andric                 Name, SuffixStr, OverloadedName, OverloadedSuffixStr, IRName,
594bdd1243dSDimitry Andric                 /*IsMask=*/false, /*HasMaskedOffOperand=*/false, HasVL,
595bdd1243dSDimitry Andric                 UnMaskedPolicyScheme, SupportOverloading, HasBuiltinAlias,
596bdd1243dSDimitry Andric                 ManualCodegen, *PolicyTypes, IntrinsicTypes, RequiredFeatures,
59706c3fb27SDimitry Andric                 NF, P, HasFRMRoundModeOp));
598bdd1243dSDimitry Andric           }
599bdd1243dSDimitry Andric         if (!HasMasked)
600bdd1243dSDimitry Andric           continue;
60181ad6265SDimitry Andric         // Create a masked intrinsic
602bdd1243dSDimitry Andric         std::optional<RVVTypes> MaskTypes =
603bdd1243dSDimitry Andric             TypeCache.computeTypes(BT, Log2LMUL, NF, MaskedPrototype);
604bdd1243dSDimitry Andric         Out.push_back(std::make_unique<RVVIntrinsic>(
605bdd1243dSDimitry Andric             Name, SuffixStr, OverloadedName, OverloadedSuffixStr, MaskedIRName,
606bdd1243dSDimitry Andric             /*IsMasked=*/true, HasMaskedOffOperand, HasVL, MaskedPolicyScheme,
607bdd1243dSDimitry Andric             SupportOverloading, HasBuiltinAlias, ManualCodegen, *MaskTypes,
60806c3fb27SDimitry Andric             IntrinsicTypes, RequiredFeatures, NF, DefaultPolicy,
60906c3fb27SDimitry Andric             HasFRMRoundModeOp));
610bdd1243dSDimitry Andric         if (MaskedPolicyScheme == PolicyScheme::SchemeNone)
611bdd1243dSDimitry Andric           continue;
612bdd1243dSDimitry Andric         for (auto P : SupportedMaskedPolicies) {
613bdd1243dSDimitry Andric           SmallVector<PrototypeDescriptor> PolicyPrototype =
614bdd1243dSDimitry Andric               RVVIntrinsic::computeBuiltinTypes(
615bdd1243dSDimitry Andric                   BasicPrototype, /*IsMasked=*/true, HasMaskedOffOperand, HasVL,
61606c3fb27SDimitry Andric                   NF, MaskedPolicyScheme, P, IsTuple);
617bdd1243dSDimitry Andric           std::optional<RVVTypes> PolicyTypes =
618bdd1243dSDimitry Andric               TypeCache.computeTypes(BT, Log2LMUL, NF, PolicyPrototype);
619fe6060f1SDimitry Andric           Out.push_back(std::make_unique<RVVIntrinsic>(
62081ad6265SDimitry Andric               Name, SuffixStr, OverloadedName, OverloadedSuffixStr,
621bdd1243dSDimitry Andric               MaskedIRName, /*IsMasked=*/true, HasMaskedOffOperand, HasVL,
622bdd1243dSDimitry Andric               MaskedPolicyScheme, SupportOverloading, HasBuiltinAlias,
623bdd1243dSDimitry Andric               ManualCodegen, *PolicyTypes, IntrinsicTypes, RequiredFeatures, NF,
62406c3fb27SDimitry Andric               P, HasFRMRoundModeOp));
625fe6060f1SDimitry Andric         }
626bdd1243dSDimitry Andric       } // End for Log2LMULList
627bdd1243dSDimitry Andric     }   // End for TypeRange
628972a253aSDimitry Andric 
629972a253aSDimitry Andric     // We don't emit vsetvli and vsetvlimax for SemaRecord.
630972a253aSDimitry Andric     // They are written in riscv_vector.td and will emit those marco define in
631972a253aSDimitry Andric     // riscv_vector.h
632972a253aSDimitry Andric     if (Name == "vsetvli" || Name == "vsetvlimax")
633972a253aSDimitry Andric       continue;
634972a253aSDimitry Andric 
635972a253aSDimitry Andric     if (!SemaRecords)
636972a253aSDimitry Andric       continue;
637972a253aSDimitry Andric 
638972a253aSDimitry Andric     // Create SemaRecord
639972a253aSDimitry Andric     SemaRecord SR;
640972a253aSDimitry Andric     SR.Name = Name.str();
641972a253aSDimitry Andric     SR.OverloadedName = OverloadedName.str();
642972a253aSDimitry Andric     BasicType TypeRangeMask = BasicType::Unknown;
643972a253aSDimitry Andric     for (char I : TypeRange)
644972a253aSDimitry Andric       TypeRangeMask |= ParseBasicType(I);
645972a253aSDimitry Andric 
646972a253aSDimitry Andric     SR.TypeRangeMask = static_cast<unsigned>(TypeRangeMask);
647972a253aSDimitry Andric 
648972a253aSDimitry Andric     unsigned Log2LMULMask = 0;
649972a253aSDimitry Andric     for (int Log2LMUL : Log2LMULList)
650972a253aSDimitry Andric       Log2LMULMask |= 1 << (Log2LMUL + 3);
651972a253aSDimitry Andric 
652972a253aSDimitry Andric     SR.Log2LMULMask = Log2LMULMask;
653972a253aSDimitry Andric 
654972a253aSDimitry Andric     SR.RequiredExtensions = 0;
655972a253aSDimitry Andric     for (auto RequiredFeature : RequiredFeatures) {
656*cb14a3feSDimitry Andric       RVVRequire RequireExt =
657*cb14a3feSDimitry Andric           StringSwitch<RVVRequire>(RequiredFeature)
658972a253aSDimitry Andric               .Case("RV64", RVV_REQ_RV64)
6595f757f3fSDimitry Andric               .Case("ZvfhminOrZvfh", RVV_REQ_ZvfhminOrZvfh)
66006c3fb27SDimitry Andric               .Case("Xsfvcp", RVV_REQ_Xsfvcp)
6615f757f3fSDimitry Andric               .Case("Xsfvfnrclipxfqf", RVV_REQ_Xsfvfnrclipxfqf)
6625f757f3fSDimitry Andric               .Case("Xsfvfwmaccqqq", RVV_REQ_Xsfvfwmaccqqq)
6635f757f3fSDimitry Andric               .Case("Xsfvqmaccdod", RVV_REQ_Xsfvqmaccdod)
6645f757f3fSDimitry Andric               .Case("Xsfvqmaccqoq", RVV_REQ_Xsfvqmaccqoq)
6655f757f3fSDimitry Andric               .Case("Zvbb", RVV_REQ_Zvbb)
6665f757f3fSDimitry Andric               .Case("Zvbc", RVV_REQ_Zvbc)
6675f757f3fSDimitry Andric               .Case("Zvkb", RVV_REQ_Zvkb)
6685f757f3fSDimitry Andric               .Case("Zvkg", RVV_REQ_Zvkg)
6695f757f3fSDimitry Andric               .Case("Zvkned", RVV_REQ_Zvkned)
6705f757f3fSDimitry Andric               .Case("Zvknha", RVV_REQ_Zvknha)
6715f757f3fSDimitry Andric               .Case("Zvknhb", RVV_REQ_Zvknhb)
6725f757f3fSDimitry Andric               .Case("Zvksed", RVV_REQ_Zvksed)
6735f757f3fSDimitry Andric               .Case("Zvksh", RVV_REQ_Zvksh)
674*cb14a3feSDimitry Andric               .Case("Experimental", RVV_REQ_Experimental)
675972a253aSDimitry Andric               .Default(RVV_REQ_None);
676972a253aSDimitry Andric       assert(RequireExt != RVV_REQ_None && "Unrecognized required feature?");
677972a253aSDimitry Andric       SR.RequiredExtensions |= RequireExt;
678972a253aSDimitry Andric     }
679972a253aSDimitry Andric 
680972a253aSDimitry Andric     SR.NF = NF;
681972a253aSDimitry Andric     SR.HasMasked = HasMasked;
682972a253aSDimitry Andric     SR.HasVL = HasVL;
683972a253aSDimitry Andric     SR.HasMaskedOffOperand = HasMaskedOffOperand;
684bdd1243dSDimitry Andric     SR.HasTailPolicy = HasTailPolicy;
685bdd1243dSDimitry Andric     SR.HasMaskPolicy = HasMaskPolicy;
686bdd1243dSDimitry Andric     SR.UnMaskedPolicyScheme = static_cast<uint8_t>(UnMaskedPolicyScheme);
687bdd1243dSDimitry Andric     SR.MaskedPolicyScheme = static_cast<uint8_t>(MaskedPolicyScheme);
688972a253aSDimitry Andric     SR.Prototype = std::move(BasicPrototype);
689972a253aSDimitry Andric     SR.Suffix = parsePrototypes(SuffixProto);
690972a253aSDimitry Andric     SR.OverloadedSuffix = parsePrototypes(OverloadedSuffixProto);
69106c3fb27SDimitry Andric     SR.IsTuple = IsTuple;
69206c3fb27SDimitry Andric     SR.HasFRMRoundModeOp = HasFRMRoundModeOp;
693972a253aSDimitry Andric 
694972a253aSDimitry Andric     SemaRecords->push_back(SR);
695fe6060f1SDimitry Andric   }
696fe6060f1SDimitry Andric }
697fe6060f1SDimitry Andric 
69881ad6265SDimitry Andric void RVVEmitter::printHeaderCode(raw_ostream &OS) {
699349cc55cSDimitry Andric   std::vector<Record *> RVVHeaders =
700349cc55cSDimitry Andric       Records.getAllDerivedDefinitions("RVVHeader");
701349cc55cSDimitry Andric   for (auto *R : RVVHeaders) {
702349cc55cSDimitry Andric     StringRef HeaderCodeStr = R->getValueAsString("HeaderCode");
703349cc55cSDimitry Andric     OS << HeaderCodeStr.str();
704349cc55cSDimitry Andric   }
705349cc55cSDimitry Andric }
706349cc55cSDimitry Andric 
707972a253aSDimitry Andric void RVVEmitter::createRVVIntrinsicRecords(std::vector<RVVIntrinsicRecord> &Out,
708972a253aSDimitry Andric                                            SemaSignatureTable &SST,
709972a253aSDimitry Andric                                            ArrayRef<SemaRecord> SemaRecords) {
710972a253aSDimitry Andric   SST.init(SemaRecords);
711972a253aSDimitry Andric 
712972a253aSDimitry Andric   for (const auto &SR : SemaRecords) {
713972a253aSDimitry Andric     Out.emplace_back(RVVIntrinsicRecord());
714972a253aSDimitry Andric     RVVIntrinsicRecord &R = Out.back();
715972a253aSDimitry Andric     R.Name = SR.Name.c_str();
716972a253aSDimitry Andric     R.OverloadedName = SR.OverloadedName.c_str();
717972a253aSDimitry Andric     R.PrototypeIndex = SST.getIndex(SR.Prototype);
718972a253aSDimitry Andric     R.SuffixIndex = SST.getIndex(SR.Suffix);
719972a253aSDimitry Andric     R.OverloadedSuffixIndex = SST.getIndex(SR.OverloadedSuffix);
720972a253aSDimitry Andric     R.PrototypeLength = SR.Prototype.size();
721972a253aSDimitry Andric     R.SuffixLength = SR.Suffix.size();
722972a253aSDimitry Andric     R.OverloadedSuffixSize = SR.OverloadedSuffix.size();
723972a253aSDimitry Andric     R.RequiredExtensions = SR.RequiredExtensions;
724972a253aSDimitry Andric     R.TypeRangeMask = SR.TypeRangeMask;
725972a253aSDimitry Andric     R.Log2LMULMask = SR.Log2LMULMask;
726972a253aSDimitry Andric     R.NF = SR.NF;
727972a253aSDimitry Andric     R.HasMasked = SR.HasMasked;
728972a253aSDimitry Andric     R.HasVL = SR.HasVL;
729972a253aSDimitry Andric     R.HasMaskedOffOperand = SR.HasMaskedOffOperand;
730bdd1243dSDimitry Andric     R.HasTailPolicy = SR.HasTailPolicy;
731bdd1243dSDimitry Andric     R.HasMaskPolicy = SR.HasMaskPolicy;
732bdd1243dSDimitry Andric     R.UnMaskedPolicyScheme = SR.UnMaskedPolicyScheme;
733bdd1243dSDimitry Andric     R.MaskedPolicyScheme = SR.MaskedPolicyScheme;
73406c3fb27SDimitry Andric     R.IsTuple = SR.IsTuple;
73506c3fb27SDimitry Andric     R.HasFRMRoundModeOp = SR.HasFRMRoundModeOp;
736972a253aSDimitry Andric 
737972a253aSDimitry Andric     assert(R.PrototypeIndex !=
738972a253aSDimitry Andric            static_cast<uint16_t>(SemaSignatureTable::INVALID_INDEX));
739972a253aSDimitry Andric     assert(R.SuffixIndex !=
740972a253aSDimitry Andric            static_cast<uint16_t>(SemaSignatureTable::INVALID_INDEX));
741972a253aSDimitry Andric     assert(R.OverloadedSuffixIndex !=
742972a253aSDimitry Andric            static_cast<uint16_t>(SemaSignatureTable::INVALID_INDEX));
743fe6060f1SDimitry Andric   }
744fe6060f1SDimitry Andric }
745fe6060f1SDimitry Andric 
746972a253aSDimitry Andric void RVVEmitter::createSema(raw_ostream &OS) {
747972a253aSDimitry Andric   std::vector<std::unique_ptr<RVVIntrinsic>> Defs;
748972a253aSDimitry Andric   std::vector<RVVIntrinsicRecord> RVVIntrinsicRecords;
749972a253aSDimitry Andric   SemaSignatureTable SST;
750972a253aSDimitry Andric   std::vector<SemaRecord> SemaRecords;
751972a253aSDimitry Andric 
752972a253aSDimitry Andric   createRVVIntrinsics(Defs, &SemaRecords);
753972a253aSDimitry Andric 
754972a253aSDimitry Andric   createRVVIntrinsicRecords(RVVIntrinsicRecords, SST, SemaRecords);
755972a253aSDimitry Andric 
756972a253aSDimitry Andric   // Emit signature table for SemaRISCVVectorLookup.cpp.
757972a253aSDimitry Andric   OS << "#ifdef DECL_SIGNATURE_TABLE\n";
758972a253aSDimitry Andric   SST.print(OS);
759972a253aSDimitry Andric   OS << "#endif\n";
760972a253aSDimitry Andric 
761972a253aSDimitry Andric   // Emit RVVIntrinsicRecords for SemaRISCVVectorLookup.cpp.
762972a253aSDimitry Andric   OS << "#ifdef DECL_INTRINSIC_RECORDS\n";
763972a253aSDimitry Andric   for (const RVVIntrinsicRecord &Record : RVVIntrinsicRecords)
764972a253aSDimitry Andric     OS << Record;
765972a253aSDimitry Andric   OS << "#endif\n";
766fe6060f1SDimitry Andric }
767fe6060f1SDimitry Andric 
768fe6060f1SDimitry Andric namespace clang {
769fe6060f1SDimitry Andric void EmitRVVHeader(RecordKeeper &Records, raw_ostream &OS) {
770fe6060f1SDimitry Andric   RVVEmitter(Records).createHeader(OS);
771fe6060f1SDimitry Andric }
772fe6060f1SDimitry Andric 
773fe6060f1SDimitry Andric void EmitRVVBuiltins(RecordKeeper &Records, raw_ostream &OS) {
774fe6060f1SDimitry Andric   RVVEmitter(Records).createBuiltins(OS);
775fe6060f1SDimitry Andric }
776fe6060f1SDimitry Andric 
777fe6060f1SDimitry Andric void EmitRVVBuiltinCG(RecordKeeper &Records, raw_ostream &OS) {
778fe6060f1SDimitry Andric   RVVEmitter(Records).createCodeGen(OS);
779fe6060f1SDimitry Andric }
780fe6060f1SDimitry Andric 
781972a253aSDimitry Andric void EmitRVVBuiltinSema(RecordKeeper &Records, raw_ostream &OS) {
782972a253aSDimitry Andric   RVVEmitter(Records).createSema(OS);
783972a253aSDimitry Andric }
784972a253aSDimitry Andric 
785fe6060f1SDimitry Andric } // End namespace clang
786