LLVM API Documentation
00001 //===- SubtargetFeature.cpp - CPU characteristics Implementation ----------===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file implements the SubtargetFeature interface. 00011 // 00012 //===----------------------------------------------------------------------===// 00013 00014 #include "llvm/Target/SubtargetFeature.h" 00015 #include "llvm/ADT/StringExtras.h" 00016 #include "llvm/Support/Streams.h" 00017 #include <algorithm> 00018 #include <ostream> 00019 #include <cassert> 00020 #include <cctype> 00021 using namespace llvm; 00022 00023 //===----------------------------------------------------------------------===// 00024 // Static Helper Functions 00025 //===----------------------------------------------------------------------===// 00026 00027 /// hasFlag - Determine if a feature has a flag; '+' or '-' 00028 /// 00029 static inline bool hasFlag(const std::string &Feature) { 00030 assert(!Feature.empty() && "Empty string"); 00031 // Get first character 00032 char Ch = Feature[0]; 00033 // Check if first character is '+' or '-' flag 00034 return Ch == '+' || Ch =='-'; 00035 } 00036 00037 /// StripFlag - Return string stripped of flag. 00038 /// 00039 static inline std::string StripFlag(const std::string &Feature) { 00040 return hasFlag(Feature) ? Feature.substr(1) : Feature; 00041 } 00042 00043 /// isEnabled - Return true if enable flag; '+'. 00044 /// 00045 static inline bool isEnabled(const std::string &Feature) { 00046 assert(!Feature.empty() && "Empty string"); 00047 // Get first character 00048 char Ch = Feature[0]; 00049 // Check if first character is '+' for enabled 00050 return Ch == '+'; 00051 } 00052 00053 /// PrependFlag - Return a string with a prepended flag; '+' or '-'. 00054 /// 00055 static inline std::string PrependFlag(const std::string &Feature, 00056 bool IsEnabled) { 00057 assert(!Feature.empty() && "Empty string"); 00058 if (hasFlag(Feature)) return Feature; 00059 return std::string(IsEnabled ? "+" : "-") + Feature; 00060 } 00061 00062 /// Split - Splits a string of comma separated items in to a vector of strings. 00063 /// 00064 static void Split(std::vector<std::string> &V, const std::string &S) { 00065 // Start at beginning of string. 00066 size_t Pos = 0; 00067 while (true) { 00068 // Find the next comma 00069 size_t Comma = S.find(',', Pos); 00070 // If no comma found then the the rest of the string is used 00071 if (Comma == std::string::npos) { 00072 // Add string to vector 00073 V.push_back(S.substr(Pos)); 00074 break; 00075 } 00076 // Otherwise add substring to vector 00077 V.push_back(S.substr(Pos, Comma - Pos)); 00078 // Advance to next item 00079 Pos = Comma + 1; 00080 } 00081 } 00082 00083 /// Join a vector of strings to a string with a comma separating each element. 00084 /// 00085 static std::string Join(const std::vector<std::string> &V) { 00086 // Start with empty string. 00087 std::string Result; 00088 // If the vector is not empty 00089 if (!V.empty()) { 00090 // Start with the CPU feature 00091 Result = V[0]; 00092 // For each successive feature 00093 for (size_t i = 1; i < V.size(); i++) { 00094 // Add a comma 00095 Result += ","; 00096 // Add the feature 00097 Result += V[i]; 00098 } 00099 } 00100 // Return the features string 00101 return Result; 00102 } 00103 00104 /// Adding features. 00105 void SubtargetFeatures::AddFeature(const std::string &String, 00106 bool IsEnabled) { 00107 // Don't add empty features 00108 if (!String.empty()) { 00109 // Convert to lowercase, prepend flag and add to vector 00110 Features.push_back(PrependFlag(LowercaseString(String), IsEnabled)); 00111 } 00112 } 00113 00114 /// Find KV in array using binary search. 00115 template<typename T> const T *Find(const std::string &S, const T *A, size_t L) { 00116 // Make the lower bound element we're looking for 00117 T KV; 00118 KV.Key = S.c_str(); 00119 // Determine the end of the array 00120 const T *Hi = A + L; 00121 // Binary search the array 00122 const T *F = std::lower_bound(A, Hi, KV); 00123 // If not found then return NULL 00124 if (F == Hi || std::string(F->Key) != S) return NULL; 00125 // Return the found array item 00126 return F; 00127 } 00128 00129 /// getLongestEntryLength - Return the length of the longest entry in the table. 00130 /// 00131 static size_t getLongestEntryLength(const SubtargetFeatureKV *Table, 00132 size_t Size) { 00133 size_t MaxLen = 0; 00134 for (size_t i = 0; i < Size; i++) 00135 MaxLen = std::max(MaxLen, std::strlen(Table[i].Key)); 00136 return MaxLen; 00137 } 00138 00139 /// Display help for feature choices. 00140 /// 00141 static void Help(const SubtargetFeatureKV *CPUTable, size_t CPUTableSize, 00142 const SubtargetFeatureKV *FeatTable, size_t FeatTableSize) { 00143 // Determine the length of the longest CPU and Feature entries. 00144 unsigned MaxCPULen = getLongestEntryLength(CPUTable, CPUTableSize); 00145 unsigned MaxFeatLen = getLongestEntryLength(FeatTable, FeatTableSize); 00146 00147 // Print the CPU table. 00148 cerr << "Available CPUs for this target:\n\n"; 00149 for (size_t i = 0; i != CPUTableSize; i++) 00150 cerr << " " << CPUTable[i].Key 00151 << std::string(MaxCPULen - std::strlen(CPUTable[i].Key), ' ') 00152 << " - " << CPUTable[i].Desc << ".\n"; 00153 cerr << "\n"; 00154 00155 // Print the Feature table. 00156 cerr << "Available features for this target:\n\n"; 00157 for (size_t i = 0; i != FeatTableSize; i++) 00158 cerr << " " << FeatTable[i].Key 00159 << std::string(MaxFeatLen - std::strlen(FeatTable[i].Key), ' ') 00160 << " - " << FeatTable[i].Desc << ".\n"; 00161 cerr << "\n"; 00162 00163 cerr << "Use +feature to enable a feature, or -feature to disable it.\n" 00164 << "For example, llc -mcpu=mycpu -mattr=+feature1,-feature2\n"; 00165 exit(1); 00166 } 00167 00168 //===----------------------------------------------------------------------===// 00169 // SubtargetFeatures Implementation 00170 //===----------------------------------------------------------------------===// 00171 00172 SubtargetFeatures::SubtargetFeatures(const std::string &Initial) { 00173 // Break up string into separate features 00174 Split(Features, Initial); 00175 } 00176 00177 00178 std::string SubtargetFeatures::getString() const { 00179 return Join(Features); 00180 } 00181 void SubtargetFeatures::setString(const std::string &Initial) { 00182 // Throw out old features 00183 Features.clear(); 00184 // Break up string into separate features 00185 Split(Features, LowercaseString(Initial)); 00186 } 00187 00188 00189 /// setCPU - Set the CPU string. Replaces previous setting. Setting to "" 00190 /// clears CPU. 00191 void SubtargetFeatures::setCPU(const std::string &String) { 00192 Features[0] = LowercaseString(String); 00193 } 00194 00195 00196 /// setCPUIfNone - Setting CPU string only if no string is set. 00197 /// 00198 void SubtargetFeatures::setCPUIfNone(const std::string &String) { 00199 if (Features[0].empty()) setCPU(String); 00200 } 00201 00202 /// SetImpliedBits - For each feature that is (transitively) implied by this 00203 /// feature, set it. 00204 /// 00205 static 00206 void SetImpliedBits(uint32_t &Bits, const SubtargetFeatureKV *FeatureEntry, 00207 const SubtargetFeatureKV *FeatureTable, 00208 size_t FeatureTableSize) { 00209 for (size_t i = 0; i < FeatureTableSize; ++i) { 00210 const SubtargetFeatureKV &FE = FeatureTable[i]; 00211 00212 if (FeatureEntry->Value == FE.Value) continue; 00213 00214 if (FeatureEntry->Implies & FE.Value) { 00215 Bits |= FE.Value; 00216 SetImpliedBits(Bits, &FE, FeatureTable, FeatureTableSize); 00217 } 00218 } 00219 } 00220 00221 /// ClearImpliedBits - For each feature that (transitively) implies this 00222 /// feature, clear it. 00223 /// 00224 static 00225 void ClearImpliedBits(uint32_t &Bits, const SubtargetFeatureKV *FeatureEntry, 00226 const SubtargetFeatureKV *FeatureTable, 00227 size_t FeatureTableSize) { 00228 for (size_t i = 0; i < FeatureTableSize; ++i) { 00229 const SubtargetFeatureKV &FE = FeatureTable[i]; 00230 00231 if (FeatureEntry->Value == FE.Value) continue; 00232 00233 if (FE.Implies & FeatureEntry->Value) { 00234 Bits &= ~FE.Value; 00235 ClearImpliedBits(Bits, &FE, FeatureTable, FeatureTableSize); 00236 } 00237 } 00238 } 00239 00240 /// getBits - Get feature bits. 00241 /// 00242 uint32_t SubtargetFeatures::getBits(const SubtargetFeatureKV *CPUTable, 00243 size_t CPUTableSize, 00244 const SubtargetFeatureKV *FeatureTable, 00245 size_t FeatureTableSize) { 00246 assert(CPUTable && "missing CPU table"); 00247 assert(FeatureTable && "missing features table"); 00248 #ifndef NDEBUG 00249 for (size_t i = 1; i < CPUTableSize; i++) { 00250 assert(strcmp(CPUTable[i - 1].Key, CPUTable[i].Key) < 0 && 00251 "CPU table is not sorted"); 00252 } 00253 for (size_t i = 1; i < FeatureTableSize; i++) { 00254 assert(strcmp(FeatureTable[i - 1].Key, FeatureTable[i].Key) < 0 && 00255 "CPU features table is not sorted"); 00256 } 00257 #endif 00258 uint32_t Bits = 0; // Resulting bits 00259 00260 // Check if help is needed 00261 if (Features[0] == "help") 00262 Help(CPUTable, CPUTableSize, FeatureTable, FeatureTableSize); 00263 00264 // Find CPU entry 00265 const SubtargetFeatureKV *CPUEntry = 00266 Find(Features[0], CPUTable, CPUTableSize); 00267 // If there is a match 00268 if (CPUEntry) { 00269 // Set base feature bits 00270 Bits = CPUEntry->Value; 00271 00272 // Set the feature implied by this CPU feature, if any. 00273 for (size_t i = 0; i < FeatureTableSize; ++i) { 00274 const SubtargetFeatureKV &FE = FeatureTable[i]; 00275 if (CPUEntry->Value & FE.Value) 00276 SetImpliedBits(Bits, &FE, FeatureTable, FeatureTableSize); 00277 } 00278 } else { 00279 cerr << "'" << Features[0] 00280 << "' is not a recognized processor for this target" 00281 << " (ignoring processor)" 00282 << "\n"; 00283 } 00284 // Iterate through each feature 00285 for (size_t i = 1; i < Features.size(); i++) { 00286 const std::string &Feature = Features[i]; 00287 00288 // Check for help 00289 if (Feature == "+help") 00290 Help(CPUTable, CPUTableSize, FeatureTable, FeatureTableSize); 00291 00292 // Find feature in table. 00293 const SubtargetFeatureKV *FeatureEntry = 00294 Find(StripFlag(Feature), FeatureTable, FeatureTableSize); 00295 // If there is a match 00296 if (FeatureEntry) { 00297 // Enable/disable feature in bits 00298 if (isEnabled(Feature)) { 00299 Bits |= FeatureEntry->Value; 00300 00301 // For each feature that this implies, set it. 00302 SetImpliedBits(Bits, FeatureEntry, FeatureTable, FeatureTableSize); 00303 } else { 00304 Bits &= ~FeatureEntry->Value; 00305 00306 // For each feature that implies this, clear it. 00307 ClearImpliedBits(Bits, FeatureEntry, FeatureTable, FeatureTableSize); 00308 } 00309 } else { 00310 cerr << "'" << Feature 00311 << "' is not a recognized feature for this target" 00312 << " (ignoring feature)" 00313 << "\n"; 00314 } 00315 } 00316 00317 return Bits; 00318 } 00319 00320 /// Get info pointer 00321 void *SubtargetFeatures::getInfo(const SubtargetInfoKV *Table, 00322 size_t TableSize) { 00323 assert(Table && "missing table"); 00324 #ifndef NDEBUG 00325 for (size_t i = 1; i < TableSize; i++) { 00326 assert(strcmp(Table[i - 1].Key, Table[i].Key) < 0 && "Table is not sorted"); 00327 } 00328 #endif 00329 00330 // Find entry 00331 const SubtargetInfoKV *Entry = Find(Features[0], Table, TableSize); 00332 00333 if (Entry) { 00334 return Entry->Value; 00335 } else { 00336 cerr << "'" << Features[0] 00337 << "' is not a recognized processor for this target" 00338 << " (ignoring processor)" 00339 << "\n"; 00340 return NULL; 00341 } 00342 } 00343 00344 /// print - Print feature string. 00345 /// 00346 void SubtargetFeatures::print(std::ostream &OS) const { 00347 for (size_t i = 0; i < Features.size(); i++) { 00348 OS << Features[i] << " "; 00349 } 00350 OS << "\n"; 00351 } 00352 00353 /// dump - Dump feature info. 00354 /// 00355 void SubtargetFeatures::dump() const { 00356 print(*cerr.stream()); 00357 }