Triple.cpp revision 206083
1193323Sed//===--- Triple.cpp - Target triple helper class --------------------------===//
2193323Sed//
3193323Sed//                     The LLVM Compiler Infrastructure
4193323Sed//
5193323Sed// This file is distributed under the University of Illinois Open Source
6193323Sed// License. See LICENSE.TXT for details.
7193323Sed//
8193323Sed//===----------------------------------------------------------------------===//
9193323Sed
10193323Sed#include "llvm/ADT/Triple.h"
11198090Srdivacky
12198090Srdivacky#include "llvm/ADT/SmallString.h"
13198090Srdivacky#include "llvm/ADT/Twine.h"
14193323Sed#include <cassert>
15193323Sed#include <cstring>
16193323Sedusing namespace llvm;
17193323Sed
18193323Sed//
19193323Sed
20193323Sedconst char *Triple::getArchTypeName(ArchType Kind) {
21193323Sed  switch (Kind) {
22193323Sed  case InvalidArch: return "<invalid>";
23193323Sed  case UnknownArch: return "unknown";
24198090Srdivacky
25198090Srdivacky  case alpha:   return "alpha";
26198090Srdivacky  case arm:     return "arm";
27198090Srdivacky  case bfin:    return "bfin";
28198090Srdivacky  case cellspu: return "cellspu";
29198090Srdivacky  case mips:    return "mips";
30198090Srdivacky  case mipsel:  return "mipsel";
31198090Srdivacky  case msp430:  return "msp430";
32198090Srdivacky  case pic16:   return "pic16";
33198090Srdivacky  case ppc64:   return "powerpc64";
34198090Srdivacky  case ppc:     return "powerpc";
35198090Srdivacky  case sparc:   return "sparc";
36203954Srdivacky  case sparcv9: return "sparcv9";
37198090Srdivacky  case systemz: return "s390x";
38198090Srdivacky  case tce:     return "tce";
39198090Srdivacky  case thumb:   return "thumb";
40198090Srdivacky  case x86:     return "i386";
41198090Srdivacky  case x86_64:  return "x86_64";
42198090Srdivacky  case xcore:   return "xcore";
43204642Srdivacky  case mblaze:  return "mblaze";
44193323Sed  }
45193323Sed
46193323Sed  return "<invalid>";
47193323Sed}
48193323Sed
49198090Srdivackyconst char *Triple::getArchTypePrefix(ArchType Kind) {
50198090Srdivacky  switch (Kind) {
51198090Srdivacky  default:
52198090Srdivacky    return 0;
53198090Srdivacky
54198090Srdivacky  case alpha:   return "alpha";
55198090Srdivacky
56198090Srdivacky  case arm:
57198090Srdivacky  case thumb:   return "arm";
58198090Srdivacky
59198090Srdivacky  case bfin:    return "bfin";
60198090Srdivacky
61198090Srdivacky  case cellspu: return "spu";
62198090Srdivacky
63198090Srdivacky  case ppc64:
64198090Srdivacky  case ppc:     return "ppc";
65198090Srdivacky
66204642Srdivacky  case mblaze:  return "mblaze";
67204642Srdivacky
68203954Srdivacky  case sparcv9:
69198090Srdivacky  case sparc:   return "sparc";
70198090Srdivacky
71198090Srdivacky  case x86:
72198090Srdivacky  case x86_64:  return "x86";
73198090Srdivacky  case xcore:   return "xcore";
74198090Srdivacky  }
75198090Srdivacky}
76198090Srdivacky
77193323Sedconst char *Triple::getVendorTypeName(VendorType Kind) {
78193323Sed  switch (Kind) {
79193323Sed  case UnknownVendor: return "unknown";
80193323Sed
81193323Sed  case Apple: return "apple";
82198090Srdivacky  case PC: return "pc";
83193323Sed  }
84193323Sed
85193323Sed  return "<invalid>";
86193323Sed}
87193323Sed
88193323Sedconst char *Triple::getOSTypeName(OSType Kind) {
89193323Sed  switch (Kind) {
90193323Sed  case UnknownOS: return "unknown";
91193323Sed
92194612Sed  case AuroraUX: return "auroraux";
93198090Srdivacky  case Cygwin: return "cygwin";
94193323Sed  case Darwin: return "darwin";
95193323Sed  case DragonFly: return "dragonfly";
96193323Sed  case FreeBSD: return "freebsd";
97193323Sed  case Linux: return "linux";
98199989Srdivacky  case Lv2: return "lv2";
99198090Srdivacky  case MinGW32: return "mingw32";
100198090Srdivacky  case MinGW64: return "mingw64";
101198090Srdivacky  case NetBSD: return "netbsd";
102195340Sed  case OpenBSD: return "openbsd";
103199481Srdivacky  case Psp: return "psp";
104198090Srdivacky  case Solaris: return "solaris";
105198090Srdivacky  case Win32: return "win32";
106198396Srdivacky  case Haiku: return "haiku";
107193323Sed  }
108193323Sed
109193323Sed  return "<invalid>";
110193323Sed}
111193323Sed
112199481SrdivackyTriple::ArchType Triple::getArchTypeForLLVMName(StringRef Name) {
113198090Srdivacky  if (Name == "alpha")
114198090Srdivacky    return alpha;
115198090Srdivacky  if (Name == "arm")
116198090Srdivacky    return arm;
117198090Srdivacky  if (Name == "bfin")
118198090Srdivacky    return bfin;
119198090Srdivacky  if (Name == "cellspu")
120198090Srdivacky    return cellspu;
121198090Srdivacky  if (Name == "mips")
122198090Srdivacky    return mips;
123198090Srdivacky  if (Name == "mipsel")
124198090Srdivacky    return mipsel;
125198090Srdivacky  if (Name == "msp430")
126198090Srdivacky    return msp430;
127198090Srdivacky  if (Name == "pic16")
128198090Srdivacky    return pic16;
129198090Srdivacky  if (Name == "ppc64")
130198090Srdivacky    return ppc64;
131198090Srdivacky  if (Name == "ppc")
132198090Srdivacky    return ppc;
133204642Srdivacky  if (Name == "mblaze")
134204642Srdivacky    return mblaze;
135198090Srdivacky  if (Name == "sparc")
136198090Srdivacky    return sparc;
137203954Srdivacky  if (Name == "sparcv9")
138203954Srdivacky    return sparcv9;
139198090Srdivacky  if (Name == "systemz")
140198090Srdivacky    return systemz;
141198090Srdivacky  if (Name == "tce")
142198090Srdivacky    return tce;
143198090Srdivacky  if (Name == "thumb")
144198090Srdivacky    return thumb;
145198090Srdivacky  if (Name == "x86")
146198090Srdivacky    return x86;
147198090Srdivacky  if (Name == "x86-64")
148198090Srdivacky    return x86_64;
149198090Srdivacky  if (Name == "xcore")
150198090Srdivacky    return xcore;
151198090Srdivacky
152198090Srdivacky  return UnknownArch;
153198090Srdivacky}
154198090Srdivacky
155199481SrdivackyTriple::ArchType Triple::getArchTypeForDarwinArchName(StringRef Str) {
156198090Srdivacky  // See arch(3) and llvm-gcc's driver-driver.c. We don't implement support for
157198090Srdivacky  // archs which Darwin doesn't use.
158198090Srdivacky
159198090Srdivacky  // The matching this routine does is fairly pointless, since it is neither the
160198090Srdivacky  // complete architecture list, nor a reasonable subset. The problem is that
161198090Srdivacky  // historically the driver driver accepts this and also ties its -march=
162198090Srdivacky  // handling to the architecture name, so we need to be careful before removing
163198090Srdivacky  // support for it.
164198090Srdivacky
165198090Srdivacky  // This code must be kept in sync with Clang's Darwin specific argument
166198090Srdivacky  // translation.
167198090Srdivacky
168198090Srdivacky  if (Str == "ppc" || Str == "ppc601" || Str == "ppc603" || Str == "ppc604" ||
169198090Srdivacky      Str == "ppc604e" || Str == "ppc750" || Str == "ppc7400" ||
170198090Srdivacky      Str == "ppc7450" || Str == "ppc970")
171198090Srdivacky    return Triple::ppc;
172198090Srdivacky
173198090Srdivacky  if (Str == "ppc64")
174198090Srdivacky    return Triple::ppc64;
175198090Srdivacky
176198090Srdivacky  if (Str == "i386" || Str == "i486" || Str == "i486SX" || Str == "pentium" ||
177198090Srdivacky      Str == "i586" || Str == "pentpro" || Str == "i686" || Str == "pentIIm3" ||
178198090Srdivacky      Str == "pentIIm5" || Str == "pentium4")
179198090Srdivacky    return Triple::x86;
180198090Srdivacky
181198090Srdivacky  if (Str == "x86_64")
182198090Srdivacky    return Triple::x86_64;
183198090Srdivacky
184198090Srdivacky  // This is derived from the driver driver.
185198090Srdivacky  if (Str == "arm" || Str == "armv4t" || Str == "armv5" || Str == "xscale" ||
186198090Srdivacky      Str == "armv6" || Str == "armv7")
187198090Srdivacky    return Triple::arm;
188198090Srdivacky
189198090Srdivacky  return Triple::UnknownArch;
190198090Srdivacky}
191198090Srdivacky
192206083Srdivacky// Returns architecture name that is understood by the target assembler.
193199481Srdivackyconst char *Triple::getArchNameForAssembler() {
194199481Srdivacky  if (getOS() != Triple::Darwin && getVendor() != Triple::Apple)
195199481Srdivacky    return NULL;
196199481Srdivacky
197199481Srdivacky  StringRef Str = getArchName();
198199481Srdivacky  if (Str == "i386")
199199481Srdivacky    return "i386";
200199481Srdivacky  if (Str == "x86_64")
201199481Srdivacky    return "x86_64";
202199481Srdivacky  if (Str == "powerpc")
203199481Srdivacky    return "ppc";
204199481Srdivacky  if (Str == "powerpc64")
205199481Srdivacky    return "ppc64";
206204642Srdivacky  if (Str == "mblaze" || Str == "microblaze")
207204642Srdivacky    return "mblaze";
208199481Srdivacky  if (Str == "arm")
209199481Srdivacky    return "arm";
210199481Srdivacky  if (Str == "armv4t" || Str == "thumbv4t")
211199481Srdivacky    return "armv4t";
212199481Srdivacky  if (Str == "armv5" || Str == "armv5e" || Str == "thumbv5" || Str == "thumbv5e")
213199481Srdivacky    return "armv5";
214199481Srdivacky  if (Str == "armv6" || Str == "thumbv6")
215199481Srdivacky    return "armv6";
216199481Srdivacky  if (Str == "armv7" || Str == "thumbv7")
217199481Srdivacky    return "armv7";
218199481Srdivacky  return NULL;
219199481Srdivacky}
220199481Srdivacky
221193323Sed//
222193323Sed
223193323Sedvoid Triple::Parse() const {
224193323Sed  assert(!isInitialized() && "Invalid parse call.");
225193323Sed
226198090Srdivacky  StringRef ArchName = getArchName();
227198090Srdivacky  StringRef VendorName = getVendorName();
228198090Srdivacky  StringRef OSName = getOSName();
229198090Srdivacky
230193323Sed  if (ArchName.size() == 4 && ArchName[0] == 'i' &&
231198090Srdivacky      ArchName[2] == '8' && ArchName[3] == '6' &&
232198090Srdivacky      ArchName[1] - '3' < 6) // i[3-9]86
233193323Sed    Arch = x86;
234193323Sed  else if (ArchName == "amd64" || ArchName == "x86_64")
235193323Sed    Arch = x86_64;
236198090Srdivacky  else if (ArchName == "bfin")
237198090Srdivacky    Arch = bfin;
238198090Srdivacky  else if (ArchName == "pic16")
239198090Srdivacky    Arch = pic16;
240193323Sed  else if (ArchName == "powerpc")
241193323Sed    Arch = ppc;
242199989Srdivacky  else if ((ArchName == "powerpc64") || (ArchName == "ppu"))
243193323Sed    Arch = ppc64;
244204642Srdivacky  else if (ArchName == "mblaze")
245204642Srdivacky    Arch = mblaze;
246198090Srdivacky  else if (ArchName == "arm" ||
247198090Srdivacky           ArchName.startswith("armv") ||
248198090Srdivacky           ArchName == "xscale")
249198090Srdivacky    Arch = arm;
250198090Srdivacky  else if (ArchName == "thumb" ||
251198090Srdivacky           ArchName.startswith("thumbv"))
252198090Srdivacky    Arch = thumb;
253198090Srdivacky  else if (ArchName.startswith("alpha"))
254198090Srdivacky    Arch = alpha;
255198090Srdivacky  else if (ArchName == "spu" || ArchName == "cellspu")
256198090Srdivacky    Arch = cellspu;
257198090Srdivacky  else if (ArchName == "msp430")
258198090Srdivacky    Arch = msp430;
259198090Srdivacky  else if (ArchName == "mips" || ArchName == "mipsallegrex")
260198090Srdivacky    Arch = mips;
261198090Srdivacky  else if (ArchName == "mipsel" || ArchName == "mipsallegrexel" ||
262198090Srdivacky           ArchName == "psp")
263198090Srdivacky    Arch = mipsel;
264198090Srdivacky  else if (ArchName == "sparc")
265198090Srdivacky    Arch = sparc;
266203954Srdivacky  else if (ArchName == "sparcv9")
267203954Srdivacky    Arch = sparcv9;
268198090Srdivacky  else if (ArchName == "s390x")
269198090Srdivacky    Arch = systemz;
270198090Srdivacky  else if (ArchName == "tce")
271198090Srdivacky    Arch = tce;
272198090Srdivacky  else if (ArchName == "xcore")
273198090Srdivacky    Arch = xcore;
274193323Sed  else
275193323Sed    Arch = UnknownArch;
276193323Sed
277198090Srdivacky
278198090Srdivacky  // Handle some exceptional cases where the OS / environment components are
279198090Srdivacky  // stuck into the vendor field.
280198090Srdivacky  if (StringRef(getTriple()).count('-') == 1) {
281198090Srdivacky    StringRef VendorName = getVendorName();
282198090Srdivacky
283198090Srdivacky    if (VendorName.startswith("mingw32")) { // 'i386-mingw32', etc.
284198090Srdivacky      Vendor = PC;
285198090Srdivacky      OS = MinGW32;
286198090Srdivacky      return;
287198090Srdivacky    }
288198090Srdivacky
289198090Srdivacky    // arm-elf is another example, but we don't currently parse anything about
290198090Srdivacky    // the environment.
291198090Srdivacky  }
292198090Srdivacky
293193323Sed  if (VendorName == "apple")
294193323Sed    Vendor = Apple;
295193323Sed  else if (VendorName == "pc")
296193323Sed    Vendor = PC;
297193323Sed  else
298193323Sed    Vendor = UnknownVendor;
299193323Sed
300198090Srdivacky  if (OSName.startswith("auroraux"))
301194612Sed    OS = AuroraUX;
302198090Srdivacky  else if (OSName.startswith("cygwin"))
303198090Srdivacky    OS = Cygwin;
304198090Srdivacky  else if (OSName.startswith("darwin"))
305193323Sed    OS = Darwin;
306198090Srdivacky  else if (OSName.startswith("dragonfly"))
307193323Sed    OS = DragonFly;
308198090Srdivacky  else if (OSName.startswith("freebsd"))
309193323Sed    OS = FreeBSD;
310198090Srdivacky  else if (OSName.startswith("linux"))
311193323Sed    OS = Linux;
312199989Srdivacky  else if (OSName.startswith("lv2"))
313199989Srdivacky    OS = Lv2;
314198090Srdivacky  else if (OSName.startswith("mingw32"))
315198090Srdivacky    OS = MinGW32;
316198090Srdivacky  else if (OSName.startswith("mingw64"))
317198090Srdivacky    OS = MinGW64;
318198090Srdivacky  else if (OSName.startswith("netbsd"))
319198090Srdivacky    OS = NetBSD;
320198090Srdivacky  else if (OSName.startswith("openbsd"))
321195340Sed    OS = OpenBSD;
322199481Srdivacky  else if (OSName.startswith("psp"))
323199481Srdivacky    OS = Psp;
324198090Srdivacky  else if (OSName.startswith("solaris"))
325198090Srdivacky    OS = Solaris;
326198090Srdivacky  else if (OSName.startswith("win32"))
327198090Srdivacky    OS = Win32;
328198396Srdivacky  else if (OSName.startswith("haiku"))
329198396Srdivacky  	OS = Haiku;
330193323Sed  else
331193323Sed    OS = UnknownOS;
332193323Sed
333193323Sed  assert(isInitialized() && "Failed to initialize!");
334193323Sed}
335193323Sed
336198090SrdivackyStringRef Triple::getArchName() const {
337198090Srdivacky  return StringRef(Data).split('-').first;           // Isolate first component
338193323Sed}
339193323Sed
340198090SrdivackyStringRef Triple::getVendorName() const {
341198090Srdivacky  StringRef Tmp = StringRef(Data).split('-').second; // Strip first component
342198090Srdivacky  return Tmp.split('-').first;                       // Isolate second component
343193323Sed}
344193323Sed
345198090SrdivackyStringRef Triple::getOSName() const {
346198090Srdivacky  StringRef Tmp = StringRef(Data).split('-').second; // Strip first component
347198090Srdivacky  Tmp = Tmp.split('-').second;                       // Strip second component
348198090Srdivacky  return Tmp.split('-').first;                       // Isolate third component
349193323Sed}
350193323Sed
351198090SrdivackyStringRef Triple::getEnvironmentName() const {
352198090Srdivacky  StringRef Tmp = StringRef(Data).split('-').second; // Strip first component
353198090Srdivacky  Tmp = Tmp.split('-').second;                       // Strip second component
354198090Srdivacky  return Tmp.split('-').second;                      // Strip third component
355193323Sed}
356193323Sed
357198090SrdivackyStringRef Triple::getOSAndEnvironmentName() const {
358198090Srdivacky  StringRef Tmp = StringRef(Data).split('-').second; // Strip first component
359198090Srdivacky  return Tmp.split('-').second;                      // Strip second component
360193323Sed}
361193323Sed
362198090Srdivackystatic unsigned EatNumber(StringRef &Str) {
363198090Srdivacky  assert(!Str.empty() && Str[0] >= '0' && Str[0] <= '9' && "Not a number");
364198090Srdivacky  unsigned Result = Str[0]-'0';
365198090Srdivacky
366198090Srdivacky  // Eat the digit.
367198090Srdivacky  Str = Str.substr(1);
368198090Srdivacky
369198090Srdivacky  // Handle "darwin11".
370198090Srdivacky  if (Result == 1 && !Str.empty() && Str[0] >= '0' && Str[0] <= '9') {
371198090Srdivacky    Result = Result*10 + (Str[0] - '0');
372198090Srdivacky    // Eat the digit.
373198090Srdivacky    Str = Str.substr(1);
374198090Srdivacky  }
375198090Srdivacky
376198090Srdivacky  return Result;
377193323Sed}
378193323Sed
379198090Srdivacky/// getDarwinNumber - Parse the 'darwin number' out of the specific target
380198090Srdivacky/// triple.  For example, if we have darwin8.5 return 8,5,0.  If any entry is
381198090Srdivacky/// not defined, return 0's.  This requires that the triple have an OSType of
382198090Srdivacky/// darwin before it is called.
383198090Srdivackyvoid Triple::getDarwinNumber(unsigned &Maj, unsigned &Min,
384198090Srdivacky                             unsigned &Revision) const {
385198090Srdivacky  assert(getOS() == Darwin && "Not a darwin target triple!");
386198090Srdivacky  StringRef OSName = getOSName();
387198090Srdivacky  assert(OSName.startswith("darwin") && "Unknown darwin target triple!");
388198090Srdivacky
389198090Srdivacky  // Strip off "darwin".
390198090Srdivacky  OSName = OSName.substr(6);
391198090Srdivacky
392198090Srdivacky  Maj = Min = Revision = 0;
393198090Srdivacky
394198090Srdivacky  if (OSName.empty() || OSName[0] < '0' || OSName[0] > '9')
395198090Srdivacky    return;
396198090Srdivacky
397198090Srdivacky  // The major version is the first digit.
398198090Srdivacky  Maj = EatNumber(OSName);
399198090Srdivacky  if (OSName.empty()) return;
400198090Srdivacky
401198090Srdivacky  // Handle minor version: 10.4.9 -> darwin8.9.
402198090Srdivacky  if (OSName[0] != '.')
403198090Srdivacky    return;
404198090Srdivacky
405198090Srdivacky  // Eat the '.'.
406198090Srdivacky  OSName = OSName.substr(1);
407198090Srdivacky
408198090Srdivacky  if (OSName.empty() || OSName[0] < '0' || OSName[0] > '9')
409198090Srdivacky    return;
410198090Srdivacky
411198090Srdivacky  Min = EatNumber(OSName);
412198090Srdivacky  if (OSName.empty()) return;
413198090Srdivacky
414198090Srdivacky  // Handle revision darwin8.9.1
415198090Srdivacky  if (OSName[0] != '.')
416198090Srdivacky    return;
417198090Srdivacky
418198090Srdivacky  // Eat the '.'.
419198090Srdivacky  OSName = OSName.substr(1);
420198090Srdivacky
421198090Srdivacky  if (OSName.empty() || OSName[0] < '0' || OSName[0] > '9')
422198090Srdivacky    return;
423198090Srdivacky
424198090Srdivacky  Revision = EatNumber(OSName);
425193323Sed}
426193323Sed
427198090Srdivackyvoid Triple::setTriple(const Twine &Str) {
428198090Srdivacky  Data = Str.str();
429193323Sed  Arch = InvalidArch;
430193323Sed}
431193323Sed
432193323Sedvoid Triple::setArch(ArchType Kind) {
433193323Sed  setArchName(getArchTypeName(Kind));
434193323Sed}
435193323Sed
436193323Sedvoid Triple::setVendor(VendorType Kind) {
437193323Sed  setVendorName(getVendorTypeName(Kind));
438193323Sed}
439193323Sed
440193323Sedvoid Triple::setOS(OSType Kind) {
441193323Sed  setOSName(getOSTypeName(Kind));
442193323Sed}
443193323Sed
444199481Srdivackyvoid Triple::setArchName(StringRef Str) {
445198090Srdivacky  // Work around a miscompilation bug for Twines in gcc 4.0.3.
446198090Srdivacky  SmallString<64> Triple;
447198090Srdivacky  Triple += Str;
448198090Srdivacky  Triple += "-";
449198090Srdivacky  Triple += getVendorName();
450198090Srdivacky  Triple += "-";
451198090Srdivacky  Triple += getOSAndEnvironmentName();
452198090Srdivacky  setTriple(Triple.str());
453193323Sed}
454193323Sed
455199481Srdivackyvoid Triple::setVendorName(StringRef Str) {
456193323Sed  setTriple(getArchName() + "-" + Str + "-" + getOSAndEnvironmentName());
457193323Sed}
458193323Sed
459199481Srdivackyvoid Triple::setOSName(StringRef Str) {
460193323Sed  if (hasEnvironment())
461193323Sed    setTriple(getArchName() + "-" + getVendorName() + "-" + Str +
462193323Sed              "-" + getEnvironmentName());
463193323Sed  else
464193323Sed    setTriple(getArchName() + "-" + getVendorName() + "-" + Str);
465193323Sed}
466193323Sed
467199481Srdivackyvoid Triple::setEnvironmentName(StringRef Str) {
468199481Srdivacky  setTriple(getArchName() + "-" + getVendorName() + "-" + getOSName() +
469193323Sed            "-" + Str);
470193323Sed}
471193323Sed
472199481Srdivackyvoid Triple::setOSAndEnvironmentName(StringRef Str) {
473193323Sed  setTriple(getArchName() + "-" + getVendorName() + "-" + Str);
474193323Sed}
475