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