blob: 29afeff87783eb357cebff308f29b7356cc8e782 [file] [log] [blame]
Jim Laskeyb3302db2005-09-01 21:36:18 +00001//===- SubtargetFeature.cpp - CPU characteristics Implementation ----------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file was developed by Jim Laskey and is distributed under the
6// University of Illinois Open Source License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file implements the SubtargetFeature interface.
11//
12//===----------------------------------------------------------------------===//
13
14#include "llvm/Target/SubtargetFeature.h"
15
16#include <string>
17#include <algorithm>
18#include <vector>
19#include <cassert>
Jeff Cohen7cd57f42005-09-02 02:51:42 +000020#include <cctype>
Jim Laskeyb3302db2005-09-01 21:36:18 +000021
22using namespace llvm;
23
24/// Splits a string of comma separated items in to a vector of strings.
25void SubtargetFeatures::Split(std::vector<std::string> &V,
26 const std::string &S) {
27 // Start at beginning of string.
28 size_t Pos = 0;
29 while (true) {
30 // Find the next comma
31 size_t Comma = S.find(',', Pos);
32 // If no comma found then the the rest of the string is used
33 if (Comma == std::string::npos) {
34 // Add string to vector
35 V.push_back(S.substr(Pos));
36 break;
37 }
38 // Otherwise add substring to vector
39 V.push_back(S.substr(Pos, Comma - Pos));
40 // Advance to next item
41 Pos = Comma + 1;
42 }
43}
44
45/// Join a vector of strings to a string with a comma separating each element.
46std::string SubtargetFeatures::Join(const std::vector<std::string> &V) {
47 // Start with empty string.
48 std::string Result;
49 // If the vector is not empty
50 if (!V.empty()) {
51 // Start with the CPU feature
52 Result = V[0];
53 // For each successive feature
54 for (size_t i = 1; i < V.size(); i++) {
55 // Add a comma
56 Result += ",";
57 // Add the feature
58 Result += V[i];
59 }
60 }
61 // Return the features string
62 return Result;
63}
64
65/// Convert a string to lowercase.
66std::string SubtargetFeatures::toLower(const std::string &S) {
67 // Copy the string
68 std::string Result = S;
69 // For each character in string
70 for (size_t i = 0; i < Result.size(); i++) {
71 // Convert character to lowercase
72 Result[i] = std::tolower(Result[i]);
73 }
74 // Return the lowercased string
75 return Result;
76}
77
78/// Adding features.
79void SubtargetFeatures::AddFeature(const std::string &String,
80 bool IsEnabled) {
81 // Don't add empty features
82 if (!String.empty()) {
83 // Convert to lowercase, prepend flag and add to vector
84 Features.push_back(PrependFlag(toLower(String), IsEnabled));
85 }
86}
87
88/// Find item in array using binary search.
89const SubtargetFeatureKV *
90SubtargetFeatures::Find(const std::string &S,
91 const SubtargetFeatureKV *A, size_t L) {
92 // Determine the end of the array
93 const SubtargetFeatureKV *Hi = A + L;
94 // Binary search the array
95 const SubtargetFeatureKV *F = std::lower_bound(A, Hi, S);
96 // If not found then return NULL
97 if (F == Hi || std::string(F->Key) != S) return NULL;
98 // Return the found array item
99 return F;
100}
101
Jim Laskey839615a2005-09-02 19:27:43 +0000102/// Display help for feature choices.
103void SubtargetFeatures::Help(const char *Heading,
104 const SubtargetFeatureKV *Table, size_t TableSize) {
105 // Determine the length of the longest key
106 size_t MaxLen = 0;
107 for (size_t i = 0; i < TableSize; i++)
108 MaxLen = std::max(MaxLen, std::strlen(Table[i].Key));
109 // Print heading
110 std::cerr << "Help for " << Heading << " choices\n\n";
111 // For each feature
112 for (size_t i = 0; i < TableSize; i++) {
113 // Compute required padding
114 size_t Pad = MaxLen - std::strlen(Table[i].Key) + 1;
115 // Print details
116 std::cerr << Table[i].Key << std::string(Pad, ' ') << " - "
117 << Table[i].Desc << "\n";
118 }
119 // Wrap it up
120 std::cerr << "\n\n";
121 // Leave tool
122 exit(1);
123}
124
Jim Laskeyb3302db2005-09-01 21:36:18 +0000125/// Parse feature string for quick usage.
126uint32_t SubtargetFeatures::Parse(const std::string &String,
127 const std::string &DefaultCPU,
128 const SubtargetFeatureKV *CPUTable,
129 size_t CPUTableSize,
130 const SubtargetFeatureKV *FeatureTable,
131 size_t FeatureTableSize) {
132 assert(CPUTable && "missing CPU table");
133 assert(FeatureTable && "missing features table");
134#ifndef NDEBUG
135 for (size_t i = 1; i < CPUTableSize; i++) {
136 assert(strcmp(CPUTable[i - 1].Key, CPUTable[i].Key) < 0 &&
137 "CPU table is not sorted");
138 }
139 for (size_t i = 1; i < FeatureTableSize; i++) {
140 assert(strcmp(FeatureTable[i - 1].Key, FeatureTable[i].Key) < 0 &&
141 "CPU features table is not sorted");
142 }
143#endif
144 std::vector<std::string> Features; // Subtarget features as a vector
145 uint32_t Bits = 0; // Resulting bits
146 // Split up features
147 Split(Features, String);
148 // Check if default is needed
149 if (Features[0].empty()) Features[0] = DefaultCPU;
Jim Laskey839615a2005-09-02 19:27:43 +0000150 // Check for help
151 if (Features[0] == "help") Help("CPU", CPUTable, CPUTableSize);
Jim Laskeyb3302db2005-09-01 21:36:18 +0000152 // Find CPU entry
153 const SubtargetFeatureKV *CPUEntry =
154 Find(Features[0], CPUTable, CPUTableSize);
155 // If there is a match
156 if (CPUEntry) {
157 // Set base feature bits
158 Bits = CPUEntry->Value;
159 } else {
Chris Lattner3eb33692005-09-07 05:44:14 +0000160 std::cerr << "'" << Features[0]
161 << "' is not a recognized processor for this target"
Jim Laskeyb3302db2005-09-01 21:36:18 +0000162 << " (ignoring processor)"
163 << "\n";
164 }
165 // Iterate through each feature
166 for (size_t i = 1; i < Features.size(); i++) {
167 // Get next feature
168 const std::string &Feature = Features[i];
Jim Laskey839615a2005-09-02 19:27:43 +0000169 // Check for help
170 if (Feature == "+help") Help("feature", FeatureTable, FeatureTableSize);
Jim Laskeyb3302db2005-09-01 21:36:18 +0000171 // Find feature in table.
172 const SubtargetFeatureKV *FeatureEntry =
173 Find(StripFlag(Feature), FeatureTable, FeatureTableSize);
174 // If there is a match
175 if (FeatureEntry) {
176 // Enable/disable feature in bits
177 if (isEnabled(Feature)) Bits |= FeatureEntry->Value;
178 else Bits &= ~FeatureEntry->Value;
179 } else {
Chris Lattner3eb33692005-09-07 05:44:14 +0000180 std::cerr << "'" << Feature
181 << "' is not a recognized feature for this target"
Jim Laskeyb3302db2005-09-01 21:36:18 +0000182 << " (ignoring feature)"
183 << "\n";
184 }
185 }
186 return Bits;
187}
188
189/// Print feature string.
190void SubtargetFeatures::print(std::ostream &OS) const {
191 for (size_t i = 0; i < Features.size(); i++) {
192 OS << Features[i] << " ";
193 }
194 OS << "\n";
195}
196
197/// Dump feature info.
198void SubtargetFeatures::dump() const {
199 print(std::cerr);
200}