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