Triple.cpp revision 29269d03af6dc3feb69d0230831a059f39c03700
1//===--- Triple.cpp - Target triple helper class --------------------------===//
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#include "llvm/ADT/Triple.h"
11
12#include "llvm/ADT/SmallString.h"
13#include "llvm/ADT/Twine.h"
14#include <cassert>
15#include <cstring>
16using namespace llvm;
17
18//
19
20const char *Triple::getArchTypeName(ArchType Kind) {
21  switch (Kind) {
22  case InvalidArch: return "<invalid>";
23  case UnknownArch: return "unknown";
24
25  case alpha:   return "alpha";
26  case arm:     return "arm";
27  case bfin:    return "bfin";
28  case cellspu: return "cellspu";
29  case mips:    return "mips";
30  case mipsel:  return "mipsel";
31  case msp430:  return "msp430";
32  case pic16:   return "pic16";
33  case ppc64:   return "powerpc64";
34  case ppc:     return "powerpc";
35  case sparc:   return "sparc";
36  case sparcv9: return "sparcv9";
37  case systemz: return "s390x";
38  case tce:     return "tce";
39  case thumb:   return "thumb";
40  case x86:     return "i386";
41  case x86_64:  return "x86_64";
42  case xcore:   return "xcore";
43  case mblaze:  return "mblaze";
44  }
45
46  return "<invalid>";
47}
48
49const char *Triple::getArchTypePrefix(ArchType Kind) {
50  switch (Kind) {
51  default:
52    return 0;
53
54  case alpha:   return "alpha";
55
56  case arm:
57  case thumb:   return "arm";
58
59  case bfin:    return "bfin";
60
61  case cellspu: return "spu";
62
63  case ppc64:
64  case ppc:     return "ppc";
65
66  case mblaze:  return "mblaze";
67
68  case sparcv9:
69  case sparc:   return "sparc";
70
71  case x86:
72  case x86_64:  return "x86";
73  case xcore:   return "xcore";
74  }
75}
76
77const char *Triple::getVendorTypeName(VendorType Kind) {
78  switch (Kind) {
79  case UnknownVendor: return "unknown";
80
81  case Apple: return "apple";
82  case PC: return "pc";
83  }
84
85  return "<invalid>";
86}
87
88const char *Triple::getOSTypeName(OSType Kind) {
89  switch (Kind) {
90  case UnknownOS: return "unknown";
91
92  case AuroraUX: return "auroraux";
93  case Cygwin: return "cygwin";
94  case Darwin: return "darwin";
95  case DragonFly: return "dragonfly";
96  case FreeBSD: return "freebsd";
97  case Linux: return "linux";
98  case Lv2: return "lv2";
99  case MinGW32: return "mingw32";
100  case MinGW64: return "mingw64";
101  case NetBSD: return "netbsd";
102  case OpenBSD: return "openbsd";
103  case Psp: return "psp";
104  case Solaris: return "solaris";
105  case Win32: return "win32";
106  case Haiku: return "haiku";
107  case Minix: return "minix";
108  }
109
110  return "<invalid>";
111}
112
113Triple::ArchType Triple::getArchTypeForLLVMName(StringRef Name) {
114  if (Name == "alpha")
115    return alpha;
116  if (Name == "arm")
117    return arm;
118  if (Name == "bfin")
119    return bfin;
120  if (Name == "cellspu")
121    return cellspu;
122  if (Name == "mips")
123    return mips;
124  if (Name == "mipsel")
125    return mipsel;
126  if (Name == "msp430")
127    return msp430;
128  if (Name == "pic16")
129    return pic16;
130  if (Name == "ppc64")
131    return ppc64;
132  if (Name == "ppc")
133    return ppc;
134  if (Name == "mblaze")
135    return mblaze;
136  if (Name == "sparc")
137    return sparc;
138  if (Name == "sparcv9")
139    return sparcv9;
140  if (Name == "systemz")
141    return systemz;
142  if (Name == "tce")
143    return tce;
144  if (Name == "thumb")
145    return thumb;
146  if (Name == "x86")
147    return x86;
148  if (Name == "x86-64")
149    return x86_64;
150  if (Name == "xcore")
151    return xcore;
152
153  return UnknownArch;
154}
155
156Triple::ArchType Triple::getArchTypeForDarwinArchName(StringRef Str) {
157  // See arch(3) and llvm-gcc's driver-driver.c. We don't implement support for
158  // archs which Darwin doesn't use.
159
160  // The matching this routine does is fairly pointless, since it is neither the
161  // complete architecture list, nor a reasonable subset. The problem is that
162  // historically the driver driver accepts this and also ties its -march=
163  // handling to the architecture name, so we need to be careful before removing
164  // support for it.
165
166  // This code must be kept in sync with Clang's Darwin specific argument
167  // translation.
168
169  if (Str == "ppc" || Str == "ppc601" || Str == "ppc603" || Str == "ppc604" ||
170      Str == "ppc604e" || Str == "ppc750" || Str == "ppc7400" ||
171      Str == "ppc7450" || Str == "ppc970")
172    return Triple::ppc;
173
174  if (Str == "ppc64")
175    return Triple::ppc64;
176
177  if (Str == "i386" || Str == "i486" || Str == "i486SX" || Str == "pentium" ||
178      Str == "i586" || Str == "pentpro" || Str == "i686" || Str == "pentIIm3" ||
179      Str == "pentIIm5" || Str == "pentium4")
180    return Triple::x86;
181
182  if (Str == "x86_64")
183    return Triple::x86_64;
184
185  // This is derived from the driver driver.
186  if (Str == "arm" || Str == "armv4t" || Str == "armv5" || Str == "xscale" ||
187      Str == "armv6" || Str == "armv7")
188    return Triple::arm;
189
190  return Triple::UnknownArch;
191}
192
193// Returns architecture name that is understood by the target assembler.
194const char *Triple::getArchNameForAssembler() {
195  if (getOS() != Triple::Darwin && getVendor() != Triple::Apple)
196    return NULL;
197
198  StringRef Str = getArchName();
199  if (Str == "i386")
200    return "i386";
201  if (Str == "x86_64")
202    return "x86_64";
203  if (Str == "powerpc")
204    return "ppc";
205  if (Str == "powerpc64")
206    return "ppc64";
207  if (Str == "mblaze" || Str == "microblaze")
208    return "mblaze";
209  if (Str == "arm")
210    return "arm";
211  if (Str == "armv4t" || Str == "thumbv4t")
212    return "armv4t";
213  if (Str == "armv5" || Str == "armv5e" || Str == "thumbv5" || Str == "thumbv5e")
214    return "armv5";
215  if (Str == "armv6" || Str == "thumbv6")
216    return "armv6";
217  if (Str == "armv7" || Str == "thumbv7")
218    return "armv7";
219  return NULL;
220}
221
222//
223
224void Triple::Parse() const {
225  assert(!isInitialized() && "Invalid parse call.");
226
227  StringRef ArchName = getArchName();
228  StringRef VendorName = getVendorName();
229  StringRef OSName = getOSName();
230
231  if (ArchName.size() == 4 && ArchName[0] == 'i' &&
232      ArchName[2] == '8' && ArchName[3] == '6' &&
233      ArchName[1] - '3' < 6) // i[3-9]86
234    Arch = x86;
235  else if (ArchName == "amd64" || ArchName == "x86_64")
236    Arch = x86_64;
237  else if (ArchName == "bfin")
238    Arch = bfin;
239  else if (ArchName == "pic16")
240    Arch = pic16;
241  else if (ArchName == "powerpc")
242    Arch = ppc;
243  else if ((ArchName == "powerpc64") || (ArchName == "ppu"))
244    Arch = ppc64;
245  else if (ArchName == "mblaze")
246    Arch = mblaze;
247  else if (ArchName == "arm" ||
248           ArchName.startswith("armv") ||
249           ArchName == "xscale")
250    Arch = arm;
251  else if (ArchName == "thumb" ||
252           ArchName.startswith("thumbv"))
253    Arch = thumb;
254  else if (ArchName.startswith("alpha"))
255    Arch = alpha;
256  else if (ArchName == "spu" || ArchName == "cellspu")
257    Arch = cellspu;
258  else if (ArchName == "msp430")
259    Arch = msp430;
260  else if (ArchName == "mips" || ArchName == "mipsallegrex")
261    Arch = mips;
262  else if (ArchName == "mipsel" || ArchName == "mipsallegrexel" ||
263           ArchName == "psp")
264    Arch = mipsel;
265  else if (ArchName == "sparc")
266    Arch = sparc;
267  else if (ArchName == "sparcv9")
268    Arch = sparcv9;
269  else if (ArchName == "s390x")
270    Arch = systemz;
271  else if (ArchName == "tce")
272    Arch = tce;
273  else if (ArchName == "xcore")
274    Arch = xcore;
275  else
276    Arch = UnknownArch;
277
278
279  // Handle some exceptional cases where the OS / environment components are
280  // stuck into the vendor field.
281  if (StringRef(getTriple()).count('-') == 1) {
282    StringRef VendorName = getVendorName();
283
284    if (VendorName.startswith("mingw32")) { // 'i386-mingw32', etc.
285      Vendor = PC;
286      OS = MinGW32;
287      return;
288    }
289
290    // arm-elf is another example, but we don't currently parse anything about
291    // the environment.
292  }
293
294  if (VendorName == "apple")
295    Vendor = Apple;
296  else if (VendorName == "pc")
297    Vendor = PC;
298  else
299    Vendor = UnknownVendor;
300
301  if (OSName.startswith("auroraux"))
302    OS = AuroraUX;
303  else if (OSName.startswith("cygwin"))
304    OS = Cygwin;
305  else if (OSName.startswith("darwin"))
306    OS = Darwin;
307  else if (OSName.startswith("dragonfly"))
308    OS = DragonFly;
309  else if (OSName.startswith("freebsd"))
310    OS = FreeBSD;
311  else if (OSName.startswith("linux"))
312    OS = Linux;
313  else if (OSName.startswith("lv2"))
314    OS = Lv2;
315  else if (OSName.startswith("mingw32"))
316    OS = MinGW32;
317  else if (OSName.startswith("mingw64"))
318    OS = MinGW64;
319  else if (OSName.startswith("netbsd"))
320    OS = NetBSD;
321  else if (OSName.startswith("openbsd"))
322    OS = OpenBSD;
323  else if (OSName.startswith("psp"))
324    OS = Psp;
325  else if (OSName.startswith("solaris"))
326    OS = Solaris;
327  else if (OSName.startswith("win32"))
328    OS = Win32;
329  else if (OSName.startswith("haiku"))
330    OS = Haiku;
331  else if (OSName.startswith("minix"))
332    OS = Minix;
333  else
334    OS = UnknownOS;
335
336  assert(isInitialized() && "Failed to initialize!");
337}
338
339StringRef Triple::getArchName() const {
340  return StringRef(Data).split('-').first;           // Isolate first component
341}
342
343StringRef Triple::getVendorName() const {
344  StringRef Tmp = StringRef(Data).split('-').second; // Strip first component
345  return Tmp.split('-').first;                       // Isolate second component
346}
347
348StringRef Triple::getOSName() const {
349  StringRef Tmp = StringRef(Data).split('-').second; // Strip first component
350  Tmp = Tmp.split('-').second;                       // Strip second component
351  return Tmp.split('-').first;                       // Isolate third component
352}
353
354StringRef Triple::getEnvironmentName() const {
355  StringRef Tmp = StringRef(Data).split('-').second; // Strip first component
356  Tmp = Tmp.split('-').second;                       // Strip second component
357  return Tmp.split('-').second;                      // Strip third component
358}
359
360StringRef Triple::getOSAndEnvironmentName() const {
361  StringRef Tmp = StringRef(Data).split('-').second; // Strip first component
362  return Tmp.split('-').second;                      // Strip second component
363}
364
365static unsigned EatNumber(StringRef &Str) {
366  assert(!Str.empty() && Str[0] >= '0' && Str[0] <= '9' && "Not a number");
367  unsigned Result = Str[0]-'0';
368
369  // Eat the digit.
370  Str = Str.substr(1);
371
372  // Handle "darwin11".
373  if (Result == 1 && !Str.empty() && Str[0] >= '0' && Str[0] <= '9') {
374    Result = Result*10 + (Str[0] - '0');
375    // Eat the digit.
376    Str = Str.substr(1);
377  }
378
379  return Result;
380}
381
382/// getDarwinNumber - Parse the 'darwin number' out of the specific target
383/// triple.  For example, if we have darwin8.5 return 8,5,0.  If any entry is
384/// not defined, return 0's.  This requires that the triple have an OSType of
385/// darwin before it is called.
386void Triple::getDarwinNumber(unsigned &Maj, unsigned &Min,
387                             unsigned &Revision) const {
388  assert(getOS() == Darwin && "Not a darwin target triple!");
389  StringRef OSName = getOSName();
390  assert(OSName.startswith("darwin") && "Unknown darwin target triple!");
391
392  // Strip off "darwin".
393  OSName = OSName.substr(6);
394
395  Maj = Min = Revision = 0;
396
397  if (OSName.empty() || OSName[0] < '0' || OSName[0] > '9')
398    return;
399
400  // The major version is the first digit.
401  Maj = EatNumber(OSName);
402  if (OSName.empty()) return;
403
404  // Handle minor version: 10.4.9 -> darwin8.9.
405  if (OSName[0] != '.')
406    return;
407
408  // Eat the '.'.
409  OSName = OSName.substr(1);
410
411  if (OSName.empty() || OSName[0] < '0' || OSName[0] > '9')
412    return;
413
414  Min = EatNumber(OSName);
415  if (OSName.empty()) return;
416
417  // Handle revision darwin8.9.1
418  if (OSName[0] != '.')
419    return;
420
421  // Eat the '.'.
422  OSName = OSName.substr(1);
423
424  if (OSName.empty() || OSName[0] < '0' || OSName[0] > '9')
425    return;
426
427  Revision = EatNumber(OSName);
428}
429
430void Triple::setTriple(const Twine &Str) {
431  Data = Str.str();
432  Arch = InvalidArch;
433}
434
435void Triple::setArch(ArchType Kind) {
436  setArchName(getArchTypeName(Kind));
437}
438
439void Triple::setVendor(VendorType Kind) {
440  setVendorName(getVendorTypeName(Kind));
441}
442
443void Triple::setOS(OSType Kind) {
444  setOSName(getOSTypeName(Kind));
445}
446
447void Triple::setArchName(StringRef Str) {
448  // Work around a miscompilation bug for Twines in gcc 4.0.3.
449  SmallString<64> Triple;
450  Triple += Str;
451  Triple += "-";
452  Triple += getVendorName();
453  Triple += "-";
454  Triple += getOSAndEnvironmentName();
455  setTriple(Triple.str());
456}
457
458void Triple::setVendorName(StringRef Str) {
459  setTriple(getArchName() + "-" + Str + "-" + getOSAndEnvironmentName());
460}
461
462void Triple::setOSName(StringRef Str) {
463  if (hasEnvironment())
464    setTriple(getArchName() + "-" + getVendorName() + "-" + Str +
465              "-" + getEnvironmentName());
466  else
467    setTriple(getArchName() + "-" + getVendorName() + "-" + Str);
468}
469
470void Triple::setEnvironmentName(StringRef Str) {
471  setTriple(getArchName() + "-" + getVendorName() + "-" + getOSName() +
472            "-" + Str);
473}
474
475void Triple::setOSAndEnvironmentName(StringRef Str) {
476  setTriple(getArchName() + "-" + getVendorName() + "-" + Str);
477}
478