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