LLVM API Documentation

SubtargetFeature.cpp

Go to the documentation of this file.
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 }