aboutsummaryrefslogtreecommitdiff
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)
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);
+}