/src/keystone/llvm/lib/MC/SubtargetFeature.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===- SubtargetFeature.cpp - CPU characteristics Implementation ----------===// |
2 | | // |
3 | | // The LLVM Compiler Infrastructure |
4 | | // |
5 | | // This file is distributed under the University of Illinois Open Source |
6 | | // License. See LICENSE.TXT for details. |
7 | | // |
8 | | //===----------------------------------------------------------------------===// |
9 | | // |
10 | | // This file implements the SubtargetFeature interface. |
11 | | // |
12 | | //===----------------------------------------------------------------------===// |
13 | | |
14 | | #include "llvm/MC/SubtargetFeature.h" |
15 | | #include "llvm/ADT/StringExtras.h" |
16 | | #include "llvm/Support/Debug.h" |
17 | | #include "llvm/Support/Format.h" |
18 | | #include "llvm/Support/raw_ostream.h" |
19 | | #include <algorithm> |
20 | | #include <cassert> |
21 | | #include <cctype> |
22 | | #include <cstdlib> |
23 | | using namespace llvm_ks; |
24 | | |
25 | | //===----------------------------------------------------------------------===// |
26 | | // Static Helper Functions |
27 | | //===----------------------------------------------------------------------===// |
28 | | |
29 | | /// hasFlag - Determine if a feature has a flag; '+' or '-' |
30 | | /// |
31 | 1.05M | static inline bool hasFlag(StringRef Feature) { |
32 | 1.05M | assert(!Feature.empty() && "Empty string"); |
33 | | // Get first character |
34 | 1.05M | char Ch = Feature[0]; |
35 | | // Check if first character is '+' or '-' flag |
36 | 1.05M | return Ch == '+' || Ch =='-'; |
37 | 1.05M | } |
38 | | |
39 | | /// StripFlag - Return string stripped of flag. |
40 | | /// |
41 | 532k | static inline std::string StripFlag(StringRef Feature) { |
42 | 532k | return hasFlag(Feature) ? Feature.substr(1) : Feature; |
43 | 532k | } |
44 | | |
45 | | /// isEnabled - Return true if enable flag; '+'. |
46 | | /// |
47 | 527k | static inline bool isEnabled(StringRef Feature) { |
48 | 527k | assert(!Feature.empty() && "Empty string"); |
49 | | // Get first character |
50 | 527k | char Ch = Feature[0]; |
51 | | // Check if first character is '+' for enabled |
52 | 527k | return Ch == '+'; |
53 | 527k | } |
54 | | |
55 | | /// Split - Splits a string of comma separated items in to a vector of strings. |
56 | | /// |
57 | 281k | static void Split(std::vector<std::string> &V, StringRef S) { |
58 | 281k | SmallVector<StringRef, 3> Tmp; |
59 | 281k | S.split(Tmp, ',', -1, false /* KeepEmpty */); |
60 | 281k | V.assign(Tmp.begin(), Tmp.end()); |
61 | 281k | } |
62 | | |
63 | | /// Adding features. |
64 | 0 | void SubtargetFeatures::AddFeature(StringRef String, bool Enable) { |
65 | | // Don't add empty features. |
66 | 0 | if (!String.empty()) |
67 | | // Convert to lowercase, prepend flag if we don't already have a flag. |
68 | 0 | Features.push_back(hasFlag(String) ? String.lower() |
69 | 0 | : (Enable ? "+" : "-") + String.lower()); |
70 | 0 | } |
71 | | |
72 | | /// Find KV in array using binary search. |
73 | | static const SubtargetFeatureKV *Find(StringRef S, |
74 | 597k | ArrayRef<SubtargetFeatureKV> A) { |
75 | | // Binary search the array |
76 | 597k | auto F = std::lower_bound(A.begin(), A.end(), S); |
77 | | // If not found then return NULL |
78 | 597k | if (F == A.end() || StringRef(F->Key) != S) return nullptr; |
79 | | // Return the found array item |
80 | 597k | return F; |
81 | 597k | } |
82 | | |
83 | | /// getLongestEntryLength - Return the length of the longest entry in the table. |
84 | | /// |
85 | 0 | static size_t getLongestEntryLength(ArrayRef<SubtargetFeatureKV> Table) { |
86 | 0 | size_t MaxLen = 0; |
87 | 0 | for (auto &I : Table) |
88 | 0 | MaxLen = std::max(MaxLen, std::strlen(I.Key)); |
89 | 0 | return MaxLen; |
90 | 0 | } |
91 | | |
92 | | /// Display help for feature choices. |
93 | | /// |
94 | | static void Help(ArrayRef<SubtargetFeatureKV> CPUTable, |
95 | 0 | ArrayRef<SubtargetFeatureKV> FeatTable) { |
96 | | // Determine the length of the longest CPU and Feature entries. |
97 | 0 | unsigned MaxCPULen = getLongestEntryLength(CPUTable); |
98 | 0 | unsigned MaxFeatLen = getLongestEntryLength(FeatTable); |
99 | | |
100 | | // Print the CPU table. |
101 | 0 | errs() << "Available CPUs for this target:\n\n"; |
102 | 0 | for (auto &CPU : CPUTable) |
103 | 0 | errs() << format(" %-*s - %s.\n", MaxCPULen, CPU.Key, CPU.Desc); |
104 | 0 | errs() << '\n'; |
105 | | |
106 | | // Print the Feature table. |
107 | 0 | errs() << "Available features for this target:\n\n"; |
108 | 0 | for (auto &Feature : FeatTable) |
109 | 0 | errs() << format(" %-*s - %s.\n", MaxFeatLen, Feature.Key, Feature.Desc); |
110 | 0 | errs() << '\n'; |
111 | |
|
112 | 0 | errs() << "Use +feature to enable a feature, or -feature to disable it.\n" |
113 | 0 | "For example, llc -mcpu=mycpu -mattr=+feature1,-feature2\n"; |
114 | 0 | } |
115 | | |
116 | | //===----------------------------------------------------------------------===// |
117 | | // SubtargetFeatures Implementation |
118 | | //===----------------------------------------------------------------------===// |
119 | | |
120 | 281k | SubtargetFeatures::SubtargetFeatures(StringRef Initial) { |
121 | | // Break up string into separate features |
122 | 281k | Split(Features, Initial); |
123 | 281k | } |
124 | | |
125 | | |
126 | 0 | std::string SubtargetFeatures::getString() const { |
127 | 0 | return join(Features.begin(), Features.end(), ","); |
128 | 0 | } |
129 | | |
130 | | /// SetImpliedBits - For each feature that is (transitively) implied by this |
131 | | /// feature, set it. |
132 | | /// |
133 | | static |
134 | | void SetImpliedBits(FeatureBitset &Bits, const SubtargetFeatureKV *FeatureEntry, |
135 | 6.48M | ArrayRef<SubtargetFeatureKV> FeatureTable) { |
136 | 617M | for (auto &FE : FeatureTable) { |
137 | 617M | if (FeatureEntry->Value == FE.Value) continue; |
138 | | |
139 | 611M | if ((FeatureEntry->Implies & FE.Value).any()) { |
140 | 5.75M | Bits |= FE.Value; |
141 | 5.75M | SetImpliedBits(Bits, &FE, FeatureTable); |
142 | 5.75M | } |
143 | 611M | } |
144 | 6.48M | } |
145 | | |
146 | | /// ClearImpliedBits - For each feature that (transitively) implies this |
147 | | /// feature, clear it. |
148 | | /// |
149 | | static |
150 | | void ClearImpliedBits(FeatureBitset &Bits, |
151 | | const SubtargetFeatureKV *FeatureEntry, |
152 | 1.17M | ArrayRef<SubtargetFeatureKV> FeatureTable) { |
153 | 122M | for (auto &FE : FeatureTable) { |
154 | 122M | if (FeatureEntry->Value == FE.Value) continue; |
155 | | |
156 | 120M | if ((FE.Implies & FeatureEntry->Value).any()) { |
157 | 968k | Bits &= ~FE.Value; |
158 | 968k | ClearImpliedBits(Bits, &FE, FeatureTable); |
159 | 968k | } |
160 | 120M | } |
161 | 1.17M | } |
162 | | |
163 | | /// ToggleFeature - Toggle a feature and update the feature bits. |
164 | | void |
165 | | SubtargetFeatures::ToggleFeature(FeatureBitset &Bits, StringRef Feature, |
166 | 4.54k | ArrayRef<SubtargetFeatureKV> FeatureTable) { |
167 | | |
168 | | // Find feature in table. |
169 | 4.54k | const SubtargetFeatureKV *FeatureEntry = |
170 | 4.54k | Find(StripFlag(Feature), FeatureTable); |
171 | | // If there is a match |
172 | 4.54k | if (FeatureEntry) { |
173 | 4.54k | if ((Bits & FeatureEntry->Value) == FeatureEntry->Value) { |
174 | 423 | Bits &= ~FeatureEntry->Value; |
175 | | // For each feature that implies this, clear it. |
176 | 423 | ClearImpliedBits(Bits, FeatureEntry, FeatureTable); |
177 | 4.11k | } else { |
178 | 4.11k | Bits |= FeatureEntry->Value; |
179 | | |
180 | | // For each feature that this implies, set it. |
181 | 4.11k | SetImpliedBits(Bits, FeatureEntry, FeatureTable); |
182 | 4.11k | } |
183 | 4.54k | } else { |
184 | 0 | errs() << "'" << Feature |
185 | 0 | << "' is not a recognized feature for this target" |
186 | 0 | << " (ignoring feature)\n"; |
187 | 0 | } |
188 | 4.54k | } |
189 | | |
190 | | void SubtargetFeatures::ApplyFeatureFlag(FeatureBitset &Bits, StringRef Feature, |
191 | 527k | ArrayRef<SubtargetFeatureKV> FeatureTable) { |
192 | | |
193 | 527k | assert(hasFlag(Feature)); |
194 | | |
195 | | // Find feature in table. |
196 | 527k | const SubtargetFeatureKV *FeatureEntry = |
197 | 527k | Find(StripFlag(Feature), FeatureTable); |
198 | | // If there is a match |
199 | 527k | if (FeatureEntry) { |
200 | | // Enable/disable feature in bits |
201 | 527k | if (isEnabled(Feature)) { |
202 | 317k | Bits |= FeatureEntry->Value; |
203 | | |
204 | | // For each feature that this implies, set it. |
205 | 317k | SetImpliedBits(Bits, FeatureEntry, FeatureTable); |
206 | 317k | } else { |
207 | 210k | Bits &= ~FeatureEntry->Value; |
208 | | |
209 | | // For each feature that implies this, clear it. |
210 | 210k | ClearImpliedBits(Bits, FeatureEntry, FeatureTable); |
211 | 210k | } |
212 | 527k | } else { |
213 | 0 | errs() << "'" << Feature |
214 | 0 | << "' is not a recognized feature for this target" |
215 | 0 | << " (ignoring feature)\n"; |
216 | 0 | } |
217 | 527k | } |
218 | | |
219 | | |
220 | | /// getFeatureBits - Get feature bits a CPU. |
221 | | /// |
222 | | FeatureBitset |
223 | | SubtargetFeatures::getFeatureBits(StringRef CPU, |
224 | | ArrayRef<SubtargetFeatureKV> CPUTable, |
225 | 281k | ArrayRef<SubtargetFeatureKV> FeatureTable) { |
226 | | |
227 | 281k | if (CPUTable.empty() || FeatureTable.empty()) |
228 | 0 | return FeatureBitset(); |
229 | | |
230 | 281k | #ifndef NDEBUG |
231 | 281k | assert(std::is_sorted(std::begin(CPUTable), std::end(CPUTable)) && |
232 | 281k | "CPU table is not sorted"); |
233 | 281k | assert(std::is_sorted(std::begin(FeatureTable), std::end(FeatureTable)) && |
234 | 281k | "CPU features table is not sorted"); |
235 | 281k | #endif |
236 | | // Resulting bits |
237 | 281k | FeatureBitset Bits; |
238 | | |
239 | | // Check if help is needed |
240 | 281k | if (CPU == "help") |
241 | 0 | Help(CPUTable, FeatureTable); |
242 | | |
243 | | // Find CPU entry if CPU name is specified. |
244 | 281k | else if (!CPU.empty()) { |
245 | 64.8k | const SubtargetFeatureKV *CPUEntry = Find(CPU, CPUTable); |
246 | | |
247 | | // If there is a match |
248 | 64.8k | if (CPUEntry) { |
249 | | // Set base feature bits |
250 | 64.8k | Bits = CPUEntry->Value; |
251 | | |
252 | | // Set the feature implied by this CPU feature, if any. |
253 | 2.07M | for (auto &FE : FeatureTable) { |
254 | 2.07M | if ((CPUEntry->Value & FE.Value).any()) |
255 | 405k | SetImpliedBits(Bits, &FE, FeatureTable); |
256 | 2.07M | } |
257 | 64.8k | } else { |
258 | 0 | errs() << "'" << CPU |
259 | 0 | << "' is not a recognized processor for this target" |
260 | 0 | << " (ignoring processor)\n"; |
261 | 0 | } |
262 | 64.8k | } |
263 | | |
264 | | // Iterate through each feature |
265 | 324k | for (auto &Feature : Features) { |
266 | | // Check for help |
267 | 324k | if (Feature == "+help") |
268 | 0 | Help(CPUTable, FeatureTable); |
269 | | |
270 | 324k | ApplyFeatureFlag(Bits, Feature, FeatureTable); |
271 | 324k | } |
272 | | |
273 | 281k | return Bits; |
274 | 281k | } |
275 | | |
276 | | /// print - Print feature string. |
277 | | /// |
278 | 0 | void SubtargetFeatures::print(raw_ostream &OS) const { |
279 | 0 | for (auto &F : Features) |
280 | 0 | OS << F << " "; |
281 | 0 | OS << "\n"; |
282 | 0 | } |
283 | | |
284 | | #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) |
285 | | /// dump - Dump feature info. |
286 | | /// |
287 | 0 | LLVM_DUMP_METHOD void SubtargetFeatures::dump() const { |
288 | 0 | } |
289 | | #endif |
290 | | |
291 | | /// Adds the default features for the specified target triple. |
292 | | /// |
293 | | /// FIXME: This is an inelegant way of specifying the features of a |
294 | | /// subtarget. It would be better if we could encode this information |
295 | | /// into the IR. See <rdar://5972456>. |
296 | | /// |
297 | 0 | void SubtargetFeatures::getDefaultSubtargetFeatures(const Triple& Triple) { |
298 | 0 | if (Triple.getVendor() == Triple::Apple) { |
299 | 0 | if (Triple.getArch() == Triple::ppc) { |
300 | | // powerpc-apple-* |
301 | 0 | AddFeature("altivec"); |
302 | 0 | } else if (Triple.getArch() == Triple::ppc64) { |
303 | | // powerpc64-apple-* |
304 | 0 | AddFeature("64bit"); |
305 | 0 | AddFeature("altivec"); |
306 | 0 | } |
307 | 0 | } |
308 | 0 | } |