Print:
[oota-llvm.git] / lib / Target / SubtargetFeature.cpp
1 //===- 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>
20 #include <cctype>
21
22 using namespace llvm;
23
24 /// Splits a string of comma separated items in to a vector of strings.
25 void 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.
46 std::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.
66 std::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.
79 void 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.
89 const SubtargetFeatureKV *
90 SubtargetFeatures::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
102 /// Display help for feature choices.
103 void 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
125 /// Parse feature string for quick usage.
126 uint32_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;
150   // Check for help
151   if (Features[0] == "help") Help("CPU", CPUTable, CPUTableSize);
152   // 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 {
160     std::cerr << "'" << Features[0]
161               << "' is not a recognized processor for this target"
162               << " (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];
169     // Check for help
170     if (Feature == "+help") Help("feature", FeatureTable, FeatureTableSize);
171     // 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 {
180       std::cerr << "'" << Feature
181                 << "' is not a recognized feature for this target"
182                 << " (ignoring feature)"
183                 << "\n";
184     }
185   }
186   return Bits;
187 }
188
189 /// Print feature string.
190 void 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.
198 void SubtargetFeatures::dump() const {
199   print(std::cerr);
200 }