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