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