Add PSP OS Target to Triple, Credit to Bruno Cardoso Lopes.
[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 //
183
184 void Triple::Parse() const {
185   assert(!isInitialized() && "Invalid parse call.");
186
187   StringRef ArchName = getArchName();
188   StringRef VendorName = getVendorName();
189   StringRef OSName = getOSName();
190
191   if (ArchName.size() == 4 && ArchName[0] == 'i' && 
192       ArchName[2] == '8' && ArchName[3] == '6' && 
193       ArchName[1] - '3' < 6) // i[3-9]86
194     Arch = x86;
195   else if (ArchName == "amd64" || ArchName == "x86_64")
196     Arch = x86_64;
197   else if (ArchName == "bfin")
198     Arch = bfin;
199   else if (ArchName == "pic16")
200     Arch = pic16;
201   else if (ArchName == "powerpc")
202     Arch = ppc;
203   else if (ArchName == "powerpc64")
204     Arch = ppc64;
205   else if (ArchName == "arm" ||
206            ArchName.startswith("armv") ||
207            ArchName == "xscale")
208     Arch = arm;
209   else if (ArchName == "thumb" ||
210            ArchName.startswith("thumbv"))
211     Arch = thumb;
212   else if (ArchName.startswith("alpha"))
213     Arch = alpha;
214   else if (ArchName == "spu" || ArchName == "cellspu")
215     Arch = cellspu;
216   else if (ArchName == "msp430")
217     Arch = msp430;
218   else if (ArchName == "mips" || ArchName == "mipsallegrex")
219     Arch = mips;
220   else if (ArchName == "mipsel" || ArchName == "mipsallegrexel" ||
221            ArchName == "psp")
222     Arch = mipsel;
223   else if (ArchName == "sparc")
224     Arch = sparc;
225   else if (ArchName == "s390x")
226     Arch = systemz;
227   else if (ArchName == "tce")
228     Arch = tce;
229   else if (ArchName == "xcore")
230     Arch = xcore;
231   else
232     Arch = UnknownArch;
233
234
235   // Handle some exceptional cases where the OS / environment components are
236   // stuck into the vendor field.
237   if (StringRef(getTriple()).count('-') == 1) {
238     StringRef VendorName = getVendorName();
239
240     if (VendorName.startswith("mingw32")) { // 'i386-mingw32', etc.
241       Vendor = PC;
242       OS = MinGW32;
243       return;
244     }
245
246     // arm-elf is another example, but we don't currently parse anything about
247     // the environment.
248   }
249
250   if (VendorName == "apple")
251     Vendor = Apple;
252   else if (VendorName == "pc")
253     Vendor = PC;
254   else
255     Vendor = UnknownVendor;
256
257   if (OSName.startswith("auroraux"))
258     OS = AuroraUX;
259   else if (OSName.startswith("cygwin"))
260     OS = Cygwin;
261   else if (OSName.startswith("darwin"))
262     OS = Darwin;
263   else if (OSName.startswith("dragonfly"))
264     OS = DragonFly;
265   else if (OSName.startswith("freebsd"))
266     OS = FreeBSD;
267   else if (OSName.startswith("linux"))
268     OS = Linux;
269   else if (OSName.startswith("mingw32"))
270     OS = MinGW32;
271   else if (OSName.startswith("mingw64"))
272     OS = MinGW64;
273   else if (OSName.startswith("netbsd"))
274     OS = NetBSD;
275   else if (OSName.startswith("openbsd"))
276     OS = OpenBSD;
277   else if (OSName.startswith("psp"))
278     OS = Psp;
279   else if (OSName.startswith("solaris"))
280     OS = Solaris;
281   else if (OSName.startswith("win32"))
282     OS = Win32;
283   else if (OSName.startswith("haiku"))
284         OS = Haiku;
285   else
286     OS = UnknownOS;
287
288   assert(isInitialized() && "Failed to initialize!");
289 }
290
291 StringRef Triple::getArchName() const {
292   return StringRef(Data).split('-').first;           // Isolate first component
293 }
294
295 StringRef Triple::getVendorName() const {
296   StringRef Tmp = StringRef(Data).split('-').second; // Strip first component
297   return Tmp.split('-').first;                       // Isolate second component
298 }
299
300 StringRef Triple::getOSName() const {
301   StringRef Tmp = StringRef(Data).split('-').second; // Strip first component
302   Tmp = Tmp.split('-').second;                       // Strip second component
303   return Tmp.split('-').first;                       // Isolate third component
304 }
305
306 StringRef Triple::getEnvironmentName() const {
307   StringRef Tmp = StringRef(Data).split('-').second; // Strip first component
308   Tmp = Tmp.split('-').second;                       // Strip second component
309   return Tmp.split('-').second;                      // Strip third component
310 }
311
312 StringRef Triple::getOSAndEnvironmentName() const {
313   StringRef Tmp = StringRef(Data).split('-').second; // Strip first component
314   return Tmp.split('-').second;                      // Strip second component
315 }
316
317 static unsigned EatNumber(StringRef &Str) {
318   assert(!Str.empty() && Str[0] >= '0' && Str[0] <= '9' && "Not a number");
319   unsigned Result = Str[0]-'0';
320   
321   // Eat the digit.
322   Str = Str.substr(1);
323   
324   // Handle "darwin11".
325   if (Result == 1 && !Str.empty() && Str[0] >= '0' && Str[0] <= '9') {
326     Result = Result*10 + (Str[0] - '0');
327     // Eat the digit.
328     Str = Str.substr(1);
329   }
330   
331   return Result;
332 }
333
334 /// getDarwinNumber - Parse the 'darwin number' out of the specific target
335 /// triple.  For example, if we have darwin8.5 return 8,5,0.  If any entry is
336 /// not defined, return 0's.  This requires that the triple have an OSType of
337 /// darwin before it is called.
338 void Triple::getDarwinNumber(unsigned &Maj, unsigned &Min,
339                              unsigned &Revision) const {
340   assert(getOS() == Darwin && "Not a darwin target triple!");
341   StringRef OSName = getOSName();
342   assert(OSName.startswith("darwin") && "Unknown darwin target triple!");
343   
344   // Strip off "darwin".
345   OSName = OSName.substr(6);
346   
347   Maj = Min = Revision = 0;
348
349   if (OSName.empty() || OSName[0] < '0' || OSName[0] > '9')
350     return;
351
352   // The major version is the first digit.
353   Maj = EatNumber(OSName);
354   if (OSName.empty()) return;
355   
356   // Handle minor version: 10.4.9 -> darwin8.9.
357   if (OSName[0] != '.')
358     return;
359   
360   // Eat the '.'.
361   OSName = OSName.substr(1);
362
363   if (OSName.empty() || OSName[0] < '0' || OSName[0] > '9')
364     return;
365   
366   Min = EatNumber(OSName);
367   if (OSName.empty()) return;
368
369   // Handle revision darwin8.9.1
370   if (OSName[0] != '.')
371     return;
372   
373   // Eat the '.'.
374   OSName = OSName.substr(1);
375   
376   if (OSName.empty() || OSName[0] < '0' || OSName[0] > '9')
377     return;
378
379   Revision = EatNumber(OSName);
380 }
381
382 void Triple::setTriple(const Twine &Str) {
383   Data = Str.str();
384   Arch = InvalidArch;
385 }
386
387 void Triple::setArch(ArchType Kind) {
388   setArchName(getArchTypeName(Kind));
389 }
390
391 void Triple::setVendor(VendorType Kind) {
392   setVendorName(getVendorTypeName(Kind));
393 }
394
395 void Triple::setOS(OSType Kind) {
396   setOSName(getOSTypeName(Kind));
397 }
398
399 void Triple::setArchName(StringRef Str) {
400   // Work around a miscompilation bug for Twines in gcc 4.0.3.
401   SmallString<64> Triple;
402   Triple += Str;
403   Triple += "-";
404   Triple += getVendorName();
405   Triple += "-";
406   Triple += getOSAndEnvironmentName();
407   setTriple(Triple.str());
408 }
409
410 void Triple::setVendorName(StringRef Str) {
411   setTriple(getArchName() + "-" + Str + "-" + getOSAndEnvironmentName());
412 }
413
414 void Triple::setOSName(StringRef Str) {
415   if (hasEnvironment())
416     setTriple(getArchName() + "-" + getVendorName() + "-" + Str +
417               "-" + getEnvironmentName());
418   else
419     setTriple(getArchName() + "-" + getVendorName() + "-" + Str);
420 }
421
422 void Triple::setEnvironmentName(StringRef Str) {
423   setTriple(getArchName() + "-" + getVendorName() + "-" + getOSName() +
424             "-" + Str);
425 }
426
427 void Triple::setOSAndEnvironmentName(StringRef Str) {
428   setTriple(getArchName() + "-" + getVendorName() + "-" + Str);
429 }