Coverage Report

Created: 2022-07-16 07:03

/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/utils/TableGen/RISCVVEmitter.cpp
Line
Count
Source (jump to first uncovered line)
1
//===- RISCVVEmitter.cpp - Generate riscv_vector.h for use with clang -----===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
//
9
// This tablegen backend is responsible for emitting riscv_vector.h which
10
// includes a declaration and definition of each intrinsic functions specified
11
// in https://github.com/riscv/rvv-intrinsic-doc.
12
//
13
// See also the documentation in include/clang/Basic/riscv_vector.td.
14
//
15
//===----------------------------------------------------------------------===//
16
17
#include "clang/Support/RISCVVIntrinsicUtils.h"
18
#include "llvm/ADT/ArrayRef.h"
19
#include "llvm/ADT/SmallSet.h"
20
#include "llvm/ADT/StringExtras.h"
21
#include "llvm/ADT/StringMap.h"
22
#include "llvm/ADT/StringSet.h"
23
#include "llvm/ADT/Twine.h"
24
#include "llvm/TableGen/Error.h"
25
#include "llvm/TableGen/Record.h"
26
#include <numeric>
27
28
using namespace llvm;
29
using namespace clang::RISCV;
30
31
namespace {
32
class RVVEmitter {
33
private:
34
  RecordKeeper &Records;
35
36
public:
37
0
  RVVEmitter(RecordKeeper &R) : Records(R) {}
38
39
  /// Emit riscv_vector.h
40
  void createHeader(raw_ostream &o);
41
42
  /// Emit all the __builtin prototypes and code needed by Sema.
43
  void createBuiltins(raw_ostream &o);
44
45
  /// Emit all the information needed to map builtin -> LLVM IR intrinsic.
46
  void createCodeGen(raw_ostream &o);
47
48
private:
49
  /// Create all intrinsics and add them to \p Out
50
  void createRVVIntrinsics(std::vector<std::unique_ptr<RVVIntrinsic>> &Out);
51
  /// Print HeaderCode in RVVHeader Record to \p Out
52
  void printHeaderCode(raw_ostream &OS);
53
54
  /// Emit Acrh predecessor definitions and body, assume the element of Defs are
55
  /// sorted by extension.
56
  void emitArchMacroAndBody(
57
      std::vector<std::unique_ptr<RVVIntrinsic>> &Defs, raw_ostream &o,
58
      std::function<void(raw_ostream &, const RVVIntrinsic &)>);
59
60
  // Emit the architecture preprocessor definitions. Return true when emits
61
  // non-empty string.
62
  bool emitMacroRestrictionStr(RISCVPredefinedMacroT PredefinedMacros,
63
                               raw_ostream &o);
64
};
65
66
} // namespace
67
68
0
static BasicType ParseBasicType(char c) {
69
0
  switch (c) {
70
0
  case 'c':
71
0
    return BasicType::Int8;
72
0
    break;
73
0
  case 's':
74
0
    return BasicType::Int16;
75
0
    break;
76
0
  case 'i':
77
0
    return BasicType::Int32;
78
0
    break;
79
0
  case 'l':
80
0
    return BasicType::Int64;
81
0
    break;
82
0
  case 'x':
83
0
    return BasicType::Float16;
84
0
    break;
85
0
  case 'f':
86
0
    return BasicType::Float32;
87
0
    break;
88
0
  case 'd':
89
0
    return BasicType::Float64;
90
0
    break;
91
92
0
  default:
93
0
    return BasicType::Unknown;
94
0
  }
95
0
}
96
97
0
void emitCodeGenSwitchBody(const RVVIntrinsic *RVVI, raw_ostream &OS) {
98
0
  if (!RVVI->getIRName().empty())
99
0
    OS << "  ID = Intrinsic::riscv_" + RVVI->getIRName() + ";\n";
100
0
  if (RVVI->getNF() >= 2)
101
0
    OS << "  NF = " + utostr(RVVI->getNF()) + ";\n";
102
0
  if (RVVI->hasManualCodegen()) {
103
0
    OS << RVVI->getManualCodegen();
104
0
    OS << "break;\n";
105
0
    return;
106
0
  }
107
108
  // Cast pointer operand of vector load intrinsic.
109
0
  for (const auto &I : enumerate(RVVI->getInputTypes())) {
110
0
    if (I.value()->isPointer()) {
111
0
      assert(RVVI->getIntrinsicTypes().front() == -1 &&
112
0
             "RVVI should be vector load intrinsic.");
113
0
      OS << "  Ops[" << I.index() << "] = Builder.CreateBitCast(Ops[";
114
0
      OS << I.index() << "], ResultType->getPointerTo());\n";
115
0
    }
116
0
  }
117
118
0
  if (RVVI->isMasked()) {
119
0
    if (RVVI->hasVL()) {
120
0
      OS << "  std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1);\n";
121
0
      if (RVVI->hasPolicyOperand())
122
0
        OS << "  Ops.push_back(ConstantInt::get(Ops.back()->getType(),"
123
0
              " TAIL_UNDISTURBED));\n";
124
0
    } else {
125
0
      OS << "  std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end());\n";
126
0
    }
127
0
  } else {
128
0
    if (RVVI->hasPolicyOperand())
129
0
      OS << "  Ops.push_back(ConstantInt::get(Ops.back()->getType(), "
130
0
            "TAIL_UNDISTURBED));\n";
131
0
    else if (RVVI->hasPassthruOperand()) {
132
0
      OS << "  Ops.push_back(llvm::UndefValue::get(ResultType));\n";
133
0
      OS << "  std::rotate(Ops.rbegin(), Ops.rbegin() + 1,  Ops.rend());\n";
134
0
    }
135
0
  }
136
137
0
  OS << "  IntrinsicTypes = {";
138
0
  ListSeparator LS;
139
0
  for (const auto &Idx : RVVI->getIntrinsicTypes()) {
140
0
    if (Idx == -1)
141
0
      OS << LS << "ResultType";
142
0
    else
143
0
      OS << LS << "Ops[" << Idx << "]->getType()";
144
0
  }
145
146
  // VL could be i64 or i32, need to encode it in IntrinsicTypes. VL is
147
  // always last operand.
148
0
  if (RVVI->hasVL())
149
0
    OS << ", Ops.back()->getType()";
150
0
  OS << "};\n";
151
0
  OS << "  break;\n";
152
0
}
153
154
0
void emitIntrinsicFuncDef(const RVVIntrinsic &RVVI, raw_ostream &OS) {
155
0
  OS << "__attribute__((__clang_builtin_alias__(";
156
0
  OS << "__builtin_rvv_" << RVVI.getBuiltinName() << ")))\n";
157
0
  OS << RVVI.getOutputType()->getTypeStr() << " " << RVVI.getName() << "(";
158
  // Emit function arguments
159
0
  const RVVTypes &InputTypes = RVVI.getInputTypes();
160
0
  if (!InputTypes.empty()) {
161
0
    ListSeparator LS;
162
0
    for (unsigned i = 0; i < InputTypes.size(); ++i)
163
0
      OS << LS << InputTypes[i]->getTypeStr();
164
0
  }
165
0
  OS << ");\n";
166
0
}
167
168
0
void emitOverloadedFuncDef(const RVVIntrinsic &RVVI, raw_ostream &OS) {
169
0
  OS << "__attribute__((__clang_builtin_alias__(";
170
0
  OS << "__builtin_rvv_" << RVVI.getBuiltinName() << ")))\n";
171
0
  OS << RVVI.getOutputType()->getTypeStr() << " " << RVVI.getOverloadedName()
172
0
     << "(";
173
  // Emit function arguments
174
0
  const RVVTypes &InputTypes = RVVI.getInputTypes();
175
0
  if (!InputTypes.empty()) {
176
0
    ListSeparator LS;
177
0
    for (unsigned i = 0; i < InputTypes.size(); ++i)
178
0
      OS << LS << InputTypes[i]->getTypeStr();
179
0
  }
180
0
  OS << ");\n";
181
0
}
182
183
//===----------------------------------------------------------------------===//
184
// RVVEmitter implementation
185
//===----------------------------------------------------------------------===//
186
0
void RVVEmitter::createHeader(raw_ostream &OS) {
187
188
0
  OS << "/*===---- riscv_vector.h - RISC-V V-extension RVVIntrinsics "
189
0
        "-------------------===\n"
190
0
        " *\n"
191
0
        " *\n"
192
0
        " * Part of the LLVM Project, under the Apache License v2.0 with LLVM "
193
0
        "Exceptions.\n"
194
0
        " * See https://llvm.org/LICENSE.txt for license information.\n"
195
0
        " * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n"
196
0
        " *\n"
197
0
        " *===-----------------------------------------------------------------"
198
0
        "------===\n"
199
0
        " */\n\n";
200
201
0
  OS << "#ifndef __RISCV_VECTOR_H\n";
202
0
  OS << "#define __RISCV_VECTOR_H\n\n";
203
204
0
  OS << "#include <stdint.h>\n";
205
0
  OS << "#include <stddef.h>\n\n";
206
207
0
  OS << "#ifndef __riscv_vector\n";
208
0
  OS << "#error \"Vector intrinsics require the vector extension.\"\n";
209
0
  OS << "#endif\n\n";
210
211
0
  OS << "#ifdef __cplusplus\n";
212
0
  OS << "extern \"C\" {\n";
213
0
  OS << "#endif\n\n";
214
215
0
  printHeaderCode(OS);
216
217
0
  std::vector<std::unique_ptr<RVVIntrinsic>> Defs;
218
0
  createRVVIntrinsics(Defs);
219
220
0
  auto printType = [&](auto T) {
221
0
    OS << "typedef " << T->getClangBuiltinStr() << " " << T->getTypeStr()
222
0
       << ";\n";
223
0
  };
224
225
0
  constexpr int Log2LMULs[] = {-3, -2, -1, 0, 1, 2, 3};
226
  // Print RVV boolean types.
227
0
  for (int Log2LMUL : Log2LMULs) {
228
0
    auto T = RVVType::computeType(BasicType::Int8, Log2LMUL,
229
0
                                  PrototypeDescriptor::Mask);
230
0
    if (T)
231
0
      printType(T.value());
232
0
  }
233
  // Print RVV int/float types.
234
0
  for (char I : StringRef("csil")) {
235
0
    BasicType BT = ParseBasicType(I);
236
0
    for (int Log2LMUL : Log2LMULs) {
237
0
      auto T = RVVType::computeType(BT, Log2LMUL, PrototypeDescriptor::Vector);
238
0
      if (T) {
239
0
        printType(T.value());
240
0
        auto UT = RVVType::computeType(
241
0
            BT, Log2LMUL,
242
0
            PrototypeDescriptor(BaseTypeModifier::Vector,
243
0
                                VectorTypeModifier::NoModifier,
244
0
                                TypeModifier::UnsignedInteger));
245
0
        printType(UT.value());
246
0
      }
247
0
    }
248
0
  }
249
0
  OS << "#if defined(__riscv_zvfh)\n";
250
0
  for (int Log2LMUL : Log2LMULs) {
251
0
    auto T = RVVType::computeType(BasicType::Float16, Log2LMUL,
252
0
                                  PrototypeDescriptor::Vector);
253
0
    if (T)
254
0
      printType(T.value());
255
0
  }
256
0
  OS << "#endif\n";
257
258
0
  OS << "#if defined(__riscv_f)\n";
259
0
  for (int Log2LMUL : Log2LMULs) {
260
0
    auto T = RVVType::computeType(BasicType::Float32, Log2LMUL,
261
0
                                  PrototypeDescriptor::Vector);
262
0
    if (T)
263
0
      printType(T.value());
264
0
  }
265
0
  OS << "#endif\n";
266
267
0
  OS << "#if defined(__riscv_d)\n";
268
0
  for (int Log2LMUL : Log2LMULs) {
269
0
    auto T = RVVType::computeType(BasicType::Float64, Log2LMUL,
270
0
                                  PrototypeDescriptor::Vector);
271
0
    if (T)
272
0
      printType(T.value());
273
0
  }
274
0
  OS << "#endif\n\n";
275
276
  // The same extension include in the same arch guard marco.
277
0
  llvm::stable_sort(Defs, [](const std::unique_ptr<RVVIntrinsic> &A,
278
0
                             const std::unique_ptr<RVVIntrinsic> &B) {
279
0
    return A->getRISCVPredefinedMacros() < B->getRISCVPredefinedMacros();
280
0
  });
281
282
0
  OS << "#define __rvv_ai static __inline__\n";
283
284
  // Print intrinsic functions with macro
285
0
  emitArchMacroAndBody(Defs, OS, [](raw_ostream &OS, const RVVIntrinsic &Inst) {
286
0
    OS << "__rvv_ai ";
287
0
    emitIntrinsicFuncDef(Inst, OS);
288
0
  });
289
290
0
  OS << "#undef __rvv_ai\n\n";
291
292
0
  OS << "#define __riscv_v_intrinsic_overloading 1\n";
293
294
  // Print Overloaded APIs
295
0
  OS << "#define __rvv_aio static __inline__ "
296
0
        "__attribute__((__overloadable__))\n";
297
298
0
  emitArchMacroAndBody(Defs, OS, [](raw_ostream &OS, const RVVIntrinsic &Inst) {
299
0
    if (!Inst.isMasked() && !Inst.hasUnMaskedOverloaded())
300
0
      return;
301
0
    OS << "__rvv_aio ";
302
0
    emitOverloadedFuncDef(Inst, OS);
303
0
  });
304
305
0
  OS << "#undef __rvv_aio\n";
306
307
0
  OS << "\n#ifdef __cplusplus\n";
308
0
  OS << "}\n";
309
0
  OS << "#endif // __cplusplus\n";
310
0
  OS << "#endif // __RISCV_VECTOR_H\n";
311
0
}
312
313
0
void RVVEmitter::createBuiltins(raw_ostream &OS) {
314
0
  std::vector<std::unique_ptr<RVVIntrinsic>> Defs;
315
0
  createRVVIntrinsics(Defs);
316
317
  // Map to keep track of which builtin names have already been emitted.
318
0
  StringMap<RVVIntrinsic *> BuiltinMap;
319
320
0
  OS << "#if defined(TARGET_BUILTIN) && !defined(RISCVV_BUILTIN)\n";
321
0
  OS << "#define RISCVV_BUILTIN(ID, TYPE, ATTRS) TARGET_BUILTIN(ID, TYPE, "
322
0
        "ATTRS, \"zve32x\")\n";
323
0
  OS << "#endif\n";
324
0
  for (auto &Def : Defs) {
325
0
    auto P =
326
0
        BuiltinMap.insert(std::make_pair(Def->getBuiltinName(), Def.get()));
327
0
    if (!P.second) {
328
      // Verf that this would have produced the same builtin definition.
329
0
      if (P.first->second->hasBuiltinAlias() != Def->hasBuiltinAlias())
330
0
        PrintFatalError("Builtin with same name has different hasAutoDef");
331
0
      else if (!Def->hasBuiltinAlias() &&
332
0
               P.first->second->getBuiltinTypeStr() != Def->getBuiltinTypeStr())
333
0
        PrintFatalError("Builtin with same name has different type string");
334
0
      continue;
335
0
    }
336
0
    OS << "RISCVV_BUILTIN(__builtin_rvv_" << Def->getBuiltinName() << ",\"";
337
0
    if (!Def->hasBuiltinAlias())
338
0
      OS << Def->getBuiltinTypeStr();
339
0
    OS << "\", \"n\")\n";
340
0
  }
341
0
  OS << "#undef RISCVV_BUILTIN\n";
342
0
}
343
344
0
void RVVEmitter::createCodeGen(raw_ostream &OS) {
345
0
  std::vector<std::unique_ptr<RVVIntrinsic>> Defs;
346
0
  createRVVIntrinsics(Defs);
347
  // IR name could be empty, use the stable sort preserves the relative order.
348
0
  llvm::stable_sort(Defs, [](const std::unique_ptr<RVVIntrinsic> &A,
349
0
                             const std::unique_ptr<RVVIntrinsic> &B) {
350
0
    return A->getIRName() < B->getIRName();
351
0
  });
352
353
  // Map to keep track of which builtin names have already been emitted.
354
0
  StringMap<RVVIntrinsic *> BuiltinMap;
355
356
  // Print switch body when the ir name or ManualCodegen changes from previous
357
  // iteration.
358
0
  RVVIntrinsic *PrevDef = Defs.begin()->get();
359
0
  for (auto &Def : Defs) {
360
0
    StringRef CurIRName = Def->getIRName();
361
0
    if (CurIRName != PrevDef->getIRName() ||
362
0
        (Def->getManualCodegen() != PrevDef->getManualCodegen())) {
363
0
      emitCodeGenSwitchBody(PrevDef, OS);
364
0
    }
365
0
    PrevDef = Def.get();
366
367
0
    auto P =
368
0
        BuiltinMap.insert(std::make_pair(Def->getBuiltinName(), Def.get()));
369
0
    if (P.second) {
370
0
      OS << "case RISCVVector::BI__builtin_rvv_" << Def->getBuiltinName()
371
0
         << ":\n";
372
0
      continue;
373
0
    }
374
375
0
    if (P.first->second->getIRName() != Def->getIRName())
376
0
      PrintFatalError("Builtin with same name has different IRName");
377
0
    else if (P.first->second->getManualCodegen() != Def->getManualCodegen())
378
0
      PrintFatalError("Builtin with same name has different ManualCodegen");
379
0
    else if (P.first->second->getNF() != Def->getNF())
380
0
      PrintFatalError("Builtin with same name has different NF");
381
0
    else if (P.first->second->isMasked() != Def->isMasked())
382
0
      PrintFatalError("Builtin with same name has different isMasked");
383
0
    else if (P.first->second->hasVL() != Def->hasVL())
384
0
      PrintFatalError("Builtin with same name has different hasVL");
385
0
    else if (P.first->second->getPolicyScheme() != Def->getPolicyScheme())
386
0
      PrintFatalError("Builtin with same name has different getPolicyScheme");
387
0
    else if (P.first->second->getIntrinsicTypes() != Def->getIntrinsicTypes())
388
0
      PrintFatalError("Builtin with same name has different IntrinsicTypes");
389
0
  }
390
0
  emitCodeGenSwitchBody(Defs.back().get(), OS);
391
0
  OS << "\n";
392
0
}
393
394
void RVVEmitter::createRVVIntrinsics(
395
0
    std::vector<std::unique_ptr<RVVIntrinsic>> &Out) {
396
0
  std::vector<Record *> RV = Records.getAllDerivedDefinitions("RVVBuiltin");
397
0
  for (auto *R : RV) {
398
0
    StringRef Name = R->getValueAsString("Name");
399
0
    StringRef SuffixProto = R->getValueAsString("Suffix");
400
0
    StringRef OverloadedName = R->getValueAsString("OverloadedName");
401
0
    StringRef OverloadedSuffixProto = R->getValueAsString("OverloadedSuffix");
402
0
    StringRef Prototypes = R->getValueAsString("Prototype");
403
0
    StringRef TypeRange = R->getValueAsString("TypeRange");
404
0
    bool HasMasked = R->getValueAsBit("HasMasked");
405
0
    bool HasMaskedOffOperand = R->getValueAsBit("HasMaskedOffOperand");
406
0
    bool HasVL = R->getValueAsBit("HasVL");
407
0
    Record *MaskedPolicyRecord = R->getValueAsDef("MaskedPolicy");
408
0
    PolicyScheme MaskedPolicy =
409
0
        static_cast<PolicyScheme>(MaskedPolicyRecord->getValueAsInt("Value"));
410
0
    Record *UnMaskedPolicyRecord = R->getValueAsDef("UnMaskedPolicy");
411
0
    PolicyScheme UnMaskedPolicy =
412
0
        static_cast<PolicyScheme>(UnMaskedPolicyRecord->getValueAsInt("Value"));
413
0
    bool HasUnMaskedOverloaded = R->getValueAsBit("HasUnMaskedOverloaded");
414
0
    std::vector<int64_t> Log2LMULList = R->getValueAsListOfInts("Log2LMUL");
415
0
    bool HasBuiltinAlias = R->getValueAsBit("HasBuiltinAlias");
416
0
    StringRef ManualCodegen = R->getValueAsString("ManualCodegen");
417
0
    StringRef MaskedManualCodegen = R->getValueAsString("MaskedManualCodegen");
418
0
    std::vector<int64_t> IntrinsicTypes =
419
0
        R->getValueAsListOfInts("IntrinsicTypes");
420
0
    std::vector<StringRef> RequiredFeatures =
421
0
        R->getValueAsListOfStrings("RequiredFeatures");
422
0
    StringRef IRName = R->getValueAsString("IRName");
423
0
    StringRef MaskedIRName = R->getValueAsString("MaskedIRName");
424
0
    unsigned NF = R->getValueAsInt("NF");
425
426
    // Parse prototype and create a list of primitive type with transformers
427
    // (operand) in Prototype. Prototype[0] is output operand.
428
0
    SmallVector<PrototypeDescriptor> Prototype = parsePrototypes(Prototypes);
429
430
0
    SmallVector<PrototypeDescriptor> SuffixDesc = parsePrototypes(SuffixProto);
431
0
    SmallVector<PrototypeDescriptor> OverloadedSuffixDesc =
432
0
        parsePrototypes(OverloadedSuffixProto);
433
434
    // Compute Builtin types
435
0
    SmallVector<PrototypeDescriptor> MaskedPrototype = Prototype;
436
0
    if (HasMasked) {
437
      // If HasMaskedOffOperand, insert result type as first input operand.
438
0
      if (HasMaskedOffOperand) {
439
0
        if (NF == 1) {
440
0
          MaskedPrototype.insert(MaskedPrototype.begin() + 1, Prototype[0]);
441
0
        } else {
442
          // Convert
443
          // (void, op0 address, op1 address, ...)
444
          // to
445
          // (void, op0 address, op1 address, ..., maskedoff0, maskedoff1, ...)
446
0
          PrototypeDescriptor MaskoffType = Prototype[1];
447
0
          MaskoffType.TM &= ~static_cast<uint8_t>(TypeModifier::Pointer);
448
0
          for (unsigned I = 0; I < NF; ++I)
449
0
            MaskedPrototype.insert(MaskedPrototype.begin() + NF + 1,
450
0
                                   MaskoffType);
451
0
        }
452
0
      }
453
0
      if (HasMaskedOffOperand && NF > 1) {
454
        // Convert
455
        // (void, op0 address, op1 address, ..., maskedoff0, maskedoff1, ...)
456
        // to
457
        // (void, op0 address, op1 address, ..., mask, maskedoff0, maskedoff1,
458
        // ...)
459
0
        MaskedPrototype.insert(MaskedPrototype.begin() + NF + 1,
460
0
                               PrototypeDescriptor::Mask);
461
0
      } else {
462
        // If HasMasked, insert PrototypeDescriptor:Mask as first input operand.
463
0
        MaskedPrototype.insert(MaskedPrototype.begin() + 1,
464
0
                               PrototypeDescriptor::Mask);
465
0
      }
466
0
    }
467
    // If HasVL, append PrototypeDescriptor:VL to last operand
468
0
    if (HasVL) {
469
0
      Prototype.push_back(PrototypeDescriptor::VL);
470
0
      MaskedPrototype.push_back(PrototypeDescriptor::VL);
471
0
    }
472
473
    // Create Intrinsics for each type and LMUL.
474
0
    for (char I : TypeRange) {
475
0
      for (int Log2LMUL : Log2LMULList) {
476
0
        BasicType BT = ParseBasicType(I);
477
0
        Optional<RVVTypes> Types =
478
0
            RVVType::computeTypes(BT, Log2LMUL, NF, Prototype);
479
        // Ignored to create new intrinsic if there are any illegal types.
480
0
        if (!Types)
481
0
          continue;
482
483
0
        auto SuffixStr = RVVIntrinsic::getSuffixStr(BT, Log2LMUL, SuffixDesc);
484
0
        auto OverloadedSuffixStr =
485
0
            RVVIntrinsic::getSuffixStr(BT, Log2LMUL, OverloadedSuffixDesc);
486
        // Create a unmasked intrinsic
487
0
        Out.push_back(std::make_unique<RVVIntrinsic>(
488
0
            Name, SuffixStr, OverloadedName, OverloadedSuffixStr, IRName,
489
0
            /*IsMasked=*/false, /*HasMaskedOffOperand=*/false, HasVL,
490
0
            UnMaskedPolicy, HasUnMaskedOverloaded, HasBuiltinAlias,
491
0
            ManualCodegen, *Types, IntrinsicTypes, RequiredFeatures, NF));
492
0
        if (HasMasked) {
493
          // Create a masked intrinsic
494
0
          Optional<RVVTypes> MaskTypes =
495
0
              RVVType::computeTypes(BT, Log2LMUL, NF, MaskedPrototype);
496
0
          Out.push_back(std::make_unique<RVVIntrinsic>(
497
0
              Name, SuffixStr, OverloadedName, OverloadedSuffixStr,
498
0
              MaskedIRName,
499
0
              /*IsMasked=*/true, HasMaskedOffOperand, HasVL, MaskedPolicy,
500
0
              HasUnMaskedOverloaded, HasBuiltinAlias, MaskedManualCodegen,
501
0
              *MaskTypes, IntrinsicTypes, RequiredFeatures, NF));
502
0
        }
503
0
      } // end for Log2LMULList
504
0
    }   // end for TypeRange
505
0
  }
506
0
}
507
508
0
void RVVEmitter::printHeaderCode(raw_ostream &OS) {
509
0
  std::vector<Record *> RVVHeaders =
510
0
      Records.getAllDerivedDefinitions("RVVHeader");
511
0
  for (auto *R : RVVHeaders) {
512
0
    StringRef HeaderCodeStr = R->getValueAsString("HeaderCode");
513
0
    OS << HeaderCodeStr.str();
514
0
  }
515
0
}
516
517
void RVVEmitter::emitArchMacroAndBody(
518
    std::vector<std::unique_ptr<RVVIntrinsic>> &Defs, raw_ostream &OS,
519
0
    std::function<void(raw_ostream &, const RVVIntrinsic &)> PrintBody) {
520
0
  RISCVPredefinedMacroT PrevMacros =
521
0
      (*Defs.begin())->getRISCVPredefinedMacros();
522
0
  bool NeedEndif = emitMacroRestrictionStr(PrevMacros, OS);
523
0
  for (auto &Def : Defs) {
524
0
    RISCVPredefinedMacroT CurMacros = Def->getRISCVPredefinedMacros();
525
0
    if (CurMacros != PrevMacros) {
526
0
      if (NeedEndif)
527
0
        OS << "#endif\n\n";
528
0
      NeedEndif = emitMacroRestrictionStr(CurMacros, OS);
529
0
      PrevMacros = CurMacros;
530
0
    }
531
0
    if (Def->hasBuiltinAlias())
532
0
      PrintBody(OS, *Def);
533
0
  }
534
0
  if (NeedEndif)
535
0
    OS << "#endif\n\n";
536
0
}
537
538
bool RVVEmitter::emitMacroRestrictionStr(RISCVPredefinedMacroT PredefinedMacros,
539
0
                                         raw_ostream &OS) {
540
0
  if (PredefinedMacros == RISCVPredefinedMacro::Basic)
541
0
    return false;
542
0
  OS << "#if ";
543
0
  ListSeparator LS(" && ");
544
0
  if (PredefinedMacros & RISCVPredefinedMacro::V)
545
0
    OS << LS << "defined(__riscv_v)";
546
0
  if (PredefinedMacros & RISCVPredefinedMacro::Zvfh)
547
0
    OS << LS << "defined(__riscv_zvfh)";
548
0
  if (PredefinedMacros & RISCVPredefinedMacro::RV64)
549
0
    OS << LS << "(__riscv_xlen == 64)";
550
0
  if (PredefinedMacros & RISCVPredefinedMacro::VectorMaxELen64)
551
0
    OS << LS << "(__riscv_v_elen >= 64)";
552
0
  if (PredefinedMacros & RISCVPredefinedMacro::VectorMaxELenFp32)
553
0
    OS << LS << "(__riscv_v_elen_fp >= 32)";
554
0
  if (PredefinedMacros & RISCVPredefinedMacro::VectorMaxELenFp64)
555
0
    OS << LS << "(__riscv_v_elen_fp >= 64)";
556
0
  OS << "\n";
557
0
  return true;
558
0
}
559
560
namespace clang {
561
0
void EmitRVVHeader(RecordKeeper &Records, raw_ostream &OS) {
562
0
  RVVEmitter(Records).createHeader(OS);
563
0
}
564
565
0
void EmitRVVBuiltins(RecordKeeper &Records, raw_ostream &OS) {
566
0
  RVVEmitter(Records).createBuiltins(OS);
567
0
}
568
569
0
void EmitRVVBuiltinCG(RecordKeeper &Records, raw_ostream &OS) {
570
0
  RVVEmitter(Records).createCodeGen(OS);
571
0
}
572
573
} // End namespace clang