Coverage Report

Created: 2022-05-14 11:35

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