aboutsummaryrefslogtreecommitdiffstats
path: root/lib/Target/SubtargetFeature.cpp
blob: 1583f4e43b661b8c28b4edf9422e3f7e5bc2e00c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
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>
#include <cctype>

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