xref: /freebsd-src/contrib/llvm-project/llvm/utils/TableGen/RISCVTargetDefEmitter.cpp (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
1*bdd1243dSDimitry Andric //===- RISCVTargetDefEmitter.cpp - Generate lists of RISCV CPUs -----------===//
2*bdd1243dSDimitry Andric //
3*bdd1243dSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*bdd1243dSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*bdd1243dSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*bdd1243dSDimitry Andric //
7*bdd1243dSDimitry Andric //===----------------------------------------------------------------------===//
8*bdd1243dSDimitry Andric //
9*bdd1243dSDimitry Andric // This tablegen backend emits the include file needed by the target
10*bdd1243dSDimitry Andric // parser to parse the RISC-V CPUs.
11*bdd1243dSDimitry Andric //
12*bdd1243dSDimitry Andric //===----------------------------------------------------------------------===//
13*bdd1243dSDimitry Andric 
14*bdd1243dSDimitry Andric #include "TableGenBackends.h"
15*bdd1243dSDimitry Andric #include "llvm/Support/RISCVISAInfo.h"
16*bdd1243dSDimitry Andric #include "llvm/TableGen/Record.h"
17*bdd1243dSDimitry Andric 
18*bdd1243dSDimitry Andric using namespace llvm;
19*bdd1243dSDimitry Andric 
20*bdd1243dSDimitry Andric using ISAInfoTy = llvm::Expected<std::unique_ptr<RISCVISAInfo>>;
21*bdd1243dSDimitry Andric 
22*bdd1243dSDimitry Andric // We can generate march string from target features as what has been described
23*bdd1243dSDimitry Andric // in RISCV ISA specification (version 20191213) 'Chapter 27. ISA Extension
24*bdd1243dSDimitry Andric // Naming Conventions'.
25*bdd1243dSDimitry Andric //
26*bdd1243dSDimitry Andric // This is almost the same as RISCVFeatures::parseFeatureBits, except that we
27*bdd1243dSDimitry Andric // get feature name from feature records instead of feature bits.
28*bdd1243dSDimitry Andric static std::string getMArch(const Record &Rec) {
29*bdd1243dSDimitry Andric   std::vector<std::string> FeatureVector;
30*bdd1243dSDimitry Andric   int XLen = 32;
31*bdd1243dSDimitry Andric 
32*bdd1243dSDimitry Andric   // Convert features to FeatureVector.
33*bdd1243dSDimitry Andric   for (auto *Feature : Rec.getValueAsListOfDefs("Features")) {
34*bdd1243dSDimitry Andric     StringRef FeatureName = Feature->getValueAsString("Name");
35*bdd1243dSDimitry Andric     if (llvm::RISCVISAInfo::isSupportedExtensionFeature(FeatureName))
36*bdd1243dSDimitry Andric       FeatureVector.push_back((Twine("+") + FeatureName).str());
37*bdd1243dSDimitry Andric     else if (FeatureName == "64bit")
38*bdd1243dSDimitry Andric       XLen = 64;
39*bdd1243dSDimitry Andric   }
40*bdd1243dSDimitry Andric 
41*bdd1243dSDimitry Andric   ISAInfoTy ISAInfo = llvm::RISCVISAInfo::parseFeatures(XLen, FeatureVector);
42*bdd1243dSDimitry Andric   if (!ISAInfo)
43*bdd1243dSDimitry Andric     report_fatal_error("Invalid features");
44*bdd1243dSDimitry Andric 
45*bdd1243dSDimitry Andric   // RISCVISAInfo::toString will generate a march string with all the extensions
46*bdd1243dSDimitry Andric   // we have added to it.
47*bdd1243dSDimitry Andric   return (*ISAInfo)->toString();
48*bdd1243dSDimitry Andric }
49*bdd1243dSDimitry Andric 
50*bdd1243dSDimitry Andric void llvm::EmitRISCVTargetDef(const RecordKeeper &RK, raw_ostream &OS) {
51*bdd1243dSDimitry Andric   OS << "#ifndef PROC\n"
52*bdd1243dSDimitry Andric      << "#define PROC(ENUM, NAME, DEFAULT_MARCH)\n"
53*bdd1243dSDimitry Andric      << "#endif\n\n";
54*bdd1243dSDimitry Andric 
55*bdd1243dSDimitry Andric   OS << "PROC(INVALID, {\"invalid\"}, {\"\"})\n";
56*bdd1243dSDimitry Andric   // Iterate on all definition records.
57*bdd1243dSDimitry Andric   for (const Record *Rec : RK.getAllDerivedDefinitions("RISCVProcessorModel")) {
58*bdd1243dSDimitry Andric     std::string MArch = Rec->getValueAsString("DefaultMarch").str();
59*bdd1243dSDimitry Andric 
60*bdd1243dSDimitry Andric     // Compute MArch from features if we don't specify it.
61*bdd1243dSDimitry Andric     if (MArch.empty())
62*bdd1243dSDimitry Andric       MArch = getMArch(*Rec);
63*bdd1243dSDimitry Andric 
64*bdd1243dSDimitry Andric     OS << "PROC(" << Rec->getName() << ", "
65*bdd1243dSDimitry Andric        << "{\"" << Rec->getValueAsString("Name") << "\"}, "
66*bdd1243dSDimitry Andric        << "{\"" << MArch << "\"})\n";
67*bdd1243dSDimitry Andric   }
68*bdd1243dSDimitry Andric   OS << "\n#undef PROC\n";
69*bdd1243dSDimitry Andric   OS << "\n";
70*bdd1243dSDimitry Andric   OS << "#ifndef TUNE_PROC\n"
71*bdd1243dSDimitry Andric      << "#define TUNE_PROC(ENUM, NAME)\n"
72*bdd1243dSDimitry Andric      << "#endif\n\n";
73*bdd1243dSDimitry Andric   OS << "TUNE_PROC(GENERIC, \"generic\")\n";
74*bdd1243dSDimitry Andric 
75*bdd1243dSDimitry Andric   for (const Record *Rec :
76*bdd1243dSDimitry Andric        RK.getAllDerivedDefinitions("RISCVTuneProcessorModel")) {
77*bdd1243dSDimitry Andric     OS << "TUNE_PROC(" << Rec->getName() << ", "
78*bdd1243dSDimitry Andric        << "\"" << Rec->getValueAsString("Name") << "\")\n";
79*bdd1243dSDimitry Andric   }
80*bdd1243dSDimitry Andric 
81*bdd1243dSDimitry Andric   OS << "\n#undef TUNE_PROC\n";
82*bdd1243dSDimitry Andric }
83