~ubuntu-branches/ubuntu/feisty/clamav/feisty

« back to all changes in this revision

Viewing changes to libclamav/c++/llvm/lib/Target/SubtargetFeature.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Kees Cook
  • Date: 2007-02-20 10:33:44 UTC
  • mto: This revision was merged to the branch mainline in revision 16.
  • Revision ID: james.westby@ubuntu.com-20070220103344-zgcu2psnx9d98fpa
Tags: upstream-0.90
ImportĀ upstreamĀ versionĀ 0.90

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
//===- SubtargetFeature.cpp - CPU characteristics Implementation ----------===//
2
 
//
3
 
//                     The LLVM Compiler Infrastructure
4
 
//
5
 
// This file is distributed under the University of Illinois Open Source
6
 
// License. See LICENSE.TXT for details.
7
 
//
8
 
//===----------------------------------------------------------------------===//
9
 
//
10
 
// This file implements the SubtargetFeature interface.
11
 
//
12
 
//===----------------------------------------------------------------------===//
13
 
 
14
 
#include "llvm/Target/SubtargetFeature.h"
15
 
#include "llvm/Support/Debug.h"
16
 
#include "llvm/Support/raw_ostream.h"
17
 
#include "llvm/ADT/StringExtras.h"
18
 
#include <algorithm>
19
 
#include <cassert>
20
 
#include <cctype>
21
 
using namespace llvm;
22
 
 
23
 
//===----------------------------------------------------------------------===//
24
 
//                          Static Helper Functions
25
 
//===----------------------------------------------------------------------===//
26
 
 
27
 
/// hasFlag - Determine if a feature has a flag; '+' or '-'
28
 
///
29
 
static inline bool hasFlag(const std::string &Feature) {
30
 
  assert(!Feature.empty() && "Empty string");
31
 
  // Get first character
32
 
  char Ch = Feature[0];
33
 
  // Check if first character is '+' or '-' flag
34
 
  return Ch == '+' || Ch =='-';
35
 
}
36
 
 
37
 
/// StripFlag - Return string stripped of flag.
38
 
///
39
 
static inline std::string StripFlag(const std::string &Feature) {
40
 
  return hasFlag(Feature) ? Feature.substr(1) : Feature;
41
 
}
42
 
 
43
 
/// isEnabled - Return true if enable flag; '+'.
44
 
///
45
 
static inline bool isEnabled(const std::string &Feature) {
46
 
  assert(!Feature.empty() && "Empty string");
47
 
  // Get first character
48
 
  char Ch = Feature[0];
49
 
  // Check if first character is '+' for enabled
50
 
  return Ch == '+';
51
 
}
52
 
 
53
 
/// PrependFlag - Return a string with a prepended flag; '+' or '-'.
54
 
///
55
 
static inline std::string PrependFlag(const std::string &Feature,
56
 
                                      bool IsEnabled) {
57
 
  assert(!Feature.empty() && "Empty string");
58
 
  if (hasFlag(Feature)) return Feature;
59
 
  return std::string(IsEnabled ? "+" : "-") + Feature;
60
 
}
61
 
 
62
 
/// Split - Splits a string of comma separated items in to a vector of strings.
63
 
///
64
 
static void Split(std::vector<std::string> &V, const std::string &S) {
65
 
  // Start at beginning of string.
66
 
  size_t Pos = 0;
67
 
  while (true) {
68
 
    // Find the next comma
69
 
    size_t Comma = S.find(',', Pos);
70
 
    // If no comma found then the rest of the string is used
71
 
    if (Comma == std::string::npos) {
72
 
      // Add string to vector
73
 
      V.push_back(S.substr(Pos));
74
 
      break;
75
 
    }
76
 
    // Otherwise add substring to vector
77
 
    V.push_back(S.substr(Pos, Comma - Pos));
78
 
    // Advance to next item
79
 
    Pos = Comma + 1;
80
 
  }
81
 
}
82
 
 
83
 
/// Join a vector of strings to a string with a comma separating each element.
84
 
///
85
 
static std::string Join(const std::vector<std::string> &V) {
86
 
  // Start with empty string.
87
 
  std::string Result;
88
 
  // If the vector is not empty 
89
 
  if (!V.empty()) {
90
 
    // Start with the CPU feature
91
 
    Result = V[0];
92
 
    // For each successive feature
93
 
    for (size_t i = 1; i < V.size(); i++) {
94
 
      // Add a comma
95
 
      Result += ",";
96
 
      // Add the feature
97
 
      Result += V[i];
98
 
    }
99
 
  }
100
 
  // Return the features string 
101
 
  return Result;
102
 
}
103
 
 
104
 
/// Adding features.
105
 
void SubtargetFeatures::AddFeature(const std::string &String,
106
 
                                   bool IsEnabled) {
107
 
  // Don't add empty features
108
 
  if (!String.empty()) {
109
 
    // Convert to lowercase, prepend flag and add to vector
110
 
    Features.push_back(PrependFlag(LowercaseString(String), IsEnabled));
111
 
  }
112
 
}
113
 
 
114
 
/// Find KV in array using binary search.
115
 
template<typename T> const T *Find(const std::string &S, const T *A, size_t L) {
116
 
  // Make the lower bound element we're looking for
117
 
  T KV;
118
 
  KV.Key = S.c_str();
119
 
  // Determine the end of the array
120
 
  const T *Hi = A + L;
121
 
  // Binary search the array
122
 
  const T *F = std::lower_bound(A, Hi, KV);
123
 
  // If not found then return NULL
124
 
  if (F == Hi || std::string(F->Key) != S) return NULL;
125
 
  // Return the found array item
126
 
  return F;
127
 
}
128
 
 
129
 
/// getLongestEntryLength - Return the length of the longest entry in the table.
130
 
///
131
 
static size_t getLongestEntryLength(const SubtargetFeatureKV *Table,
132
 
                                    size_t Size) {
133
 
  size_t MaxLen = 0;
134
 
  for (size_t i = 0; i < Size; i++)
135
 
    MaxLen = std::max(MaxLen, std::strlen(Table[i].Key));
136
 
  return MaxLen;
137
 
}
138
 
 
139
 
/// Display help for feature choices.
140
 
///
141
 
static void Help(const SubtargetFeatureKV *CPUTable, size_t CPUTableSize,
142
 
                 const SubtargetFeatureKV *FeatTable, size_t FeatTableSize) {
143
 
  // Determine the length of the longest CPU and Feature entries.
144
 
  unsigned MaxCPULen  = getLongestEntryLength(CPUTable, CPUTableSize);
145
 
  unsigned MaxFeatLen = getLongestEntryLength(FeatTable, FeatTableSize);
146
 
 
147
 
  // Print the CPU table.
148
 
  errs() << "Available CPUs for this target:\n\n";
149
 
  for (size_t i = 0; i != CPUTableSize; i++)
150
 
    errs() << "  " << CPUTable[i].Key
151
 
         << std::string(MaxCPULen - std::strlen(CPUTable[i].Key), ' ')
152
 
         << " - " << CPUTable[i].Desc << ".\n";
153
 
  errs() << "\n";
154
 
  
155
 
  // Print the Feature table.
156
 
  errs() << "Available features for this target:\n\n";
157
 
  for (size_t i = 0; i != FeatTableSize; i++)
158
 
    errs() << "  " << FeatTable[i].Key
159
 
         << std::string(MaxFeatLen - std::strlen(FeatTable[i].Key), ' ')
160
 
         << " - " << FeatTable[i].Desc << ".\n";
161
 
  errs() << "\n";
162
 
  
163
 
  errs() << "Use +feature to enable a feature, or -feature to disable it.\n"
164
 
       << "For example, llc -mcpu=mycpu -mattr=+feature1,-feature2\n";
165
 
  exit(1);
166
 
}
167
 
 
168
 
//===----------------------------------------------------------------------===//
169
 
//                    SubtargetFeatures Implementation
170
 
//===----------------------------------------------------------------------===//
171
 
 
172
 
SubtargetFeatures::SubtargetFeatures(const std::string &Initial) {
173
 
  // Break up string into separate features
174
 
  Split(Features, Initial);
175
 
}
176
 
 
177
 
 
178
 
std::string SubtargetFeatures::getString() const {
179
 
  return Join(Features);
180
 
}
181
 
void SubtargetFeatures::setString(const std::string &Initial) {
182
 
  // Throw out old features
183
 
  Features.clear();
184
 
  // Break up string into separate features
185
 
  Split(Features, LowercaseString(Initial));
186
 
}
187
 
 
188
 
 
189
 
/// setCPU - Set the CPU string.  Replaces previous setting.  Setting to ""
190
 
/// clears CPU.
191
 
void SubtargetFeatures::setCPU(const std::string &String) {
192
 
  Features[0] = LowercaseString(String);
193
 
}
194
 
 
195
 
 
196
 
/// setCPUIfNone - Setting CPU string only if no string is set.
197
 
///
198
 
void SubtargetFeatures::setCPUIfNone(const std::string &String) {
199
 
  if (Features[0].empty()) setCPU(String);
200
 
}
201
 
 
202
 
/// getCPU - Returns current CPU.
203
 
///
204
 
const std::string & SubtargetFeatures::getCPU() const {
205
 
  return Features[0];
206
 
}
207
 
 
208
 
 
209
 
/// SetImpliedBits - For each feature that is (transitively) implied by this
210
 
/// feature, set it.
211
 
///
212
 
static
213
 
void SetImpliedBits(uint32_t &Bits, const SubtargetFeatureKV *FeatureEntry,
214
 
                    const SubtargetFeatureKV *FeatureTable,
215
 
                    size_t FeatureTableSize) {
216
 
  for (size_t i = 0; i < FeatureTableSize; ++i) {
217
 
    const SubtargetFeatureKV &FE = FeatureTable[i];
218
 
 
219
 
    if (FeatureEntry->Value == FE.Value) continue;
220
 
 
221
 
    if (FeatureEntry->Implies & FE.Value) {
222
 
      Bits |= FE.Value;
223
 
      SetImpliedBits(Bits, &FE, FeatureTable, FeatureTableSize);
224
 
    }
225
 
  }
226
 
}
227
 
 
228
 
/// ClearImpliedBits - For each feature that (transitively) implies this
229
 
/// feature, clear it.
230
 
/// 
231
 
static
232
 
void ClearImpliedBits(uint32_t &Bits, const SubtargetFeatureKV *FeatureEntry,
233
 
                      const SubtargetFeatureKV *FeatureTable,
234
 
                      size_t FeatureTableSize) {
235
 
  for (size_t i = 0; i < FeatureTableSize; ++i) {
236
 
    const SubtargetFeatureKV &FE = FeatureTable[i];
237
 
 
238
 
    if (FeatureEntry->Value == FE.Value) continue;
239
 
 
240
 
    if (FE.Implies & FeatureEntry->Value) {
241
 
      Bits &= ~FE.Value;
242
 
      ClearImpliedBits(Bits, &FE, FeatureTable, FeatureTableSize);
243
 
    }
244
 
  }
245
 
}
246
 
 
247
 
/// getBits - Get feature bits.
248
 
///
249
 
uint32_t SubtargetFeatures::getBits(const SubtargetFeatureKV *CPUTable,
250
 
                                          size_t CPUTableSize,
251
 
                                    const SubtargetFeatureKV *FeatureTable,
252
 
                                          size_t FeatureTableSize) {
253
 
  assert(CPUTable && "missing CPU table");
254
 
  assert(FeatureTable && "missing features table");
255
 
#ifndef NDEBUG
256
 
  for (size_t i = 1; i < CPUTableSize; i++) {
257
 
    assert(strcmp(CPUTable[i - 1].Key, CPUTable[i].Key) < 0 &&
258
 
           "CPU table is not sorted");
259
 
  }
260
 
  for (size_t i = 1; i < FeatureTableSize; i++) {
261
 
    assert(strcmp(FeatureTable[i - 1].Key, FeatureTable[i].Key) < 0 &&
262
 
          "CPU features table is not sorted");
263
 
  }
264
 
#endif
265
 
  uint32_t Bits = 0;                    // Resulting bits
266
 
 
267
 
  // Check if help is needed
268
 
  if (Features[0] == "help")
269
 
    Help(CPUTable, CPUTableSize, FeatureTable, FeatureTableSize);
270
 
  
271
 
  // Find CPU entry
272
 
  const SubtargetFeatureKV *CPUEntry =
273
 
                            Find(Features[0], CPUTable, CPUTableSize);
274
 
  // If there is a match
275
 
  if (CPUEntry) {
276
 
    // Set base feature bits
277
 
    Bits = CPUEntry->Value;
278
 
 
279
 
    // Set the feature implied by this CPU feature, if any.
280
 
    for (size_t i = 0; i < FeatureTableSize; ++i) {
281
 
      const SubtargetFeatureKV &FE = FeatureTable[i];
282
 
      if (CPUEntry->Value & FE.Value)
283
 
        SetImpliedBits(Bits, &FE, FeatureTable, FeatureTableSize);
284
 
    }
285
 
  } else {
286
 
    errs() << "'" << Features[0]
287
 
           << "' is not a recognized processor for this target"
288
 
           << " (ignoring processor)\n";
289
 
  }
290
 
  // Iterate through each feature
291
 
  for (size_t i = 1; i < Features.size(); i++) {
292
 
    const std::string &Feature = Features[i];
293
 
    
294
 
    // Check for help
295
 
    if (Feature == "+help")
296
 
      Help(CPUTable, CPUTableSize, FeatureTable, FeatureTableSize);
297
 
    
298
 
    // Find feature in table.
299
 
    const SubtargetFeatureKV *FeatureEntry =
300
 
                       Find(StripFlag(Feature), FeatureTable, FeatureTableSize);
301
 
    // If there is a match
302
 
    if (FeatureEntry) {
303
 
      // Enable/disable feature in bits
304
 
      if (isEnabled(Feature)) {
305
 
        Bits |=  FeatureEntry->Value;
306
 
 
307
 
        // For each feature that this implies, set it.
308
 
        SetImpliedBits(Bits, FeatureEntry, FeatureTable, FeatureTableSize);
309
 
      } else {
310
 
        Bits &= ~FeatureEntry->Value;
311
 
 
312
 
        // For each feature that implies this, clear it.
313
 
        ClearImpliedBits(Bits, FeatureEntry, FeatureTable, FeatureTableSize);
314
 
      }
315
 
    } else {
316
 
      errs() << "'" << Feature
317
 
             << "' is not a recognized feature for this target"
318
 
             << " (ignoring feature)\n";
319
 
    }
320
 
  }
321
 
 
322
 
  return Bits;
323
 
}
324
 
 
325
 
/// Get info pointer
326
 
void *SubtargetFeatures::getInfo(const SubtargetInfoKV *Table,
327
 
                                       size_t TableSize) {
328
 
  assert(Table && "missing table");
329
 
#ifndef NDEBUG
330
 
  for (size_t i = 1; i < TableSize; i++) {
331
 
    assert(strcmp(Table[i - 1].Key, Table[i].Key) < 0 && "Table is not sorted");
332
 
  }
333
 
#endif
334
 
 
335
 
  // Find entry
336
 
  const SubtargetInfoKV *Entry = Find(Features[0], Table, TableSize);
337
 
  
338
 
  if (Entry) {
339
 
    return Entry->Value;
340
 
  } else {
341
 
    errs() << "'" << Features[0]
342
 
           << "' is not a recognized processor for this target"
343
 
           << " (ignoring processor)\n";
344
 
    return NULL;
345
 
  }
346
 
}
347
 
 
348
 
/// print - Print feature string.
349
 
///
350
 
void SubtargetFeatures::print(raw_ostream &OS) const {
351
 
  for (size_t i = 0, e = Features.size(); i != e; ++i)
352
 
    OS << Features[i] << "  ";
353
 
  OS << "\n";
354
 
}
355
 
 
356
 
/// dump - Dump feature info.
357
 
///
358
 
void SubtargetFeatures::dump() const {
359
 
  print(dbgs());
360
 
}
361
 
 
362
 
/// getDefaultSubtargetFeatures - Return a string listing the features
363
 
/// associated with the target triple.
364
 
///
365
 
/// FIXME: This is an inelegant way of specifying the features of a
366
 
/// subtarget. It would be better if we could encode this information
367
 
/// into the IR. See <rdar://5972456>.
368
 
///
369
 
void SubtargetFeatures::getDefaultSubtargetFeatures(const std::string &CPU,
370
 
                                                    const Triple& Triple) {
371
 
  setCPU(CPU);
372
 
 
373
 
  if (Triple.getVendor() == Triple::Apple) {
374
 
    if (Triple.getArch() == Triple::ppc) {
375
 
      // powerpc-apple-*
376
 
      AddFeature("altivec");
377
 
    } else if (Triple.getArch() == Triple::ppc64) {
378
 
      // powerpc64-apple-*
379
 
      AddFeature("64bit");
380
 
      AddFeature("altivec");
381
 
    }
382
 
  }
383
 
}