xref: /freebsd/contrib/llvm-project/llvm/utils/TableGen/Basic/TargetFeaturesEmitter.cpp (revision c4b244af42a1f20937939a824b753a92c9c0a46f)
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 
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 
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 
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 
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 
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 
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