df28b98b6896bebbe226fe52e84108c55b652982
[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/Twine.h"
13 #include <cassert>
14 #include <cstring>
15 using namespace llvm;
16
17 //
18
19 const char *Triple::getArchTypeName(ArchType Kind) {
20   switch (Kind) {
21   case InvalidArch: return "<invalid>";
22   case UnknownArch: return "unknown";
23     
24   case alpha:   return "alpha";
25   case arm:     return "arm";
26   case bfin:    return "bfin";
27   case cellspu: return "cellspu";
28   case mips:    return "mips";
29   case mipsel:  return "mipsel";
30   case msp430:  return "msp430";
31   case pic16:   return "pic16";
32   case ppc64:   return "powerpc64";
33   case ppc:     return "powerpc";
34   case sparc:   return "sparc";
35   case systemz: return "s390x";
36   case thumb:   return "thumb";
37   case x86:     return "i386";
38   case x86_64:  return "x86_64";
39   case xcore:   return "xcore";
40   }
41
42   return "<invalid>";
43 }
44
45 const char *Triple::getVendorTypeName(VendorType Kind) {
46   switch (Kind) {
47   case UnknownVendor: return "unknown";
48
49   case Apple: return "apple";
50   case PC: return "pc";
51   }
52
53   return "<invalid>";
54 }
55
56 const char *Triple::getOSTypeName(OSType Kind) {
57   switch (Kind) {
58   case UnknownOS: return "unknown";
59
60   case AuroraUX: return "auroraux";
61   case Cygwin: return "cygwin";
62   case Darwin: return "darwin";
63   case DragonFly: return "dragonfly";
64   case FreeBSD: return "freebsd";
65   case Linux: return "linux";
66   case MinGW32: return "mingw32";
67   case MinGW64: return "mingw64";
68   case NetBSD: return "netbsd";
69   case OpenBSD: return "openbsd";
70   case Solaris: return "solaris";
71   case Win32: return "win32";
72   }
73
74   return "<invalid>";
75 }
76
77 Triple::ArchType Triple::getArchTypeForLLVMName(const StringRef &Name) {
78   if (Name == "alpha")
79     return alpha;
80   if (Name == "arm")
81     return arm;
82   if (Name == "bfin")
83     return bfin;
84   if (Name == "cellspu")
85     return cellspu;
86   if (Name == "mips")
87     return mips;
88   if (Name == "mipsel")
89     return mipsel;
90   if (Name == "msp430")
91     return msp430;
92   if (Name == "pic16")
93     return pic16;
94   if (Name == "ppc64")
95     return ppc64;
96   if (Name == "ppc")
97     return ppc;
98   if (Name == "sparc")
99     return sparc;
100   if (Name == "systemz")
101     return systemz;
102   if (Name == "thumb")
103     return thumb;
104   if (Name == "x86")
105     return x86;
106   if (Name == "x86-64")
107     return x86_64;
108   if (Name == "xcore")
109     return xcore;
110
111   return UnknownArch;
112 }
113
114 //
115
116 void Triple::Parse() const {
117   assert(!isInitialized() && "Invalid parse call.");
118
119   StringRef ArchName = getArchName();
120   StringRef VendorName = getVendorName();
121   StringRef OSName = getOSName();
122
123   if (ArchName.size() == 4 && ArchName[0] == 'i' && 
124       ArchName[2] == '8' && ArchName[3] == '6' && 
125       ArchName[1] - '3' < 6) // i[3-9]86
126     Arch = x86;
127   else if (ArchName == "amd64" || ArchName == "x86_64")
128     Arch = x86_64;
129   else if (ArchName == "bfin")
130     Arch = bfin;
131   else if (ArchName == "pic16")
132     Arch = pic16;
133   else if (ArchName == "powerpc")
134     Arch = ppc;
135   else if (ArchName == "powerpc64")
136     Arch = ppc64;
137   else if (ArchName == "arm" ||
138            ArchName.startswith("armv") ||
139            ArchName == "xscale")
140     Arch = arm;
141   else if (ArchName == "thumb" ||
142            ArchName.startswith("thumbv"))
143     Arch = thumb;
144   else if (ArchName.startswith("alpha"))
145     Arch = alpha;
146   else if (ArchName == "spu" || ArchName == "cellspu")
147     Arch = cellspu;
148   else if (ArchName == "msp430")
149     Arch = msp430;
150   else if (ArchName == "mips" || ArchName == "mipsallegrex")
151     Arch = mips;
152   else if (ArchName == "mipsel" || ArchName == "mipsallegrexel" ||
153            ArchName == "psp")
154     Arch = mipsel;
155   else if (ArchName == "sparc")
156     Arch = sparc;
157   else if (ArchName == "s390x")
158     Arch = systemz;
159   else
160     Arch = UnknownArch;
161
162
163   // Handle some exceptional cases where the OS / environment components are
164   // stuck into the vendor field.
165   if (StringRef(getTriple()).count('-') == 1) {
166     StringRef VendorName = getVendorName();
167
168     if (VendorName.startswith("mingw32")) { // 'i386-mingw32', etc.
169       Vendor = PC;
170       OS = MinGW32;
171       return;
172     }
173
174     // arm-elf is another example, but we don't currently parse anything about
175     // the environment.
176   }
177
178   if (VendorName == "apple")
179     Vendor = Apple;
180   else if (VendorName == "pc")
181     Vendor = PC;
182   else
183     Vendor = UnknownVendor;
184
185   if (OSName.startswith("auroraux"))
186     OS = AuroraUX;
187   else if (OSName.startswith("cygwin"))
188     OS = Cygwin;
189   else if (OSName.startswith("darwin"))
190     OS = Darwin;
191   else if (OSName.startswith("dragonfly"))
192     OS = DragonFly;
193   else if (OSName.startswith("freebsd"))
194     OS = FreeBSD;
195   else if (OSName.startswith("linux"))
196     OS = Linux;
197   else if (OSName.startswith("mingw32"))
198     OS = MinGW32;
199   else if (OSName.startswith("mingw64"))
200     OS = MinGW64;
201   else if (OSName.startswith("netbsd"))
202     OS = NetBSD;
203   else if (OSName.startswith("openbsd"))
204     OS = OpenBSD;
205   else if (OSName.startswith("solaris"))
206     OS = Solaris;
207   else if (OSName.startswith("win32"))
208     OS = Win32;
209   else
210     OS = UnknownOS;
211
212   assert(isInitialized() && "Failed to initialize!");
213 }
214
215 StringRef Triple::getArchName() const {
216   return StringRef(Data).split('-').first;           // Isolate first component
217 }
218
219 StringRef Triple::getVendorName() const {
220   StringRef Tmp = StringRef(Data).split('-').second; // Strip first component
221   return Tmp.split('-').first;                       // Isolate second component
222 }
223
224 StringRef Triple::getOSName() const {
225   StringRef Tmp = StringRef(Data).split('-').second; // Strip first component
226   Tmp = Tmp.split('-').second;                       // Strip second component
227   return Tmp.split('-').first;                       // Isolate third component
228 }
229
230 StringRef Triple::getEnvironmentName() const {
231   StringRef Tmp = StringRef(Data).split('-').second; // Strip first component
232   Tmp = Tmp.split('-').second;                       // Strip second component
233   return Tmp.split('-').second;                      // Strip third component
234 }
235
236 StringRef Triple::getOSAndEnvironmentName() const {
237   StringRef Tmp = StringRef(Data).split('-').second; // Strip first component
238   return Tmp.split('-').second;                      // Strip second component
239 }
240
241 static unsigned EatNumber(StringRef &Str) {
242   assert(!Str.empty() && Str[0] >= '0' && Str[0] <= '9' && "Not a number");
243   unsigned Result = Str[0]-'0';
244   
245   // Eat the digit.
246   Str = Str.substr(1);
247   
248   // Handle "darwin11".
249   if (Result == 1 && !Str.empty() && Str[0] >= '0' && Str[0] <= '9') {
250     Result = Result*10 + (Str[0] - '0');
251     // Eat the digit.
252     Str = Str.substr(1);
253   }
254   
255   return Result;
256 }
257
258 /// getDarwinNumber - Parse the 'darwin number' out of the specific target
259 /// triple.  For example, if we have darwin8.5 return 8,5,0.  If any entry is
260 /// not defined, return 0's.  This requires that the triple have an OSType of
261 /// darwin before it is called.
262 void Triple::getDarwinNumber(unsigned &Maj, unsigned &Min,
263                              unsigned &Revision) const {
264   assert(getOS() == Darwin && "Not a darwin target triple!");
265   StringRef OSName = getOSName();
266   assert(OSName.startswith("darwin") && "Unknown darwin target triple!");
267   
268   // Strip off "darwin".
269   OSName = OSName.substr(6);
270   
271   Maj = Min = Revision = 0;
272
273   if (OSName.empty() || OSName[0] < '0' || OSName[0] > '9')
274     return;
275
276   // The major version is the first digit.
277   Maj = EatNumber(OSName);
278   if (OSName.empty()) return;
279   
280   // Handle minor version: 10.4.9 -> darwin8.9.
281   if (OSName[0] != '.')
282     return;
283   
284   // Eat the '.'.
285   OSName = OSName.substr(1);
286
287   if (OSName.empty() || OSName[0] < '0' || OSName[0] > '9')
288     return;
289   
290   Min = EatNumber(OSName);
291   if (OSName.empty()) return;
292
293   // Handle revision darwin8.9.1
294   if (OSName[0] != '.')
295     return;
296   
297   // Eat the '.'.
298   OSName = OSName.substr(1);
299   
300   if (OSName.empty() || OSName[0] < '0' || OSName[0] > '9')
301     return;
302
303   Revision = EatNumber(OSName);
304 }
305
306 void Triple::setTriple(const Twine &Str) {
307   Data = Str.str();
308   Arch = InvalidArch;
309 }
310
311 void Triple::setArch(ArchType Kind) {
312   setArchName(getArchTypeName(Kind));
313 }
314
315 void Triple::setVendor(VendorType Kind) {
316   setVendorName(getVendorTypeName(Kind));
317 }
318
319 void Triple::setOS(OSType Kind) {
320   setOSName(getOSTypeName(Kind));
321 }
322
323 void Triple::setArchName(const StringRef &Str) {
324   setTriple(Str + "-" + getVendorName() + "-" + getOSAndEnvironmentName());
325 }
326
327 void Triple::setVendorName(const StringRef &Str) {
328   setTriple(getArchName() + "-" + Str + "-" + getOSAndEnvironmentName());
329 }
330
331 void Triple::setOSName(const StringRef &Str) {
332   if (hasEnvironment())
333     setTriple(getArchName() + "-" + getVendorName() + "-" + Str +
334               "-" + getEnvironmentName());
335   else
336     setTriple(getArchName() + "-" + getVendorName() + "-" + Str);
337 }
338
339 void Triple::setEnvironmentName(const StringRef &Str) {
340   setTriple(getArchName() + "-" + getVendorName() + "-" + getOSName() + 
341             "-" + Str);
342 }
343
344 void Triple::setOSAndEnvironmentName(const StringRef &Str) {
345   setTriple(getArchName() + "-" + getVendorName() + "-" + Str);
346 }