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