1 //===- TargetFeaturesEmitter.cpp - Generate CPU Target feature ----===//
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 exports cpu target features
10 // and cpu sub-type.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "TargetFeaturesEmitter.h"
15 #include "llvm/TableGen/Error.h"
16 #include "llvm/TableGen/TableGenBackend.h"
17 #include "llvm/TargetParser/SubtargetFeature.h"
18
19 using namespace llvm;
20
21 using FeatureMapTy = DenseMap<const Record *, unsigned>;
22 using ConstRecVec = std::vector<const Record *>;
23
TargetFeaturesEmitter(const RecordKeeper & R)24 TargetFeaturesEmitter::TargetFeaturesEmitter(const RecordKeeper &R)
25 : Records(R) {
26 ArrayRef<const Record *> Targets = Records.getAllDerivedDefinitions("Target");
27 if (Targets.size() == 0)
28 PrintFatalError("No 'Target' subclasses defined!");
29 if (Targets.size() != 1)
30 PrintFatalError("Multiple subclasses of Target defined!");
31 Target = Targets[0]->getName();
32 }
33
enumeration(raw_ostream & OS)34 FeatureMapTy TargetFeaturesEmitter::enumeration(raw_ostream &OS) {
35 ArrayRef<const Record *> DefList =
36 Records.getAllDerivedDefinitions("SubtargetFeature");
37
38 unsigned N = DefList.size();
39 if (N == 0)
40 return FeatureMapTy();
41
42 if (N + 1 > MAX_SUBTARGET_FEATURES)
43 PrintFatalError(
44 "Too many subtarget features! Bump MAX_SUBTARGET_FEATURES.");
45
46 OS << "namespace " << Target << " {\n";
47
48 OS << "enum {\n";
49
50 FeatureMapTy FeatureMap;
51 for (unsigned I = 0; I < N; ++I) {
52 const Record *Def = DefList[I];
53 // Print the Feature Name.
54 OS << " " << Def->getName() << " = " << I << ",\n";
55
56 FeatureMap[Def] = I;
57 }
58
59 OS << " " << "NumSubtargetFeatures = " << N << "\n";
60
61 // Close enumeration and namespace
62 OS << "};\n";
63 OS << "} // end namespace " << Target << "\n";
64 return FeatureMap;
65 }
66
printFeatureMask(raw_ostream & OS,ArrayRef<const Record * > FeatureList,const FeatureMapTy & FeatureMap)67 void TargetFeaturesEmitter::printFeatureMask(
68 raw_ostream &OS, ArrayRef<const Record *> FeatureList,
69 const FeatureMapTy &FeatureMap) {
70 std::array<uint64_t, MAX_SUBTARGET_WORDS> Mask = {};
71 for (const Record *Feature : FeatureList) {
72 unsigned Bit = FeatureMap.lookup(Feature);
73 Mask[Bit / 64] |= 1ULL << (Bit % 64);
74 }
75
76 OS << "{ { { ";
77 for (unsigned I = 0; I != Mask.size(); ++I) {
78 OS << "0x";
79 OS.write_hex(Mask[I]);
80 OS << "ULL, ";
81 }
82 OS << "} } }";
83 }
84
printFeatureKeyValues(raw_ostream & OS,const FeatureMapTy & FeatureMap)85 void TargetFeaturesEmitter::printFeatureKeyValues(
86 raw_ostream &OS, const FeatureMapTy &FeatureMap) {
87 std::vector<const Record *> FeatureList =
88 Records.getAllDerivedDefinitions("SubtargetFeature");
89
90 // Remove features with empty name.
91 llvm::erase_if(FeatureList, [](const Record *Rec) {
92 return Rec->getValueAsString("Name").empty();
93 });
94
95 if (FeatureList.empty())
96 return;
97
98 llvm::sort(FeatureList, LessRecordFieldName());
99
100 // Begin feature table.
101 OS << "// Sorted (by key) array of values for CPU features.\n"
102 << "extern const llvm::BasicSubtargetFeatureKV " << "Basic" << Target
103 << "FeatureKV[] = {\n";
104
105 for (const Record *Feature : FeatureList) {
106 StringRef Name = Feature->getName();
107 StringRef ValueName = Feature->getValueAsString("Name");
108
109 OS << " { " << "\"" << ValueName << "\", " << Target << "::" << Name
110 << ", ";
111
112 ConstRecVec ImpliesList = Feature->getValueAsListOfDefs("Implies");
113
114 printFeatureMask(OS, ImpliesList, FeatureMap);
115
116 OS << " },\n";
117 }
118
119 // End feature table.
120 OS << "};\n";
121 }
122
printCPUKeyValues(raw_ostream & OS,const FeatureMapTy & FeatureMap)123 void TargetFeaturesEmitter::printCPUKeyValues(raw_ostream &OS,
124 const FeatureMapTy &FeatureMap) {
125 // Gather and sort processor information
126 std::vector<const Record *> ProcessorList =
127 Records.getAllDerivedDefinitions("Processor");
128 llvm::sort(ProcessorList, LessRecordFieldName());
129
130 // Begin processor table.
131 OS << "// Sorted (by key) array of values for CPU subtype.\n"
132 << "extern const llvm::BasicSubtargetSubTypeKV " << "Basic" << Target
133 << "SubTypeKV[] = {\n";
134
135 for (const Record *Processor : ProcessorList) {
136 StringRef Name = Processor->getValueAsString("Name");
137 ConstRecVec FeatureList = Processor->getValueAsListOfDefs("Features");
138
139 OS << " { " << "\"" << Name << "\", ";
140
141 printFeatureMask(OS, FeatureList, FeatureMap);
142 OS << " },\n";
143 }
144
145 // End processor table.
146 OS << "};\n";
147 }
148
run(raw_ostream & OS)149 void TargetFeaturesEmitter::run(raw_ostream &OS) {
150 OS << "// Autogenerated by TargetFeatureEmitter.cpp\n\n";
151
152 OS << "\n#ifdef GET_SUBTARGETFEATURES_ENUM\n";
153 OS << "#undef GET_SUBTARGETFEATURES_ENUM\n\n";
154
155 OS << "namespace llvm {\n";
156 auto FeatureMap = enumeration(OS);
157 OS << "} // end namespace llvm\n\n";
158 OS << "#endif // GET_SUBTARGETFEATURES_ENUM\n\n";
159
160 OS << "\n#ifdef GET_SUBTARGETFEATURES_KV\n";
161 OS << "#undef GET_SUBTARGETFEATURES_KV\n\n";
162
163 OS << "namespace llvm {\n";
164 printFeatureKeyValues(OS, FeatureMap);
165 OS << "\n";
166
167 printCPUKeyValues(OS, FeatureMap);
168 OS << "\n";
169 OS << "} // end namespace llvm\n\n";
170 OS << "#endif // GET_SUBTARGETFEATURES_KV\n\n";
171 }
172
173 static TableGen::Emitter::OptClass<TargetFeaturesEmitter>
174 X("gen-target-features", "Generate subtarget enumerations");
175