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"
11249423Sdim#include "llvm/ADT/STLExtras.h"
12198090Srdivacky#include "llvm/ADT/SmallString.h"
13234353Sdim#include "llvm/ADT/StringSwitch.h"
14234353Sdim#include "llvm/Support/ErrorHandling.h"
15193323Sed#include <cstring>
16193323Sedusing namespace llvm;
17193323Sed
18193323Sedconst char *Triple::getArchTypeName(ArchType Kind) {
19193323Sed  switch (Kind) {
20193323Sed  case UnknownArch: return "unknown";
21218893Sdim
22249423Sdim  case aarch64: return "aarch64";
23198090Srdivacky  case arm:     return "arm";
24234353Sdim  case hexagon: return "hexagon";
25198090Srdivacky  case mips:    return "mips";
26198090Srdivacky  case mipsel:  return "mipsel";
27226633Sdim  case mips64:  return "mips64";
28226633Sdim  case mips64el:return "mips64el";
29198090Srdivacky  case msp430:  return "msp430";
30198090Srdivacky  case ppc64:   return "powerpc64";
31263508Sdim  case ppc64le: return "powerpc64le";
32198090Srdivacky  case ppc:     return "powerpc";
33234353Sdim  case r600:    return "r600";
34198090Srdivacky  case sparc:   return "sparc";
35203954Srdivacky  case sparcv9: return "sparcv9";
36251662Sdim  case systemz: return "s390x";
37198090Srdivacky  case tce:     return "tce";
38198090Srdivacky  case thumb:   return "thumb";
39198090Srdivacky  case x86:     return "i386";
40198090Srdivacky  case x86_64:  return "x86_64";
41198090Srdivacky  case xcore:   return "xcore";
42239462Sdim  case nvptx:   return "nvptx";
43239462Sdim  case nvptx64: return "nvptx64";
44226633Sdim  case le32:    return "le32";
45226633Sdim  case amdil:   return "amdil";
46243830Sdim  case spir:    return "spir";
47243830Sdim  case spir64:  return "spir64";
48193323Sed  }
49193323Sed
50234353Sdim  llvm_unreachable("Invalid ArchType!");
51193323Sed}
52193323Sed
53198090Srdivackyconst char *Triple::getArchTypePrefix(ArchType Kind) {
54198090Srdivacky  switch (Kind) {
55198090Srdivacky  default:
56198090Srdivacky    return 0;
57198090Srdivacky
58249423Sdim  case aarch64: return "aarch64";
59249423Sdim
60198090Srdivacky  case arm:
61198090Srdivacky  case thumb:   return "arm";
62198090Srdivacky
63198090Srdivacky  case ppc64:
64263508Sdim  case ppc64le:
65198090Srdivacky  case ppc:     return "ppc";
66198090Srdivacky
67239462Sdim  case mips:
68239462Sdim  case mipsel:
69239462Sdim  case mips64:
70239462Sdim  case mips64el:return "mips";
71234353Sdim
72239462Sdim  case hexagon: return "hexagon";
73239462Sdim
74234353Sdim  case r600:    return "r600";
75234353Sdim
76203954Srdivacky  case sparcv9:
77198090Srdivacky  case sparc:   return "sparc";
78198090Srdivacky
79251662Sdim  case systemz: return "systemz";
80251662Sdim
81198090Srdivacky  case x86:
82198090Srdivacky  case x86_64:  return "x86";
83218893Sdim
84198090Srdivacky  case xcore:   return "xcore";
85218893Sdim
86239462Sdim  case nvptx:   return "nvptx";
87239462Sdim  case nvptx64: return "nvptx";
88226633Sdim  case le32:    return "le32";
89226633Sdim  case amdil:   return "amdil";
90243830Sdim  case spir:    return "spir";
91243830Sdim  case spir64:  return "spir";
92198090Srdivacky  }
93198090Srdivacky}
94198090Srdivacky
95193323Sedconst char *Triple::getVendorTypeName(VendorType Kind) {
96193323Sed  switch (Kind) {
97193323Sed  case UnknownVendor: return "unknown";
98193323Sed
99193323Sed  case Apple: return "apple";
100198090Srdivacky  case PC: return "pc";
101221345Sdim  case SCEI: return "scei";
102234353Sdim  case BGP: return "bgp";
103234353Sdim  case BGQ: return "bgq";
104243830Sdim  case Freescale: return "fsl";
105243830Sdim  case IBM: return "ibm";
106263508Sdim  case NVIDIA: return "nvidia";
107193323Sed  }
108193323Sed
109234353Sdim  llvm_unreachable("Invalid VendorType!");
110193323Sed}
111193323Sed
112193323Sedconst char *Triple::getOSTypeName(OSType Kind) {
113193323Sed  switch (Kind) {
114193323Sed  case UnknownOS: return "unknown";
115193323Sed
116194612Sed  case AuroraUX: return "auroraux";
117198090Srdivacky  case Cygwin: return "cygwin";
118193323Sed  case Darwin: return "darwin";
119193323Sed  case DragonFly: return "dragonfly";
120193323Sed  case FreeBSD: return "freebsd";
121221345Sdim  case IOS: return "ios";
122226633Sdim  case KFreeBSD: return "kfreebsd";
123193323Sed  case Linux: return "linux";
124199989Srdivacky  case Lv2: return "lv2";
125221345Sdim  case MacOSX: return "macosx";
126198090Srdivacky  case MinGW32: return "mingw32";
127198090Srdivacky  case NetBSD: return "netbsd";
128195340Sed  case OpenBSD: return "openbsd";
129198090Srdivacky  case Solaris: return "solaris";
130198090Srdivacky  case Win32: return "win32";
131198396Srdivacky  case Haiku: return "haiku";
132210299Sed  case Minix: return "minix";
133224145Sdim  case RTEMS: return "rtems";
134249423Sdim  case NaCl: return "nacl";
135234353Sdim  case CNK: return "cnk";
136239462Sdim  case Bitrig: return "bitrig";
137243830Sdim  case AIX: return "aix";
138263508Sdim  case CUDA: return "cuda";
139263508Sdim  case NVCL: return "nvcl";
140193323Sed  }
141193323Sed
142234353Sdim  llvm_unreachable("Invalid OSType");
143193323Sed}
144193323Sed
145218893Sdimconst char *Triple::getEnvironmentTypeName(EnvironmentType Kind) {
146218893Sdim  switch (Kind) {
147218893Sdim  case UnknownEnvironment: return "unknown";
148218893Sdim  case GNU: return "gnu";
149234353Sdim  case GNUEABIHF: return "gnueabihf";
150218893Sdim  case GNUEABI: return "gnueabi";
151249423Sdim  case GNUX32: return "gnux32";
152218893Sdim  case EABI: return "eabi";
153218893Sdim  case MachO: return "macho";
154243830Sdim  case Android: return "android";
155243830Sdim  case ELF: return "elf";
156218893Sdim  }
157218893Sdim
158234353Sdim  llvm_unreachable("Invalid EnvironmentType!");
159218893Sdim}
160218893Sdim
161199481SrdivackyTriple::ArchType Triple::getArchTypeForLLVMName(StringRef Name) {
162234353Sdim  return StringSwitch<Triple::ArchType>(Name)
163249423Sdim    .Case("aarch64", aarch64)
164234353Sdim    .Case("arm", arm)
165234353Sdim    .Case("mips", mips)
166234353Sdim    .Case("mipsel", mipsel)
167234353Sdim    .Case("mips64", mips64)
168234353Sdim    .Case("mips64el", mips64el)
169234353Sdim    .Case("msp430", msp430)
170234353Sdim    .Case("ppc64", ppc64)
171234353Sdim    .Case("ppc32", ppc)
172234353Sdim    .Case("ppc", ppc)
173263508Sdim    .Case("ppc64le", ppc64le)
174234353Sdim    .Case("r600", r600)
175234353Sdim    .Case("hexagon", hexagon)
176234353Sdim    .Case("sparc", sparc)
177234353Sdim    .Case("sparcv9", sparcv9)
178251662Sdim    .Case("systemz", systemz)
179234353Sdim    .Case("tce", tce)
180234353Sdim    .Case("thumb", thumb)
181234353Sdim    .Case("x86", x86)
182234353Sdim    .Case("x86-64", x86_64)
183234353Sdim    .Case("xcore", xcore)
184239462Sdim    .Case("nvptx", nvptx)
185239462Sdim    .Case("nvptx64", nvptx64)
186234353Sdim    .Case("le32", le32)
187234353Sdim    .Case("amdil", amdil)
188243830Sdim    .Case("spir", spir)
189243830Sdim    .Case("spir64", spir64)
190234353Sdim    .Default(UnknownArch);
191198090Srdivacky}
192198090Srdivacky
193206083Srdivacky// Returns architecture name that is understood by the target assembler.
194199481Srdivackyconst char *Triple::getArchNameForAssembler() {
195221345Sdim  if (!isOSDarwin() && getVendor() != Triple::Apple)
196199481Srdivacky    return NULL;
197199481Srdivacky
198234353Sdim  return StringSwitch<const char*>(getArchName())
199234353Sdim    .Case("i386", "i386")
200234353Sdim    .Case("x86_64", "x86_64")
201234353Sdim    .Case("powerpc", "ppc")
202234353Sdim    .Case("powerpc64", "ppc64")
203263508Sdim    .Case("powerpc64le", "ppc64le")
204234353Sdim    .Case("arm", "arm")
205234353Sdim    .Cases("armv4t", "thumbv4t", "armv4t")
206234353Sdim    .Cases("armv5", "armv5e", "thumbv5", "thumbv5e", "armv5")
207234353Sdim    .Cases("armv6", "thumbv6", "armv6")
208234353Sdim    .Cases("armv7", "thumbv7", "armv7")
209234353Sdim    .Case("r600", "r600")
210239462Sdim    .Case("nvptx", "nvptx")
211239462Sdim    .Case("nvptx64", "nvptx64")
212234353Sdim    .Case("le32", "le32")
213234353Sdim    .Case("amdil", "amdil")
214243830Sdim    .Case("spir", "spir")
215243830Sdim    .Case("spir64", "spir64")
216234353Sdim    .Default(NULL);
217199481Srdivacky}
218199481Srdivacky
219234353Sdimstatic Triple::ArchType parseArch(StringRef ArchName) {
220234353Sdim  return StringSwitch<Triple::ArchType>(ArchName)
221234353Sdim    .Cases("i386", "i486", "i586", "i686", Triple::x86)
222234353Sdim    // FIXME: Do we need to support these?
223234353Sdim    .Cases("i786", "i886", "i986", Triple::x86)
224263508Sdim    .Cases("amd64", "x86_64", "x86_64h", Triple::x86_64)
225234353Sdim    .Case("powerpc", Triple::ppc)
226234353Sdim    .Cases("powerpc64", "ppu", Triple::ppc64)
227263508Sdim    .Case("powerpc64le", Triple::ppc64le)
228249423Sdim    .Case("aarch64", Triple::aarch64)
229234353Sdim    .Cases("arm", "xscale", Triple::arm)
230234353Sdim    // FIXME: It would be good to replace these with explicit names for all the
231234353Sdim    // various suffixes supported.
232234353Sdim    .StartsWith("armv", Triple::arm)
233234353Sdim    .Case("thumb", Triple::thumb)
234234353Sdim    .StartsWith("thumbv", Triple::thumb)
235234353Sdim    .Case("msp430", Triple::msp430)
236234353Sdim    .Cases("mips", "mipseb", "mipsallegrex", Triple::mips)
237234353Sdim    .Cases("mipsel", "mipsallegrexel", Triple::mipsel)
238234353Sdim    .Cases("mips64", "mips64eb", Triple::mips64)
239234353Sdim    .Case("mips64el", Triple::mips64el)
240234353Sdim    .Case("r600", Triple::r600)
241234353Sdim    .Case("hexagon", Triple::hexagon)
242251662Sdim    .Case("s390x", Triple::systemz)
243234353Sdim    .Case("sparc", Triple::sparc)
244263508Sdim    .Cases("sparcv9", "sparc64", Triple::sparcv9)
245234353Sdim    .Case("tce", Triple::tce)
246234353Sdim    .Case("xcore", Triple::xcore)
247239462Sdim    .Case("nvptx", Triple::nvptx)
248239462Sdim    .Case("nvptx64", Triple::nvptx64)
249234353Sdim    .Case("le32", Triple::le32)
250234353Sdim    .Case("amdil", Triple::amdil)
251243830Sdim    .Case("spir", Triple::spir)
252243830Sdim    .Case("spir64", Triple::spir64)
253234353Sdim    .Default(Triple::UnknownArch);
254234353Sdim}
255193323Sed
256234353Sdimstatic Triple::VendorType parseVendor(StringRef VendorName) {
257234353Sdim  return StringSwitch<Triple::VendorType>(VendorName)
258234353Sdim    .Case("apple", Triple::Apple)
259234353Sdim    .Case("pc", Triple::PC)
260234353Sdim    .Case("scei", Triple::SCEI)
261234353Sdim    .Case("bgp", Triple::BGP)
262234353Sdim    .Case("bgq", Triple::BGQ)
263243830Sdim    .Case("fsl", Triple::Freescale)
264243830Sdim    .Case("ibm", Triple::IBM)
265263508Sdim    .Case("nvidia", Triple::NVIDIA)
266234353Sdim    .Default(Triple::UnknownVendor);
267212904Sdim}
268193323Sed
269234353Sdimstatic Triple::OSType parseOS(StringRef OSName) {
270234353Sdim  return StringSwitch<Triple::OSType>(OSName)
271234353Sdim    .StartsWith("auroraux", Triple::AuroraUX)
272234353Sdim    .StartsWith("cygwin", Triple::Cygwin)
273234353Sdim    .StartsWith("darwin", Triple::Darwin)
274234353Sdim    .StartsWith("dragonfly", Triple::DragonFly)
275234353Sdim    .StartsWith("freebsd", Triple::FreeBSD)
276234353Sdim    .StartsWith("ios", Triple::IOS)
277234353Sdim    .StartsWith("kfreebsd", Triple::KFreeBSD)
278234353Sdim    .StartsWith("linux", Triple::Linux)
279234353Sdim    .StartsWith("lv2", Triple::Lv2)
280234353Sdim    .StartsWith("macosx", Triple::MacOSX)
281234353Sdim    .StartsWith("mingw32", Triple::MinGW32)
282234353Sdim    .StartsWith("netbsd", Triple::NetBSD)
283234353Sdim    .StartsWith("openbsd", Triple::OpenBSD)
284234353Sdim    .StartsWith("solaris", Triple::Solaris)
285234353Sdim    .StartsWith("win32", Triple::Win32)
286234353Sdim    .StartsWith("haiku", Triple::Haiku)
287234353Sdim    .StartsWith("minix", Triple::Minix)
288234353Sdim    .StartsWith("rtems", Triple::RTEMS)
289249423Sdim    .StartsWith("nacl", Triple::NaCl)
290234353Sdim    .StartsWith("cnk", Triple::CNK)
291239462Sdim    .StartsWith("bitrig", Triple::Bitrig)
292243830Sdim    .StartsWith("aix", Triple::AIX)
293263508Sdim    .StartsWith("cuda", Triple::CUDA)
294263508Sdim    .StartsWith("nvcl", Triple::NVCL)
295234353Sdim    .Default(Triple::UnknownOS);
296212904Sdim}
297193323Sed
298234353Sdimstatic Triple::EnvironmentType parseEnvironment(StringRef EnvironmentName) {
299234353Sdim  return StringSwitch<Triple::EnvironmentType>(EnvironmentName)
300234353Sdim    .StartsWith("eabi", Triple::EABI)
301234353Sdim    .StartsWith("gnueabihf", Triple::GNUEABIHF)
302234353Sdim    .StartsWith("gnueabi", Triple::GNUEABI)
303249423Sdim    .StartsWith("gnux32", Triple::GNUX32)
304234353Sdim    .StartsWith("gnu", Triple::GNU)
305234353Sdim    .StartsWith("macho", Triple::MachO)
306243830Sdim    .StartsWith("android", Triple::Android)
307243830Sdim    .StartsWith("elf", Triple::ELF)
308234353Sdim    .Default(Triple::UnknownEnvironment);
309212904Sdim}
310193323Sed
311234353Sdim/// \brief Construct a triple from the string representation provided.
312234353Sdim///
313234353Sdim/// This stores the string representation and parses the various pieces into
314234353Sdim/// enum members.
315234353SdimTriple::Triple(const Twine &Str)
316234353Sdim    : Data(Str.str()),
317234353Sdim      Arch(parseArch(getArchName())),
318234353Sdim      Vendor(parseVendor(getVendorName())),
319234353Sdim      OS(parseOS(getOSName())),
320234353Sdim      Environment(parseEnvironment(getEnvironmentName())) {
321218893Sdim}
322218893Sdim
323234353Sdim/// \brief Construct a triple from string representations of the architecture,
324234353Sdim/// vendor, and OS.
325234353Sdim///
326234353Sdim/// This joins each argument into a canonical string representation and parses
327234353Sdim/// them into enum members. It leaves the environment unknown and omits it from
328234353Sdim/// the string representation.
329234353SdimTriple::Triple(const Twine &ArchStr, const Twine &VendorStr, const Twine &OSStr)
330234353Sdim    : Data((ArchStr + Twine('-') + VendorStr + Twine('-') + OSStr).str()),
331234353Sdim      Arch(parseArch(ArchStr.str())),
332234353Sdim      Vendor(parseVendor(VendorStr.str())),
333234353Sdim      OS(parseOS(OSStr.str())),
334234353Sdim      Environment() {
335234353Sdim}
336212904Sdim
337234353Sdim/// \brief Construct a triple from string representations of the architecture,
338234353Sdim/// vendor, OS, and environment.
339234353Sdim///
340234353Sdim/// This joins each argument into a canonical string representation and parses
341234353Sdim/// them into enum members.
342234353SdimTriple::Triple(const Twine &ArchStr, const Twine &VendorStr, const Twine &OSStr,
343234353Sdim               const Twine &EnvironmentStr)
344234353Sdim    : Data((ArchStr + Twine('-') + VendorStr + Twine('-') + OSStr + Twine('-') +
345234353Sdim            EnvironmentStr).str()),
346234353Sdim      Arch(parseArch(ArchStr.str())),
347234353Sdim      Vendor(parseVendor(VendorStr.str())),
348234353Sdim      OS(parseOS(OSStr.str())),
349234353Sdim      Environment(parseEnvironment(EnvironmentStr.str())) {
350193323Sed}
351193323Sed
352212904Sdimstd::string Triple::normalize(StringRef Str) {
353212904Sdim  // Parse into components.
354212904Sdim  SmallVector<StringRef, 4> Components;
355234353Sdim  Str.split(Components, "-");
356212904Sdim
357212904Sdim  // If the first component corresponds to a known architecture, preferentially
358212904Sdim  // use it for the architecture.  If the second component corresponds to a
359212904Sdim  // known vendor, preferentially use it for the vendor, etc.  This avoids silly
360212904Sdim  // component movement when a component parses as (eg) both a valid arch and a
361212904Sdim  // valid os.
362212904Sdim  ArchType Arch = UnknownArch;
363212904Sdim  if (Components.size() > 0)
364234353Sdim    Arch = parseArch(Components[0]);
365212904Sdim  VendorType Vendor = UnknownVendor;
366212904Sdim  if (Components.size() > 1)
367234353Sdim    Vendor = parseVendor(Components[1]);
368212904Sdim  OSType OS = UnknownOS;
369212904Sdim  if (Components.size() > 2)
370234353Sdim    OS = parseOS(Components[2]);
371218893Sdim  EnvironmentType Environment = UnknownEnvironment;
372218893Sdim  if (Components.size() > 3)
373234353Sdim    Environment = parseEnvironment(Components[3]);
374212904Sdim
375212904Sdim  // Note which components are already in their final position.  These will not
376212904Sdim  // be moved.
377218893Sdim  bool Found[4];
378212904Sdim  Found[0] = Arch != UnknownArch;
379212904Sdim  Found[1] = Vendor != UnknownVendor;
380212904Sdim  Found[2] = OS != UnknownOS;
381218893Sdim  Found[3] = Environment != UnknownEnvironment;
382212904Sdim
383212904Sdim  // If they are not there already, permute the components into their canonical
384212904Sdim  // positions by seeing if they parse as a valid architecture, and if so moving
385212904Sdim  // the component to the architecture position etc.
386218893Sdim  for (unsigned Pos = 0; Pos != array_lengthof(Found); ++Pos) {
387212904Sdim    if (Found[Pos])
388212904Sdim      continue; // Already in the canonical position.
389212904Sdim
390212904Sdim    for (unsigned Idx = 0; Idx != Components.size(); ++Idx) {
391212904Sdim      // Do not reparse any components that already matched.
392218893Sdim      if (Idx < array_lengthof(Found) && Found[Idx])
393212904Sdim        continue;
394212904Sdim
395212904Sdim      // Does this component parse as valid for the target position?
396212904Sdim      bool Valid = false;
397212904Sdim      StringRef Comp = Components[Idx];
398212904Sdim      switch (Pos) {
399234353Sdim      default: llvm_unreachable("unexpected component type!");
400212904Sdim      case 0:
401234353Sdim        Arch = parseArch(Comp);
402212904Sdim        Valid = Arch != UnknownArch;
403212904Sdim        break;
404212904Sdim      case 1:
405234353Sdim        Vendor = parseVendor(Comp);
406212904Sdim        Valid = Vendor != UnknownVendor;
407212904Sdim        break;
408212904Sdim      case 2:
409234353Sdim        OS = parseOS(Comp);
410212904Sdim        Valid = OS != UnknownOS;
411212904Sdim        break;
412218893Sdim      case 3:
413234353Sdim        Environment = parseEnvironment(Comp);
414218893Sdim        Valid = Environment != UnknownEnvironment;
415218893Sdim        break;
416212904Sdim      }
417212904Sdim      if (!Valid)
418212904Sdim        continue; // Nope, try the next component.
419212904Sdim
420212904Sdim      // Move the component to the target position, pushing any non-fixed
421212904Sdim      // components that are in the way to the right.  This tends to give
422212904Sdim      // good results in the common cases of a forgotten vendor component
423212904Sdim      // or a wrongly positioned environment.
424212904Sdim      if (Pos < Idx) {
425212904Sdim        // Insert left, pushing the existing components to the right.  For
426212904Sdim        // example, a-b-i386 -> i386-a-b when moving i386 to the front.
427212904Sdim        StringRef CurrentComponent(""); // The empty component.
428212904Sdim        // Replace the component we are moving with an empty component.
429212904Sdim        std::swap(CurrentComponent, Components[Idx]);
430212904Sdim        // Insert the component being moved at Pos, displacing any existing
431212904Sdim        // components to the right.
432212904Sdim        for (unsigned i = Pos; !CurrentComponent.empty(); ++i) {
433212904Sdim          // Skip over any fixed components.
434234353Sdim          while (i < array_lengthof(Found) && Found[i])
435234353Sdim            ++i;
436212904Sdim          // Place the component at the new position, getting the component
437212904Sdim          // that was at this position - it will be moved right.
438212904Sdim          std::swap(CurrentComponent, Components[i]);
439212904Sdim        }
440212904Sdim      } else if (Pos > Idx) {
441212904Sdim        // Push right by inserting empty components until the component at Idx
442212904Sdim        // reaches the target position Pos.  For example, pc-a -> -pc-a when
443212904Sdim        // moving pc to the second position.
444212904Sdim        do {
445212904Sdim          // Insert one empty component at Idx.
446212904Sdim          StringRef CurrentComponent(""); // The empty component.
447218893Sdim          for (unsigned i = Idx; i < Components.size();) {
448212904Sdim            // Place the component at the new position, getting the component
449212904Sdim            // that was at this position - it will be moved right.
450212904Sdim            std::swap(CurrentComponent, Components[i]);
451212904Sdim            // If it was placed on top of an empty component then we are done.
452212904Sdim            if (CurrentComponent.empty())
453212904Sdim              break;
454218893Sdim            // Advance to the next component, skipping any fixed components.
455218893Sdim            while (++i < array_lengthof(Found) && Found[i])
456218893Sdim              ;
457212904Sdim          }
458212904Sdim          // The last component was pushed off the end - append it.
459212904Sdim          if (!CurrentComponent.empty())
460212904Sdim            Components.push_back(CurrentComponent);
461212904Sdim
462212904Sdim          // Advance Idx to the component's new position.
463234353Sdim          while (++Idx < array_lengthof(Found) && Found[Idx])
464234353Sdim            ;
465212904Sdim        } while (Idx < Pos); // Add more until the final position is reached.
466212904Sdim      }
467212904Sdim      assert(Pos < Components.size() && Components[Pos] == Comp &&
468212904Sdim             "Component moved wrong!");
469212904Sdim      Found[Pos] = true;
470212904Sdim      break;
471212904Sdim    }
472212904Sdim  }
473212904Sdim
474212904Sdim  // Special case logic goes here.  At this point Arch, Vendor and OS have the
475212904Sdim  // correct values for the computed components.
476212904Sdim
477212904Sdim  // Stick the corrected components back together to form the normalized string.
478212904Sdim  std::string Normalized;
479212904Sdim  for (unsigned i = 0, e = Components.size(); i != e; ++i) {
480212904Sdim    if (i) Normalized += '-';
481212904Sdim    Normalized += Components[i];
482212904Sdim  }
483212904Sdim  return Normalized;
484212904Sdim}
485212904Sdim
486198090SrdivackyStringRef Triple::getArchName() const {
487198090Srdivacky  return StringRef(Data).split('-').first;           // Isolate first component
488193323Sed}
489193323Sed
490198090SrdivackyStringRef Triple::getVendorName() const {
491198090Srdivacky  StringRef Tmp = StringRef(Data).split('-').second; // Strip first component
492198090Srdivacky  return Tmp.split('-').first;                       // Isolate second component
493193323Sed}
494193323Sed
495198090SrdivackyStringRef Triple::getOSName() const {
496198090Srdivacky  StringRef Tmp = StringRef(Data).split('-').second; // Strip first component
497198090Srdivacky  Tmp = Tmp.split('-').second;                       // Strip second component
498198090Srdivacky  return Tmp.split('-').first;                       // Isolate third component
499193323Sed}
500193323Sed
501198090SrdivackyStringRef Triple::getEnvironmentName() const {
502198090Srdivacky  StringRef Tmp = StringRef(Data).split('-').second; // Strip first component
503198090Srdivacky  Tmp = Tmp.split('-').second;                       // Strip second component
504198090Srdivacky  return Tmp.split('-').second;                      // Strip third component
505193323Sed}
506193323Sed
507198090SrdivackyStringRef Triple::getOSAndEnvironmentName() const {
508198090Srdivacky  StringRef Tmp = StringRef(Data).split('-').second; // Strip first component
509198090Srdivacky  return Tmp.split('-').second;                      // Strip second component
510193323Sed}
511193323Sed
512198090Srdivackystatic unsigned EatNumber(StringRef &Str) {
513198090Srdivacky  assert(!Str.empty() && Str[0] >= '0' && Str[0] <= '9' && "Not a number");
514221345Sdim  unsigned Result = 0;
515218893Sdim
516221345Sdim  do {
517221345Sdim    // Consume the leading digit.
518221345Sdim    Result = Result*10 + (Str[0] - '0');
519218893Sdim
520198090Srdivacky    // Eat the digit.
521198090Srdivacky    Str = Str.substr(1);
522221345Sdim  } while (!Str.empty() && Str[0] >= '0' && Str[0] <= '9');
523218893Sdim
524198090Srdivacky  return Result;
525193323Sed}
526193323Sed
527221345Sdimvoid Triple::getOSVersion(unsigned &Major, unsigned &Minor,
528221345Sdim                          unsigned &Micro) const {
529198090Srdivacky  StringRef OSName = getOSName();
530218893Sdim
531221345Sdim  // Assume that the OS portion of the triple starts with the canonical name.
532221345Sdim  StringRef OSTypeName = getOSTypeName(getOS());
533221345Sdim  if (OSName.startswith(OSTypeName))
534221345Sdim    OSName = OSName.substr(OSTypeName.size());
535218893Sdim
536221345Sdim  // Any unset version defaults to 0.
537221345Sdim  Major = Minor = Micro = 0;
538198090Srdivacky
539221345Sdim  // Parse up to three components.
540221345Sdim  unsigned *Components[3] = { &Major, &Minor, &Micro };
541221345Sdim  for (unsigned i = 0; i != 3; ++i) {
542221345Sdim    if (OSName.empty() || OSName[0] < '0' || OSName[0] > '9')
543221345Sdim      break;
544198090Srdivacky
545221345Sdim    // Consume the leading number.
546221345Sdim    *Components[i] = EatNumber(OSName);
547218893Sdim
548221345Sdim    // Consume the separator, if present.
549221345Sdim    if (OSName.startswith("."))
550221345Sdim      OSName = OSName.substr(1);
551221345Sdim  }
552193323Sed}
553193323Sed
554234353Sdimbool Triple::getMacOSXVersion(unsigned &Major, unsigned &Minor,
555234353Sdim                              unsigned &Micro) const {
556234353Sdim  getOSVersion(Major, Minor, Micro);
557234353Sdim
558234353Sdim  switch (getOS()) {
559234353Sdim  default: llvm_unreachable("unexpected OS for Darwin triple");
560234353Sdim  case Darwin:
561234353Sdim    // Default to darwin8, i.e., MacOSX 10.4.
562234353Sdim    if (Major == 0)
563234353Sdim      Major = 8;
564234353Sdim    // Darwin version numbers are skewed from OS X versions.
565234353Sdim    if (Major < 4)
566234353Sdim      return false;
567234353Sdim    Micro = 0;
568234353Sdim    Minor = Major - 4;
569234353Sdim    Major = 10;
570234353Sdim    break;
571234353Sdim  case MacOSX:
572234353Sdim    // Default to 10.4.
573234353Sdim    if (Major == 0) {
574234353Sdim      Major = 10;
575234353Sdim      Minor = 4;
576234353Sdim    }
577234353Sdim    if (Major != 10)
578234353Sdim      return false;
579234353Sdim    break;
580234353Sdim  case IOS:
581234353Sdim    // Ignore the version from the triple.  This is only handled because the
582234353Sdim    // the clang driver combines OS X and IOS support into a common Darwin
583234353Sdim    // toolchain that wants to know the OS X version number even when targeting
584234353Sdim    // IOS.
585234353Sdim    Major = 10;
586234353Sdim    Minor = 4;
587234353Sdim    Micro = 0;
588234353Sdim    break;
589234353Sdim  }
590234353Sdim  return true;
591234353Sdim}
592234353Sdim
593239462Sdimvoid Triple::getiOSVersion(unsigned &Major, unsigned &Minor,
594239462Sdim                           unsigned &Micro) const {
595239462Sdim  switch (getOS()) {
596239462Sdim  default: llvm_unreachable("unexpected OS for Darwin triple");
597239462Sdim  case Darwin:
598239462Sdim  case MacOSX:
599239462Sdim    // Ignore the version from the triple.  This is only handled because the
600239462Sdim    // the clang driver combines OS X and IOS support into a common Darwin
601239462Sdim    // toolchain that wants to know the iOS version number even when targeting
602239462Sdim    // OS X.
603239462Sdim    Major = 3;
604239462Sdim    Minor = 0;
605239462Sdim    Micro = 0;
606239462Sdim    break;
607239462Sdim  case IOS:
608239462Sdim    getOSVersion(Major, Minor, Micro);
609239462Sdim    // Default to 3.0.
610239462Sdim    if (Major == 0)
611239462Sdim      Major = 3;
612239462Sdim    break;
613239462Sdim  }
614239462Sdim}
615239462Sdim
616198090Srdivackyvoid Triple::setTriple(const Twine &Str) {
617234353Sdim  *this = Triple(Str);
618193323Sed}
619193323Sed
620193323Sedvoid Triple::setArch(ArchType Kind) {
621193323Sed  setArchName(getArchTypeName(Kind));
622193323Sed}
623193323Sed
624193323Sedvoid Triple::setVendor(VendorType Kind) {
625193323Sed  setVendorName(getVendorTypeName(Kind));
626193323Sed}
627193323Sed
628193323Sedvoid Triple::setOS(OSType Kind) {
629193323Sed  setOSName(getOSTypeName(Kind));
630193323Sed}
631193323Sed
632218893Sdimvoid Triple::setEnvironment(EnvironmentType Kind) {
633218893Sdim  setEnvironmentName(getEnvironmentTypeName(Kind));
634218893Sdim}
635218893Sdim
636199481Srdivackyvoid Triple::setArchName(StringRef Str) {
637198090Srdivacky  // Work around a miscompilation bug for Twines in gcc 4.0.3.
638198090Srdivacky  SmallString<64> Triple;
639198090Srdivacky  Triple += Str;
640198090Srdivacky  Triple += "-";
641198090Srdivacky  Triple += getVendorName();
642198090Srdivacky  Triple += "-";
643198090Srdivacky  Triple += getOSAndEnvironmentName();
644198090Srdivacky  setTriple(Triple.str());
645193323Sed}
646193323Sed
647199481Srdivackyvoid Triple::setVendorName(StringRef Str) {
648193323Sed  setTriple(getArchName() + "-" + Str + "-" + getOSAndEnvironmentName());
649193323Sed}
650193323Sed
651199481Srdivackyvoid Triple::setOSName(StringRef Str) {
652193323Sed  if (hasEnvironment())
653193323Sed    setTriple(getArchName() + "-" + getVendorName() + "-" + Str +
654193323Sed              "-" + getEnvironmentName());
655193323Sed  else
656193323Sed    setTriple(getArchName() + "-" + getVendorName() + "-" + Str);
657193323Sed}
658193323Sed
659199481Srdivackyvoid Triple::setEnvironmentName(StringRef Str) {
660199481Srdivacky  setTriple(getArchName() + "-" + getVendorName() + "-" + getOSName() +
661193323Sed            "-" + Str);
662193323Sed}
663193323Sed
664199481Srdivackyvoid Triple::setOSAndEnvironmentName(StringRef Str) {
665193323Sed  setTriple(getArchName() + "-" + getVendorName() + "-" + Str);
666193323Sed}
667234353Sdim
668234353Sdimstatic unsigned getArchPointerBitWidth(llvm::Triple::ArchType Arch) {
669234353Sdim  switch (Arch) {
670234353Sdim  case llvm::Triple::UnknownArch:
671234353Sdim    return 0;
672234353Sdim
673234353Sdim  case llvm::Triple::msp430:
674234353Sdim    return 16;
675234353Sdim
676234353Sdim  case llvm::Triple::amdil:
677234353Sdim  case llvm::Triple::arm:
678234353Sdim  case llvm::Triple::hexagon:
679234353Sdim  case llvm::Triple::le32:
680234353Sdim  case llvm::Triple::mips:
681234353Sdim  case llvm::Triple::mipsel:
682239462Sdim  case llvm::Triple::nvptx:
683234353Sdim  case llvm::Triple::ppc:
684234353Sdim  case llvm::Triple::r600:
685234353Sdim  case llvm::Triple::sparc:
686234353Sdim  case llvm::Triple::tce:
687234353Sdim  case llvm::Triple::thumb:
688234353Sdim  case llvm::Triple::x86:
689234353Sdim  case llvm::Triple::xcore:
690243830Sdim  case llvm::Triple::spir:
691234353Sdim    return 32;
692234353Sdim
693249423Sdim  case llvm::Triple::aarch64:
694234353Sdim  case llvm::Triple::mips64:
695234353Sdim  case llvm::Triple::mips64el:
696239462Sdim  case llvm::Triple::nvptx64:
697234353Sdim  case llvm::Triple::ppc64:
698263508Sdim  case llvm::Triple::ppc64le:
699234353Sdim  case llvm::Triple::sparcv9:
700251662Sdim  case llvm::Triple::systemz:
701234353Sdim  case llvm::Triple::x86_64:
702243830Sdim  case llvm::Triple::spir64:
703234353Sdim    return 64;
704234353Sdim  }
705234353Sdim  llvm_unreachable("Invalid architecture value");
706234353Sdim}
707234353Sdim
708234353Sdimbool Triple::isArch64Bit() const {
709234353Sdim  return getArchPointerBitWidth(getArch()) == 64;
710234353Sdim}
711234353Sdim
712234353Sdimbool Triple::isArch32Bit() const {
713234353Sdim  return getArchPointerBitWidth(getArch()) == 32;
714234353Sdim}
715234353Sdim
716234353Sdimbool Triple::isArch16Bit() const {
717234353Sdim  return getArchPointerBitWidth(getArch()) == 16;
718234353Sdim}
719234353Sdim
720234353SdimTriple Triple::get32BitArchVariant() const {
721234353Sdim  Triple T(*this);
722234353Sdim  switch (getArch()) {
723234353Sdim  case Triple::UnknownArch:
724249423Sdim  case Triple::aarch64:
725234353Sdim  case Triple::msp430:
726251662Sdim  case Triple::systemz:
727263508Sdim  case Triple::ppc64le:
728234353Sdim    T.setArch(UnknownArch);
729234353Sdim    break;
730234353Sdim
731234353Sdim  case Triple::amdil:
732243830Sdim  case Triple::spir:
733234353Sdim  case Triple::arm:
734234353Sdim  case Triple::hexagon:
735234353Sdim  case Triple::le32:
736234353Sdim  case Triple::mips:
737234353Sdim  case Triple::mipsel:
738239462Sdim  case Triple::nvptx:
739234353Sdim  case Triple::ppc:
740234353Sdim  case Triple::r600:
741234353Sdim  case Triple::sparc:
742234353Sdim  case Triple::tce:
743234353Sdim  case Triple::thumb:
744234353Sdim  case Triple::x86:
745234353Sdim  case Triple::xcore:
746234353Sdim    // Already 32-bit.
747234353Sdim    break;
748234353Sdim
749234353Sdim  case Triple::mips64:    T.setArch(Triple::mips);    break;
750234353Sdim  case Triple::mips64el:  T.setArch(Triple::mipsel);  break;
751239462Sdim  case Triple::nvptx64:   T.setArch(Triple::nvptx);   break;
752234353Sdim  case Triple::ppc64:     T.setArch(Triple::ppc);   break;
753234353Sdim  case Triple::sparcv9:   T.setArch(Triple::sparc);   break;
754234353Sdim  case Triple::x86_64:    T.setArch(Triple::x86);     break;
755243830Sdim  case Triple::spir64:    T.setArch(Triple::spir);    break;
756234353Sdim  }
757234353Sdim  return T;
758234353Sdim}
759234353Sdim
760234353SdimTriple Triple::get64BitArchVariant() const {
761234353Sdim  Triple T(*this);
762234353Sdim  switch (getArch()) {
763234353Sdim  case Triple::UnknownArch:
764234353Sdim  case Triple::amdil:
765234353Sdim  case Triple::arm:
766234353Sdim  case Triple::hexagon:
767234353Sdim  case Triple::le32:
768234353Sdim  case Triple::msp430:
769234353Sdim  case Triple::r600:
770234353Sdim  case Triple::tce:
771234353Sdim  case Triple::thumb:
772234353Sdim  case Triple::xcore:
773234353Sdim    T.setArch(UnknownArch);
774234353Sdim    break;
775234353Sdim
776249423Sdim  case Triple::aarch64:
777243830Sdim  case Triple::spir64:
778234353Sdim  case Triple::mips64:
779234353Sdim  case Triple::mips64el:
780239462Sdim  case Triple::nvptx64:
781234353Sdim  case Triple::ppc64:
782263508Sdim  case Triple::ppc64le:
783234353Sdim  case Triple::sparcv9:
784251662Sdim  case Triple::systemz:
785234353Sdim  case Triple::x86_64:
786234353Sdim    // Already 64-bit.
787234353Sdim    break;
788234353Sdim
789234353Sdim  case Triple::mips:    T.setArch(Triple::mips64);    break;
790234353Sdim  case Triple::mipsel:  T.setArch(Triple::mips64el);  break;
791239462Sdim  case Triple::nvptx:   T.setArch(Triple::nvptx64);   break;
792234353Sdim  case Triple::ppc:     T.setArch(Triple::ppc64);     break;
793234353Sdim  case Triple::sparc:   T.setArch(Triple::sparcv9);   break;
794234353Sdim  case Triple::x86:     T.setArch(Triple::x86_64);    break;
795243830Sdim  case Triple::spir:    T.setArch(Triple::spir64);    break;
796234353Sdim  }
797234353Sdim  return T;
798234353Sdim}
799