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