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