1 | //===- RISCVTargetDefEmitter.cpp - Generate lists of RISC-V CPUs ----------===// |
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 emits the include file needed by the target |
10 | // parser to parse the RISC-V CPUs. |
11 | // |
12 | //===----------------------------------------------------------------------===// |
13 | |
14 | #include "llvm/Support/RISCVISAUtils.h" |
15 | #include "llvm/TableGen/Record.h" |
16 | #include "llvm/TableGen/TableGenBackend.h" |
17 | |
18 | using namespace llvm; |
19 | |
20 | // We can generate march string from target features as what has been described |
21 | // in RISC-V ISA specification (version 20191213) 'Chapter 27. ISA Extension |
22 | // Naming Conventions'. |
23 | // |
24 | // This is almost the same as RISCVFeatures::parseFeatureBits, except that we |
25 | // get feature name from feature records instead of feature bits. |
26 | static void printMArch(raw_ostream &OS, const Record &Rec) { |
27 | std::map<std::string, RISCVISAUtils::ExtensionVersion, |
28 | RISCVISAUtils::ExtensionComparator> |
29 | Extensions; |
30 | unsigned XLen = 0; |
31 | |
32 | // Convert features to FeatureVector. |
33 | for (auto *Feature : Rec.getValueAsListOfDefs(FieldName: "Features" )) { |
34 | StringRef FeatureName = Feature->getValueAsString(FieldName: "Name" ); |
35 | if (Feature->isSubClassOf(Name: "RISCVExtension" )) { |
36 | unsigned Major = Feature->getValueAsInt(FieldName: "MajorVersion" ); |
37 | unsigned Minor = Feature->getValueAsInt(FieldName: "MinorVersion" ); |
38 | Extensions[FeatureName.str()] = {.Major: Major, .Minor: Minor}; |
39 | } else if (FeatureName == "64bit" ) { |
40 | assert(XLen == 0 && "Already determined XLen" ); |
41 | XLen = 64; |
42 | } else if (FeatureName == "32bit" ) { |
43 | assert(XLen == 0 && "Already determined XLen" ); |
44 | XLen = 32; |
45 | } |
46 | } |
47 | |
48 | assert(XLen != 0 && "Unable to determine XLen" ); |
49 | |
50 | OS << "rv" << XLen; |
51 | |
52 | ListSeparator LS("_" ); |
53 | for (auto const &Ext : Extensions) |
54 | OS << LS << Ext.first << Ext.second.Major << 'p' << Ext.second.Minor; |
55 | } |
56 | |
57 | static void EmitRISCVTargetDef(RecordKeeper &RK, raw_ostream &OS) { |
58 | OS << "#ifndef PROC\n" |
59 | << "#define PROC(ENUM, NAME, DEFAULT_MARCH, FAST_UNALIGNED_ACCESS)\n" |
60 | << "#endif\n\n" ; |
61 | |
62 | // Iterate on all definition records. |
63 | for (const Record *Rec : RK.getAllDerivedDefinitions(ClassName: "RISCVProcessorModel" )) { |
64 | bool FastScalarUnalignedAccess = |
65 | any_of(Range: Rec->getValueAsListOfDefs(FieldName: "Features" ), P: [&](auto &Feature) { |
66 | return Feature->getValueAsString("Name" ) == "unaligned-scalar-mem" ; |
67 | }); |
68 | |
69 | bool FastVectorUnalignedAccess = |
70 | any_of(Range: Rec->getValueAsListOfDefs(FieldName: "Features" ), P: [&](auto &Feature) { |
71 | return Feature->getValueAsString("Name" ) == "unaligned-vector-mem" ; |
72 | }); |
73 | |
74 | bool FastUnalignedAccess = |
75 | FastScalarUnalignedAccess && FastVectorUnalignedAccess; |
76 | |
77 | OS << "PROC(" << Rec->getName() << ", {\"" << Rec->getValueAsString(FieldName: "Name" ) |
78 | << "\"}, {\"" ; |
79 | |
80 | StringRef MArch = Rec->getValueAsString(FieldName: "DefaultMarch" ); |
81 | |
82 | // Compute MArch from features if we don't specify it. |
83 | if (MArch.empty()) |
84 | printMArch(OS, Rec: *Rec); |
85 | else |
86 | OS << MArch; |
87 | OS << "\"}, " << FastUnalignedAccess << ")\n" ; |
88 | } |
89 | OS << "\n#undef PROC\n" ; |
90 | OS << "\n" ; |
91 | OS << "#ifndef TUNE_PROC\n" |
92 | << "#define TUNE_PROC(ENUM, NAME)\n" |
93 | << "#endif\n\n" ; |
94 | |
95 | for (const Record *Rec : |
96 | RK.getAllDerivedDefinitions(ClassName: "RISCVTuneProcessorModel" )) { |
97 | OS << "TUNE_PROC(" << Rec->getName() << ", " |
98 | << "\"" << Rec->getValueAsString(FieldName: "Name" ) << "\")\n" ; |
99 | } |
100 | |
101 | OS << "\n#undef TUNE_PROC\n" ; |
102 | } |
103 | |
104 | static TableGen::Emitter::Opt X("gen-riscv-target-def" , EmitRISCVTargetDef, |
105 | "Generate the list of CPU for RISCV" ); |
106 | |