xref: /freebsd-src/contrib/llvm-project/clang/utils/TableGen/RISCVVEmitter.cpp (revision 81ad626541db97eb356e2c1d4a20eb2a26a766ab)
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 
17*81ad6265SDimitry 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"
23fe6060f1SDimitry Andric #include "llvm/ADT/Twine.h"
24fe6060f1SDimitry Andric #include "llvm/TableGen/Error.h"
25fe6060f1SDimitry Andric #include "llvm/TableGen/Record.h"
26fe6060f1SDimitry Andric #include <numeric>
27fe6060f1SDimitry Andric 
28fe6060f1SDimitry Andric using namespace llvm;
29*81ad6265SDimitry Andric using namespace clang::RISCV;
30fe6060f1SDimitry Andric 
31fe6060f1SDimitry Andric namespace {
32fe6060f1SDimitry Andric class RVVEmitter {
33fe6060f1SDimitry Andric private:
34fe6060f1SDimitry Andric   RecordKeeper &Records;
35fe6060f1SDimitry Andric 
36fe6060f1SDimitry Andric public:
37fe6060f1SDimitry Andric   RVVEmitter(RecordKeeper &R) : Records(R) {}
38fe6060f1SDimitry Andric 
39fe6060f1SDimitry Andric   /// Emit riscv_vector.h
40fe6060f1SDimitry Andric   void createHeader(raw_ostream &o);
41fe6060f1SDimitry Andric 
42fe6060f1SDimitry Andric   /// Emit all the __builtin prototypes and code needed by Sema.
43fe6060f1SDimitry Andric   void createBuiltins(raw_ostream &o);
44fe6060f1SDimitry Andric 
45fe6060f1SDimitry Andric   /// Emit all the information needed to map builtin -> LLVM IR intrinsic.
46fe6060f1SDimitry Andric   void createCodeGen(raw_ostream &o);
47fe6060f1SDimitry Andric 
48fe6060f1SDimitry Andric private:
49fe6060f1SDimitry Andric   /// Create all intrinsics and add them to \p Out
50fe6060f1SDimitry Andric   void createRVVIntrinsics(std::vector<std::unique_ptr<RVVIntrinsic>> &Out);
51*81ad6265SDimitry Andric   /// Print HeaderCode in RVVHeader Record to \p Out
52*81ad6265SDimitry Andric   void printHeaderCode(raw_ostream &OS);
53fe6060f1SDimitry Andric 
54fe6060f1SDimitry Andric   /// Emit Acrh predecessor definitions and body, assume the element of Defs are
55fe6060f1SDimitry Andric   /// sorted by extension.
56fe6060f1SDimitry Andric   void emitArchMacroAndBody(
57fe6060f1SDimitry Andric       std::vector<std::unique_ptr<RVVIntrinsic>> &Defs, raw_ostream &o,
58fe6060f1SDimitry Andric       std::function<void(raw_ostream &, const RVVIntrinsic &)>);
59fe6060f1SDimitry Andric 
60fe6060f1SDimitry Andric   // Emit the architecture preprocessor definitions. Return true when emits
61fe6060f1SDimitry Andric   // non-empty string.
6204eeddc0SDimitry Andric   bool emitMacroRestrictionStr(RISCVPredefinedMacroT PredefinedMacros,
6304eeddc0SDimitry Andric                                raw_ostream &o);
64fe6060f1SDimitry Andric };
65fe6060f1SDimitry Andric 
66fe6060f1SDimitry Andric } // namespace
67fe6060f1SDimitry Andric 
68*81ad6265SDimitry Andric static BasicType ParseBasicType(char c) {
69*81ad6265SDimitry Andric   switch (c) {
70fe6060f1SDimitry Andric   case 'c':
71*81ad6265SDimitry Andric     return BasicType::Int8;
72fe6060f1SDimitry Andric     break;
73fe6060f1SDimitry Andric   case 's':
74*81ad6265SDimitry Andric     return BasicType::Int16;
75fe6060f1SDimitry Andric     break;
76fe6060f1SDimitry Andric   case 'i':
77*81ad6265SDimitry Andric     return BasicType::Int32;
78fe6060f1SDimitry Andric     break;
79fe6060f1SDimitry Andric   case 'l':
80*81ad6265SDimitry Andric     return BasicType::Int64;
81fe6060f1SDimitry Andric     break;
82fe6060f1SDimitry Andric   case 'x':
83*81ad6265SDimitry Andric     return BasicType::Float16;
84fe6060f1SDimitry Andric     break;
85fe6060f1SDimitry Andric   case 'f':
86*81ad6265SDimitry Andric     return BasicType::Float32;
87fe6060f1SDimitry Andric     break;
88fe6060f1SDimitry Andric   case 'd':
89*81ad6265SDimitry Andric     return BasicType::Float64;
90fe6060f1SDimitry Andric     break;
91*81ad6265SDimitry Andric 
92fe6060f1SDimitry Andric   default:
93*81ad6265SDimitry Andric     return BasicType::Unknown;
94fe6060f1SDimitry Andric   }
95fe6060f1SDimitry Andric }
96fe6060f1SDimitry Andric 
97*81ad6265SDimitry Andric void emitCodeGenSwitchBody(const RVVIntrinsic *RVVI, raw_ostream &OS) {
98*81ad6265SDimitry Andric   if (!RVVI->getIRName().empty())
99*81ad6265SDimitry Andric     OS << "  ID = Intrinsic::riscv_" + RVVI->getIRName() + ";\n";
100*81ad6265SDimitry Andric   if (RVVI->getNF() >= 2)
101*81ad6265SDimitry Andric     OS << "  NF = " + utostr(RVVI->getNF()) + ";\n";
102*81ad6265SDimitry Andric   if (RVVI->hasManualCodegen()) {
103*81ad6265SDimitry Andric     OS << RVVI->getManualCodegen();
104fe6060f1SDimitry Andric     OS << "break;\n";
105fe6060f1SDimitry Andric     return;
106fe6060f1SDimitry Andric   }
107fe6060f1SDimitry Andric 
108*81ad6265SDimitry Andric   if (RVVI->isMasked()) {
109*81ad6265SDimitry Andric     if (RVVI->hasVL()) {
110fe6060f1SDimitry Andric       OS << "  std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1);\n";
111*81ad6265SDimitry Andric       if (RVVI->hasPolicyOperand())
112349cc55cSDimitry Andric         OS << "  Ops.push_back(ConstantInt::get(Ops.back()->getType(),"
113349cc55cSDimitry Andric               " TAIL_UNDISTURBED));\n";
114fe6060f1SDimitry Andric     } else {
115fe6060f1SDimitry Andric       OS << "  std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end());\n";
116fe6060f1SDimitry Andric     }
117*81ad6265SDimitry Andric   } else {
118*81ad6265SDimitry Andric     if (RVVI->hasPolicyOperand())
119*81ad6265SDimitry Andric       OS << "  Ops.push_back(ConstantInt::get(Ops.back()->getType(), "
120*81ad6265SDimitry Andric             "TAIL_UNDISTURBED));\n";
121*81ad6265SDimitry Andric     else if (RVVI->hasPassthruOperand()) {
122*81ad6265SDimitry Andric       OS << "  Ops.push_back(llvm::UndefValue::get(ResultType));\n";
123*81ad6265SDimitry Andric       OS << "  std::rotate(Ops.rbegin(), Ops.rbegin() + 1,  Ops.rend());\n";
124*81ad6265SDimitry Andric     }
125fe6060f1SDimitry Andric   }
126fe6060f1SDimitry Andric 
127fe6060f1SDimitry Andric   OS << "  IntrinsicTypes = {";
128fe6060f1SDimitry Andric   ListSeparator LS;
129*81ad6265SDimitry Andric   for (const auto &Idx : RVVI->getIntrinsicTypes()) {
130fe6060f1SDimitry Andric     if (Idx == -1)
131fe6060f1SDimitry Andric       OS << LS << "ResultType";
132fe6060f1SDimitry Andric     else
133fe6060f1SDimitry Andric       OS << LS << "Ops[" << Idx << "]->getType()";
134fe6060f1SDimitry Andric   }
135fe6060f1SDimitry Andric 
136fe6060f1SDimitry Andric   // VL could be i64 or i32, need to encode it in IntrinsicTypes. VL is
137fe6060f1SDimitry Andric   // always last operand.
138*81ad6265SDimitry Andric   if (RVVI->hasVL())
139fe6060f1SDimitry Andric     OS << ", Ops.back()->getType()";
140fe6060f1SDimitry Andric   OS << "};\n";
141fe6060f1SDimitry Andric   OS << "  break;\n";
142fe6060f1SDimitry Andric }
143fe6060f1SDimitry Andric 
144*81ad6265SDimitry Andric void emitIntrinsicFuncDef(const RVVIntrinsic &RVVI, raw_ostream &OS) {
145349cc55cSDimitry Andric   OS << "__attribute__((__clang_builtin_alias__(";
146*81ad6265SDimitry Andric   OS << "__builtin_rvv_" << RVVI.getBuiltinName() << ")))\n";
147*81ad6265SDimitry Andric   OS << RVVI.getOutputType()->getTypeStr() << " " << RVVI.getName() << "(";
148349cc55cSDimitry Andric   // Emit function arguments
149*81ad6265SDimitry Andric   const RVVTypes &InputTypes = RVVI.getInputTypes();
150fe6060f1SDimitry Andric   if (!InputTypes.empty()) {
151fe6060f1SDimitry Andric     ListSeparator LS;
152349cc55cSDimitry Andric     for (unsigned i = 0; i < InputTypes.size(); ++i)
153349cc55cSDimitry Andric       OS << LS << InputTypes[i]->getTypeStr();
154fe6060f1SDimitry Andric   }
155349cc55cSDimitry Andric   OS << ");\n";
156fe6060f1SDimitry Andric }
157fe6060f1SDimitry Andric 
158*81ad6265SDimitry Andric void emitOverloadedFuncDef(const RVVIntrinsic &RVVI, raw_ostream &OS) {
159349cc55cSDimitry Andric   OS << "__attribute__((__clang_builtin_alias__(";
160*81ad6265SDimitry Andric   OS << "__builtin_rvv_" << RVVI.getBuiltinName() << ")))\n";
161*81ad6265SDimitry Andric   OS << RVVI.getOutputType()->getTypeStr() << " " << RVVI.getOverloadedName()
162*81ad6265SDimitry Andric      << "(";
163fe6060f1SDimitry Andric   // Emit function arguments
164*81ad6265SDimitry Andric   const RVVTypes &InputTypes = RVVI.getInputTypes();
165fe6060f1SDimitry Andric   if (!InputTypes.empty()) {
166fe6060f1SDimitry Andric     ListSeparator LS;
167fe6060f1SDimitry Andric     for (unsigned i = 0; i < InputTypes.size(); ++i)
168349cc55cSDimitry Andric       OS << LS << InputTypes[i]->getTypeStr();
169fe6060f1SDimitry Andric   }
170349cc55cSDimitry Andric   OS << ");\n";
171fe6060f1SDimitry Andric }
172fe6060f1SDimitry Andric 
173fe6060f1SDimitry Andric //===----------------------------------------------------------------------===//
174fe6060f1SDimitry Andric // RVVEmitter implementation
175fe6060f1SDimitry Andric //===----------------------------------------------------------------------===//
176fe6060f1SDimitry Andric void RVVEmitter::createHeader(raw_ostream &OS) {
177fe6060f1SDimitry Andric 
178fe6060f1SDimitry Andric   OS << "/*===---- riscv_vector.h - RISC-V V-extension RVVIntrinsics "
179fe6060f1SDimitry Andric         "-------------------===\n"
180fe6060f1SDimitry Andric         " *\n"
181fe6060f1SDimitry Andric         " *\n"
182fe6060f1SDimitry Andric         " * Part of the LLVM Project, under the Apache License v2.0 with LLVM "
183fe6060f1SDimitry Andric         "Exceptions.\n"
184fe6060f1SDimitry Andric         " * See https://llvm.org/LICENSE.txt for license information.\n"
185fe6060f1SDimitry Andric         " * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n"
186fe6060f1SDimitry Andric         " *\n"
187fe6060f1SDimitry Andric         " *===-----------------------------------------------------------------"
188fe6060f1SDimitry Andric         "------===\n"
189fe6060f1SDimitry Andric         " */\n\n";
190fe6060f1SDimitry Andric 
191fe6060f1SDimitry Andric   OS << "#ifndef __RISCV_VECTOR_H\n";
192fe6060f1SDimitry Andric   OS << "#define __RISCV_VECTOR_H\n\n";
193fe6060f1SDimitry Andric 
194fe6060f1SDimitry Andric   OS << "#include <stdint.h>\n";
195fe6060f1SDimitry Andric   OS << "#include <stddef.h>\n\n";
196fe6060f1SDimitry Andric 
197fe6060f1SDimitry Andric   OS << "#ifndef __riscv_vector\n";
198fe6060f1SDimitry Andric   OS << "#error \"Vector intrinsics require the vector extension.\"\n";
199fe6060f1SDimitry Andric   OS << "#endif\n\n";
200fe6060f1SDimitry Andric 
201fe6060f1SDimitry Andric   OS << "#ifdef __cplusplus\n";
202fe6060f1SDimitry Andric   OS << "extern \"C\" {\n";
203fe6060f1SDimitry Andric   OS << "#endif\n\n";
204fe6060f1SDimitry Andric 
205*81ad6265SDimitry Andric   printHeaderCode(OS);
206349cc55cSDimitry Andric 
207fe6060f1SDimitry Andric   std::vector<std::unique_ptr<RVVIntrinsic>> Defs;
208fe6060f1SDimitry Andric   createRVVIntrinsics(Defs);
209fe6060f1SDimitry Andric 
210fe6060f1SDimitry Andric   auto printType = [&](auto T) {
211fe6060f1SDimitry Andric     OS << "typedef " << T->getClangBuiltinStr() << " " << T->getTypeStr()
212fe6060f1SDimitry Andric        << ";\n";
213fe6060f1SDimitry Andric   };
214fe6060f1SDimitry Andric 
215fe6060f1SDimitry Andric   constexpr int Log2LMULs[] = {-3, -2, -1, 0, 1, 2, 3};
216fe6060f1SDimitry Andric   // Print RVV boolean types.
217fe6060f1SDimitry Andric   for (int Log2LMUL : Log2LMULs) {
218*81ad6265SDimitry Andric     auto T = RVVType::computeType(BasicType::Int8, Log2LMUL,
219*81ad6265SDimitry Andric                                   PrototypeDescriptor::Mask);
220*81ad6265SDimitry Andric     if (T)
221fe6060f1SDimitry Andric       printType(T.getValue());
222fe6060f1SDimitry Andric   }
223fe6060f1SDimitry Andric   // Print RVV int/float types.
224fe6060f1SDimitry Andric   for (char I : StringRef("csil")) {
225*81ad6265SDimitry Andric     BasicType BT = ParseBasicType(I);
226fe6060f1SDimitry Andric     for (int Log2LMUL : Log2LMULs) {
227*81ad6265SDimitry Andric       auto T = RVVType::computeType(BT, Log2LMUL, PrototypeDescriptor::Vector);
228*81ad6265SDimitry Andric       if (T) {
229fe6060f1SDimitry Andric         printType(T.getValue());
230*81ad6265SDimitry Andric         auto UT = RVVType::computeType(
231*81ad6265SDimitry Andric             BT, Log2LMUL,
232*81ad6265SDimitry Andric             PrototypeDescriptor(BaseTypeModifier::Vector,
233*81ad6265SDimitry Andric                                 VectorTypeModifier::NoModifier,
234*81ad6265SDimitry Andric                                 TypeModifier::UnsignedInteger));
235fe6060f1SDimitry Andric         printType(UT.getValue());
236fe6060f1SDimitry Andric       }
237fe6060f1SDimitry Andric     }
238fe6060f1SDimitry Andric   }
239*81ad6265SDimitry Andric   OS << "#if defined(__riscv_zvfh)\n";
240fe6060f1SDimitry Andric   for (int Log2LMUL : Log2LMULs) {
241*81ad6265SDimitry Andric     auto T = RVVType::computeType(BasicType::Float16, Log2LMUL,
242*81ad6265SDimitry Andric                                   PrototypeDescriptor::Vector);
243*81ad6265SDimitry Andric     if (T)
244fe6060f1SDimitry Andric       printType(T.getValue());
245fe6060f1SDimitry Andric   }
246fe6060f1SDimitry Andric   OS << "#endif\n";
247fe6060f1SDimitry Andric 
248fe6060f1SDimitry Andric   OS << "#if defined(__riscv_f)\n";
249fe6060f1SDimitry Andric   for (int Log2LMUL : Log2LMULs) {
250*81ad6265SDimitry Andric     auto T = RVVType::computeType(BasicType::Float32, Log2LMUL,
251*81ad6265SDimitry Andric                                   PrototypeDescriptor::Vector);
252*81ad6265SDimitry Andric     if (T)
253fe6060f1SDimitry Andric       printType(T.getValue());
254fe6060f1SDimitry Andric   }
255fe6060f1SDimitry Andric   OS << "#endif\n";
256fe6060f1SDimitry Andric 
257fe6060f1SDimitry Andric   OS << "#if defined(__riscv_d)\n";
258fe6060f1SDimitry Andric   for (int Log2LMUL : Log2LMULs) {
259*81ad6265SDimitry Andric     auto T = RVVType::computeType(BasicType::Float64, Log2LMUL,
260*81ad6265SDimitry Andric                                   PrototypeDescriptor::Vector);
261*81ad6265SDimitry Andric     if (T)
262fe6060f1SDimitry Andric       printType(T.getValue());
263fe6060f1SDimitry Andric   }
264fe6060f1SDimitry Andric   OS << "#endif\n\n";
265fe6060f1SDimitry Andric 
266fe6060f1SDimitry Andric   // The same extension include in the same arch guard marco.
267349cc55cSDimitry Andric   llvm::stable_sort(Defs, [](const std::unique_ptr<RVVIntrinsic> &A,
268fe6060f1SDimitry Andric                              const std::unique_ptr<RVVIntrinsic> &B) {
26904eeddc0SDimitry Andric     return A->getRISCVPredefinedMacros() < B->getRISCVPredefinedMacros();
270fe6060f1SDimitry Andric   });
271fe6060f1SDimitry Andric 
272349cc55cSDimitry Andric   OS << "#define __rvv_ai static __inline__\n";
273349cc55cSDimitry Andric 
274fe6060f1SDimitry Andric   // Print intrinsic functions with macro
275fe6060f1SDimitry Andric   emitArchMacroAndBody(Defs, OS, [](raw_ostream &OS, const RVVIntrinsic &Inst) {
276349cc55cSDimitry Andric     OS << "__rvv_ai ";
277*81ad6265SDimitry Andric     emitIntrinsicFuncDef(Inst, OS);
278fe6060f1SDimitry Andric   });
279fe6060f1SDimitry Andric 
280349cc55cSDimitry Andric   OS << "#undef __rvv_ai\n\n";
281349cc55cSDimitry Andric 
282fe6060f1SDimitry Andric   OS << "#define __riscv_v_intrinsic_overloading 1\n";
283fe6060f1SDimitry Andric 
284fe6060f1SDimitry Andric   // Print Overloaded APIs
285349cc55cSDimitry Andric   OS << "#define __rvv_aio static __inline__ "
286349cc55cSDimitry Andric         "__attribute__((__overloadable__))\n";
287fe6060f1SDimitry Andric 
288fe6060f1SDimitry Andric   emitArchMacroAndBody(Defs, OS, [](raw_ostream &OS, const RVVIntrinsic &Inst) {
289*81ad6265SDimitry Andric     if (!Inst.isMasked() && !Inst.hasUnMaskedOverloaded())
290fe6060f1SDimitry Andric       return;
291349cc55cSDimitry Andric     OS << "__rvv_aio ";
292*81ad6265SDimitry Andric     emitOverloadedFuncDef(Inst, OS);
293fe6060f1SDimitry Andric   });
294fe6060f1SDimitry Andric 
295349cc55cSDimitry Andric   OS << "#undef __rvv_aio\n";
296349cc55cSDimitry Andric 
297fe6060f1SDimitry Andric   OS << "\n#ifdef __cplusplus\n";
298fe6060f1SDimitry Andric   OS << "}\n";
299349cc55cSDimitry Andric   OS << "#endif // __cplusplus\n";
300fe6060f1SDimitry Andric   OS << "#endif // __RISCV_VECTOR_H\n";
301fe6060f1SDimitry Andric }
302fe6060f1SDimitry Andric 
303fe6060f1SDimitry Andric void RVVEmitter::createBuiltins(raw_ostream &OS) {
304fe6060f1SDimitry Andric   std::vector<std::unique_ptr<RVVIntrinsic>> Defs;
305fe6060f1SDimitry Andric   createRVVIntrinsics(Defs);
306fe6060f1SDimitry Andric 
307349cc55cSDimitry Andric   // Map to keep track of which builtin names have already been emitted.
308349cc55cSDimitry Andric   StringMap<RVVIntrinsic *> BuiltinMap;
309349cc55cSDimitry Andric 
310fe6060f1SDimitry Andric   OS << "#if defined(TARGET_BUILTIN) && !defined(RISCVV_BUILTIN)\n";
311fe6060f1SDimitry Andric   OS << "#define RISCVV_BUILTIN(ID, TYPE, ATTRS) TARGET_BUILTIN(ID, TYPE, "
312*81ad6265SDimitry Andric         "ATTRS, \"zve32x\")\n";
313fe6060f1SDimitry Andric   OS << "#endif\n";
314fe6060f1SDimitry Andric   for (auto &Def : Defs) {
315349cc55cSDimitry Andric     auto P =
316349cc55cSDimitry Andric         BuiltinMap.insert(std::make_pair(Def->getBuiltinName(), Def.get()));
317349cc55cSDimitry Andric     if (!P.second) {
318*81ad6265SDimitry Andric       // Verf that this would have produced the same builtin definition.
319*81ad6265SDimitry Andric       if (P.first->second->hasBuiltinAlias() != Def->hasBuiltinAlias())
320349cc55cSDimitry Andric         PrintFatalError("Builtin with same name has different hasAutoDef");
321*81ad6265SDimitry Andric       else if (!Def->hasBuiltinAlias() &&
322*81ad6265SDimitry Andric                P.first->second->getBuiltinTypeStr() != Def->getBuiltinTypeStr())
323349cc55cSDimitry Andric         PrintFatalError("Builtin with same name has different type string");
324349cc55cSDimitry Andric       continue;
325349cc55cSDimitry Andric     }
326349cc55cSDimitry Andric     OS << "RISCVV_BUILTIN(__builtin_rvv_" << Def->getBuiltinName() << ",\"";
327*81ad6265SDimitry Andric     if (!Def->hasBuiltinAlias())
328349cc55cSDimitry Andric       OS << Def->getBuiltinTypeStr();
329349cc55cSDimitry Andric     OS << "\", \"n\")\n";
330fe6060f1SDimitry Andric   }
331fe6060f1SDimitry Andric   OS << "#undef RISCVV_BUILTIN\n";
332fe6060f1SDimitry Andric }
333fe6060f1SDimitry Andric 
334fe6060f1SDimitry Andric void RVVEmitter::createCodeGen(raw_ostream &OS) {
335fe6060f1SDimitry Andric   std::vector<std::unique_ptr<RVVIntrinsic>> Defs;
336fe6060f1SDimitry Andric   createRVVIntrinsics(Defs);
337fe6060f1SDimitry Andric   // IR name could be empty, use the stable sort preserves the relative order.
338349cc55cSDimitry Andric   llvm::stable_sort(Defs, [](const std::unique_ptr<RVVIntrinsic> &A,
339fe6060f1SDimitry Andric                              const std::unique_ptr<RVVIntrinsic> &B) {
340fe6060f1SDimitry Andric     return A->getIRName() < B->getIRName();
341fe6060f1SDimitry Andric   });
342349cc55cSDimitry Andric 
343349cc55cSDimitry Andric   // Map to keep track of which builtin names have already been emitted.
344349cc55cSDimitry Andric   StringMap<RVVIntrinsic *> BuiltinMap;
345349cc55cSDimitry Andric 
346fe6060f1SDimitry Andric   // Print switch body when the ir name or ManualCodegen changes from previous
347fe6060f1SDimitry Andric   // iteration.
348fe6060f1SDimitry Andric   RVVIntrinsic *PrevDef = Defs.begin()->get();
349fe6060f1SDimitry Andric   for (auto &Def : Defs) {
350fe6060f1SDimitry Andric     StringRef CurIRName = Def->getIRName();
351fe6060f1SDimitry Andric     if (CurIRName != PrevDef->getIRName() ||
352fe6060f1SDimitry Andric         (Def->getManualCodegen() != PrevDef->getManualCodegen())) {
353*81ad6265SDimitry Andric       emitCodeGenSwitchBody(PrevDef, OS);
354fe6060f1SDimitry Andric     }
355fe6060f1SDimitry Andric     PrevDef = Def.get();
356349cc55cSDimitry Andric 
357349cc55cSDimitry Andric     auto P =
358349cc55cSDimitry Andric         BuiltinMap.insert(std::make_pair(Def->getBuiltinName(), Def.get()));
359349cc55cSDimitry Andric     if (P.second) {
360349cc55cSDimitry Andric       OS << "case RISCVVector::BI__builtin_rvv_" << Def->getBuiltinName()
361349cc55cSDimitry Andric          << ":\n";
362349cc55cSDimitry Andric       continue;
363349cc55cSDimitry Andric     }
364349cc55cSDimitry Andric 
365349cc55cSDimitry Andric     if (P.first->second->getIRName() != Def->getIRName())
366349cc55cSDimitry Andric       PrintFatalError("Builtin with same name has different IRName");
367349cc55cSDimitry Andric     else if (P.first->second->getManualCodegen() != Def->getManualCodegen())
368349cc55cSDimitry Andric       PrintFatalError("Builtin with same name has different ManualCodegen");
369349cc55cSDimitry Andric     else if (P.first->second->getNF() != Def->getNF())
370349cc55cSDimitry Andric       PrintFatalError("Builtin with same name has different NF");
371*81ad6265SDimitry Andric     else if (P.first->second->isMasked() != Def->isMasked())
372*81ad6265SDimitry Andric       PrintFatalError("Builtin with same name has different isMasked");
373349cc55cSDimitry Andric     else if (P.first->second->hasVL() != Def->hasVL())
374*81ad6265SDimitry Andric       PrintFatalError("Builtin with same name has different hasVL");
375*81ad6265SDimitry Andric     else if (P.first->second->getPolicyScheme() != Def->getPolicyScheme())
376*81ad6265SDimitry Andric       PrintFatalError("Builtin with same name has different getPolicyScheme");
377349cc55cSDimitry Andric     else if (P.first->second->getIntrinsicTypes() != Def->getIntrinsicTypes())
378349cc55cSDimitry Andric       PrintFatalError("Builtin with same name has different IntrinsicTypes");
379fe6060f1SDimitry Andric   }
380*81ad6265SDimitry Andric   emitCodeGenSwitchBody(Defs.back().get(), OS);
381fe6060f1SDimitry Andric   OS << "\n";
382fe6060f1SDimitry Andric }
383fe6060f1SDimitry Andric 
384fe6060f1SDimitry Andric void RVVEmitter::createRVVIntrinsics(
385fe6060f1SDimitry Andric     std::vector<std::unique_ptr<RVVIntrinsic>> &Out) {
386fe6060f1SDimitry Andric   std::vector<Record *> RV = Records.getAllDerivedDefinitions("RVVBuiltin");
387fe6060f1SDimitry Andric   for (auto *R : RV) {
388fe6060f1SDimitry Andric     StringRef Name = R->getValueAsString("Name");
389fe6060f1SDimitry Andric     StringRef SuffixProto = R->getValueAsString("Suffix");
390*81ad6265SDimitry Andric     StringRef OverloadedName = R->getValueAsString("OverloadedName");
391*81ad6265SDimitry Andric     StringRef OverloadedSuffixProto = R->getValueAsString("OverloadedSuffix");
392fe6060f1SDimitry Andric     StringRef Prototypes = R->getValueAsString("Prototype");
393fe6060f1SDimitry Andric     StringRef TypeRange = R->getValueAsString("TypeRange");
394*81ad6265SDimitry Andric     bool HasMasked = R->getValueAsBit("HasMasked");
395fe6060f1SDimitry Andric     bool HasMaskedOffOperand = R->getValueAsBit("HasMaskedOffOperand");
396fe6060f1SDimitry Andric     bool HasVL = R->getValueAsBit("HasVL");
397*81ad6265SDimitry Andric     Record *MaskedPolicyRecord = R->getValueAsDef("MaskedPolicy");
398*81ad6265SDimitry Andric     PolicyScheme MaskedPolicy =
399*81ad6265SDimitry Andric         static_cast<PolicyScheme>(MaskedPolicyRecord->getValueAsInt("Value"));
400*81ad6265SDimitry Andric     Record *UnMaskedPolicyRecord = R->getValueAsDef("UnMaskedPolicy");
401*81ad6265SDimitry Andric     PolicyScheme UnMaskedPolicy =
402*81ad6265SDimitry Andric         static_cast<PolicyScheme>(UnMaskedPolicyRecord->getValueAsInt("Value"));
403*81ad6265SDimitry Andric     bool HasUnMaskedOverloaded = R->getValueAsBit("HasUnMaskedOverloaded");
404fe6060f1SDimitry Andric     std::vector<int64_t> Log2LMULList = R->getValueAsListOfInts("Log2LMUL");
405*81ad6265SDimitry Andric     bool HasBuiltinAlias = R->getValueAsBit("HasBuiltinAlias");
406fe6060f1SDimitry Andric     StringRef ManualCodegen = R->getValueAsString("ManualCodegen");
407*81ad6265SDimitry Andric     StringRef MaskedManualCodegen = R->getValueAsString("MaskedManualCodegen");
408fe6060f1SDimitry Andric     std::vector<int64_t> IntrinsicTypes =
409fe6060f1SDimitry Andric         R->getValueAsListOfInts("IntrinsicTypes");
41004eeddc0SDimitry Andric     std::vector<StringRef> RequiredFeatures =
41104eeddc0SDimitry Andric         R->getValueAsListOfStrings("RequiredFeatures");
412fe6060f1SDimitry Andric     StringRef IRName = R->getValueAsString("IRName");
413*81ad6265SDimitry Andric     StringRef MaskedIRName = R->getValueAsString("MaskedIRName");
414fe6060f1SDimitry Andric     unsigned NF = R->getValueAsInt("NF");
415fe6060f1SDimitry Andric 
416fe6060f1SDimitry Andric     // Parse prototype and create a list of primitive type with transformers
417*81ad6265SDimitry Andric     // (operand) in Prototype. Prototype[0] is output operand.
418*81ad6265SDimitry Andric     SmallVector<PrototypeDescriptor> Prototype = parsePrototypes(Prototypes);
419*81ad6265SDimitry Andric 
420*81ad6265SDimitry Andric     SmallVector<PrototypeDescriptor> SuffixDesc = parsePrototypes(SuffixProto);
421*81ad6265SDimitry Andric     SmallVector<PrototypeDescriptor> OverloadedSuffixDesc =
422*81ad6265SDimitry Andric         parsePrototypes(OverloadedSuffixProto);
423fe6060f1SDimitry Andric 
424fe6060f1SDimitry Andric     // Compute Builtin types
425*81ad6265SDimitry Andric     SmallVector<PrototypeDescriptor> MaskedPrototype = Prototype;
426*81ad6265SDimitry Andric     if (HasMasked) {
427fe6060f1SDimitry Andric       // If HasMaskedOffOperand, insert result type as first input operand.
428fe6060f1SDimitry Andric       if (HasMaskedOffOperand) {
429fe6060f1SDimitry Andric         if (NF == 1) {
430*81ad6265SDimitry Andric           MaskedPrototype.insert(MaskedPrototype.begin() + 1, Prototype[0]);
431fe6060f1SDimitry Andric         } else {
432fe6060f1SDimitry Andric           // Convert
433fe6060f1SDimitry Andric           // (void, op0 address, op1 address, ...)
434fe6060f1SDimitry Andric           // to
435fe6060f1SDimitry Andric           // (void, op0 address, op1 address, ..., maskedoff0, maskedoff1, ...)
436*81ad6265SDimitry Andric           PrototypeDescriptor MaskoffType = Prototype[1];
437*81ad6265SDimitry Andric           MaskoffType.TM &= ~static_cast<uint8_t>(TypeModifier::Pointer);
438fe6060f1SDimitry Andric           for (unsigned I = 0; I < NF; ++I)
439*81ad6265SDimitry Andric             MaskedPrototype.insert(MaskedPrototype.begin() + NF + 1,
440*81ad6265SDimitry Andric                                    MaskoffType);
441fe6060f1SDimitry Andric         }
442fe6060f1SDimitry Andric       }
443fe6060f1SDimitry Andric       if (HasMaskedOffOperand && NF > 1) {
444fe6060f1SDimitry Andric         // Convert
445fe6060f1SDimitry Andric         // (void, op0 address, op1 address, ..., maskedoff0, maskedoff1, ...)
446fe6060f1SDimitry Andric         // to
447fe6060f1SDimitry Andric         // (void, op0 address, op1 address, ..., mask, maskedoff0, maskedoff1,
448fe6060f1SDimitry Andric         // ...)
449*81ad6265SDimitry Andric         MaskedPrototype.insert(MaskedPrototype.begin() + NF + 1,
450*81ad6265SDimitry Andric                                PrototypeDescriptor::Mask);
451fe6060f1SDimitry Andric       } else {
452*81ad6265SDimitry Andric         // If HasMasked, insert PrototypeDescriptor:Mask as first input operand.
453*81ad6265SDimitry Andric         MaskedPrototype.insert(MaskedPrototype.begin() + 1,
454*81ad6265SDimitry Andric                                PrototypeDescriptor::Mask);
455fe6060f1SDimitry Andric       }
456fe6060f1SDimitry Andric     }
457*81ad6265SDimitry Andric     // If HasVL, append PrototypeDescriptor:VL to last operand
458fe6060f1SDimitry Andric     if (HasVL) {
459*81ad6265SDimitry Andric       Prototype.push_back(PrototypeDescriptor::VL);
460*81ad6265SDimitry Andric       MaskedPrototype.push_back(PrototypeDescriptor::VL);
461fe6060f1SDimitry Andric     }
462fe6060f1SDimitry Andric 
463fe6060f1SDimitry Andric     // Create Intrinsics for each type and LMUL.
464fe6060f1SDimitry Andric     for (char I : TypeRange) {
465fe6060f1SDimitry Andric       for (int Log2LMUL : Log2LMULList) {
466*81ad6265SDimitry Andric         BasicType BT = ParseBasicType(I);
467*81ad6265SDimitry Andric         Optional<RVVTypes> Types =
468*81ad6265SDimitry Andric             RVVType::computeTypes(BT, Log2LMUL, NF, Prototype);
469fe6060f1SDimitry Andric         // Ignored to create new intrinsic if there are any illegal types.
470*81ad6265SDimitry Andric         if (!Types)
471fe6060f1SDimitry Andric           continue;
472fe6060f1SDimitry Andric 
473*81ad6265SDimitry Andric         auto SuffixStr = RVVIntrinsic::getSuffixStr(BT, Log2LMUL, SuffixDesc);
474*81ad6265SDimitry Andric         auto OverloadedSuffixStr =
475*81ad6265SDimitry Andric             RVVIntrinsic::getSuffixStr(BT, Log2LMUL, OverloadedSuffixDesc);
476*81ad6265SDimitry Andric         // Create a unmasked intrinsic
477fe6060f1SDimitry Andric         Out.push_back(std::make_unique<RVVIntrinsic>(
478*81ad6265SDimitry Andric             Name, SuffixStr, OverloadedName, OverloadedSuffixStr, IRName,
479*81ad6265SDimitry Andric             /*IsMasked=*/false, /*HasMaskedOffOperand=*/false, HasVL,
480*81ad6265SDimitry Andric             UnMaskedPolicy, HasUnMaskedOverloaded, HasBuiltinAlias,
481*81ad6265SDimitry Andric             ManualCodegen, *Types, IntrinsicTypes, RequiredFeatures, NF));
482*81ad6265SDimitry Andric         if (HasMasked) {
483*81ad6265SDimitry Andric           // Create a masked intrinsic
484fe6060f1SDimitry Andric           Optional<RVVTypes> MaskTypes =
485*81ad6265SDimitry Andric               RVVType::computeTypes(BT, Log2LMUL, NF, MaskedPrototype);
486fe6060f1SDimitry Andric           Out.push_back(std::make_unique<RVVIntrinsic>(
487*81ad6265SDimitry Andric               Name, SuffixStr, OverloadedName, OverloadedSuffixStr,
488*81ad6265SDimitry Andric               MaskedIRName,
489*81ad6265SDimitry Andric               /*IsMasked=*/true, HasMaskedOffOperand, HasVL, MaskedPolicy,
490*81ad6265SDimitry Andric               HasUnMaskedOverloaded, HasBuiltinAlias, MaskedManualCodegen,
491*81ad6265SDimitry Andric               *MaskTypes, IntrinsicTypes, RequiredFeatures, NF));
492fe6060f1SDimitry Andric         }
493fe6060f1SDimitry Andric       } // end for Log2LMULList
494fe6060f1SDimitry Andric     }   // end for TypeRange
495fe6060f1SDimitry Andric   }
496fe6060f1SDimitry Andric }
497fe6060f1SDimitry Andric 
498*81ad6265SDimitry Andric void RVVEmitter::printHeaderCode(raw_ostream &OS) {
499349cc55cSDimitry Andric   std::vector<Record *> RVVHeaders =
500349cc55cSDimitry Andric       Records.getAllDerivedDefinitions("RVVHeader");
501349cc55cSDimitry Andric   for (auto *R : RVVHeaders) {
502349cc55cSDimitry Andric     StringRef HeaderCodeStr = R->getValueAsString("HeaderCode");
503349cc55cSDimitry Andric     OS << HeaderCodeStr.str();
504349cc55cSDimitry Andric   }
505349cc55cSDimitry Andric }
506349cc55cSDimitry Andric 
507fe6060f1SDimitry Andric void RVVEmitter::emitArchMacroAndBody(
508fe6060f1SDimitry Andric     std::vector<std::unique_ptr<RVVIntrinsic>> &Defs, raw_ostream &OS,
509fe6060f1SDimitry Andric     std::function<void(raw_ostream &, const RVVIntrinsic &)> PrintBody) {
51004eeddc0SDimitry Andric   RISCVPredefinedMacroT PrevMacros =
51104eeddc0SDimitry Andric       (*Defs.begin())->getRISCVPredefinedMacros();
51204eeddc0SDimitry Andric   bool NeedEndif = emitMacroRestrictionStr(PrevMacros, OS);
513fe6060f1SDimitry Andric   for (auto &Def : Defs) {
51404eeddc0SDimitry Andric     RISCVPredefinedMacroT CurMacros = Def->getRISCVPredefinedMacros();
51504eeddc0SDimitry Andric     if (CurMacros != PrevMacros) {
516fe6060f1SDimitry Andric       if (NeedEndif)
517fe6060f1SDimitry Andric         OS << "#endif\n\n";
51804eeddc0SDimitry Andric       NeedEndif = emitMacroRestrictionStr(CurMacros, OS);
51904eeddc0SDimitry Andric       PrevMacros = CurMacros;
520fe6060f1SDimitry Andric     }
521*81ad6265SDimitry Andric     if (Def->hasBuiltinAlias())
522fe6060f1SDimitry Andric       PrintBody(OS, *Def);
523fe6060f1SDimitry Andric   }
524fe6060f1SDimitry Andric   if (NeedEndif)
525fe6060f1SDimitry Andric     OS << "#endif\n\n";
526fe6060f1SDimitry Andric }
527fe6060f1SDimitry Andric 
52804eeddc0SDimitry Andric bool RVVEmitter::emitMacroRestrictionStr(RISCVPredefinedMacroT PredefinedMacros,
52904eeddc0SDimitry Andric                                          raw_ostream &OS) {
53004eeddc0SDimitry Andric   if (PredefinedMacros == RISCVPredefinedMacro::Basic)
531fe6060f1SDimitry Andric     return false;
532fe6060f1SDimitry Andric   OS << "#if ";
533fe6060f1SDimitry Andric   ListSeparator LS(" && ");
53404eeddc0SDimitry Andric   if (PredefinedMacros & RISCVPredefinedMacro::V)
53504eeddc0SDimitry Andric     OS << LS << "defined(__riscv_v)";
536*81ad6265SDimitry Andric   if (PredefinedMacros & RISCVPredefinedMacro::Zvfh)
537*81ad6265SDimitry Andric     OS << LS << "defined(__riscv_zvfh)";
53804eeddc0SDimitry Andric   if (PredefinedMacros & RISCVPredefinedMacro::RV64)
53904eeddc0SDimitry Andric     OS << LS << "(__riscv_xlen == 64)";
54004eeddc0SDimitry Andric   if (PredefinedMacros & RISCVPredefinedMacro::VectorMaxELen64)
54104eeddc0SDimitry Andric     OS << LS << "(__riscv_v_elen >= 64)";
54204eeddc0SDimitry Andric   if (PredefinedMacros & RISCVPredefinedMacro::VectorMaxELenFp32)
54304eeddc0SDimitry Andric     OS << LS << "(__riscv_v_elen_fp >= 32)";
54404eeddc0SDimitry Andric   if (PredefinedMacros & RISCVPredefinedMacro::VectorMaxELenFp64)
54504eeddc0SDimitry Andric     OS << LS << "(__riscv_v_elen_fp >= 64)";
546fe6060f1SDimitry Andric   OS << "\n";
547fe6060f1SDimitry Andric   return true;
548fe6060f1SDimitry Andric }
549fe6060f1SDimitry Andric 
550fe6060f1SDimitry Andric namespace clang {
551fe6060f1SDimitry Andric void EmitRVVHeader(RecordKeeper &Records, raw_ostream &OS) {
552fe6060f1SDimitry Andric   RVVEmitter(Records).createHeader(OS);
553fe6060f1SDimitry Andric }
554fe6060f1SDimitry Andric 
555fe6060f1SDimitry Andric void EmitRVVBuiltins(RecordKeeper &Records, raw_ostream &OS) {
556fe6060f1SDimitry Andric   RVVEmitter(Records).createBuiltins(OS);
557fe6060f1SDimitry Andric }
558fe6060f1SDimitry Andric 
559fe6060f1SDimitry Andric void EmitRVVBuiltinCG(RecordKeeper &Records, raw_ostream &OS) {
560fe6060f1SDimitry Andric   RVVEmitter(Records).createCodeGen(OS);
561fe6060f1SDimitry Andric }
562fe6060f1SDimitry Andric 
563fe6060f1SDimitry Andric } // End namespace clang
564