xref: /freebsd/contrib/llvm-project/clang/utils/TableGen/RISCVVEmitter.cpp (revision 753f127f3ace09432b2baeffd71a308760641a62)
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"
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;
2981ad6265SDimitry 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);
5181ad6265SDimitry Andric   /// Print HeaderCode in RVVHeader Record to \p Out
5281ad6265SDimitry 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 
6881ad6265SDimitry Andric static BasicType ParseBasicType(char c) {
6981ad6265SDimitry Andric   switch (c) {
70fe6060f1SDimitry Andric   case 'c':
7181ad6265SDimitry Andric     return BasicType::Int8;
72fe6060f1SDimitry Andric     break;
73fe6060f1SDimitry Andric   case 's':
7481ad6265SDimitry Andric     return BasicType::Int16;
75fe6060f1SDimitry Andric     break;
76fe6060f1SDimitry Andric   case 'i':
7781ad6265SDimitry Andric     return BasicType::Int32;
78fe6060f1SDimitry Andric     break;
79fe6060f1SDimitry Andric   case 'l':
8081ad6265SDimitry Andric     return BasicType::Int64;
81fe6060f1SDimitry Andric     break;
82fe6060f1SDimitry Andric   case 'x':
8381ad6265SDimitry Andric     return BasicType::Float16;
84fe6060f1SDimitry Andric     break;
85fe6060f1SDimitry Andric   case 'f':
8681ad6265SDimitry Andric     return BasicType::Float32;
87fe6060f1SDimitry Andric     break;
88fe6060f1SDimitry Andric   case 'd':
8981ad6265SDimitry Andric     return BasicType::Float64;
90fe6060f1SDimitry Andric     break;
9181ad6265SDimitry Andric 
92fe6060f1SDimitry Andric   default:
9381ad6265SDimitry Andric     return BasicType::Unknown;
94fe6060f1SDimitry Andric   }
95fe6060f1SDimitry Andric }
96fe6060f1SDimitry Andric 
9781ad6265SDimitry Andric void emitCodeGenSwitchBody(const RVVIntrinsic *RVVI, raw_ostream &OS) {
9881ad6265SDimitry Andric   if (!RVVI->getIRName().empty())
9981ad6265SDimitry Andric     OS << "  ID = Intrinsic::riscv_" + RVVI->getIRName() + ";\n";
10081ad6265SDimitry Andric   if (RVVI->getNF() >= 2)
10181ad6265SDimitry Andric     OS << "  NF = " + utostr(RVVI->getNF()) + ";\n";
10281ad6265SDimitry Andric   if (RVVI->hasManualCodegen()) {
10381ad6265SDimitry Andric     OS << RVVI->getManualCodegen();
104fe6060f1SDimitry Andric     OS << "break;\n";
105fe6060f1SDimitry Andric     return;
106fe6060f1SDimitry Andric   }
107fe6060f1SDimitry Andric 
108*753f127fSDimitry Andric   // Cast pointer operand of vector load intrinsic.
109*753f127fSDimitry Andric   for (const auto &I : enumerate(RVVI->getInputTypes())) {
110*753f127fSDimitry Andric     if (I.value()->isPointer()) {
111*753f127fSDimitry Andric       assert(RVVI->getIntrinsicTypes().front() == -1 &&
112*753f127fSDimitry Andric              "RVVI should be vector load intrinsic.");
113*753f127fSDimitry Andric       OS << "  Ops[" << I.index() << "] = Builder.CreateBitCast(Ops[";
114*753f127fSDimitry Andric       OS << I.index() << "], ResultType->getPointerTo());\n";
115*753f127fSDimitry Andric     }
116*753f127fSDimitry Andric   }
117*753f127fSDimitry Andric 
11881ad6265SDimitry Andric   if (RVVI->isMasked()) {
11981ad6265SDimitry Andric     if (RVVI->hasVL()) {
120fe6060f1SDimitry Andric       OS << "  std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1);\n";
12181ad6265SDimitry Andric       if (RVVI->hasPolicyOperand())
122349cc55cSDimitry Andric         OS << "  Ops.push_back(ConstantInt::get(Ops.back()->getType(),"
123349cc55cSDimitry Andric               " TAIL_UNDISTURBED));\n";
124fe6060f1SDimitry Andric     } else {
125fe6060f1SDimitry Andric       OS << "  std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end());\n";
126fe6060f1SDimitry Andric     }
12781ad6265SDimitry Andric   } else {
12881ad6265SDimitry Andric     if (RVVI->hasPolicyOperand())
12981ad6265SDimitry Andric       OS << "  Ops.push_back(ConstantInt::get(Ops.back()->getType(), "
13081ad6265SDimitry Andric             "TAIL_UNDISTURBED));\n";
13181ad6265SDimitry Andric     else if (RVVI->hasPassthruOperand()) {
13281ad6265SDimitry Andric       OS << "  Ops.push_back(llvm::UndefValue::get(ResultType));\n";
13381ad6265SDimitry Andric       OS << "  std::rotate(Ops.rbegin(), Ops.rbegin() + 1,  Ops.rend());\n";
13481ad6265SDimitry Andric     }
135fe6060f1SDimitry Andric   }
136fe6060f1SDimitry Andric 
137fe6060f1SDimitry Andric   OS << "  IntrinsicTypes = {";
138fe6060f1SDimitry Andric   ListSeparator LS;
13981ad6265SDimitry Andric   for (const auto &Idx : RVVI->getIntrinsicTypes()) {
140fe6060f1SDimitry Andric     if (Idx == -1)
141fe6060f1SDimitry Andric       OS << LS << "ResultType";
142fe6060f1SDimitry Andric     else
143fe6060f1SDimitry Andric       OS << LS << "Ops[" << Idx << "]->getType()";
144fe6060f1SDimitry Andric   }
145fe6060f1SDimitry Andric 
146fe6060f1SDimitry Andric   // VL could be i64 or i32, need to encode it in IntrinsicTypes. VL is
147fe6060f1SDimitry Andric   // always last operand.
14881ad6265SDimitry Andric   if (RVVI->hasVL())
149fe6060f1SDimitry Andric     OS << ", Ops.back()->getType()";
150fe6060f1SDimitry Andric   OS << "};\n";
151fe6060f1SDimitry Andric   OS << "  break;\n";
152fe6060f1SDimitry Andric }
153fe6060f1SDimitry Andric 
15481ad6265SDimitry Andric void emitIntrinsicFuncDef(const RVVIntrinsic &RVVI, raw_ostream &OS) {
155349cc55cSDimitry Andric   OS << "__attribute__((__clang_builtin_alias__(";
15681ad6265SDimitry Andric   OS << "__builtin_rvv_" << RVVI.getBuiltinName() << ")))\n";
15781ad6265SDimitry Andric   OS << RVVI.getOutputType()->getTypeStr() << " " << RVVI.getName() << "(";
158349cc55cSDimitry Andric   // Emit function arguments
15981ad6265SDimitry Andric   const RVVTypes &InputTypes = RVVI.getInputTypes();
160fe6060f1SDimitry Andric   if (!InputTypes.empty()) {
161fe6060f1SDimitry Andric     ListSeparator LS;
162349cc55cSDimitry Andric     for (unsigned i = 0; i < InputTypes.size(); ++i)
163349cc55cSDimitry Andric       OS << LS << InputTypes[i]->getTypeStr();
164fe6060f1SDimitry Andric   }
165349cc55cSDimitry Andric   OS << ");\n";
166fe6060f1SDimitry Andric }
167fe6060f1SDimitry Andric 
16881ad6265SDimitry Andric void emitOverloadedFuncDef(const RVVIntrinsic &RVVI, raw_ostream &OS) {
169349cc55cSDimitry Andric   OS << "__attribute__((__clang_builtin_alias__(";
17081ad6265SDimitry Andric   OS << "__builtin_rvv_" << RVVI.getBuiltinName() << ")))\n";
17181ad6265SDimitry Andric   OS << RVVI.getOutputType()->getTypeStr() << " " << RVVI.getOverloadedName()
17281ad6265SDimitry Andric      << "(";
173fe6060f1SDimitry Andric   // Emit function arguments
17481ad6265SDimitry Andric   const RVVTypes &InputTypes = RVVI.getInputTypes();
175fe6060f1SDimitry Andric   if (!InputTypes.empty()) {
176fe6060f1SDimitry Andric     ListSeparator LS;
177fe6060f1SDimitry Andric     for (unsigned i = 0; i < InputTypes.size(); ++i)
178349cc55cSDimitry Andric       OS << LS << InputTypes[i]->getTypeStr();
179fe6060f1SDimitry Andric   }
180349cc55cSDimitry Andric   OS << ");\n";
181fe6060f1SDimitry Andric }
182fe6060f1SDimitry Andric 
183fe6060f1SDimitry Andric //===----------------------------------------------------------------------===//
184fe6060f1SDimitry Andric // RVVEmitter implementation
185fe6060f1SDimitry Andric //===----------------------------------------------------------------------===//
186fe6060f1SDimitry Andric void RVVEmitter::createHeader(raw_ostream &OS) {
187fe6060f1SDimitry Andric 
188fe6060f1SDimitry Andric   OS << "/*===---- riscv_vector.h - RISC-V V-extension RVVIntrinsics "
189fe6060f1SDimitry Andric         "-------------------===\n"
190fe6060f1SDimitry Andric         " *\n"
191fe6060f1SDimitry Andric         " *\n"
192fe6060f1SDimitry Andric         " * Part of the LLVM Project, under the Apache License v2.0 with LLVM "
193fe6060f1SDimitry Andric         "Exceptions.\n"
194fe6060f1SDimitry Andric         " * See https://llvm.org/LICENSE.txt for license information.\n"
195fe6060f1SDimitry Andric         " * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n"
196fe6060f1SDimitry Andric         " *\n"
197fe6060f1SDimitry Andric         " *===-----------------------------------------------------------------"
198fe6060f1SDimitry Andric         "------===\n"
199fe6060f1SDimitry Andric         " */\n\n";
200fe6060f1SDimitry Andric 
201fe6060f1SDimitry Andric   OS << "#ifndef __RISCV_VECTOR_H\n";
202fe6060f1SDimitry Andric   OS << "#define __RISCV_VECTOR_H\n\n";
203fe6060f1SDimitry Andric 
204fe6060f1SDimitry Andric   OS << "#include <stdint.h>\n";
205fe6060f1SDimitry Andric   OS << "#include <stddef.h>\n\n";
206fe6060f1SDimitry Andric 
207fe6060f1SDimitry Andric   OS << "#ifndef __riscv_vector\n";
208fe6060f1SDimitry Andric   OS << "#error \"Vector intrinsics require the vector extension.\"\n";
209fe6060f1SDimitry Andric   OS << "#endif\n\n";
210fe6060f1SDimitry Andric 
211fe6060f1SDimitry Andric   OS << "#ifdef __cplusplus\n";
212fe6060f1SDimitry Andric   OS << "extern \"C\" {\n";
213fe6060f1SDimitry Andric   OS << "#endif\n\n";
214fe6060f1SDimitry Andric 
21581ad6265SDimitry Andric   printHeaderCode(OS);
216349cc55cSDimitry Andric 
217fe6060f1SDimitry Andric   std::vector<std::unique_ptr<RVVIntrinsic>> Defs;
218fe6060f1SDimitry Andric   createRVVIntrinsics(Defs);
219fe6060f1SDimitry Andric 
220fe6060f1SDimitry Andric   auto printType = [&](auto T) {
221fe6060f1SDimitry Andric     OS << "typedef " << T->getClangBuiltinStr() << " " << T->getTypeStr()
222fe6060f1SDimitry Andric        << ";\n";
223fe6060f1SDimitry Andric   };
224fe6060f1SDimitry Andric 
225fe6060f1SDimitry Andric   constexpr int Log2LMULs[] = {-3, -2, -1, 0, 1, 2, 3};
226fe6060f1SDimitry Andric   // Print RVV boolean types.
227fe6060f1SDimitry Andric   for (int Log2LMUL : Log2LMULs) {
22881ad6265SDimitry Andric     auto T = RVVType::computeType(BasicType::Int8, Log2LMUL,
22981ad6265SDimitry Andric                                   PrototypeDescriptor::Mask);
23081ad6265SDimitry Andric     if (T)
231*753f127fSDimitry Andric       printType(T.value());
232fe6060f1SDimitry Andric   }
233fe6060f1SDimitry Andric   // Print RVV int/float types.
234fe6060f1SDimitry Andric   for (char I : StringRef("csil")) {
23581ad6265SDimitry Andric     BasicType BT = ParseBasicType(I);
236fe6060f1SDimitry Andric     for (int Log2LMUL : Log2LMULs) {
23781ad6265SDimitry Andric       auto T = RVVType::computeType(BT, Log2LMUL, PrototypeDescriptor::Vector);
23881ad6265SDimitry Andric       if (T) {
239*753f127fSDimitry Andric         printType(T.value());
24081ad6265SDimitry Andric         auto UT = RVVType::computeType(
24181ad6265SDimitry Andric             BT, Log2LMUL,
24281ad6265SDimitry Andric             PrototypeDescriptor(BaseTypeModifier::Vector,
24381ad6265SDimitry Andric                                 VectorTypeModifier::NoModifier,
24481ad6265SDimitry Andric                                 TypeModifier::UnsignedInteger));
245*753f127fSDimitry Andric         printType(UT.value());
246fe6060f1SDimitry Andric       }
247fe6060f1SDimitry Andric     }
248fe6060f1SDimitry Andric   }
24981ad6265SDimitry Andric   OS << "#if defined(__riscv_zvfh)\n";
250fe6060f1SDimitry Andric   for (int Log2LMUL : Log2LMULs) {
25181ad6265SDimitry Andric     auto T = RVVType::computeType(BasicType::Float16, Log2LMUL,
25281ad6265SDimitry Andric                                   PrototypeDescriptor::Vector);
25381ad6265SDimitry Andric     if (T)
254*753f127fSDimitry Andric       printType(T.value());
255fe6060f1SDimitry Andric   }
256fe6060f1SDimitry Andric   OS << "#endif\n";
257fe6060f1SDimitry Andric 
258fe6060f1SDimitry Andric   OS << "#if defined(__riscv_f)\n";
259fe6060f1SDimitry Andric   for (int Log2LMUL : Log2LMULs) {
26081ad6265SDimitry Andric     auto T = RVVType::computeType(BasicType::Float32, Log2LMUL,
26181ad6265SDimitry Andric                                   PrototypeDescriptor::Vector);
26281ad6265SDimitry Andric     if (T)
263*753f127fSDimitry Andric       printType(T.value());
264fe6060f1SDimitry Andric   }
265fe6060f1SDimitry Andric   OS << "#endif\n";
266fe6060f1SDimitry Andric 
267fe6060f1SDimitry Andric   OS << "#if defined(__riscv_d)\n";
268fe6060f1SDimitry Andric   for (int Log2LMUL : Log2LMULs) {
26981ad6265SDimitry Andric     auto T = RVVType::computeType(BasicType::Float64, Log2LMUL,
27081ad6265SDimitry Andric                                   PrototypeDescriptor::Vector);
27181ad6265SDimitry Andric     if (T)
272*753f127fSDimitry Andric       printType(T.value());
273fe6060f1SDimitry Andric   }
274fe6060f1SDimitry Andric   OS << "#endif\n\n";
275fe6060f1SDimitry Andric 
276fe6060f1SDimitry Andric   // The same extension include in the same arch guard marco.
277349cc55cSDimitry Andric   llvm::stable_sort(Defs, [](const std::unique_ptr<RVVIntrinsic> &A,
278fe6060f1SDimitry Andric                              const std::unique_ptr<RVVIntrinsic> &B) {
27904eeddc0SDimitry Andric     return A->getRISCVPredefinedMacros() < B->getRISCVPredefinedMacros();
280fe6060f1SDimitry Andric   });
281fe6060f1SDimitry Andric 
282349cc55cSDimitry Andric   OS << "#define __rvv_ai static __inline__\n";
283349cc55cSDimitry Andric 
284fe6060f1SDimitry Andric   // Print intrinsic functions with macro
285fe6060f1SDimitry Andric   emitArchMacroAndBody(Defs, OS, [](raw_ostream &OS, const RVVIntrinsic &Inst) {
286349cc55cSDimitry Andric     OS << "__rvv_ai ";
28781ad6265SDimitry Andric     emitIntrinsicFuncDef(Inst, OS);
288fe6060f1SDimitry Andric   });
289fe6060f1SDimitry Andric 
290349cc55cSDimitry Andric   OS << "#undef __rvv_ai\n\n";
291349cc55cSDimitry Andric 
292fe6060f1SDimitry Andric   OS << "#define __riscv_v_intrinsic_overloading 1\n";
293fe6060f1SDimitry Andric 
294fe6060f1SDimitry Andric   // Print Overloaded APIs
295349cc55cSDimitry Andric   OS << "#define __rvv_aio static __inline__ "
296349cc55cSDimitry Andric         "__attribute__((__overloadable__))\n";
297fe6060f1SDimitry Andric 
298fe6060f1SDimitry Andric   emitArchMacroAndBody(Defs, OS, [](raw_ostream &OS, const RVVIntrinsic &Inst) {
29981ad6265SDimitry Andric     if (!Inst.isMasked() && !Inst.hasUnMaskedOverloaded())
300fe6060f1SDimitry Andric       return;
301349cc55cSDimitry Andric     OS << "__rvv_aio ";
30281ad6265SDimitry Andric     emitOverloadedFuncDef(Inst, OS);
303fe6060f1SDimitry Andric   });
304fe6060f1SDimitry Andric 
305349cc55cSDimitry Andric   OS << "#undef __rvv_aio\n";
306349cc55cSDimitry Andric 
307fe6060f1SDimitry Andric   OS << "\n#ifdef __cplusplus\n";
308fe6060f1SDimitry Andric   OS << "}\n";
309349cc55cSDimitry Andric   OS << "#endif // __cplusplus\n";
310fe6060f1SDimitry Andric   OS << "#endif // __RISCV_VECTOR_H\n";
311fe6060f1SDimitry Andric }
312fe6060f1SDimitry Andric 
313fe6060f1SDimitry Andric void RVVEmitter::createBuiltins(raw_ostream &OS) {
314fe6060f1SDimitry Andric   std::vector<std::unique_ptr<RVVIntrinsic>> Defs;
315fe6060f1SDimitry Andric   createRVVIntrinsics(Defs);
316fe6060f1SDimitry Andric 
317349cc55cSDimitry Andric   // Map to keep track of which builtin names have already been emitted.
318349cc55cSDimitry Andric   StringMap<RVVIntrinsic *> BuiltinMap;
319349cc55cSDimitry Andric 
320fe6060f1SDimitry Andric   OS << "#if defined(TARGET_BUILTIN) && !defined(RISCVV_BUILTIN)\n";
321fe6060f1SDimitry Andric   OS << "#define RISCVV_BUILTIN(ID, TYPE, ATTRS) TARGET_BUILTIN(ID, TYPE, "
32281ad6265SDimitry Andric         "ATTRS, \"zve32x\")\n";
323fe6060f1SDimitry Andric   OS << "#endif\n";
324fe6060f1SDimitry Andric   for (auto &Def : Defs) {
325349cc55cSDimitry Andric     auto P =
326349cc55cSDimitry Andric         BuiltinMap.insert(std::make_pair(Def->getBuiltinName(), Def.get()));
327349cc55cSDimitry Andric     if (!P.second) {
32881ad6265SDimitry Andric       // Verf that this would have produced the same builtin definition.
32981ad6265SDimitry Andric       if (P.first->second->hasBuiltinAlias() != Def->hasBuiltinAlias())
330349cc55cSDimitry Andric         PrintFatalError("Builtin with same name has different hasAutoDef");
33181ad6265SDimitry Andric       else if (!Def->hasBuiltinAlias() &&
33281ad6265SDimitry Andric                P.first->second->getBuiltinTypeStr() != Def->getBuiltinTypeStr())
333349cc55cSDimitry Andric         PrintFatalError("Builtin with same name has different type string");
334349cc55cSDimitry Andric       continue;
335349cc55cSDimitry Andric     }
336349cc55cSDimitry Andric     OS << "RISCVV_BUILTIN(__builtin_rvv_" << Def->getBuiltinName() << ",\"";
33781ad6265SDimitry Andric     if (!Def->hasBuiltinAlias())
338349cc55cSDimitry Andric       OS << Def->getBuiltinTypeStr();
339349cc55cSDimitry Andric     OS << "\", \"n\")\n";
340fe6060f1SDimitry Andric   }
341fe6060f1SDimitry Andric   OS << "#undef RISCVV_BUILTIN\n";
342fe6060f1SDimitry Andric }
343fe6060f1SDimitry Andric 
344fe6060f1SDimitry Andric void RVVEmitter::createCodeGen(raw_ostream &OS) {
345fe6060f1SDimitry Andric   std::vector<std::unique_ptr<RVVIntrinsic>> Defs;
346fe6060f1SDimitry Andric   createRVVIntrinsics(Defs);
347fe6060f1SDimitry Andric   // IR name could be empty, use the stable sort preserves the relative order.
348349cc55cSDimitry Andric   llvm::stable_sort(Defs, [](const std::unique_ptr<RVVIntrinsic> &A,
349fe6060f1SDimitry Andric                              const std::unique_ptr<RVVIntrinsic> &B) {
350fe6060f1SDimitry Andric     return A->getIRName() < B->getIRName();
351fe6060f1SDimitry Andric   });
352349cc55cSDimitry Andric 
353349cc55cSDimitry Andric   // Map to keep track of which builtin names have already been emitted.
354349cc55cSDimitry Andric   StringMap<RVVIntrinsic *> BuiltinMap;
355349cc55cSDimitry Andric 
356fe6060f1SDimitry Andric   // Print switch body when the ir name or ManualCodegen changes from previous
357fe6060f1SDimitry Andric   // iteration.
358fe6060f1SDimitry Andric   RVVIntrinsic *PrevDef = Defs.begin()->get();
359fe6060f1SDimitry Andric   for (auto &Def : Defs) {
360fe6060f1SDimitry Andric     StringRef CurIRName = Def->getIRName();
361fe6060f1SDimitry Andric     if (CurIRName != PrevDef->getIRName() ||
362fe6060f1SDimitry Andric         (Def->getManualCodegen() != PrevDef->getManualCodegen())) {
36381ad6265SDimitry Andric       emitCodeGenSwitchBody(PrevDef, OS);
364fe6060f1SDimitry Andric     }
365fe6060f1SDimitry Andric     PrevDef = Def.get();
366349cc55cSDimitry Andric 
367349cc55cSDimitry Andric     auto P =
368349cc55cSDimitry Andric         BuiltinMap.insert(std::make_pair(Def->getBuiltinName(), Def.get()));
369349cc55cSDimitry Andric     if (P.second) {
370349cc55cSDimitry Andric       OS << "case RISCVVector::BI__builtin_rvv_" << Def->getBuiltinName()
371349cc55cSDimitry Andric          << ":\n";
372349cc55cSDimitry Andric       continue;
373349cc55cSDimitry Andric     }
374349cc55cSDimitry Andric 
375349cc55cSDimitry Andric     if (P.first->second->getIRName() != Def->getIRName())
376349cc55cSDimitry Andric       PrintFatalError("Builtin with same name has different IRName");
377349cc55cSDimitry Andric     else if (P.first->second->getManualCodegen() != Def->getManualCodegen())
378349cc55cSDimitry Andric       PrintFatalError("Builtin with same name has different ManualCodegen");
379349cc55cSDimitry Andric     else if (P.first->second->getNF() != Def->getNF())
380349cc55cSDimitry Andric       PrintFatalError("Builtin with same name has different NF");
38181ad6265SDimitry Andric     else if (P.first->second->isMasked() != Def->isMasked())
38281ad6265SDimitry Andric       PrintFatalError("Builtin with same name has different isMasked");
383349cc55cSDimitry Andric     else if (P.first->second->hasVL() != Def->hasVL())
38481ad6265SDimitry Andric       PrintFatalError("Builtin with same name has different hasVL");
38581ad6265SDimitry Andric     else if (P.first->second->getPolicyScheme() != Def->getPolicyScheme())
38681ad6265SDimitry Andric       PrintFatalError("Builtin with same name has different getPolicyScheme");
387349cc55cSDimitry Andric     else if (P.first->second->getIntrinsicTypes() != Def->getIntrinsicTypes())
388349cc55cSDimitry Andric       PrintFatalError("Builtin with same name has different IntrinsicTypes");
389fe6060f1SDimitry Andric   }
39081ad6265SDimitry Andric   emitCodeGenSwitchBody(Defs.back().get(), OS);
391fe6060f1SDimitry Andric   OS << "\n";
392fe6060f1SDimitry Andric }
393fe6060f1SDimitry Andric 
394fe6060f1SDimitry Andric void RVVEmitter::createRVVIntrinsics(
395fe6060f1SDimitry Andric     std::vector<std::unique_ptr<RVVIntrinsic>> &Out) {
396fe6060f1SDimitry Andric   std::vector<Record *> RV = Records.getAllDerivedDefinitions("RVVBuiltin");
397fe6060f1SDimitry Andric   for (auto *R : RV) {
398fe6060f1SDimitry Andric     StringRef Name = R->getValueAsString("Name");
399fe6060f1SDimitry Andric     StringRef SuffixProto = R->getValueAsString("Suffix");
40081ad6265SDimitry Andric     StringRef OverloadedName = R->getValueAsString("OverloadedName");
40181ad6265SDimitry Andric     StringRef OverloadedSuffixProto = R->getValueAsString("OverloadedSuffix");
402fe6060f1SDimitry Andric     StringRef Prototypes = R->getValueAsString("Prototype");
403fe6060f1SDimitry Andric     StringRef TypeRange = R->getValueAsString("TypeRange");
40481ad6265SDimitry Andric     bool HasMasked = R->getValueAsBit("HasMasked");
405fe6060f1SDimitry Andric     bool HasMaskedOffOperand = R->getValueAsBit("HasMaskedOffOperand");
406fe6060f1SDimitry Andric     bool HasVL = R->getValueAsBit("HasVL");
40781ad6265SDimitry Andric     Record *MaskedPolicyRecord = R->getValueAsDef("MaskedPolicy");
40881ad6265SDimitry Andric     PolicyScheme MaskedPolicy =
40981ad6265SDimitry Andric         static_cast<PolicyScheme>(MaskedPolicyRecord->getValueAsInt("Value"));
41081ad6265SDimitry Andric     Record *UnMaskedPolicyRecord = R->getValueAsDef("UnMaskedPolicy");
41181ad6265SDimitry Andric     PolicyScheme UnMaskedPolicy =
41281ad6265SDimitry Andric         static_cast<PolicyScheme>(UnMaskedPolicyRecord->getValueAsInt("Value"));
41381ad6265SDimitry Andric     bool HasUnMaskedOverloaded = R->getValueAsBit("HasUnMaskedOverloaded");
414fe6060f1SDimitry Andric     std::vector<int64_t> Log2LMULList = R->getValueAsListOfInts("Log2LMUL");
41581ad6265SDimitry Andric     bool HasBuiltinAlias = R->getValueAsBit("HasBuiltinAlias");
416fe6060f1SDimitry Andric     StringRef ManualCodegen = R->getValueAsString("ManualCodegen");
41781ad6265SDimitry Andric     StringRef MaskedManualCodegen = R->getValueAsString("MaskedManualCodegen");
418fe6060f1SDimitry Andric     std::vector<int64_t> IntrinsicTypes =
419fe6060f1SDimitry Andric         R->getValueAsListOfInts("IntrinsicTypes");
42004eeddc0SDimitry Andric     std::vector<StringRef> RequiredFeatures =
42104eeddc0SDimitry Andric         R->getValueAsListOfStrings("RequiredFeatures");
422fe6060f1SDimitry Andric     StringRef IRName = R->getValueAsString("IRName");
42381ad6265SDimitry Andric     StringRef MaskedIRName = R->getValueAsString("MaskedIRName");
424fe6060f1SDimitry Andric     unsigned NF = R->getValueAsInt("NF");
425fe6060f1SDimitry Andric 
426fe6060f1SDimitry Andric     // Parse prototype and create a list of primitive type with transformers
42781ad6265SDimitry Andric     // (operand) in Prototype. Prototype[0] is output operand.
42881ad6265SDimitry Andric     SmallVector<PrototypeDescriptor> Prototype = parsePrototypes(Prototypes);
42981ad6265SDimitry Andric 
43081ad6265SDimitry Andric     SmallVector<PrototypeDescriptor> SuffixDesc = parsePrototypes(SuffixProto);
43181ad6265SDimitry Andric     SmallVector<PrototypeDescriptor> OverloadedSuffixDesc =
43281ad6265SDimitry Andric         parsePrototypes(OverloadedSuffixProto);
433fe6060f1SDimitry Andric 
434fe6060f1SDimitry Andric     // Compute Builtin types
43581ad6265SDimitry Andric     SmallVector<PrototypeDescriptor> MaskedPrototype = Prototype;
43681ad6265SDimitry Andric     if (HasMasked) {
437fe6060f1SDimitry Andric       // If HasMaskedOffOperand, insert result type as first input operand.
438fe6060f1SDimitry Andric       if (HasMaskedOffOperand) {
439fe6060f1SDimitry Andric         if (NF == 1) {
44081ad6265SDimitry Andric           MaskedPrototype.insert(MaskedPrototype.begin() + 1, Prototype[0]);
441fe6060f1SDimitry Andric         } else {
442fe6060f1SDimitry Andric           // Convert
443fe6060f1SDimitry Andric           // (void, op0 address, op1 address, ...)
444fe6060f1SDimitry Andric           // to
445fe6060f1SDimitry Andric           // (void, op0 address, op1 address, ..., maskedoff0, maskedoff1, ...)
44681ad6265SDimitry Andric           PrototypeDescriptor MaskoffType = Prototype[1];
44781ad6265SDimitry Andric           MaskoffType.TM &= ~static_cast<uint8_t>(TypeModifier::Pointer);
448fe6060f1SDimitry Andric           for (unsigned I = 0; I < NF; ++I)
44981ad6265SDimitry Andric             MaskedPrototype.insert(MaskedPrototype.begin() + NF + 1,
45081ad6265SDimitry Andric                                    MaskoffType);
451fe6060f1SDimitry Andric         }
452fe6060f1SDimitry Andric       }
453fe6060f1SDimitry Andric       if (HasMaskedOffOperand && NF > 1) {
454fe6060f1SDimitry Andric         // Convert
455fe6060f1SDimitry Andric         // (void, op0 address, op1 address, ..., maskedoff0, maskedoff1, ...)
456fe6060f1SDimitry Andric         // to
457fe6060f1SDimitry Andric         // (void, op0 address, op1 address, ..., mask, maskedoff0, maskedoff1,
458fe6060f1SDimitry Andric         // ...)
45981ad6265SDimitry Andric         MaskedPrototype.insert(MaskedPrototype.begin() + NF + 1,
46081ad6265SDimitry Andric                                PrototypeDescriptor::Mask);
461fe6060f1SDimitry Andric       } else {
46281ad6265SDimitry Andric         // If HasMasked, insert PrototypeDescriptor:Mask as first input operand.
46381ad6265SDimitry Andric         MaskedPrototype.insert(MaskedPrototype.begin() + 1,
46481ad6265SDimitry Andric                                PrototypeDescriptor::Mask);
465fe6060f1SDimitry Andric       }
466fe6060f1SDimitry Andric     }
46781ad6265SDimitry Andric     // If HasVL, append PrototypeDescriptor:VL to last operand
468fe6060f1SDimitry Andric     if (HasVL) {
46981ad6265SDimitry Andric       Prototype.push_back(PrototypeDescriptor::VL);
47081ad6265SDimitry Andric       MaskedPrototype.push_back(PrototypeDescriptor::VL);
471fe6060f1SDimitry Andric     }
472fe6060f1SDimitry Andric 
473fe6060f1SDimitry Andric     // Create Intrinsics for each type and LMUL.
474fe6060f1SDimitry Andric     for (char I : TypeRange) {
475fe6060f1SDimitry Andric       for (int Log2LMUL : Log2LMULList) {
47681ad6265SDimitry Andric         BasicType BT = ParseBasicType(I);
47781ad6265SDimitry Andric         Optional<RVVTypes> Types =
47881ad6265SDimitry Andric             RVVType::computeTypes(BT, Log2LMUL, NF, Prototype);
479fe6060f1SDimitry Andric         // Ignored to create new intrinsic if there are any illegal types.
48081ad6265SDimitry Andric         if (!Types)
481fe6060f1SDimitry Andric           continue;
482fe6060f1SDimitry Andric 
48381ad6265SDimitry Andric         auto SuffixStr = RVVIntrinsic::getSuffixStr(BT, Log2LMUL, SuffixDesc);
48481ad6265SDimitry Andric         auto OverloadedSuffixStr =
48581ad6265SDimitry Andric             RVVIntrinsic::getSuffixStr(BT, Log2LMUL, OverloadedSuffixDesc);
48681ad6265SDimitry Andric         // Create a unmasked intrinsic
487fe6060f1SDimitry Andric         Out.push_back(std::make_unique<RVVIntrinsic>(
48881ad6265SDimitry Andric             Name, SuffixStr, OverloadedName, OverloadedSuffixStr, IRName,
48981ad6265SDimitry Andric             /*IsMasked=*/false, /*HasMaskedOffOperand=*/false, HasVL,
49081ad6265SDimitry Andric             UnMaskedPolicy, HasUnMaskedOverloaded, HasBuiltinAlias,
49181ad6265SDimitry Andric             ManualCodegen, *Types, IntrinsicTypes, RequiredFeatures, NF));
49281ad6265SDimitry Andric         if (HasMasked) {
49381ad6265SDimitry Andric           // Create a masked intrinsic
494fe6060f1SDimitry Andric           Optional<RVVTypes> MaskTypes =
49581ad6265SDimitry Andric               RVVType::computeTypes(BT, Log2LMUL, NF, MaskedPrototype);
496fe6060f1SDimitry Andric           Out.push_back(std::make_unique<RVVIntrinsic>(
49781ad6265SDimitry Andric               Name, SuffixStr, OverloadedName, OverloadedSuffixStr,
49881ad6265SDimitry Andric               MaskedIRName,
49981ad6265SDimitry Andric               /*IsMasked=*/true, HasMaskedOffOperand, HasVL, MaskedPolicy,
50081ad6265SDimitry Andric               HasUnMaskedOverloaded, HasBuiltinAlias, MaskedManualCodegen,
50181ad6265SDimitry Andric               *MaskTypes, IntrinsicTypes, RequiredFeatures, NF));
502fe6060f1SDimitry Andric         }
503fe6060f1SDimitry Andric       } // end for Log2LMULList
504fe6060f1SDimitry Andric     }   // end for TypeRange
505fe6060f1SDimitry Andric   }
506fe6060f1SDimitry Andric }
507fe6060f1SDimitry Andric 
50881ad6265SDimitry Andric void RVVEmitter::printHeaderCode(raw_ostream &OS) {
509349cc55cSDimitry Andric   std::vector<Record *> RVVHeaders =
510349cc55cSDimitry Andric       Records.getAllDerivedDefinitions("RVVHeader");
511349cc55cSDimitry Andric   for (auto *R : RVVHeaders) {
512349cc55cSDimitry Andric     StringRef HeaderCodeStr = R->getValueAsString("HeaderCode");
513349cc55cSDimitry Andric     OS << HeaderCodeStr.str();
514349cc55cSDimitry Andric   }
515349cc55cSDimitry Andric }
516349cc55cSDimitry Andric 
517fe6060f1SDimitry Andric void RVVEmitter::emitArchMacroAndBody(
518fe6060f1SDimitry Andric     std::vector<std::unique_ptr<RVVIntrinsic>> &Defs, raw_ostream &OS,
519fe6060f1SDimitry Andric     std::function<void(raw_ostream &, const RVVIntrinsic &)> PrintBody) {
52004eeddc0SDimitry Andric   RISCVPredefinedMacroT PrevMacros =
52104eeddc0SDimitry Andric       (*Defs.begin())->getRISCVPredefinedMacros();
52204eeddc0SDimitry Andric   bool NeedEndif = emitMacroRestrictionStr(PrevMacros, OS);
523fe6060f1SDimitry Andric   for (auto &Def : Defs) {
52404eeddc0SDimitry Andric     RISCVPredefinedMacroT CurMacros = Def->getRISCVPredefinedMacros();
52504eeddc0SDimitry Andric     if (CurMacros != PrevMacros) {
526fe6060f1SDimitry Andric       if (NeedEndif)
527fe6060f1SDimitry Andric         OS << "#endif\n\n";
52804eeddc0SDimitry Andric       NeedEndif = emitMacroRestrictionStr(CurMacros, OS);
52904eeddc0SDimitry Andric       PrevMacros = CurMacros;
530fe6060f1SDimitry Andric     }
53181ad6265SDimitry Andric     if (Def->hasBuiltinAlias())
532fe6060f1SDimitry Andric       PrintBody(OS, *Def);
533fe6060f1SDimitry Andric   }
534fe6060f1SDimitry Andric   if (NeedEndif)
535fe6060f1SDimitry Andric     OS << "#endif\n\n";
536fe6060f1SDimitry Andric }
537fe6060f1SDimitry Andric 
53804eeddc0SDimitry Andric bool RVVEmitter::emitMacroRestrictionStr(RISCVPredefinedMacroT PredefinedMacros,
53904eeddc0SDimitry Andric                                          raw_ostream &OS) {
54004eeddc0SDimitry Andric   if (PredefinedMacros == RISCVPredefinedMacro::Basic)
541fe6060f1SDimitry Andric     return false;
542fe6060f1SDimitry Andric   OS << "#if ";
543fe6060f1SDimitry Andric   ListSeparator LS(" && ");
54404eeddc0SDimitry Andric   if (PredefinedMacros & RISCVPredefinedMacro::V)
54504eeddc0SDimitry Andric     OS << LS << "defined(__riscv_v)";
54681ad6265SDimitry Andric   if (PredefinedMacros & RISCVPredefinedMacro::Zvfh)
54781ad6265SDimitry Andric     OS << LS << "defined(__riscv_zvfh)";
54804eeddc0SDimitry Andric   if (PredefinedMacros & RISCVPredefinedMacro::RV64)
54904eeddc0SDimitry Andric     OS << LS << "(__riscv_xlen == 64)";
55004eeddc0SDimitry Andric   if (PredefinedMacros & RISCVPredefinedMacro::VectorMaxELen64)
55104eeddc0SDimitry Andric     OS << LS << "(__riscv_v_elen >= 64)";
55204eeddc0SDimitry Andric   if (PredefinedMacros & RISCVPredefinedMacro::VectorMaxELenFp32)
55304eeddc0SDimitry Andric     OS << LS << "(__riscv_v_elen_fp >= 32)";
55404eeddc0SDimitry Andric   if (PredefinedMacros & RISCVPredefinedMacro::VectorMaxELenFp64)
55504eeddc0SDimitry Andric     OS << LS << "(__riscv_v_elen_fp >= 64)";
556fe6060f1SDimitry Andric   OS << "\n";
557fe6060f1SDimitry Andric   return true;
558fe6060f1SDimitry Andric }
559fe6060f1SDimitry Andric 
560fe6060f1SDimitry Andric namespace clang {
561fe6060f1SDimitry Andric void EmitRVVHeader(RecordKeeper &Records, raw_ostream &OS) {
562fe6060f1SDimitry Andric   RVVEmitter(Records).createHeader(OS);
563fe6060f1SDimitry Andric }
564fe6060f1SDimitry Andric 
565fe6060f1SDimitry Andric void EmitRVVBuiltins(RecordKeeper &Records, raw_ostream &OS) {
566fe6060f1SDimitry Andric   RVVEmitter(Records).createBuiltins(OS);
567fe6060f1SDimitry Andric }
568fe6060f1SDimitry Andric 
569fe6060f1SDimitry Andric void EmitRVVBuiltinCG(RecordKeeper &Records, raw_ostream &OS) {
570fe6060f1SDimitry Andric   RVVEmitter(Records).createCodeGen(OS);
571fe6060f1SDimitry Andric }
572fe6060f1SDimitry Andric 
573fe6060f1SDimitry Andric } // End namespace clang
574