xref: /freebsd/contrib/llvm-project/clang/utils/TableGen/RISCVVEmitter.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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.
49cb14a3feSDimitry 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;
70*0fca6ea1SDimitry Andric   LLVM_PREFERRED_TYPE(PolicyScheme)
71bdd1243dSDimitry Andric   uint8_t UnMaskedPolicyScheme : 2;
72*0fca6ea1SDimitry Andric   LLVM_PREFERRED_TYPE(PolicyScheme)
73bdd1243dSDimitry Andric   uint8_t MaskedPolicyScheme : 2;
74972a253aSDimitry Andric };
75972a253aSDimitry Andric 
76972a253aSDimitry Andric // Compressed function signature table.
77972a253aSDimitry Andric class SemaSignatureTable {
78972a253aSDimitry Andric private:
79972a253aSDimitry Andric   std::vector<PrototypeDescriptor> SignatureTable;
80972a253aSDimitry Andric 
81972a253aSDimitry Andric   void insert(ArrayRef<PrototypeDescriptor> Signature);
82972a253aSDimitry Andric 
83972a253aSDimitry Andric public:
84972a253aSDimitry Andric   static constexpr unsigned INVALID_INDEX = ~0U;
85972a253aSDimitry Andric 
86972a253aSDimitry Andric   // Create compressed signature table from SemaRecords.
87972a253aSDimitry Andric   void init(ArrayRef<SemaRecord> SemaRecords);
88972a253aSDimitry Andric 
89972a253aSDimitry Andric   // Query the Signature, return INVALID_INDEX if not found.
90972a253aSDimitry Andric   unsigned getIndex(ArrayRef<PrototypeDescriptor> Signature);
91972a253aSDimitry Andric 
92972a253aSDimitry Andric   /// Print signature table in RVVHeader Record to \p OS
93972a253aSDimitry Andric   void print(raw_ostream &OS);
94972a253aSDimitry Andric };
95972a253aSDimitry Andric 
96fe6060f1SDimitry Andric class RVVEmitter {
97fe6060f1SDimitry Andric private:
98fe6060f1SDimitry Andric   RecordKeeper &Records;
99bdd1243dSDimitry Andric   RVVTypeCache TypeCache;
100fe6060f1SDimitry Andric 
101fe6060f1SDimitry Andric public:
RVVEmitter(RecordKeeper & R)102fe6060f1SDimitry Andric   RVVEmitter(RecordKeeper &R) : Records(R) {}
103fe6060f1SDimitry Andric 
104fe6060f1SDimitry Andric   /// Emit riscv_vector.h
105fe6060f1SDimitry Andric   void createHeader(raw_ostream &o);
106fe6060f1SDimitry Andric 
107fe6060f1SDimitry Andric   /// Emit all the __builtin prototypes and code needed by Sema.
108fe6060f1SDimitry Andric   void createBuiltins(raw_ostream &o);
109fe6060f1SDimitry Andric 
110fe6060f1SDimitry Andric   /// Emit all the information needed to map builtin -> LLVM IR intrinsic.
111fe6060f1SDimitry Andric   void createCodeGen(raw_ostream &o);
112fe6060f1SDimitry Andric 
113972a253aSDimitry Andric   /// Emit all the information needed by SemaRISCVVectorLookup.cpp.
114972a253aSDimitry Andric   /// We've large number of intrinsic function for RVV, creating a customized
115972a253aSDimitry Andric   /// could speed up the compilation time.
116972a253aSDimitry Andric   void createSema(raw_ostream &o);
117972a253aSDimitry Andric 
118fe6060f1SDimitry Andric private:
119972a253aSDimitry Andric   /// Create all intrinsics and add them to \p Out and SemaRecords.
120972a253aSDimitry Andric   void createRVVIntrinsics(std::vector<std::unique_ptr<RVVIntrinsic>> &Out,
121972a253aSDimitry Andric                            std::vector<SemaRecord> *SemaRecords = nullptr);
122972a253aSDimitry Andric   /// Create all intrinsic records and SemaSignatureTable from SemaRecords.
123972a253aSDimitry Andric   void createRVVIntrinsicRecords(std::vector<RVVIntrinsicRecord> &Out,
124972a253aSDimitry Andric                                  SemaSignatureTable &SST,
125972a253aSDimitry Andric                                  ArrayRef<SemaRecord> SemaRecords);
126972a253aSDimitry Andric 
12781ad6265SDimitry Andric   /// Print HeaderCode in RVVHeader Record to \p Out
12881ad6265SDimitry Andric   void printHeaderCode(raw_ostream &OS);
129fe6060f1SDimitry Andric };
130fe6060f1SDimitry Andric 
131fe6060f1SDimitry Andric } // namespace
132fe6060f1SDimitry Andric 
ParseBasicType(char c)13381ad6265SDimitry Andric static BasicType ParseBasicType(char c) {
13481ad6265SDimitry Andric   switch (c) {
135fe6060f1SDimitry Andric   case 'c':
13681ad6265SDimitry Andric     return BasicType::Int8;
137fe6060f1SDimitry Andric     break;
138fe6060f1SDimitry Andric   case 's':
13981ad6265SDimitry Andric     return BasicType::Int16;
140fe6060f1SDimitry Andric     break;
141fe6060f1SDimitry Andric   case 'i':
14281ad6265SDimitry Andric     return BasicType::Int32;
143fe6060f1SDimitry Andric     break;
144fe6060f1SDimitry Andric   case 'l':
14581ad6265SDimitry Andric     return BasicType::Int64;
146fe6060f1SDimitry Andric     break;
147fe6060f1SDimitry Andric   case 'x':
14881ad6265SDimitry Andric     return BasicType::Float16;
149fe6060f1SDimitry Andric     break;
150fe6060f1SDimitry Andric   case 'f':
15181ad6265SDimitry Andric     return BasicType::Float32;
152fe6060f1SDimitry Andric     break;
153fe6060f1SDimitry Andric   case 'd':
15481ad6265SDimitry Andric     return BasicType::Float64;
155fe6060f1SDimitry Andric     break;
156647cbc5dSDimitry Andric   case 'y':
1575f757f3fSDimitry Andric     return BasicType::BFloat16;
1585f757f3fSDimitry Andric     break;
159fe6060f1SDimitry Andric   default:
16081ad6265SDimitry Andric     return BasicType::Unknown;
161fe6060f1SDimitry Andric   }
162fe6060f1SDimitry Andric }
163fe6060f1SDimitry Andric 
getTupleVTM(unsigned NF)16406c3fb27SDimitry Andric static VectorTypeModifier getTupleVTM(unsigned NF) {
16506c3fb27SDimitry Andric   assert(2 <= NF && NF <= 8 && "2 <= NF <= 8");
16606c3fb27SDimitry Andric   return static_cast<VectorTypeModifier>(
16706c3fb27SDimitry Andric       static_cast<uint8_t>(VectorTypeModifier::Tuple2) + (NF - 2));
16806c3fb27SDimitry Andric }
16906c3fb27SDimitry Andric 
emitCodeGenSwitchBody(const RVVIntrinsic * RVVI,raw_ostream & OS)17081ad6265SDimitry Andric void emitCodeGenSwitchBody(const RVVIntrinsic *RVVI, raw_ostream &OS) {
17181ad6265SDimitry Andric   if (!RVVI->getIRName().empty())
17281ad6265SDimitry Andric     OS << "  ID = Intrinsic::riscv_" + RVVI->getIRName() + ";\n";
17381ad6265SDimitry Andric   if (RVVI->getNF() >= 2)
17481ad6265SDimitry Andric     OS << "  NF = " + utostr(RVVI->getNF()) + ";\n";
175bdd1243dSDimitry Andric 
176bdd1243dSDimitry Andric   OS << "  PolicyAttrs = " << RVVI->getPolicyAttrsBits() << ";\n";
177bdd1243dSDimitry Andric 
17881ad6265SDimitry Andric   if (RVVI->hasManualCodegen()) {
179bdd1243dSDimitry Andric     OS << "IsMasked = " << (RVVI->isMasked() ? "true" : "false") << ";\n";
18081ad6265SDimitry Andric     OS << RVVI->getManualCodegen();
181fe6060f1SDimitry Andric     OS << "break;\n";
182fe6060f1SDimitry Andric     return;
183fe6060f1SDimitry Andric   }
184fe6060f1SDimitry Andric 
185753f127fSDimitry Andric   for (const auto &I : enumerate(RVVI->getInputTypes())) {
186753f127fSDimitry Andric     if (I.value()->isPointer()) {
187753f127fSDimitry Andric       assert(RVVI->getIntrinsicTypes().front() == -1 &&
188753f127fSDimitry Andric              "RVVI should be vector load intrinsic.");
189753f127fSDimitry Andric     }
190753f127fSDimitry Andric   }
191753f127fSDimitry Andric 
19281ad6265SDimitry Andric   if (RVVI->isMasked()) {
19381ad6265SDimitry Andric     if (RVVI->hasVL()) {
194fe6060f1SDimitry Andric       OS << "  std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1);\n";
19581ad6265SDimitry Andric       if (RVVI->hasPolicyOperand())
196349cc55cSDimitry Andric         OS << "  Ops.push_back(ConstantInt::get(Ops.back()->getType(),"
197bdd1243dSDimitry Andric               " PolicyAttrs));\n";
198bdd1243dSDimitry Andric       if (RVVI->hasMaskedOffOperand() && RVVI->getPolicyAttrs().isTAMAPolicy())
199bdd1243dSDimitry Andric         OS << "  Ops.insert(Ops.begin(), "
200bdd1243dSDimitry Andric               "llvm::PoisonValue::get(ResultType));\n";
201bdd1243dSDimitry Andric       // Masked reduction cases.
202bdd1243dSDimitry Andric       if (!RVVI->hasMaskedOffOperand() && RVVI->hasPassthruOperand() &&
203bdd1243dSDimitry Andric           RVVI->getPolicyAttrs().isTAMAPolicy())
204bdd1243dSDimitry Andric         OS << "  Ops.insert(Ops.begin(), "
205bdd1243dSDimitry Andric               "llvm::PoisonValue::get(ResultType));\n";
206fe6060f1SDimitry Andric     } else {
207fe6060f1SDimitry Andric       OS << "  std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end());\n";
208fe6060f1SDimitry Andric     }
20981ad6265SDimitry Andric   } else {
21081ad6265SDimitry Andric     if (RVVI->hasPolicyOperand())
21181ad6265SDimitry Andric       OS << "  Ops.push_back(ConstantInt::get(Ops.back()->getType(), "
212bdd1243dSDimitry Andric             "PolicyAttrs));\n";
213bdd1243dSDimitry Andric     else if (RVVI->hasPassthruOperand() && RVVI->getPolicyAttrs().isTAPolicy())
214bdd1243dSDimitry Andric       OS << "  Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType));\n";
215fe6060f1SDimitry Andric   }
216fe6060f1SDimitry Andric 
217fe6060f1SDimitry Andric   OS << "  IntrinsicTypes = {";
218fe6060f1SDimitry Andric   ListSeparator LS;
21981ad6265SDimitry Andric   for (const auto &Idx : RVVI->getIntrinsicTypes()) {
220fe6060f1SDimitry Andric     if (Idx == -1)
221fe6060f1SDimitry Andric       OS << LS << "ResultType";
222fe6060f1SDimitry Andric     else
223fe6060f1SDimitry Andric       OS << LS << "Ops[" << Idx << "]->getType()";
224fe6060f1SDimitry Andric   }
225fe6060f1SDimitry Andric 
226fe6060f1SDimitry Andric   // VL could be i64 or i32, need to encode it in IntrinsicTypes. VL is
227fe6060f1SDimitry Andric   // always last operand.
22881ad6265SDimitry Andric   if (RVVI->hasVL())
229fe6060f1SDimitry Andric     OS << ", Ops.back()->getType()";
230fe6060f1SDimitry Andric   OS << "};\n";
231fe6060f1SDimitry Andric   OS << "  break;\n";
232fe6060f1SDimitry Andric }
233fe6060f1SDimitry Andric 
234972a253aSDimitry Andric //===----------------------------------------------------------------------===//
235972a253aSDimitry Andric // SemaSignatureTable implementation
236972a253aSDimitry Andric //===----------------------------------------------------------------------===//
init(ArrayRef<SemaRecord> SemaRecords)237972a253aSDimitry Andric void SemaSignatureTable::init(ArrayRef<SemaRecord> SemaRecords) {
238972a253aSDimitry Andric   // Sort signature entries by length, let longer signature insert first, to
239972a253aSDimitry Andric   // make it more possible to reuse table entries, that can reduce ~10% table
240972a253aSDimitry Andric   // size.
241972a253aSDimitry Andric   struct Compare {
242972a253aSDimitry Andric     bool operator()(const SmallVector<PrototypeDescriptor> &A,
243972a253aSDimitry Andric                     const SmallVector<PrototypeDescriptor> &B) const {
244972a253aSDimitry Andric       if (A.size() != B.size())
245972a253aSDimitry Andric         return A.size() > B.size();
246972a253aSDimitry Andric 
247972a253aSDimitry Andric       size_t Len = A.size();
248972a253aSDimitry Andric       for (size_t i = 0; i < Len; ++i) {
249972a253aSDimitry Andric         if (A[i] != B[i])
250972a253aSDimitry Andric           return A[i] < B[i];
251fe6060f1SDimitry Andric       }
252fe6060f1SDimitry Andric 
253972a253aSDimitry Andric       return false;
254fe6060f1SDimitry Andric     }
255972a253aSDimitry Andric   };
256972a253aSDimitry Andric 
257972a253aSDimitry Andric   std::set<SmallVector<PrototypeDescriptor>, Compare> Signatures;
258972a253aSDimitry Andric   auto InsertToSignatureSet =
259972a253aSDimitry Andric       [&](const SmallVector<PrototypeDescriptor> &Signature) {
260972a253aSDimitry Andric         if (Signature.empty())
261972a253aSDimitry Andric           return;
262972a253aSDimitry Andric 
263972a253aSDimitry Andric         Signatures.insert(Signature);
264972a253aSDimitry Andric       };
265972a253aSDimitry Andric 
266972a253aSDimitry Andric   assert(!SemaRecords.empty());
267972a253aSDimitry Andric 
2685f757f3fSDimitry Andric   for (const SemaRecord &SR : SemaRecords) {
269972a253aSDimitry Andric     InsertToSignatureSet(SR.Prototype);
270972a253aSDimitry Andric     InsertToSignatureSet(SR.Suffix);
271972a253aSDimitry Andric     InsertToSignatureSet(SR.OverloadedSuffix);
2725f757f3fSDimitry Andric   }
273972a253aSDimitry Andric 
2745f757f3fSDimitry Andric   for (auto &Sig : Signatures)
2755f757f3fSDimitry Andric     insert(Sig);
276972a253aSDimitry Andric }
277972a253aSDimitry Andric 
insert(ArrayRef<PrototypeDescriptor> Signature)278972a253aSDimitry Andric void SemaSignatureTable::insert(ArrayRef<PrototypeDescriptor> Signature) {
279972a253aSDimitry Andric   if (getIndex(Signature) != INVALID_INDEX)
280972a253aSDimitry Andric     return;
281972a253aSDimitry Andric 
282972a253aSDimitry Andric   // Insert Signature into SignatureTable if not found in the table.
283972a253aSDimitry Andric   SignatureTable.insert(SignatureTable.begin(), Signature.begin(),
284972a253aSDimitry Andric                         Signature.end());
285972a253aSDimitry Andric }
286972a253aSDimitry Andric 
getIndex(ArrayRef<PrototypeDescriptor> Signature)287972a253aSDimitry Andric unsigned SemaSignatureTable::getIndex(ArrayRef<PrototypeDescriptor> Signature) {
288972a253aSDimitry Andric   // Empty signature could be point into any index since there is length
289972a253aSDimitry Andric   // field when we use, so just always point it to 0.
290972a253aSDimitry Andric   if (Signature.empty())
291972a253aSDimitry Andric     return 0;
292972a253aSDimitry Andric 
293972a253aSDimitry Andric   // Checking Signature already in table or not.
2945f757f3fSDimitry Andric   if (Signature.size() <= SignatureTable.size()) {
295972a253aSDimitry Andric     size_t Bound = SignatureTable.size() - Signature.size() + 1;
296972a253aSDimitry Andric     for (size_t Index = 0; Index < Bound; ++Index) {
297972a253aSDimitry Andric       if (equal(Signature.begin(), Signature.end(),
298972a253aSDimitry Andric                 SignatureTable.begin() + Index))
299972a253aSDimitry Andric         return Index;
300972a253aSDimitry Andric     }
301972a253aSDimitry Andric   }
302972a253aSDimitry Andric 
303972a253aSDimitry Andric   return INVALID_INDEX;
304972a253aSDimitry Andric }
305972a253aSDimitry Andric 
print(raw_ostream & OS)306972a253aSDimitry Andric void SemaSignatureTable::print(raw_ostream &OS) {
307972a253aSDimitry Andric   for (const auto &Sig : SignatureTable)
308972a253aSDimitry Andric     OS << "PrototypeDescriptor(" << static_cast<int>(Sig.PT) << ", "
309972a253aSDimitry Andric        << static_cast<int>(Sig.VTM) << ", " << static_cast<int>(Sig.TM)
310972a253aSDimitry Andric        << "),\n";
311fe6060f1SDimitry Andric }
312fe6060f1SDimitry Andric 
313fe6060f1SDimitry Andric //===----------------------------------------------------------------------===//
314fe6060f1SDimitry Andric // RVVEmitter implementation
315fe6060f1SDimitry Andric //===----------------------------------------------------------------------===//
createHeader(raw_ostream & OS)316fe6060f1SDimitry Andric void RVVEmitter::createHeader(raw_ostream &OS) {
317fe6060f1SDimitry Andric 
318fe6060f1SDimitry Andric   OS << "/*===---- riscv_vector.h - RISC-V V-extension RVVIntrinsics "
319fe6060f1SDimitry Andric         "-------------------===\n"
320fe6060f1SDimitry Andric         " *\n"
321fe6060f1SDimitry Andric         " *\n"
322fe6060f1SDimitry Andric         " * Part of the LLVM Project, under the Apache License v2.0 with LLVM "
323fe6060f1SDimitry Andric         "Exceptions.\n"
324fe6060f1SDimitry Andric         " * See https://llvm.org/LICENSE.txt for license information.\n"
325fe6060f1SDimitry Andric         " * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n"
326fe6060f1SDimitry Andric         " *\n"
327fe6060f1SDimitry Andric         " *===-----------------------------------------------------------------"
328fe6060f1SDimitry Andric         "------===\n"
329fe6060f1SDimitry Andric         " */\n\n";
330fe6060f1SDimitry Andric 
331fe6060f1SDimitry Andric   OS << "#ifndef __RISCV_VECTOR_H\n";
332fe6060f1SDimitry Andric   OS << "#define __RISCV_VECTOR_H\n\n";
333fe6060f1SDimitry Andric 
334fe6060f1SDimitry Andric   OS << "#include <stdint.h>\n";
335fe6060f1SDimitry Andric   OS << "#include <stddef.h>\n\n";
336fe6060f1SDimitry Andric 
337fe6060f1SDimitry Andric   OS << "#ifdef __cplusplus\n";
338fe6060f1SDimitry Andric   OS << "extern \"C\" {\n";
339fe6060f1SDimitry Andric   OS << "#endif\n\n";
340fe6060f1SDimitry Andric 
341972a253aSDimitry Andric   OS << "#pragma clang riscv intrinsic vector\n\n";
342349cc55cSDimitry Andric 
343972a253aSDimitry Andric   printHeaderCode(OS);
344fe6060f1SDimitry Andric 
345fe6060f1SDimitry Andric   auto printType = [&](auto T) {
346fe6060f1SDimitry Andric     OS << "typedef " << T->getClangBuiltinStr() << " " << T->getTypeStr()
347fe6060f1SDimitry Andric        << ";\n";
348fe6060f1SDimitry Andric   };
349fe6060f1SDimitry Andric 
350fe6060f1SDimitry Andric   constexpr int Log2LMULs[] = {-3, -2, -1, 0, 1, 2, 3};
351fe6060f1SDimitry Andric   // Print RVV boolean types.
352fe6060f1SDimitry Andric   for (int Log2LMUL : Log2LMULs) {
353bdd1243dSDimitry Andric     auto T = TypeCache.computeType(BasicType::Int8, Log2LMUL,
35481ad6265SDimitry Andric                                    PrototypeDescriptor::Mask);
35581ad6265SDimitry Andric     if (T)
356bdd1243dSDimitry Andric       printType(*T);
357fe6060f1SDimitry Andric   }
358fe6060f1SDimitry Andric   // Print RVV int/float types.
359fe6060f1SDimitry Andric   for (char I : StringRef("csil")) {
36081ad6265SDimitry Andric     BasicType BT = ParseBasicType(I);
361fe6060f1SDimitry Andric     for (int Log2LMUL : Log2LMULs) {
362bdd1243dSDimitry Andric       auto T = TypeCache.computeType(BT, Log2LMUL, PrototypeDescriptor::Vector);
36381ad6265SDimitry Andric       if (T) {
364bdd1243dSDimitry Andric         printType(*T);
365bdd1243dSDimitry Andric         auto UT = TypeCache.computeType(
36681ad6265SDimitry Andric             BT, Log2LMUL,
36781ad6265SDimitry Andric             PrototypeDescriptor(BaseTypeModifier::Vector,
36881ad6265SDimitry Andric                                 VectorTypeModifier::NoModifier,
36981ad6265SDimitry Andric                                 TypeModifier::UnsignedInteger));
370bdd1243dSDimitry Andric         printType(*UT);
371fe6060f1SDimitry Andric       }
37206c3fb27SDimitry Andric       for (int NF = 2; NF <= 8; ++NF) {
37306c3fb27SDimitry Andric         auto TupleT = TypeCache.computeType(
37406c3fb27SDimitry Andric             BT, Log2LMUL,
37506c3fb27SDimitry Andric             PrototypeDescriptor(BaseTypeModifier::Vector, getTupleVTM(NF),
37606c3fb27SDimitry Andric                                 TypeModifier::SignedInteger));
37706c3fb27SDimitry Andric         auto TupleUT = TypeCache.computeType(
37806c3fb27SDimitry Andric             BT, Log2LMUL,
37906c3fb27SDimitry Andric             PrototypeDescriptor(BaseTypeModifier::Vector, getTupleVTM(NF),
38006c3fb27SDimitry Andric                                 TypeModifier::UnsignedInteger));
38106c3fb27SDimitry Andric         if (TupleT)
38206c3fb27SDimitry Andric           printType(*TupleT);
38306c3fb27SDimitry Andric         if (TupleUT)
38406c3fb27SDimitry Andric           printType(*TupleUT);
385fe6060f1SDimitry Andric       }
386fe6060f1SDimitry Andric     }
387fe6060f1SDimitry Andric   }
388fe6060f1SDimitry Andric 
3895f757f3fSDimitry Andric   for (BasicType BT : {BasicType::Float16, BasicType::Float32,
3905f757f3fSDimitry Andric                        BasicType::Float64, BasicType::BFloat16}) {
391fe6060f1SDimitry Andric     for (int Log2LMUL : Log2LMULs) {
39206c3fb27SDimitry Andric       auto T = TypeCache.computeType(BT, Log2LMUL, PrototypeDescriptor::Vector);
39381ad6265SDimitry Andric       if (T)
394bdd1243dSDimitry Andric         printType(*T);
39506c3fb27SDimitry Andric       for (int NF = 2; NF <= 8; ++NF) {
39606c3fb27SDimitry Andric         auto TupleT = TypeCache.computeType(
39706c3fb27SDimitry Andric             BT, Log2LMUL,
39806c3fb27SDimitry Andric             PrototypeDescriptor(BaseTypeModifier::Vector, getTupleVTM(NF),
3995f757f3fSDimitry Andric                                 (BT == BasicType::BFloat16
4005f757f3fSDimitry Andric                                      ? TypeModifier::BFloat
4015f757f3fSDimitry Andric                                      : TypeModifier::Float)));
40206c3fb27SDimitry Andric         if (TupleT)
40306c3fb27SDimitry Andric           printType(*TupleT);
404fe6060f1SDimitry Andric       }
405fe6060f1SDimitry Andric     }
40606c3fb27SDimitry Andric   }
407fe6060f1SDimitry Andric 
408fe6060f1SDimitry Andric   OS << "#define __riscv_v_intrinsic_overloading 1\n";
409fe6060f1SDimitry Andric 
410fe6060f1SDimitry Andric   OS << "\n#ifdef __cplusplus\n";
411fe6060f1SDimitry Andric   OS << "}\n";
412349cc55cSDimitry Andric   OS << "#endif // __cplusplus\n";
413fe6060f1SDimitry Andric   OS << "#endif // __RISCV_VECTOR_H\n";
414fe6060f1SDimitry Andric }
415fe6060f1SDimitry Andric 
createBuiltins(raw_ostream & OS)416fe6060f1SDimitry Andric void RVVEmitter::createBuiltins(raw_ostream &OS) {
417fe6060f1SDimitry Andric   std::vector<std::unique_ptr<RVVIntrinsic>> Defs;
418fe6060f1SDimitry Andric   createRVVIntrinsics(Defs);
419fe6060f1SDimitry Andric 
420349cc55cSDimitry Andric   // Map to keep track of which builtin names have already been emitted.
421349cc55cSDimitry Andric   StringMap<RVVIntrinsic *> BuiltinMap;
422349cc55cSDimitry Andric 
423fe6060f1SDimitry Andric   OS << "#if defined(TARGET_BUILTIN) && !defined(RISCVV_BUILTIN)\n";
424fe6060f1SDimitry Andric   OS << "#define RISCVV_BUILTIN(ID, TYPE, ATTRS) TARGET_BUILTIN(ID, TYPE, "
42581ad6265SDimitry Andric         "ATTRS, \"zve32x\")\n";
426fe6060f1SDimitry Andric   OS << "#endif\n";
427fe6060f1SDimitry Andric   for (auto &Def : Defs) {
428349cc55cSDimitry Andric     auto P =
429349cc55cSDimitry Andric         BuiltinMap.insert(std::make_pair(Def->getBuiltinName(), Def.get()));
430349cc55cSDimitry Andric     if (!P.second) {
43181ad6265SDimitry Andric       // Verf that this would have produced the same builtin definition.
43281ad6265SDimitry Andric       if (P.first->second->hasBuiltinAlias() != Def->hasBuiltinAlias())
433349cc55cSDimitry Andric         PrintFatalError("Builtin with same name has different hasAutoDef");
43481ad6265SDimitry Andric       else if (!Def->hasBuiltinAlias() &&
43581ad6265SDimitry Andric                P.first->second->getBuiltinTypeStr() != Def->getBuiltinTypeStr())
436349cc55cSDimitry Andric         PrintFatalError("Builtin with same name has different type string");
437349cc55cSDimitry Andric       continue;
438349cc55cSDimitry Andric     }
439349cc55cSDimitry Andric     OS << "RISCVV_BUILTIN(__builtin_rvv_" << Def->getBuiltinName() << ",\"";
44081ad6265SDimitry Andric     if (!Def->hasBuiltinAlias())
441349cc55cSDimitry Andric       OS << Def->getBuiltinTypeStr();
442349cc55cSDimitry Andric     OS << "\", \"n\")\n";
443fe6060f1SDimitry Andric   }
444fe6060f1SDimitry Andric   OS << "#undef RISCVV_BUILTIN\n";
445fe6060f1SDimitry Andric }
446fe6060f1SDimitry Andric 
createCodeGen(raw_ostream & OS)447fe6060f1SDimitry Andric void RVVEmitter::createCodeGen(raw_ostream &OS) {
448fe6060f1SDimitry Andric   std::vector<std::unique_ptr<RVVIntrinsic>> Defs;
449fe6060f1SDimitry Andric   createRVVIntrinsics(Defs);
450fe6060f1SDimitry Andric   // IR name could be empty, use the stable sort preserves the relative order.
451349cc55cSDimitry Andric   llvm::stable_sort(Defs, [](const std::unique_ptr<RVVIntrinsic> &A,
452fe6060f1SDimitry Andric                              const std::unique_ptr<RVVIntrinsic> &B) {
453bdd1243dSDimitry Andric     if (A->getIRName() == B->getIRName())
454bdd1243dSDimitry Andric       return (A->getPolicyAttrs() < B->getPolicyAttrs());
455bdd1243dSDimitry Andric     return (A->getIRName() < B->getIRName());
456fe6060f1SDimitry Andric   });
457349cc55cSDimitry Andric 
458349cc55cSDimitry Andric   // Map to keep track of which builtin names have already been emitted.
459349cc55cSDimitry Andric   StringMap<RVVIntrinsic *> BuiltinMap;
460349cc55cSDimitry Andric 
461bdd1243dSDimitry Andric   // Print switch body when the ir name, ManualCodegen or policy changes from
462bdd1243dSDimitry Andric   // previous iteration.
463fe6060f1SDimitry Andric   RVVIntrinsic *PrevDef = Defs.begin()->get();
464fe6060f1SDimitry Andric   for (auto &Def : Defs) {
465fe6060f1SDimitry Andric     StringRef CurIRName = Def->getIRName();
466fe6060f1SDimitry Andric     if (CurIRName != PrevDef->getIRName() ||
467bdd1243dSDimitry Andric         (Def->getManualCodegen() != PrevDef->getManualCodegen()) ||
468bdd1243dSDimitry Andric         (Def->getPolicyAttrs() != PrevDef->getPolicyAttrs())) {
46981ad6265SDimitry Andric       emitCodeGenSwitchBody(PrevDef, OS);
470fe6060f1SDimitry Andric     }
471fe6060f1SDimitry Andric     PrevDef = Def.get();
472349cc55cSDimitry Andric 
473349cc55cSDimitry Andric     auto P =
474349cc55cSDimitry Andric         BuiltinMap.insert(std::make_pair(Def->getBuiltinName(), Def.get()));
475349cc55cSDimitry Andric     if (P.second) {
476349cc55cSDimitry Andric       OS << "case RISCVVector::BI__builtin_rvv_" << Def->getBuiltinName()
477349cc55cSDimitry Andric          << ":\n";
478349cc55cSDimitry Andric       continue;
479349cc55cSDimitry Andric     }
480349cc55cSDimitry Andric 
481349cc55cSDimitry Andric     if (P.first->second->getIRName() != Def->getIRName())
482349cc55cSDimitry Andric       PrintFatalError("Builtin with same name has different IRName");
483349cc55cSDimitry Andric     else if (P.first->second->getManualCodegen() != Def->getManualCodegen())
484349cc55cSDimitry Andric       PrintFatalError("Builtin with same name has different ManualCodegen");
48581ad6265SDimitry Andric     else if (P.first->second->isMasked() != Def->isMasked())
48681ad6265SDimitry Andric       PrintFatalError("Builtin with same name has different isMasked");
487349cc55cSDimitry Andric     else if (P.first->second->hasVL() != Def->hasVL())
48881ad6265SDimitry Andric       PrintFatalError("Builtin with same name has different hasVL");
48981ad6265SDimitry Andric     else if (P.first->second->getPolicyScheme() != Def->getPolicyScheme())
49081ad6265SDimitry Andric       PrintFatalError("Builtin with same name has different getPolicyScheme");
491349cc55cSDimitry Andric     else if (P.first->second->getIntrinsicTypes() != Def->getIntrinsicTypes())
492349cc55cSDimitry Andric       PrintFatalError("Builtin with same name has different IntrinsicTypes");
493fe6060f1SDimitry Andric   }
49481ad6265SDimitry Andric   emitCodeGenSwitchBody(Defs.back().get(), OS);
495fe6060f1SDimitry Andric   OS << "\n";
496fe6060f1SDimitry Andric }
497fe6060f1SDimitry Andric 
createRVVIntrinsics(std::vector<std::unique_ptr<RVVIntrinsic>> & Out,std::vector<SemaRecord> * SemaRecords)498fe6060f1SDimitry Andric void RVVEmitter::createRVVIntrinsics(
499972a253aSDimitry Andric     std::vector<std::unique_ptr<RVVIntrinsic>> &Out,
500972a253aSDimitry Andric     std::vector<SemaRecord> *SemaRecords) {
501fe6060f1SDimitry Andric   std::vector<Record *> RV = Records.getAllDerivedDefinitions("RVVBuiltin");
502fe6060f1SDimitry Andric   for (auto *R : RV) {
503fe6060f1SDimitry Andric     StringRef Name = R->getValueAsString("Name");
504fe6060f1SDimitry Andric     StringRef SuffixProto = R->getValueAsString("Suffix");
50581ad6265SDimitry Andric     StringRef OverloadedName = R->getValueAsString("OverloadedName");
50681ad6265SDimitry Andric     StringRef OverloadedSuffixProto = R->getValueAsString("OverloadedSuffix");
507fe6060f1SDimitry Andric     StringRef Prototypes = R->getValueAsString("Prototype");
508fe6060f1SDimitry Andric     StringRef TypeRange = R->getValueAsString("TypeRange");
50981ad6265SDimitry Andric     bool HasMasked = R->getValueAsBit("HasMasked");
510fe6060f1SDimitry Andric     bool HasMaskedOffOperand = R->getValueAsBit("HasMaskedOffOperand");
511fe6060f1SDimitry Andric     bool HasVL = R->getValueAsBit("HasVL");
512972a253aSDimitry Andric     Record *MPSRecord = R->getValueAsDef("MaskedPolicyScheme");
513972a253aSDimitry Andric     auto MaskedPolicyScheme =
514972a253aSDimitry Andric         static_cast<PolicyScheme>(MPSRecord->getValueAsInt("Value"));
515972a253aSDimitry Andric     Record *UMPSRecord = R->getValueAsDef("UnMaskedPolicyScheme");
516972a253aSDimitry Andric     auto UnMaskedPolicyScheme =
517972a253aSDimitry Andric         static_cast<PolicyScheme>(UMPSRecord->getValueAsInt("Value"));
518fe6060f1SDimitry Andric     std::vector<int64_t> Log2LMULList = R->getValueAsListOfInts("Log2LMUL");
519bdd1243dSDimitry Andric     bool HasTailPolicy = R->getValueAsBit("HasTailPolicy");
520bdd1243dSDimitry Andric     bool HasMaskPolicy = R->getValueAsBit("HasMaskPolicy");
521bdd1243dSDimitry Andric     bool SupportOverloading = R->getValueAsBit("SupportOverloading");
52281ad6265SDimitry Andric     bool HasBuiltinAlias = R->getValueAsBit("HasBuiltinAlias");
523fe6060f1SDimitry Andric     StringRef ManualCodegen = R->getValueAsString("ManualCodegen");
524fe6060f1SDimitry Andric     std::vector<int64_t> IntrinsicTypes =
525fe6060f1SDimitry Andric         R->getValueAsListOfInts("IntrinsicTypes");
52604eeddc0SDimitry Andric     std::vector<StringRef> RequiredFeatures =
52704eeddc0SDimitry Andric         R->getValueAsListOfStrings("RequiredFeatures");
528fe6060f1SDimitry Andric     StringRef IRName = R->getValueAsString("IRName");
52981ad6265SDimitry Andric     StringRef MaskedIRName = R->getValueAsString("MaskedIRName");
530fe6060f1SDimitry Andric     unsigned NF = R->getValueAsInt("NF");
53106c3fb27SDimitry Andric     bool IsTuple = R->getValueAsBit("IsTuple");
53206c3fb27SDimitry Andric     bool HasFRMRoundModeOp = R->getValueAsBit("HasFRMRoundModeOp");
533fe6060f1SDimitry Andric 
5341ac55f4cSDimitry Andric     const Policy DefaultPolicy;
535bdd1243dSDimitry Andric     SmallVector<Policy> SupportedUnMaskedPolicies =
5361ac55f4cSDimitry Andric         RVVIntrinsic::getSupportedUnMaskedPolicies();
537bdd1243dSDimitry Andric     SmallVector<Policy> SupportedMaskedPolicies =
538bdd1243dSDimitry Andric         RVVIntrinsic::getSupportedMaskedPolicies(HasTailPolicy, HasMaskPolicy);
539bdd1243dSDimitry Andric 
540fe6060f1SDimitry Andric     // Parse prototype and create a list of primitive type with transformers
54181ad6265SDimitry Andric     // (operand) in Prototype. Prototype[0] is output operand.
542972a253aSDimitry Andric     SmallVector<PrototypeDescriptor> BasicPrototype =
543972a253aSDimitry Andric         parsePrototypes(Prototypes);
54481ad6265SDimitry Andric 
54581ad6265SDimitry Andric     SmallVector<PrototypeDescriptor> SuffixDesc = parsePrototypes(SuffixProto);
54681ad6265SDimitry Andric     SmallVector<PrototypeDescriptor> OverloadedSuffixDesc =
54781ad6265SDimitry Andric         parsePrototypes(OverloadedSuffixProto);
548fe6060f1SDimitry Andric 
549fe6060f1SDimitry Andric     // Compute Builtin types
550972a253aSDimitry Andric     auto Prototype = RVVIntrinsic::computeBuiltinTypes(
551bdd1243dSDimitry Andric         BasicPrototype, /*IsMasked=*/false,
552bdd1243dSDimitry Andric         /*HasMaskedOffOperand=*/false, HasVL, NF, UnMaskedPolicyScheme,
55306c3fb27SDimitry Andric         DefaultPolicy, IsTuple);
55406c3fb27SDimitry Andric     llvm::SmallVector<PrototypeDescriptor> MaskedPrototype;
55506c3fb27SDimitry Andric     if (HasMasked)
55606c3fb27SDimitry Andric       MaskedPrototype = RVVIntrinsic::computeBuiltinTypes(
557bdd1243dSDimitry Andric           BasicPrototype, /*IsMasked=*/true, HasMaskedOffOperand, HasVL, NF,
55806c3fb27SDimitry Andric           MaskedPolicyScheme, DefaultPolicy, IsTuple);
559fe6060f1SDimitry Andric 
560fe6060f1SDimitry Andric     // Create Intrinsics for each type and LMUL.
561fe6060f1SDimitry Andric     for (char I : TypeRange) {
562fe6060f1SDimitry Andric       for (int Log2LMUL : Log2LMULList) {
56381ad6265SDimitry Andric         BasicType BT = ParseBasicType(I);
564bdd1243dSDimitry Andric         std::optional<RVVTypes> Types =
565bdd1243dSDimitry Andric             TypeCache.computeTypes(BT, Log2LMUL, NF, Prototype);
566fe6060f1SDimitry Andric         // Ignored to create new intrinsic if there are any illegal types.
56781ad6265SDimitry Andric         if (!Types)
568fe6060f1SDimitry Andric           continue;
569fe6060f1SDimitry Andric 
570bdd1243dSDimitry Andric         auto SuffixStr =
571bdd1243dSDimitry Andric             RVVIntrinsic::getSuffixStr(TypeCache, BT, Log2LMUL, SuffixDesc);
572bdd1243dSDimitry Andric         auto OverloadedSuffixStr = RVVIntrinsic::getSuffixStr(
573bdd1243dSDimitry Andric             TypeCache, BT, Log2LMUL, OverloadedSuffixDesc);
57481ad6265SDimitry Andric         // Create a unmasked intrinsic
575fe6060f1SDimitry Andric         Out.push_back(std::make_unique<RVVIntrinsic>(
57681ad6265SDimitry Andric             Name, SuffixStr, OverloadedName, OverloadedSuffixStr, IRName,
57781ad6265SDimitry Andric             /*IsMasked=*/false, /*HasMaskedOffOperand=*/false, HasVL,
578bdd1243dSDimitry Andric             UnMaskedPolicyScheme, SupportOverloading, HasBuiltinAlias,
579*0fca6ea1SDimitry Andric             ManualCodegen, *Types, IntrinsicTypes, NF, DefaultPolicy,
580*0fca6ea1SDimitry Andric             HasFRMRoundModeOp));
581bdd1243dSDimitry Andric         if (UnMaskedPolicyScheme != PolicyScheme::SchemeNone)
582bdd1243dSDimitry Andric           for (auto P : SupportedUnMaskedPolicies) {
583bdd1243dSDimitry Andric             SmallVector<PrototypeDescriptor> PolicyPrototype =
584bdd1243dSDimitry Andric                 RVVIntrinsic::computeBuiltinTypes(
585bdd1243dSDimitry Andric                     BasicPrototype, /*IsMasked=*/false,
586bdd1243dSDimitry Andric                     /*HasMaskedOffOperand=*/false, HasVL, NF,
58706c3fb27SDimitry Andric                     UnMaskedPolicyScheme, P, IsTuple);
588bdd1243dSDimitry Andric             std::optional<RVVTypes> PolicyTypes =
589bdd1243dSDimitry Andric                 TypeCache.computeTypes(BT, Log2LMUL, NF, PolicyPrototype);
590bdd1243dSDimitry Andric             Out.push_back(std::make_unique<RVVIntrinsic>(
591bdd1243dSDimitry Andric                 Name, SuffixStr, OverloadedName, OverloadedSuffixStr, IRName,
592bdd1243dSDimitry Andric                 /*IsMask=*/false, /*HasMaskedOffOperand=*/false, HasVL,
593bdd1243dSDimitry Andric                 UnMaskedPolicyScheme, SupportOverloading, HasBuiltinAlias,
594*0fca6ea1SDimitry Andric                 ManualCodegen, *PolicyTypes, IntrinsicTypes, NF, P,
595*0fca6ea1SDimitry Andric                 HasFRMRoundModeOp));
596bdd1243dSDimitry Andric           }
597bdd1243dSDimitry Andric         if (!HasMasked)
598bdd1243dSDimitry Andric           continue;
59981ad6265SDimitry Andric         // Create a masked intrinsic
600bdd1243dSDimitry Andric         std::optional<RVVTypes> MaskTypes =
601bdd1243dSDimitry Andric             TypeCache.computeTypes(BT, Log2LMUL, NF, MaskedPrototype);
602bdd1243dSDimitry Andric         Out.push_back(std::make_unique<RVVIntrinsic>(
603bdd1243dSDimitry Andric             Name, SuffixStr, OverloadedName, OverloadedSuffixStr, MaskedIRName,
604bdd1243dSDimitry Andric             /*IsMasked=*/true, HasMaskedOffOperand, HasVL, MaskedPolicyScheme,
605bdd1243dSDimitry Andric             SupportOverloading, HasBuiltinAlias, ManualCodegen, *MaskTypes,
606*0fca6ea1SDimitry Andric             IntrinsicTypes, NF, DefaultPolicy, HasFRMRoundModeOp));
607bdd1243dSDimitry Andric         if (MaskedPolicyScheme == PolicyScheme::SchemeNone)
608bdd1243dSDimitry Andric           continue;
609bdd1243dSDimitry Andric         for (auto P : SupportedMaskedPolicies) {
610bdd1243dSDimitry Andric           SmallVector<PrototypeDescriptor> PolicyPrototype =
611bdd1243dSDimitry Andric               RVVIntrinsic::computeBuiltinTypes(
612bdd1243dSDimitry Andric                   BasicPrototype, /*IsMasked=*/true, HasMaskedOffOperand, HasVL,
61306c3fb27SDimitry Andric                   NF, MaskedPolicyScheme, P, IsTuple);
614bdd1243dSDimitry Andric           std::optional<RVVTypes> PolicyTypes =
615bdd1243dSDimitry Andric               TypeCache.computeTypes(BT, Log2LMUL, NF, PolicyPrototype);
616fe6060f1SDimitry Andric           Out.push_back(std::make_unique<RVVIntrinsic>(
61781ad6265SDimitry Andric               Name, SuffixStr, OverloadedName, OverloadedSuffixStr,
618bdd1243dSDimitry Andric               MaskedIRName, /*IsMasked=*/true, HasMaskedOffOperand, HasVL,
619bdd1243dSDimitry Andric               MaskedPolicyScheme, SupportOverloading, HasBuiltinAlias,
620*0fca6ea1SDimitry Andric               ManualCodegen, *PolicyTypes, IntrinsicTypes, NF, P,
621*0fca6ea1SDimitry Andric               HasFRMRoundModeOp));
622fe6060f1SDimitry Andric         }
623bdd1243dSDimitry Andric       } // End for Log2LMULList
624bdd1243dSDimitry Andric     }   // End for TypeRange
625972a253aSDimitry Andric 
626972a253aSDimitry Andric     // We don't emit vsetvli and vsetvlimax for SemaRecord.
627972a253aSDimitry Andric     // They are written in riscv_vector.td and will emit those marco define in
628972a253aSDimitry Andric     // riscv_vector.h
629972a253aSDimitry Andric     if (Name == "vsetvli" || Name == "vsetvlimax")
630972a253aSDimitry Andric       continue;
631972a253aSDimitry Andric 
632972a253aSDimitry Andric     if (!SemaRecords)
633972a253aSDimitry Andric       continue;
634972a253aSDimitry Andric 
635972a253aSDimitry Andric     // Create SemaRecord
636972a253aSDimitry Andric     SemaRecord SR;
637972a253aSDimitry Andric     SR.Name = Name.str();
638972a253aSDimitry Andric     SR.OverloadedName = OverloadedName.str();
639972a253aSDimitry Andric     BasicType TypeRangeMask = BasicType::Unknown;
640972a253aSDimitry Andric     for (char I : TypeRange)
641972a253aSDimitry Andric       TypeRangeMask |= ParseBasicType(I);
642972a253aSDimitry Andric 
643972a253aSDimitry Andric     SR.TypeRangeMask = static_cast<unsigned>(TypeRangeMask);
644972a253aSDimitry Andric 
645972a253aSDimitry Andric     unsigned Log2LMULMask = 0;
646972a253aSDimitry Andric     for (int Log2LMUL : Log2LMULList)
647972a253aSDimitry Andric       Log2LMULMask |= 1 << (Log2LMUL + 3);
648972a253aSDimitry Andric 
649972a253aSDimitry Andric     SR.Log2LMULMask = Log2LMULMask;
650972a253aSDimitry Andric 
651972a253aSDimitry Andric     SR.RequiredExtensions = 0;
652972a253aSDimitry Andric     for (auto RequiredFeature : RequiredFeatures) {
653cb14a3feSDimitry Andric       RVVRequire RequireExt =
654cb14a3feSDimitry Andric           StringSwitch<RVVRequire>(RequiredFeature)
655972a253aSDimitry Andric               .Case("RV64", RVV_REQ_RV64)
6567a6dacacSDimitry Andric               .Case("Zvfhmin", RVV_REQ_Zvfhmin)
65706c3fb27SDimitry Andric               .Case("Xsfvcp", RVV_REQ_Xsfvcp)
6585f757f3fSDimitry Andric               .Case("Xsfvfnrclipxfqf", RVV_REQ_Xsfvfnrclipxfqf)
6595f757f3fSDimitry Andric               .Case("Xsfvfwmaccqqq", RVV_REQ_Xsfvfwmaccqqq)
6605f757f3fSDimitry Andric               .Case("Xsfvqmaccdod", RVV_REQ_Xsfvqmaccdod)
6615f757f3fSDimitry Andric               .Case("Xsfvqmaccqoq", RVV_REQ_Xsfvqmaccqoq)
6625f757f3fSDimitry Andric               .Case("Zvbb", RVV_REQ_Zvbb)
6635f757f3fSDimitry Andric               .Case("Zvbc", RVV_REQ_Zvbc)
6645f757f3fSDimitry Andric               .Case("Zvkb", RVV_REQ_Zvkb)
6655f757f3fSDimitry Andric               .Case("Zvkg", RVV_REQ_Zvkg)
6665f757f3fSDimitry Andric               .Case("Zvkned", RVV_REQ_Zvkned)
6675f757f3fSDimitry Andric               .Case("Zvknha", RVV_REQ_Zvknha)
6685f757f3fSDimitry Andric               .Case("Zvknhb", RVV_REQ_Zvknhb)
6695f757f3fSDimitry Andric               .Case("Zvksed", RVV_REQ_Zvksed)
6705f757f3fSDimitry Andric               .Case("Zvksh", RVV_REQ_Zvksh)
671*0fca6ea1SDimitry Andric               .Case("Zvfbfwma", RVV_REQ_Zvfbfwma)
672*0fca6ea1SDimitry Andric               .Case("Zvfbfmin", RVV_REQ_Zvfbfmin)
673cb14a3feSDimitry Andric               .Case("Experimental", RVV_REQ_Experimental)
674972a253aSDimitry Andric               .Default(RVV_REQ_None);
675972a253aSDimitry Andric       assert(RequireExt != RVV_REQ_None && "Unrecognized required feature?");
676972a253aSDimitry Andric       SR.RequiredExtensions |= RequireExt;
677972a253aSDimitry Andric     }
678972a253aSDimitry Andric 
679972a253aSDimitry Andric     SR.NF = NF;
680972a253aSDimitry Andric     SR.HasMasked = HasMasked;
681972a253aSDimitry Andric     SR.HasVL = HasVL;
682972a253aSDimitry Andric     SR.HasMaskedOffOperand = HasMaskedOffOperand;
683bdd1243dSDimitry Andric     SR.HasTailPolicy = HasTailPolicy;
684bdd1243dSDimitry Andric     SR.HasMaskPolicy = HasMaskPolicy;
685bdd1243dSDimitry Andric     SR.UnMaskedPolicyScheme = static_cast<uint8_t>(UnMaskedPolicyScheme);
686bdd1243dSDimitry Andric     SR.MaskedPolicyScheme = static_cast<uint8_t>(MaskedPolicyScheme);
687972a253aSDimitry Andric     SR.Prototype = std::move(BasicPrototype);
688972a253aSDimitry Andric     SR.Suffix = parsePrototypes(SuffixProto);
689972a253aSDimitry Andric     SR.OverloadedSuffix = parsePrototypes(OverloadedSuffixProto);
69006c3fb27SDimitry Andric     SR.IsTuple = IsTuple;
69106c3fb27SDimitry Andric     SR.HasFRMRoundModeOp = HasFRMRoundModeOp;
692972a253aSDimitry Andric 
693972a253aSDimitry Andric     SemaRecords->push_back(SR);
694fe6060f1SDimitry Andric   }
695fe6060f1SDimitry Andric }
696fe6060f1SDimitry Andric 
printHeaderCode(raw_ostream & OS)69781ad6265SDimitry Andric void RVVEmitter::printHeaderCode(raw_ostream &OS) {
698349cc55cSDimitry Andric   std::vector<Record *> RVVHeaders =
699349cc55cSDimitry Andric       Records.getAllDerivedDefinitions("RVVHeader");
700349cc55cSDimitry Andric   for (auto *R : RVVHeaders) {
701349cc55cSDimitry Andric     StringRef HeaderCodeStr = R->getValueAsString("HeaderCode");
702349cc55cSDimitry Andric     OS << HeaderCodeStr.str();
703349cc55cSDimitry Andric   }
704349cc55cSDimitry Andric }
705349cc55cSDimitry Andric 
createRVVIntrinsicRecords(std::vector<RVVIntrinsicRecord> & Out,SemaSignatureTable & SST,ArrayRef<SemaRecord> SemaRecords)706972a253aSDimitry Andric void RVVEmitter::createRVVIntrinsicRecords(std::vector<RVVIntrinsicRecord> &Out,
707972a253aSDimitry Andric                                            SemaSignatureTable &SST,
708972a253aSDimitry Andric                                            ArrayRef<SemaRecord> SemaRecords) {
709972a253aSDimitry Andric   SST.init(SemaRecords);
710972a253aSDimitry Andric 
711972a253aSDimitry Andric   for (const auto &SR : SemaRecords) {
712972a253aSDimitry Andric     Out.emplace_back(RVVIntrinsicRecord());
713972a253aSDimitry Andric     RVVIntrinsicRecord &R = Out.back();
714972a253aSDimitry Andric     R.Name = SR.Name.c_str();
715972a253aSDimitry Andric     R.OverloadedName = SR.OverloadedName.c_str();
716972a253aSDimitry Andric     R.PrototypeIndex = SST.getIndex(SR.Prototype);
717972a253aSDimitry Andric     R.SuffixIndex = SST.getIndex(SR.Suffix);
718972a253aSDimitry Andric     R.OverloadedSuffixIndex = SST.getIndex(SR.OverloadedSuffix);
719972a253aSDimitry Andric     R.PrototypeLength = SR.Prototype.size();
720972a253aSDimitry Andric     R.SuffixLength = SR.Suffix.size();
721972a253aSDimitry Andric     R.OverloadedSuffixSize = SR.OverloadedSuffix.size();
722972a253aSDimitry Andric     R.RequiredExtensions = SR.RequiredExtensions;
723972a253aSDimitry Andric     R.TypeRangeMask = SR.TypeRangeMask;
724972a253aSDimitry Andric     R.Log2LMULMask = SR.Log2LMULMask;
725972a253aSDimitry Andric     R.NF = SR.NF;
726972a253aSDimitry Andric     R.HasMasked = SR.HasMasked;
727972a253aSDimitry Andric     R.HasVL = SR.HasVL;
728972a253aSDimitry Andric     R.HasMaskedOffOperand = SR.HasMaskedOffOperand;
729bdd1243dSDimitry Andric     R.HasTailPolicy = SR.HasTailPolicy;
730bdd1243dSDimitry Andric     R.HasMaskPolicy = SR.HasMaskPolicy;
731bdd1243dSDimitry Andric     R.UnMaskedPolicyScheme = SR.UnMaskedPolicyScheme;
732bdd1243dSDimitry Andric     R.MaskedPolicyScheme = SR.MaskedPolicyScheme;
73306c3fb27SDimitry Andric     R.IsTuple = SR.IsTuple;
73406c3fb27SDimitry Andric     R.HasFRMRoundModeOp = SR.HasFRMRoundModeOp;
735972a253aSDimitry Andric 
736972a253aSDimitry Andric     assert(R.PrototypeIndex !=
737972a253aSDimitry Andric            static_cast<uint16_t>(SemaSignatureTable::INVALID_INDEX));
738972a253aSDimitry Andric     assert(R.SuffixIndex !=
739972a253aSDimitry Andric            static_cast<uint16_t>(SemaSignatureTable::INVALID_INDEX));
740972a253aSDimitry Andric     assert(R.OverloadedSuffixIndex !=
741972a253aSDimitry Andric            static_cast<uint16_t>(SemaSignatureTable::INVALID_INDEX));
742fe6060f1SDimitry Andric   }
743fe6060f1SDimitry Andric }
744fe6060f1SDimitry Andric 
createSema(raw_ostream & OS)745972a253aSDimitry Andric void RVVEmitter::createSema(raw_ostream &OS) {
746972a253aSDimitry Andric   std::vector<std::unique_ptr<RVVIntrinsic>> Defs;
747972a253aSDimitry Andric   std::vector<RVVIntrinsicRecord> RVVIntrinsicRecords;
748972a253aSDimitry Andric   SemaSignatureTable SST;
749972a253aSDimitry Andric   std::vector<SemaRecord> SemaRecords;
750972a253aSDimitry Andric 
751972a253aSDimitry Andric   createRVVIntrinsics(Defs, &SemaRecords);
752972a253aSDimitry Andric 
753972a253aSDimitry Andric   createRVVIntrinsicRecords(RVVIntrinsicRecords, SST, SemaRecords);
754972a253aSDimitry Andric 
755972a253aSDimitry Andric   // Emit signature table for SemaRISCVVectorLookup.cpp.
756972a253aSDimitry Andric   OS << "#ifdef DECL_SIGNATURE_TABLE\n";
757972a253aSDimitry Andric   SST.print(OS);
758972a253aSDimitry Andric   OS << "#endif\n";
759972a253aSDimitry Andric 
760972a253aSDimitry Andric   // Emit RVVIntrinsicRecords for SemaRISCVVectorLookup.cpp.
761972a253aSDimitry Andric   OS << "#ifdef DECL_INTRINSIC_RECORDS\n";
762972a253aSDimitry Andric   for (const RVVIntrinsicRecord &Record : RVVIntrinsicRecords)
763972a253aSDimitry Andric     OS << Record;
764972a253aSDimitry Andric   OS << "#endif\n";
765fe6060f1SDimitry Andric }
766fe6060f1SDimitry Andric 
767fe6060f1SDimitry Andric namespace clang {
EmitRVVHeader(RecordKeeper & Records,raw_ostream & OS)768fe6060f1SDimitry Andric void EmitRVVHeader(RecordKeeper &Records, raw_ostream &OS) {
769fe6060f1SDimitry Andric   RVVEmitter(Records).createHeader(OS);
770fe6060f1SDimitry Andric }
771fe6060f1SDimitry Andric 
EmitRVVBuiltins(RecordKeeper & Records,raw_ostream & OS)772fe6060f1SDimitry Andric void EmitRVVBuiltins(RecordKeeper &Records, raw_ostream &OS) {
773fe6060f1SDimitry Andric   RVVEmitter(Records).createBuiltins(OS);
774fe6060f1SDimitry Andric }
775fe6060f1SDimitry Andric 
EmitRVVBuiltinCG(RecordKeeper & Records,raw_ostream & OS)776fe6060f1SDimitry Andric void EmitRVVBuiltinCG(RecordKeeper &Records, raw_ostream &OS) {
777fe6060f1SDimitry Andric   RVVEmitter(Records).createCodeGen(OS);
778fe6060f1SDimitry Andric }
779fe6060f1SDimitry Andric 
EmitRVVBuiltinSema(RecordKeeper & Records,raw_ostream & OS)780972a253aSDimitry Andric void EmitRVVBuiltinSema(RecordKeeper &Records, raw_ostream &OS) {
781972a253aSDimitry Andric   RVVEmitter(Records).createSema(OS);
782972a253aSDimitry Andric }
783972a253aSDimitry Andric 
784fe6060f1SDimitry Andric } // End namespace clang
785