xref: /freebsd-src/contrib/llvm-project/clang/utils/TableGen/RISCVVEmitter.cpp (revision 1ac55f4cb0001fed92329746c730aa9a947c09a5)
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.
49972a253aSDimitry Andric   unsigned 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 
60bdd1243dSDimitry Andric   // BitMask for supported policies.
61bdd1243dSDimitry Andric   uint16_t PolicyBitMask;
62bdd1243dSDimitry Andric 
63972a253aSDimitry Andric   // Number of field, large than 1 if it's segment load/store.
64972a253aSDimitry Andric   unsigned NF;
65972a253aSDimitry Andric 
66972a253aSDimitry Andric   bool HasMasked :1;
67972a253aSDimitry Andric   bool HasVL :1;
68972a253aSDimitry Andric   bool HasMaskedOffOperand :1;
69bdd1243dSDimitry Andric   bool HasTailPolicy : 1;
70bdd1243dSDimitry Andric   bool HasMaskPolicy : 1;
71bdd1243dSDimitry Andric   uint8_t UnMaskedPolicyScheme : 2;
72bdd1243dSDimitry Andric   uint8_t MaskedPolicyScheme : 2;
73972a253aSDimitry Andric };
74972a253aSDimitry Andric 
75972a253aSDimitry Andric // Compressed function signature table.
76972a253aSDimitry Andric class SemaSignatureTable {
77972a253aSDimitry Andric private:
78972a253aSDimitry Andric   std::vector<PrototypeDescriptor> SignatureTable;
79972a253aSDimitry Andric 
80972a253aSDimitry Andric   void insert(ArrayRef<PrototypeDescriptor> Signature);
81972a253aSDimitry Andric 
82972a253aSDimitry Andric public:
83972a253aSDimitry Andric   static constexpr unsigned INVALID_INDEX = ~0U;
84972a253aSDimitry Andric 
85972a253aSDimitry Andric   // Create compressed signature table from SemaRecords.
86972a253aSDimitry Andric   void init(ArrayRef<SemaRecord> SemaRecords);
87972a253aSDimitry Andric 
88972a253aSDimitry Andric   // Query the Signature, return INVALID_INDEX if not found.
89972a253aSDimitry Andric   unsigned getIndex(ArrayRef<PrototypeDescriptor> Signature);
90972a253aSDimitry Andric 
91972a253aSDimitry Andric   /// Print signature table in RVVHeader Record to \p OS
92972a253aSDimitry Andric   void print(raw_ostream &OS);
93972a253aSDimitry Andric };
94972a253aSDimitry Andric 
95fe6060f1SDimitry Andric class RVVEmitter {
96fe6060f1SDimitry Andric private:
97fe6060f1SDimitry Andric   RecordKeeper &Records;
98bdd1243dSDimitry Andric   RVVTypeCache TypeCache;
99fe6060f1SDimitry Andric 
100fe6060f1SDimitry Andric public:
101fe6060f1SDimitry Andric   RVVEmitter(RecordKeeper &R) : Records(R) {}
102fe6060f1SDimitry Andric 
103fe6060f1SDimitry Andric   /// Emit riscv_vector.h
104fe6060f1SDimitry Andric   void createHeader(raw_ostream &o);
105fe6060f1SDimitry Andric 
106fe6060f1SDimitry Andric   /// Emit all the __builtin prototypes and code needed by Sema.
107fe6060f1SDimitry Andric   void createBuiltins(raw_ostream &o);
108fe6060f1SDimitry Andric 
109fe6060f1SDimitry Andric   /// Emit all the information needed to map builtin -> LLVM IR intrinsic.
110fe6060f1SDimitry Andric   void createCodeGen(raw_ostream &o);
111fe6060f1SDimitry Andric 
112972a253aSDimitry Andric   /// Emit all the information needed by SemaRISCVVectorLookup.cpp.
113972a253aSDimitry Andric   /// We've large number of intrinsic function for RVV, creating a customized
114972a253aSDimitry Andric   /// could speed up the compilation time.
115972a253aSDimitry Andric   void createSema(raw_ostream &o);
116972a253aSDimitry Andric 
117fe6060f1SDimitry Andric private:
118972a253aSDimitry Andric   /// Create all intrinsics and add them to \p Out and SemaRecords.
119972a253aSDimitry Andric   void createRVVIntrinsics(std::vector<std::unique_ptr<RVVIntrinsic>> &Out,
120972a253aSDimitry Andric                            std::vector<SemaRecord> *SemaRecords = nullptr);
121972a253aSDimitry Andric   /// Create all intrinsic records and SemaSignatureTable from SemaRecords.
122972a253aSDimitry Andric   void createRVVIntrinsicRecords(std::vector<RVVIntrinsicRecord> &Out,
123972a253aSDimitry Andric                                  SemaSignatureTable &SST,
124972a253aSDimitry Andric                                  ArrayRef<SemaRecord> SemaRecords);
125972a253aSDimitry Andric 
12681ad6265SDimitry Andric   /// Print HeaderCode in RVVHeader Record to \p Out
12781ad6265SDimitry Andric   void printHeaderCode(raw_ostream &OS);
128fe6060f1SDimitry Andric };
129fe6060f1SDimitry Andric 
130fe6060f1SDimitry Andric } // namespace
131fe6060f1SDimitry Andric 
13281ad6265SDimitry Andric static BasicType ParseBasicType(char c) {
13381ad6265SDimitry Andric   switch (c) {
134fe6060f1SDimitry Andric   case 'c':
13581ad6265SDimitry Andric     return BasicType::Int8;
136fe6060f1SDimitry Andric     break;
137fe6060f1SDimitry Andric   case 's':
13881ad6265SDimitry Andric     return BasicType::Int16;
139fe6060f1SDimitry Andric     break;
140fe6060f1SDimitry Andric   case 'i':
14181ad6265SDimitry Andric     return BasicType::Int32;
142fe6060f1SDimitry Andric     break;
143fe6060f1SDimitry Andric   case 'l':
14481ad6265SDimitry Andric     return BasicType::Int64;
145fe6060f1SDimitry Andric     break;
146fe6060f1SDimitry Andric   case 'x':
14781ad6265SDimitry Andric     return BasicType::Float16;
148fe6060f1SDimitry Andric     break;
149fe6060f1SDimitry Andric   case 'f':
15081ad6265SDimitry Andric     return BasicType::Float32;
151fe6060f1SDimitry Andric     break;
152fe6060f1SDimitry Andric   case 'd':
15381ad6265SDimitry Andric     return BasicType::Float64;
154fe6060f1SDimitry Andric     break;
15581ad6265SDimitry Andric 
156fe6060f1SDimitry Andric   default:
15781ad6265SDimitry Andric     return BasicType::Unknown;
158fe6060f1SDimitry Andric   }
159fe6060f1SDimitry Andric }
160fe6060f1SDimitry Andric 
16181ad6265SDimitry Andric void emitCodeGenSwitchBody(const RVVIntrinsic *RVVI, raw_ostream &OS) {
16281ad6265SDimitry Andric   if (!RVVI->getIRName().empty())
16381ad6265SDimitry Andric     OS << "  ID = Intrinsic::riscv_" + RVVI->getIRName() + ";\n";
16481ad6265SDimitry Andric   if (RVVI->getNF() >= 2)
16581ad6265SDimitry Andric     OS << "  NF = " + utostr(RVVI->getNF()) + ";\n";
166bdd1243dSDimitry Andric 
167bdd1243dSDimitry Andric   OS << "  PolicyAttrs = " << RVVI->getPolicyAttrsBits() << ";\n";
168bdd1243dSDimitry Andric 
16981ad6265SDimitry Andric   if (RVVI->hasManualCodegen()) {
170bdd1243dSDimitry Andric     OS << "IsMasked = " << (RVVI->isMasked() ? "true" : "false") << ";\n";
17181ad6265SDimitry Andric     OS << RVVI->getManualCodegen();
172fe6060f1SDimitry Andric     OS << "break;\n";
173fe6060f1SDimitry Andric     return;
174fe6060f1SDimitry Andric   }
175fe6060f1SDimitry Andric 
176753f127fSDimitry Andric   // Cast pointer operand of vector load intrinsic.
177753f127fSDimitry Andric   for (const auto &I : enumerate(RVVI->getInputTypes())) {
178753f127fSDimitry Andric     if (I.value()->isPointer()) {
179753f127fSDimitry Andric       assert(RVVI->getIntrinsicTypes().front() == -1 &&
180753f127fSDimitry Andric              "RVVI should be vector load intrinsic.");
181753f127fSDimitry Andric       OS << "  Ops[" << I.index() << "] = Builder.CreateBitCast(Ops[";
182753f127fSDimitry Andric       OS << I.index() << "], ResultType->getPointerTo());\n";
183753f127fSDimitry Andric     }
184753f127fSDimitry Andric   }
185753f127fSDimitry Andric 
18681ad6265SDimitry Andric   if (RVVI->isMasked()) {
18781ad6265SDimitry Andric     if (RVVI->hasVL()) {
188fe6060f1SDimitry Andric       OS << "  std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1);\n";
18981ad6265SDimitry Andric       if (RVVI->hasPolicyOperand())
190349cc55cSDimitry Andric         OS << "  Ops.push_back(ConstantInt::get(Ops.back()->getType(),"
191bdd1243dSDimitry Andric               " PolicyAttrs));\n";
192bdd1243dSDimitry Andric       if (RVVI->hasMaskedOffOperand() && RVVI->getPolicyAttrs().isTAMAPolicy())
193bdd1243dSDimitry Andric         OS << "  Ops.insert(Ops.begin(), "
194bdd1243dSDimitry Andric               "llvm::PoisonValue::get(ResultType));\n";
195bdd1243dSDimitry Andric       // Masked reduction cases.
196bdd1243dSDimitry Andric       if (!RVVI->hasMaskedOffOperand() && RVVI->hasPassthruOperand() &&
197bdd1243dSDimitry Andric           RVVI->getPolicyAttrs().isTAMAPolicy())
198bdd1243dSDimitry Andric         OS << "  Ops.insert(Ops.begin(), "
199bdd1243dSDimitry Andric               "llvm::PoisonValue::get(ResultType));\n";
200fe6060f1SDimitry Andric     } else {
201fe6060f1SDimitry Andric       OS << "  std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end());\n";
202fe6060f1SDimitry Andric     }
20381ad6265SDimitry Andric   } else {
20481ad6265SDimitry Andric     if (RVVI->hasPolicyOperand())
20581ad6265SDimitry Andric       OS << "  Ops.push_back(ConstantInt::get(Ops.back()->getType(), "
206bdd1243dSDimitry Andric             "PolicyAttrs));\n";
207bdd1243dSDimitry Andric     else if (RVVI->hasPassthruOperand() && RVVI->getPolicyAttrs().isTAPolicy())
208bdd1243dSDimitry Andric       OS << "  Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType));\n";
209fe6060f1SDimitry Andric   }
210fe6060f1SDimitry Andric 
211fe6060f1SDimitry Andric   OS << "  IntrinsicTypes = {";
212fe6060f1SDimitry Andric   ListSeparator LS;
21381ad6265SDimitry Andric   for (const auto &Idx : RVVI->getIntrinsicTypes()) {
214fe6060f1SDimitry Andric     if (Idx == -1)
215fe6060f1SDimitry Andric       OS << LS << "ResultType";
216fe6060f1SDimitry Andric     else
217fe6060f1SDimitry Andric       OS << LS << "Ops[" << Idx << "]->getType()";
218fe6060f1SDimitry Andric   }
219fe6060f1SDimitry Andric 
220fe6060f1SDimitry Andric   // VL could be i64 or i32, need to encode it in IntrinsicTypes. VL is
221fe6060f1SDimitry Andric   // always last operand.
22281ad6265SDimitry Andric   if (RVVI->hasVL())
223fe6060f1SDimitry Andric     OS << ", Ops.back()->getType()";
224fe6060f1SDimitry Andric   OS << "};\n";
225fe6060f1SDimitry Andric   OS << "  break;\n";
226fe6060f1SDimitry Andric }
227fe6060f1SDimitry Andric 
228972a253aSDimitry Andric //===----------------------------------------------------------------------===//
229972a253aSDimitry Andric // SemaSignatureTable implementation
230972a253aSDimitry Andric //===----------------------------------------------------------------------===//
231972a253aSDimitry Andric void SemaSignatureTable::init(ArrayRef<SemaRecord> SemaRecords) {
232972a253aSDimitry Andric   // Sort signature entries by length, let longer signature insert first, to
233972a253aSDimitry Andric   // make it more possible to reuse table entries, that can reduce ~10% table
234972a253aSDimitry Andric   // size.
235972a253aSDimitry Andric   struct Compare {
236972a253aSDimitry Andric     bool operator()(const SmallVector<PrototypeDescriptor> &A,
237972a253aSDimitry Andric                     const SmallVector<PrototypeDescriptor> &B) const {
238972a253aSDimitry Andric       if (A.size() != B.size())
239972a253aSDimitry Andric         return A.size() > B.size();
240972a253aSDimitry Andric 
241972a253aSDimitry Andric       size_t Len = A.size();
242972a253aSDimitry Andric       for (size_t i = 0; i < Len; ++i) {
243972a253aSDimitry Andric         if (A[i] != B[i])
244972a253aSDimitry Andric           return A[i] < B[i];
245fe6060f1SDimitry Andric       }
246fe6060f1SDimitry Andric 
247972a253aSDimitry Andric       return false;
248fe6060f1SDimitry Andric     }
249972a253aSDimitry Andric   };
250972a253aSDimitry Andric 
251972a253aSDimitry Andric   std::set<SmallVector<PrototypeDescriptor>, Compare> Signatures;
252972a253aSDimitry Andric   auto InsertToSignatureSet =
253972a253aSDimitry Andric       [&](const SmallVector<PrototypeDescriptor> &Signature) {
254972a253aSDimitry Andric         if (Signature.empty())
255972a253aSDimitry Andric           return;
256972a253aSDimitry Andric 
257972a253aSDimitry Andric         Signatures.insert(Signature);
258972a253aSDimitry Andric       };
259972a253aSDimitry Andric 
260972a253aSDimitry Andric   assert(!SemaRecords.empty());
261972a253aSDimitry Andric 
262972a253aSDimitry Andric   llvm::for_each(SemaRecords, [&](const SemaRecord &SR) {
263972a253aSDimitry Andric     InsertToSignatureSet(SR.Prototype);
264972a253aSDimitry Andric     InsertToSignatureSet(SR.Suffix);
265972a253aSDimitry Andric     InsertToSignatureSet(SR.OverloadedSuffix);
266972a253aSDimitry Andric   });
267972a253aSDimitry Andric 
268972a253aSDimitry Andric   llvm::for_each(Signatures, [this](auto &Sig) { insert(Sig); });
269972a253aSDimitry Andric }
270972a253aSDimitry Andric 
271972a253aSDimitry Andric void SemaSignatureTable::insert(ArrayRef<PrototypeDescriptor> Signature) {
272972a253aSDimitry Andric   if (getIndex(Signature) != INVALID_INDEX)
273972a253aSDimitry Andric     return;
274972a253aSDimitry Andric 
275972a253aSDimitry Andric   // Insert Signature into SignatureTable if not found in the table.
276972a253aSDimitry Andric   SignatureTable.insert(SignatureTable.begin(), Signature.begin(),
277972a253aSDimitry Andric                         Signature.end());
278972a253aSDimitry Andric }
279972a253aSDimitry Andric 
280972a253aSDimitry Andric unsigned SemaSignatureTable::getIndex(ArrayRef<PrototypeDescriptor> Signature) {
281972a253aSDimitry Andric   // Empty signature could be point into any index since there is length
282972a253aSDimitry Andric   // field when we use, so just always point it to 0.
283972a253aSDimitry Andric   if (Signature.empty())
284972a253aSDimitry Andric     return 0;
285972a253aSDimitry Andric 
286972a253aSDimitry Andric   // Checking Signature already in table or not.
287972a253aSDimitry Andric   if (Signature.size() < SignatureTable.size()) {
288972a253aSDimitry Andric     size_t Bound = SignatureTable.size() - Signature.size() + 1;
289972a253aSDimitry Andric     for (size_t Index = 0; Index < Bound; ++Index) {
290972a253aSDimitry Andric       if (equal(Signature.begin(), Signature.end(),
291972a253aSDimitry Andric                 SignatureTable.begin() + Index))
292972a253aSDimitry Andric         return Index;
293972a253aSDimitry Andric     }
294972a253aSDimitry Andric   }
295972a253aSDimitry Andric 
296972a253aSDimitry Andric   return INVALID_INDEX;
297972a253aSDimitry Andric }
298972a253aSDimitry Andric 
299972a253aSDimitry Andric void SemaSignatureTable::print(raw_ostream &OS) {
300972a253aSDimitry Andric   for (const auto &Sig : SignatureTable)
301972a253aSDimitry Andric     OS << "PrototypeDescriptor(" << static_cast<int>(Sig.PT) << ", "
302972a253aSDimitry Andric        << static_cast<int>(Sig.VTM) << ", " << static_cast<int>(Sig.TM)
303972a253aSDimitry Andric        << "),\n";
304fe6060f1SDimitry Andric }
305fe6060f1SDimitry Andric 
306fe6060f1SDimitry Andric //===----------------------------------------------------------------------===//
307fe6060f1SDimitry Andric // RVVEmitter implementation
308fe6060f1SDimitry Andric //===----------------------------------------------------------------------===//
309fe6060f1SDimitry Andric void RVVEmitter::createHeader(raw_ostream &OS) {
310fe6060f1SDimitry Andric 
311fe6060f1SDimitry Andric   OS << "/*===---- riscv_vector.h - RISC-V V-extension RVVIntrinsics "
312fe6060f1SDimitry Andric         "-------------------===\n"
313fe6060f1SDimitry Andric         " *\n"
314fe6060f1SDimitry Andric         " *\n"
315fe6060f1SDimitry Andric         " * Part of the LLVM Project, under the Apache License v2.0 with LLVM "
316fe6060f1SDimitry Andric         "Exceptions.\n"
317fe6060f1SDimitry Andric         " * See https://llvm.org/LICENSE.txt for license information.\n"
318fe6060f1SDimitry Andric         " * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n"
319fe6060f1SDimitry Andric         " *\n"
320fe6060f1SDimitry Andric         " *===-----------------------------------------------------------------"
321fe6060f1SDimitry Andric         "------===\n"
322fe6060f1SDimitry Andric         " */\n\n";
323fe6060f1SDimitry Andric 
324fe6060f1SDimitry Andric   OS << "#ifndef __RISCV_VECTOR_H\n";
325fe6060f1SDimitry Andric   OS << "#define __RISCV_VECTOR_H\n\n";
326fe6060f1SDimitry Andric 
327fe6060f1SDimitry Andric   OS << "#include <stdint.h>\n";
328fe6060f1SDimitry Andric   OS << "#include <stddef.h>\n\n";
329fe6060f1SDimitry Andric 
330fe6060f1SDimitry Andric   OS << "#ifndef __riscv_vector\n";
331fe6060f1SDimitry Andric   OS << "#error \"Vector intrinsics require the vector extension.\"\n";
332fe6060f1SDimitry Andric   OS << "#endif\n\n";
333fe6060f1SDimitry Andric 
334fe6060f1SDimitry Andric   OS << "#ifdef __cplusplus\n";
335fe6060f1SDimitry Andric   OS << "extern \"C\" {\n";
336fe6060f1SDimitry Andric   OS << "#endif\n\n";
337fe6060f1SDimitry Andric 
338972a253aSDimitry Andric   OS << "#pragma clang riscv intrinsic vector\n\n";
339349cc55cSDimitry Andric 
340972a253aSDimitry Andric   printHeaderCode(OS);
341fe6060f1SDimitry Andric 
342fe6060f1SDimitry Andric   auto printType = [&](auto T) {
343fe6060f1SDimitry Andric     OS << "typedef " << T->getClangBuiltinStr() << " " << T->getTypeStr()
344fe6060f1SDimitry Andric        << ";\n";
345fe6060f1SDimitry Andric   };
346fe6060f1SDimitry Andric 
347fe6060f1SDimitry Andric   constexpr int Log2LMULs[] = {-3, -2, -1, 0, 1, 2, 3};
348fe6060f1SDimitry Andric   // Print RVV boolean types.
349fe6060f1SDimitry Andric   for (int Log2LMUL : Log2LMULs) {
350bdd1243dSDimitry Andric     auto T = TypeCache.computeType(BasicType::Int8, Log2LMUL,
35181ad6265SDimitry Andric                                    PrototypeDescriptor::Mask);
35281ad6265SDimitry Andric     if (T)
353bdd1243dSDimitry Andric       printType(*T);
354fe6060f1SDimitry Andric   }
355fe6060f1SDimitry Andric   // Print RVV int/float types.
356fe6060f1SDimitry Andric   for (char I : StringRef("csil")) {
35781ad6265SDimitry Andric     BasicType BT = ParseBasicType(I);
358fe6060f1SDimitry Andric     for (int Log2LMUL : Log2LMULs) {
359bdd1243dSDimitry Andric       auto T = TypeCache.computeType(BT, Log2LMUL, PrototypeDescriptor::Vector);
36081ad6265SDimitry Andric       if (T) {
361bdd1243dSDimitry Andric         printType(*T);
362bdd1243dSDimitry Andric         auto UT = TypeCache.computeType(
36381ad6265SDimitry Andric             BT, Log2LMUL,
36481ad6265SDimitry Andric             PrototypeDescriptor(BaseTypeModifier::Vector,
36581ad6265SDimitry Andric                                 VectorTypeModifier::NoModifier,
36681ad6265SDimitry Andric                                 TypeModifier::UnsignedInteger));
367bdd1243dSDimitry Andric         printType(*UT);
368fe6060f1SDimitry Andric       }
369fe6060f1SDimitry Andric     }
370fe6060f1SDimitry Andric   }
37181ad6265SDimitry Andric   OS << "#if defined(__riscv_zvfh)\n";
372fe6060f1SDimitry Andric   for (int Log2LMUL : Log2LMULs) {
373bdd1243dSDimitry Andric     auto T = TypeCache.computeType(BasicType::Float16, Log2LMUL,
37481ad6265SDimitry Andric                                    PrototypeDescriptor::Vector);
37581ad6265SDimitry Andric     if (T)
376bdd1243dSDimitry Andric       printType(*T);
377fe6060f1SDimitry Andric   }
378fe6060f1SDimitry Andric   OS << "#endif\n";
379fe6060f1SDimitry Andric 
380972a253aSDimitry Andric   OS << "#if (__riscv_v_elen_fp >= 32)\n";
381fe6060f1SDimitry Andric   for (int Log2LMUL : Log2LMULs) {
382bdd1243dSDimitry Andric     auto T = TypeCache.computeType(BasicType::Float32, Log2LMUL,
38381ad6265SDimitry Andric                                    PrototypeDescriptor::Vector);
38481ad6265SDimitry Andric     if (T)
385bdd1243dSDimitry Andric       printType(*T);
386fe6060f1SDimitry Andric   }
387fe6060f1SDimitry Andric   OS << "#endif\n";
388fe6060f1SDimitry Andric 
389972a253aSDimitry Andric   OS << "#if (__riscv_v_elen_fp >= 64)\n";
390fe6060f1SDimitry Andric   for (int Log2LMUL : Log2LMULs) {
391bdd1243dSDimitry Andric     auto T = TypeCache.computeType(BasicType::Float64, Log2LMUL,
39281ad6265SDimitry Andric                                    PrototypeDescriptor::Vector);
39381ad6265SDimitry Andric     if (T)
394bdd1243dSDimitry Andric       printType(*T);
395fe6060f1SDimitry Andric   }
396fe6060f1SDimitry Andric   OS << "#endif\n\n";
397fe6060f1SDimitry Andric 
398fe6060f1SDimitry Andric   OS << "#define __riscv_v_intrinsic_overloading 1\n";
399fe6060f1SDimitry Andric 
400fe6060f1SDimitry Andric   OS << "\n#ifdef __cplusplus\n";
401fe6060f1SDimitry Andric   OS << "}\n";
402349cc55cSDimitry Andric   OS << "#endif // __cplusplus\n";
403fe6060f1SDimitry Andric   OS << "#endif // __RISCV_VECTOR_H\n";
404fe6060f1SDimitry Andric }
405fe6060f1SDimitry Andric 
406fe6060f1SDimitry Andric void RVVEmitter::createBuiltins(raw_ostream &OS) {
407fe6060f1SDimitry Andric   std::vector<std::unique_ptr<RVVIntrinsic>> Defs;
408fe6060f1SDimitry Andric   createRVVIntrinsics(Defs);
409fe6060f1SDimitry Andric 
410349cc55cSDimitry Andric   // Map to keep track of which builtin names have already been emitted.
411349cc55cSDimitry Andric   StringMap<RVVIntrinsic *> BuiltinMap;
412349cc55cSDimitry Andric 
413fe6060f1SDimitry Andric   OS << "#if defined(TARGET_BUILTIN) && !defined(RISCVV_BUILTIN)\n";
414fe6060f1SDimitry Andric   OS << "#define RISCVV_BUILTIN(ID, TYPE, ATTRS) TARGET_BUILTIN(ID, TYPE, "
41581ad6265SDimitry Andric         "ATTRS, \"zve32x\")\n";
416fe6060f1SDimitry Andric   OS << "#endif\n";
417fe6060f1SDimitry Andric   for (auto &Def : Defs) {
418349cc55cSDimitry Andric     auto P =
419349cc55cSDimitry Andric         BuiltinMap.insert(std::make_pair(Def->getBuiltinName(), Def.get()));
420349cc55cSDimitry Andric     if (!P.second) {
42181ad6265SDimitry Andric       // Verf that this would have produced the same builtin definition.
42281ad6265SDimitry Andric       if (P.first->second->hasBuiltinAlias() != Def->hasBuiltinAlias())
423349cc55cSDimitry Andric         PrintFatalError("Builtin with same name has different hasAutoDef");
42481ad6265SDimitry Andric       else if (!Def->hasBuiltinAlias() &&
42581ad6265SDimitry Andric                P.first->second->getBuiltinTypeStr() != Def->getBuiltinTypeStr())
426349cc55cSDimitry Andric         PrintFatalError("Builtin with same name has different type string");
427349cc55cSDimitry Andric       continue;
428349cc55cSDimitry Andric     }
429349cc55cSDimitry Andric     OS << "RISCVV_BUILTIN(__builtin_rvv_" << Def->getBuiltinName() << ",\"";
43081ad6265SDimitry Andric     if (!Def->hasBuiltinAlias())
431349cc55cSDimitry Andric       OS << Def->getBuiltinTypeStr();
432349cc55cSDimitry Andric     OS << "\", \"n\")\n";
433fe6060f1SDimitry Andric   }
434fe6060f1SDimitry Andric   OS << "#undef RISCVV_BUILTIN\n";
435fe6060f1SDimitry Andric }
436fe6060f1SDimitry Andric 
437fe6060f1SDimitry Andric void RVVEmitter::createCodeGen(raw_ostream &OS) {
438fe6060f1SDimitry Andric   std::vector<std::unique_ptr<RVVIntrinsic>> Defs;
439fe6060f1SDimitry Andric   createRVVIntrinsics(Defs);
440fe6060f1SDimitry Andric   // IR name could be empty, use the stable sort preserves the relative order.
441349cc55cSDimitry Andric   llvm::stable_sort(Defs, [](const std::unique_ptr<RVVIntrinsic> &A,
442fe6060f1SDimitry Andric                              const std::unique_ptr<RVVIntrinsic> &B) {
443bdd1243dSDimitry Andric     if (A->getIRName() == B->getIRName())
444bdd1243dSDimitry Andric       return (A->getPolicyAttrs() < B->getPolicyAttrs());
445bdd1243dSDimitry Andric     return (A->getIRName() < B->getIRName());
446fe6060f1SDimitry Andric   });
447349cc55cSDimitry Andric 
448349cc55cSDimitry Andric   // Map to keep track of which builtin names have already been emitted.
449349cc55cSDimitry Andric   StringMap<RVVIntrinsic *> BuiltinMap;
450349cc55cSDimitry Andric 
451bdd1243dSDimitry Andric   // Print switch body when the ir name, ManualCodegen or policy changes from
452bdd1243dSDimitry Andric   // previous iteration.
453fe6060f1SDimitry Andric   RVVIntrinsic *PrevDef = Defs.begin()->get();
454fe6060f1SDimitry Andric   for (auto &Def : Defs) {
455fe6060f1SDimitry Andric     StringRef CurIRName = Def->getIRName();
456fe6060f1SDimitry Andric     if (CurIRName != PrevDef->getIRName() ||
457bdd1243dSDimitry Andric         (Def->getManualCodegen() != PrevDef->getManualCodegen()) ||
458bdd1243dSDimitry Andric         (Def->getPolicyAttrs() != PrevDef->getPolicyAttrs())) {
45981ad6265SDimitry Andric       emitCodeGenSwitchBody(PrevDef, OS);
460fe6060f1SDimitry Andric     }
461fe6060f1SDimitry Andric     PrevDef = Def.get();
462349cc55cSDimitry Andric 
463349cc55cSDimitry Andric     auto P =
464349cc55cSDimitry Andric         BuiltinMap.insert(std::make_pair(Def->getBuiltinName(), Def.get()));
465349cc55cSDimitry Andric     if (P.second) {
466349cc55cSDimitry Andric       OS << "case RISCVVector::BI__builtin_rvv_" << Def->getBuiltinName()
467349cc55cSDimitry Andric          << ":\n";
468349cc55cSDimitry Andric       continue;
469349cc55cSDimitry Andric     }
470349cc55cSDimitry Andric 
471349cc55cSDimitry Andric     if (P.first->second->getIRName() != Def->getIRName())
472349cc55cSDimitry Andric       PrintFatalError("Builtin with same name has different IRName");
473349cc55cSDimitry Andric     else if (P.first->second->getManualCodegen() != Def->getManualCodegen())
474349cc55cSDimitry Andric       PrintFatalError("Builtin with same name has different ManualCodegen");
475349cc55cSDimitry Andric     else if (P.first->second->getNF() != Def->getNF())
476349cc55cSDimitry Andric       PrintFatalError("Builtin with same name has different NF");
47781ad6265SDimitry Andric     else if (P.first->second->isMasked() != Def->isMasked())
47881ad6265SDimitry Andric       PrintFatalError("Builtin with same name has different isMasked");
479349cc55cSDimitry Andric     else if (P.first->second->hasVL() != Def->hasVL())
48081ad6265SDimitry Andric       PrintFatalError("Builtin with same name has different hasVL");
48181ad6265SDimitry Andric     else if (P.first->second->getPolicyScheme() != Def->getPolicyScheme())
48281ad6265SDimitry Andric       PrintFatalError("Builtin with same name has different getPolicyScheme");
483349cc55cSDimitry Andric     else if (P.first->second->getIntrinsicTypes() != Def->getIntrinsicTypes())
484349cc55cSDimitry Andric       PrintFatalError("Builtin with same name has different IntrinsicTypes");
485fe6060f1SDimitry Andric   }
48681ad6265SDimitry Andric   emitCodeGenSwitchBody(Defs.back().get(), OS);
487fe6060f1SDimitry Andric   OS << "\n";
488fe6060f1SDimitry Andric }
489fe6060f1SDimitry Andric 
490fe6060f1SDimitry Andric void RVVEmitter::createRVVIntrinsics(
491972a253aSDimitry Andric     std::vector<std::unique_ptr<RVVIntrinsic>> &Out,
492972a253aSDimitry Andric     std::vector<SemaRecord> *SemaRecords) {
493fe6060f1SDimitry Andric   std::vector<Record *> RV = Records.getAllDerivedDefinitions("RVVBuiltin");
494fe6060f1SDimitry Andric   for (auto *R : RV) {
495fe6060f1SDimitry Andric     StringRef Name = R->getValueAsString("Name");
496fe6060f1SDimitry Andric     StringRef SuffixProto = R->getValueAsString("Suffix");
49781ad6265SDimitry Andric     StringRef OverloadedName = R->getValueAsString("OverloadedName");
49881ad6265SDimitry Andric     StringRef OverloadedSuffixProto = R->getValueAsString("OverloadedSuffix");
499fe6060f1SDimitry Andric     StringRef Prototypes = R->getValueAsString("Prototype");
500fe6060f1SDimitry Andric     StringRef TypeRange = R->getValueAsString("TypeRange");
50181ad6265SDimitry Andric     bool HasMasked = R->getValueAsBit("HasMasked");
502fe6060f1SDimitry Andric     bool HasMaskedOffOperand = R->getValueAsBit("HasMaskedOffOperand");
503fe6060f1SDimitry Andric     bool HasVL = R->getValueAsBit("HasVL");
504972a253aSDimitry Andric     Record *MPSRecord = R->getValueAsDef("MaskedPolicyScheme");
505972a253aSDimitry Andric     auto MaskedPolicyScheme =
506972a253aSDimitry Andric         static_cast<PolicyScheme>(MPSRecord->getValueAsInt("Value"));
507972a253aSDimitry Andric     Record *UMPSRecord = R->getValueAsDef("UnMaskedPolicyScheme");
508972a253aSDimitry Andric     auto UnMaskedPolicyScheme =
509972a253aSDimitry Andric         static_cast<PolicyScheme>(UMPSRecord->getValueAsInt("Value"));
510fe6060f1SDimitry Andric     std::vector<int64_t> Log2LMULList = R->getValueAsListOfInts("Log2LMUL");
511bdd1243dSDimitry Andric     bool HasTailPolicy = R->getValueAsBit("HasTailPolicy");
512bdd1243dSDimitry Andric     bool HasMaskPolicy = R->getValueAsBit("HasMaskPolicy");
513bdd1243dSDimitry Andric     bool SupportOverloading = R->getValueAsBit("SupportOverloading");
51481ad6265SDimitry Andric     bool HasBuiltinAlias = R->getValueAsBit("HasBuiltinAlias");
515fe6060f1SDimitry Andric     StringRef ManualCodegen = R->getValueAsString("ManualCodegen");
516fe6060f1SDimitry Andric     std::vector<int64_t> IntrinsicTypes =
517fe6060f1SDimitry Andric         R->getValueAsListOfInts("IntrinsicTypes");
51804eeddc0SDimitry Andric     std::vector<StringRef> RequiredFeatures =
51904eeddc0SDimitry Andric         R->getValueAsListOfStrings("RequiredFeatures");
520fe6060f1SDimitry Andric     StringRef IRName = R->getValueAsString("IRName");
52181ad6265SDimitry Andric     StringRef MaskedIRName = R->getValueAsString("MaskedIRName");
522fe6060f1SDimitry Andric     unsigned NF = R->getValueAsInt("NF");
523fe6060f1SDimitry Andric 
524*1ac55f4cSDimitry Andric     const Policy DefaultPolicy;
525bdd1243dSDimitry Andric     SmallVector<Policy> SupportedUnMaskedPolicies =
526*1ac55f4cSDimitry Andric         RVVIntrinsic::getSupportedUnMaskedPolicies();
527bdd1243dSDimitry Andric     SmallVector<Policy> SupportedMaskedPolicies =
528bdd1243dSDimitry Andric         RVVIntrinsic::getSupportedMaskedPolicies(HasTailPolicy, HasMaskPolicy);
529bdd1243dSDimitry Andric 
530fe6060f1SDimitry Andric     // Parse prototype and create a list of primitive type with transformers
53181ad6265SDimitry Andric     // (operand) in Prototype. Prototype[0] is output operand.
532972a253aSDimitry Andric     SmallVector<PrototypeDescriptor> BasicPrototype =
533972a253aSDimitry Andric         parsePrototypes(Prototypes);
53481ad6265SDimitry Andric 
53581ad6265SDimitry Andric     SmallVector<PrototypeDescriptor> SuffixDesc = parsePrototypes(SuffixProto);
53681ad6265SDimitry Andric     SmallVector<PrototypeDescriptor> OverloadedSuffixDesc =
53781ad6265SDimitry Andric         parsePrototypes(OverloadedSuffixProto);
538fe6060f1SDimitry Andric 
539fe6060f1SDimitry Andric     // Compute Builtin types
540972a253aSDimitry Andric     auto Prototype = RVVIntrinsic::computeBuiltinTypes(
541bdd1243dSDimitry Andric         BasicPrototype, /*IsMasked=*/false,
542bdd1243dSDimitry Andric         /*HasMaskedOffOperand=*/false, HasVL, NF, UnMaskedPolicyScheme,
543bdd1243dSDimitry Andric         DefaultPolicy);
544972a253aSDimitry Andric     auto MaskedPrototype = RVVIntrinsic::computeBuiltinTypes(
545bdd1243dSDimitry Andric         BasicPrototype, /*IsMasked=*/true, HasMaskedOffOperand, HasVL, NF,
546bdd1243dSDimitry Andric         MaskedPolicyScheme, DefaultPolicy);
547fe6060f1SDimitry Andric 
548fe6060f1SDimitry Andric     // Create Intrinsics for each type and LMUL.
549fe6060f1SDimitry Andric     for (char I : TypeRange) {
550fe6060f1SDimitry Andric       for (int Log2LMUL : Log2LMULList) {
55181ad6265SDimitry Andric         BasicType BT = ParseBasicType(I);
552bdd1243dSDimitry Andric         std::optional<RVVTypes> Types =
553bdd1243dSDimitry Andric             TypeCache.computeTypes(BT, Log2LMUL, NF, Prototype);
554fe6060f1SDimitry Andric         // Ignored to create new intrinsic if there are any illegal types.
55581ad6265SDimitry Andric         if (!Types)
556fe6060f1SDimitry Andric           continue;
557fe6060f1SDimitry Andric 
558bdd1243dSDimitry Andric         auto SuffixStr =
559bdd1243dSDimitry Andric             RVVIntrinsic::getSuffixStr(TypeCache, BT, Log2LMUL, SuffixDesc);
560bdd1243dSDimitry Andric         auto OverloadedSuffixStr = RVVIntrinsic::getSuffixStr(
561bdd1243dSDimitry Andric             TypeCache, BT, Log2LMUL, OverloadedSuffixDesc);
56281ad6265SDimitry Andric         // Create a unmasked intrinsic
563fe6060f1SDimitry Andric         Out.push_back(std::make_unique<RVVIntrinsic>(
56481ad6265SDimitry Andric             Name, SuffixStr, OverloadedName, OverloadedSuffixStr, IRName,
56581ad6265SDimitry Andric             /*IsMasked=*/false, /*HasMaskedOffOperand=*/false, HasVL,
566bdd1243dSDimitry Andric             UnMaskedPolicyScheme, SupportOverloading, HasBuiltinAlias,
567bdd1243dSDimitry Andric             ManualCodegen, *Types, IntrinsicTypes, RequiredFeatures, NF,
568bdd1243dSDimitry Andric             DefaultPolicy));
569bdd1243dSDimitry Andric         if (UnMaskedPolicyScheme != PolicyScheme::SchemeNone)
570bdd1243dSDimitry Andric           for (auto P : SupportedUnMaskedPolicies) {
571bdd1243dSDimitry Andric             SmallVector<PrototypeDescriptor> PolicyPrototype =
572bdd1243dSDimitry Andric                 RVVIntrinsic::computeBuiltinTypes(
573bdd1243dSDimitry Andric                     BasicPrototype, /*IsMasked=*/false,
574bdd1243dSDimitry Andric                     /*HasMaskedOffOperand=*/false, HasVL, NF,
575bdd1243dSDimitry Andric                     UnMaskedPolicyScheme, P);
576bdd1243dSDimitry Andric             std::optional<RVVTypes> PolicyTypes =
577bdd1243dSDimitry Andric                 TypeCache.computeTypes(BT, Log2LMUL, NF, PolicyPrototype);
578bdd1243dSDimitry Andric             Out.push_back(std::make_unique<RVVIntrinsic>(
579bdd1243dSDimitry Andric                 Name, SuffixStr, OverloadedName, OverloadedSuffixStr, IRName,
580bdd1243dSDimitry Andric                 /*IsMask=*/false, /*HasMaskedOffOperand=*/false, HasVL,
581bdd1243dSDimitry Andric                 UnMaskedPolicyScheme, SupportOverloading, HasBuiltinAlias,
582bdd1243dSDimitry Andric                 ManualCodegen, *PolicyTypes, IntrinsicTypes, RequiredFeatures,
583bdd1243dSDimitry Andric                 NF, P));
584bdd1243dSDimitry Andric           }
585bdd1243dSDimitry Andric         if (!HasMasked)
586bdd1243dSDimitry Andric           continue;
58781ad6265SDimitry Andric         // Create a masked intrinsic
588bdd1243dSDimitry Andric         std::optional<RVVTypes> MaskTypes =
589bdd1243dSDimitry Andric             TypeCache.computeTypes(BT, Log2LMUL, NF, MaskedPrototype);
590bdd1243dSDimitry Andric         Out.push_back(std::make_unique<RVVIntrinsic>(
591bdd1243dSDimitry Andric             Name, SuffixStr, OverloadedName, OverloadedSuffixStr, MaskedIRName,
592bdd1243dSDimitry Andric             /*IsMasked=*/true, HasMaskedOffOperand, HasVL, MaskedPolicyScheme,
593bdd1243dSDimitry Andric             SupportOverloading, HasBuiltinAlias, ManualCodegen, *MaskTypes,
594bdd1243dSDimitry Andric             IntrinsicTypes, RequiredFeatures, NF, DefaultPolicy));
595bdd1243dSDimitry Andric         if (MaskedPolicyScheme == PolicyScheme::SchemeNone)
596bdd1243dSDimitry Andric           continue;
597bdd1243dSDimitry Andric         for (auto P : SupportedMaskedPolicies) {
598bdd1243dSDimitry Andric           SmallVector<PrototypeDescriptor> PolicyPrototype =
599bdd1243dSDimitry Andric               RVVIntrinsic::computeBuiltinTypes(
600bdd1243dSDimitry Andric                   BasicPrototype, /*IsMasked=*/true, HasMaskedOffOperand, HasVL,
601bdd1243dSDimitry Andric                   NF, MaskedPolicyScheme, P);
602bdd1243dSDimitry Andric           std::optional<RVVTypes> PolicyTypes =
603bdd1243dSDimitry Andric               TypeCache.computeTypes(BT, Log2LMUL, NF, PolicyPrototype);
604fe6060f1SDimitry Andric           Out.push_back(std::make_unique<RVVIntrinsic>(
60581ad6265SDimitry Andric               Name, SuffixStr, OverloadedName, OverloadedSuffixStr,
606bdd1243dSDimitry Andric               MaskedIRName, /*IsMasked=*/true, HasMaskedOffOperand, HasVL,
607bdd1243dSDimitry Andric               MaskedPolicyScheme, SupportOverloading, HasBuiltinAlias,
608bdd1243dSDimitry Andric               ManualCodegen, *PolicyTypes, IntrinsicTypes, RequiredFeatures, NF,
609bdd1243dSDimitry Andric               P));
610fe6060f1SDimitry Andric         }
611bdd1243dSDimitry Andric       } // End for Log2LMULList
612bdd1243dSDimitry Andric     }   // End for TypeRange
613972a253aSDimitry Andric 
614972a253aSDimitry Andric     // We don't emit vsetvli and vsetvlimax for SemaRecord.
615972a253aSDimitry Andric     // They are written in riscv_vector.td and will emit those marco define in
616972a253aSDimitry Andric     // riscv_vector.h
617972a253aSDimitry Andric     if (Name == "vsetvli" || Name == "vsetvlimax")
618972a253aSDimitry Andric       continue;
619972a253aSDimitry Andric 
620972a253aSDimitry Andric     if (!SemaRecords)
621972a253aSDimitry Andric       continue;
622972a253aSDimitry Andric 
623972a253aSDimitry Andric     // Create SemaRecord
624972a253aSDimitry Andric     SemaRecord SR;
625972a253aSDimitry Andric     SR.Name = Name.str();
626972a253aSDimitry Andric     SR.OverloadedName = OverloadedName.str();
627972a253aSDimitry Andric     BasicType TypeRangeMask = BasicType::Unknown;
628972a253aSDimitry Andric     for (char I : TypeRange)
629972a253aSDimitry Andric       TypeRangeMask |= ParseBasicType(I);
630972a253aSDimitry Andric 
631972a253aSDimitry Andric     SR.TypeRangeMask = static_cast<unsigned>(TypeRangeMask);
632972a253aSDimitry Andric 
633972a253aSDimitry Andric     unsigned Log2LMULMask = 0;
634972a253aSDimitry Andric     for (int Log2LMUL : Log2LMULList)
635972a253aSDimitry Andric       Log2LMULMask |= 1 << (Log2LMUL + 3);
636972a253aSDimitry Andric 
637972a253aSDimitry Andric     SR.Log2LMULMask = Log2LMULMask;
638972a253aSDimitry Andric 
639972a253aSDimitry Andric     SR.RequiredExtensions = 0;
640972a253aSDimitry Andric     for (auto RequiredFeature : RequiredFeatures) {
641972a253aSDimitry Andric       RVVRequire RequireExt = StringSwitch<RVVRequire>(RequiredFeature)
642972a253aSDimitry Andric                                   .Case("RV64", RVV_REQ_RV64)
643972a253aSDimitry Andric                                   .Case("FullMultiply", RVV_REQ_FullMultiply)
644972a253aSDimitry Andric                                   .Default(RVV_REQ_None);
645972a253aSDimitry Andric       assert(RequireExt != RVV_REQ_None && "Unrecognized required feature?");
646972a253aSDimitry Andric       SR.RequiredExtensions |= RequireExt;
647972a253aSDimitry Andric     }
648972a253aSDimitry Andric 
649972a253aSDimitry Andric     SR.NF = NF;
650972a253aSDimitry Andric     SR.HasMasked = HasMasked;
651972a253aSDimitry Andric     SR.HasVL = HasVL;
652972a253aSDimitry Andric     SR.HasMaskedOffOperand = HasMaskedOffOperand;
653bdd1243dSDimitry Andric     SR.HasTailPolicy = HasTailPolicy;
654bdd1243dSDimitry Andric     SR.HasMaskPolicy = HasMaskPolicy;
655bdd1243dSDimitry Andric     SR.UnMaskedPolicyScheme = static_cast<uint8_t>(UnMaskedPolicyScheme);
656bdd1243dSDimitry Andric     SR.MaskedPolicyScheme = static_cast<uint8_t>(MaskedPolicyScheme);
657972a253aSDimitry Andric     SR.Prototype = std::move(BasicPrototype);
658972a253aSDimitry Andric     SR.Suffix = parsePrototypes(SuffixProto);
659972a253aSDimitry Andric     SR.OverloadedSuffix = parsePrototypes(OverloadedSuffixProto);
660972a253aSDimitry Andric 
661972a253aSDimitry Andric     SemaRecords->push_back(SR);
662fe6060f1SDimitry Andric   }
663fe6060f1SDimitry Andric }
664fe6060f1SDimitry Andric 
66581ad6265SDimitry Andric void RVVEmitter::printHeaderCode(raw_ostream &OS) {
666349cc55cSDimitry Andric   std::vector<Record *> RVVHeaders =
667349cc55cSDimitry Andric       Records.getAllDerivedDefinitions("RVVHeader");
668349cc55cSDimitry Andric   for (auto *R : RVVHeaders) {
669349cc55cSDimitry Andric     StringRef HeaderCodeStr = R->getValueAsString("HeaderCode");
670349cc55cSDimitry Andric     OS << HeaderCodeStr.str();
671349cc55cSDimitry Andric   }
672349cc55cSDimitry Andric }
673349cc55cSDimitry Andric 
674972a253aSDimitry Andric void RVVEmitter::createRVVIntrinsicRecords(std::vector<RVVIntrinsicRecord> &Out,
675972a253aSDimitry Andric                                            SemaSignatureTable &SST,
676972a253aSDimitry Andric                                            ArrayRef<SemaRecord> SemaRecords) {
677972a253aSDimitry Andric   SST.init(SemaRecords);
678972a253aSDimitry Andric 
679972a253aSDimitry Andric   for (const auto &SR : SemaRecords) {
680972a253aSDimitry Andric     Out.emplace_back(RVVIntrinsicRecord());
681972a253aSDimitry Andric     RVVIntrinsicRecord &R = Out.back();
682972a253aSDimitry Andric     R.Name = SR.Name.c_str();
683972a253aSDimitry Andric     R.OverloadedName = SR.OverloadedName.c_str();
684972a253aSDimitry Andric     R.PrototypeIndex = SST.getIndex(SR.Prototype);
685972a253aSDimitry Andric     R.SuffixIndex = SST.getIndex(SR.Suffix);
686972a253aSDimitry Andric     R.OverloadedSuffixIndex = SST.getIndex(SR.OverloadedSuffix);
687972a253aSDimitry Andric     R.PrototypeLength = SR.Prototype.size();
688972a253aSDimitry Andric     R.SuffixLength = SR.Suffix.size();
689972a253aSDimitry Andric     R.OverloadedSuffixSize = SR.OverloadedSuffix.size();
690972a253aSDimitry Andric     R.RequiredExtensions = SR.RequiredExtensions;
691972a253aSDimitry Andric     R.TypeRangeMask = SR.TypeRangeMask;
692972a253aSDimitry Andric     R.Log2LMULMask = SR.Log2LMULMask;
693972a253aSDimitry Andric     R.NF = SR.NF;
694972a253aSDimitry Andric     R.HasMasked = SR.HasMasked;
695972a253aSDimitry Andric     R.HasVL = SR.HasVL;
696972a253aSDimitry Andric     R.HasMaskedOffOperand = SR.HasMaskedOffOperand;
697bdd1243dSDimitry Andric     R.HasTailPolicy = SR.HasTailPolicy;
698bdd1243dSDimitry Andric     R.HasMaskPolicy = SR.HasMaskPolicy;
699bdd1243dSDimitry Andric     R.UnMaskedPolicyScheme = SR.UnMaskedPolicyScheme;
700bdd1243dSDimitry Andric     R.MaskedPolicyScheme = SR.MaskedPolicyScheme;
701972a253aSDimitry Andric 
702972a253aSDimitry Andric     assert(R.PrototypeIndex !=
703972a253aSDimitry Andric            static_cast<uint16_t>(SemaSignatureTable::INVALID_INDEX));
704972a253aSDimitry Andric     assert(R.SuffixIndex !=
705972a253aSDimitry Andric            static_cast<uint16_t>(SemaSignatureTable::INVALID_INDEX));
706972a253aSDimitry Andric     assert(R.OverloadedSuffixIndex !=
707972a253aSDimitry Andric            static_cast<uint16_t>(SemaSignatureTable::INVALID_INDEX));
708fe6060f1SDimitry Andric   }
709fe6060f1SDimitry Andric }
710fe6060f1SDimitry Andric 
711972a253aSDimitry Andric void RVVEmitter::createSema(raw_ostream &OS) {
712972a253aSDimitry Andric   std::vector<std::unique_ptr<RVVIntrinsic>> Defs;
713972a253aSDimitry Andric   std::vector<RVVIntrinsicRecord> RVVIntrinsicRecords;
714972a253aSDimitry Andric   SemaSignatureTable SST;
715972a253aSDimitry Andric   std::vector<SemaRecord> SemaRecords;
716972a253aSDimitry Andric 
717972a253aSDimitry Andric   createRVVIntrinsics(Defs, &SemaRecords);
718972a253aSDimitry Andric 
719972a253aSDimitry Andric   createRVVIntrinsicRecords(RVVIntrinsicRecords, SST, SemaRecords);
720972a253aSDimitry Andric 
721972a253aSDimitry Andric   // Emit signature table for SemaRISCVVectorLookup.cpp.
722972a253aSDimitry Andric   OS << "#ifdef DECL_SIGNATURE_TABLE\n";
723972a253aSDimitry Andric   SST.print(OS);
724972a253aSDimitry Andric   OS << "#endif\n";
725972a253aSDimitry Andric 
726972a253aSDimitry Andric   // Emit RVVIntrinsicRecords for SemaRISCVVectorLookup.cpp.
727972a253aSDimitry Andric   OS << "#ifdef DECL_INTRINSIC_RECORDS\n";
728972a253aSDimitry Andric   for (const RVVIntrinsicRecord &Record : RVVIntrinsicRecords)
729972a253aSDimitry Andric     OS << Record;
730972a253aSDimitry Andric   OS << "#endif\n";
731fe6060f1SDimitry Andric }
732fe6060f1SDimitry Andric 
733fe6060f1SDimitry Andric namespace clang {
734fe6060f1SDimitry Andric void EmitRVVHeader(RecordKeeper &Records, raw_ostream &OS) {
735fe6060f1SDimitry Andric   RVVEmitter(Records).createHeader(OS);
736fe6060f1SDimitry Andric }
737fe6060f1SDimitry Andric 
738fe6060f1SDimitry Andric void EmitRVVBuiltins(RecordKeeper &Records, raw_ostream &OS) {
739fe6060f1SDimitry Andric   RVVEmitter(Records).createBuiltins(OS);
740fe6060f1SDimitry Andric }
741fe6060f1SDimitry Andric 
742fe6060f1SDimitry Andric void EmitRVVBuiltinCG(RecordKeeper &Records, raw_ostream &OS) {
743fe6060f1SDimitry Andric   RVVEmitter(Records).createCodeGen(OS);
744fe6060f1SDimitry Andric }
745fe6060f1SDimitry Andric 
746972a253aSDimitry Andric void EmitRVVBuiltinSema(RecordKeeper &Records, raw_ostream &OS) {
747972a253aSDimitry Andric   RVVEmitter(Records).createSema(OS);
748972a253aSDimitry Andric }
749972a253aSDimitry Andric 
750fe6060f1SDimitry Andric } // End namespace clang
751