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