summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJim Laskey <jlaskey@mac.com>2005-09-01 21:36:18 +0000
committerJim Laskey <jlaskey@mac.com>2005-09-01 21:36:18 +0000
commitb3302db18a779527a4b1cd7a2024543ade7e83c6 (patch)
tree0af07d0ca38b72d0a0d34e8bf5b92f15df213335
parent75592e4137c3ae7800e1fb8736db28a65bb3c94d (diff)
downloadllvm-b3302db18a779527a4b1cd7a2024543ade7e83c6.tar.gz
llvm-b3302db18a779527a4b1cd7a2024543ade7e83c6.tar.bz2
llvm-b3302db18a779527a4b1cd7a2024543ade7e83c6.tar.xz
This new class provides support for platform specific "features". The intent
is to manage processor specific attributes from the command line. See examples of use in llc/lli and PowerPCTargetSubtarget. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23191 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/llvm/Target/SubtargetFeature.h145
-rw-r--r--lib/Target/SubtargetFeature.cpp173
2 files changed, 318 insertions, 0 deletions
diff --git a/include/llvm/Target/SubtargetFeature.h b/include/llvm/Target/SubtargetFeature.h
new file mode 100644
index 0000000000..43200a27a1
--- /dev/null
+++ b/include/llvm/Target/SubtargetFeature.h
@@ -0,0 +1,145 @@
+//===-- llvm/Target/SubtargetFeature.h - CPU characteristics ----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file was developed by Jim Laskey and is distributed under the
+// University of Illinois Open Source License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines and manages user or tool specified CPU characteristics.
+// The intent is to be able to package specific features that should or should
+// not be used on a specific target processor. A tool, such as llc, could, as
+// as example, gather chip info from the command line, a long with features
+// that should be used on that chip.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TARGET_SUBTARGETFEATURE_H
+#define LLVM_TARGET_SUBTARGETFEATURE_H
+
+
+#include <string>
+#include <vector>
+#include <iostream>
+#include <cassert>
+
+namespace llvm {
+
+//===----------------------------------------------------------------------===//
+///
+/// SubtargetFeatureKV - Used to provide key value pairs for feature and
+/// CPU bit flags.
+//
+struct SubtargetFeatureKV {
+ const char *Key; // K-V key string
+ uint32_t Value; // K-V integer value
+
+ // Compare routine for std binary search
+ bool operator<(const std::string &S) const {
+ return strcmp(Key, S.c_str()) < 0;
+ }
+};
+
+//===----------------------------------------------------------------------===//
+///
+/// SubtargetFeatures - Manages the enabling and disabling of subtarget
+/// specific features. Features are encoded as a string of the form
+/// "cpu,+attr1,+attr2,-attr3,...,+attrN"
+/// A comma separates each feature from the next (all lowercase.)
+/// The first feature is always the CPU subtype (eg. pentiumm). If the CPU
+/// value is "generic" then the CPU subtype should be generic for the target.
+/// Each of the remaining features is prefixed with + or - indicating whether
+/// that feature should be enabled or disabled contrary to the cpu
+/// specification.
+///
+
+class SubtargetFeatures {
+private:
+ std::vector<std::string> Features; // Subtarget features as a vector
+
+ // Determine if a feature has a flag; '+' or '-'
+ static inline bool hasFlag(const std::string &Feature) {
+ assert(!Feature.empty() && "Empty string");
+ // Get first character
+ char Ch = Feature[0];
+ // Check if first character is '+' or '-' flag
+ return Ch == '+' || Ch =='-';
+ }
+
+ // Return true if enable flag; '+'.
+ static inline bool isEnabled(const std::string &Feature) {
+ assert(!Feature.empty() && "Empty string");
+ // Get first character
+ char Ch = Feature[0];
+ // Check if first character is '+' for enabled
+ return Ch == '+';
+ }
+
+ // Return a string with a prepended flag; '+' or '-'.
+ static inline std::string PrependFlag(const std::string &Feature,
+ bool IsEnabled) {
+ assert(!Feature.empty() && "Empty string");
+ if (hasFlag(Feature)) return Feature;
+ return std::string(IsEnabled ? "+" : "-") + Feature;
+ }
+
+ // Return string stripped of flag.
+ static inline std::string StripFlag(const std::string &Feature) {
+ return hasFlag(Feature) ? Feature.substr(1) : Feature;
+ }
+
+ /// Splits a string of comma separated items in to a vector of strings.
+ static void Split(std::vector<std::string> &V, const std::string &S);
+
+ /// Join a vector of strings into a string with a comma separating each
+ /// item.
+ static std::string Join(const std::vector<std::string> &V);
+
+ /// Convert a string to lowercase.
+ static std::string toLower(const std::string &S);
+
+ /// Find item in array using binary search.
+ static const SubtargetFeatureKV *Find(const std::string &S,
+ const SubtargetFeatureKV *A, size_t L);
+
+public:
+ /// Ctor.
+ SubtargetFeatures(const std::string Initial = std::string()) {
+ // Break up string into separate features
+ Split(Features, Initial);
+ }
+
+ /// Features string accessors.
+ inline std::string getString() const { return Join(Features); }
+ void setString(const std::string &Initial) {
+ // Throw out old features
+ Features.clear();
+ // Break up string into separate features
+ Split(Features, toLower(Initial));
+ }
+
+ /// Setting CPU string. Replaces previous setting. Setting to "" clears CPU.
+ void setCPU(std::string String) { Features[0] = toLower(String); }
+
+ /// Adding Features.
+ void AddFeature(const std::string &String, bool IsEnabled = true);
+
+ /// Parse feature string for quick usage.
+ static uint32_t Parse(const std::string &String,
+ const std::string &DefaultCPU,
+ const SubtargetFeatureKV *CPUTable,
+ size_t CPUTableSize,
+ const SubtargetFeatureKV *FeatureTable,
+ size_t FeatureTableSize);
+
+ /// Print feature string.
+ void print(std::ostream &OS) const;
+
+ // Dump feature info.
+ void dump() const;
+};
+
+} // End namespace llvm
+
+#endif
diff --git a/lib/Target/SubtargetFeature.cpp b/lib/Target/SubtargetFeature.cpp
new file mode 100644
index 0000000000..dc3aef2c1f
--- /dev/null
+++ b/lib/Target/SubtargetFeature.cpp
@@ -0,0 +1,173 @@
+//===- SubtargetFeature.cpp - CPU characteristics Implementation ----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file was developed by Jim Laskey and is distributed under the
+// University of Illinois Open Source License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the SubtargetFeature interface.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Target/SubtargetFeature.h"
+
+#include <string>
+#include <algorithm>
+#include <vector>
+#include <cassert>
+
+
+using namespace llvm;
+
+/// Splits a string of comma separated items in to a vector of strings.
+void SubtargetFeatures::Split(std::vector<std::string> &V,
+ const std::string &S) {
+ // Start at beginning of string.
+ size_t Pos = 0;
+ while (true) {
+ // Find the next comma
+ size_t Comma = S.find(',', Pos);
+ // If no comma found then the the rest of the string is used
+ if (Comma == std::string::npos) {
+ // Add string to vector
+ V.push_back(S.substr(Pos));
+ break;
+ }
+ // Otherwise add substring to vector
+ V.push_back(S.substr(Pos, Comma - Pos));
+ // Advance to next item
+ Pos = Comma + 1;
+ }
+}
+
+/// Join a vector of strings to a string with a comma separating each element.
+std::string SubtargetFeatures::Join(const std::vector<std::string> &V) {
+ // Start with empty string.
+ std::string Result;
+ // If the vector is not empty
+ if (!V.empty()) {
+ // Start with the CPU feature
+ Result = V[0];
+ // For each successive feature
+ for (size_t i = 1; i < V.size(); i++) {
+ // Add a comma
+ Result += ",";
+ // Add the feature
+ Result += V[i];
+ }
+ }
+ // Return the features string
+ return Result;
+}
+
+/// Convert a string to lowercase.
+std::string SubtargetFeatures::toLower(const std::string &S) {
+ // Copy the string
+ std::string Result = S;
+ // For each character in string
+ for (size_t i = 0; i < Result.size(); i++) {
+ // Convert character to lowercase
+ Result[i] = std::tolower(Result[i]);
+ }
+ // Return the lowercased string
+ return Result;
+}
+
+/// Adding features.
+void SubtargetFeatures::AddFeature(const std::string &String,
+ bool IsEnabled) {
+ // Don't add empty features
+ if (!String.empty()) {
+ // Convert to lowercase, prepend flag and add to vector
+ Features.push_back(PrependFlag(toLower(String), IsEnabled));
+ }
+}
+
+/// Find item in array using binary search.
+const SubtargetFeatureKV *
+SubtargetFeatures::Find(const std::string &S,
+ const SubtargetFeatureKV *A, size_t L) {
+ // Determine the end of the array
+ const SubtargetFeatureKV *Hi = A + L;
+ // Binary search the array
+ const SubtargetFeatureKV *F = std::lower_bound(A, Hi, S);
+ // If not found then return NULL
+ if (F == Hi || std::string(F->Key) != S) return NULL;
+ // Return the found array item
+ return F;
+}
+
+/// Parse feature string for quick usage.
+uint32_t SubtargetFeatures::Parse(const std::string &String,
+ const std::string &DefaultCPU,
+ const SubtargetFeatureKV *CPUTable,
+ size_t CPUTableSize,
+ const SubtargetFeatureKV *FeatureTable,
+ size_t FeatureTableSize) {
+ assert(CPUTable && "missing CPU table");
+ assert(FeatureTable && "missing features table");
+#ifndef NDEBUG
+ for (size_t i = 1; i < CPUTableSize; i++) {
+ assert(strcmp(CPUTable[i - 1].Key, CPUTable[i].Key) < 0 &&
+ "CPU table is not sorted");
+ }
+ for (size_t i = 1; i < FeatureTableSize; i++) {
+ assert(strcmp(FeatureTable[i - 1].Key, FeatureTable[i].Key) < 0 &&
+ "CPU features table is not sorted");
+ }
+#endif
+ std::vector<std::string> Features; // Subtarget features as a vector
+ uint32_t Bits = 0; // Resulting bits
+ // Split up features
+ Split(Features, String);
+ // Check if default is needed
+ if (Features[0].empty()) Features[0] = DefaultCPU;
+ // Find CPU entry
+ const SubtargetFeatureKV *CPUEntry =
+ Find(Features[0], CPUTable, CPUTableSize);
+ // If there is a match
+ if (CPUEntry) {
+ // Set base feature bits
+ Bits = CPUEntry->Value;
+ } else {
+ std::cerr << Features[0]
+ << " is not a recognized processor for this target"
+ << " (ignoring processor)"
+ << "\n";
+ }
+ // Iterate through each feature
+ for (size_t i = 1; i < Features.size(); i++) {
+ // Get next feature
+ const std::string &Feature = Features[i];
+ // Find feature in table.
+ const SubtargetFeatureKV *FeatureEntry =
+ Find(StripFlag(Feature), FeatureTable, FeatureTableSize);
+ // If there is a match
+ if (FeatureEntry) {
+ // Enable/disable feature in bits
+ if (isEnabled(Feature)) Bits |= FeatureEntry->Value;
+ else Bits &= ~FeatureEntry->Value;
+ } else {
+ std::cerr << Feature
+ << " is not a recognized feature for this target"
+ << " (ignoring feature)"
+ << "\n";
+ }
+ }
+ return Bits;
+}
+
+/// Print feature string.
+void SubtargetFeatures::print(std::ostream &OS) const {
+ for (size_t i = 0; i < Features.size(); i++) {
+ OS << Features[i] << " ";
+ }
+ OS << "\n";
+}
+
+/// Dump feature info.
+void SubtargetFeatures::dump() const {
+ print(std::cerr);
+}