Home | History | Annotate | Download | only in Support
      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 #include "llvm/ADT/SmallString.h"
     12 #include "llvm/ADT/STLExtras.h"
     13 #include <cstring>
     14 using namespace llvm;
     15 
     16 const char *Triple::getArchTypeName(ArchType Kind) {
     17   switch (Kind) {
     18   case InvalidArch: return "<invalid>";
     19   case UnknownArch: return "unknown";
     20 
     21   case alpha:   return "alpha";
     22   case arm:     return "arm";
     23   case bfin:    return "bfin";
     24   case cellspu: return "cellspu";
     25   case mips:    return "mips";
     26   case mipsel:  return "mipsel";
     27   case mips64:  return "mips64";
     28   case mips64el:return "mips64el";
     29   case msp430:  return "msp430";
     30   case ppc64:   return "powerpc64";
     31   case ppc:     return "powerpc";
     32   case sparc:   return "sparc";
     33   case sparcv9: return "sparcv9";
     34   case systemz: return "s390x";
     35   case tce:     return "tce";
     36   case thumb:   return "thumb";
     37   case x86:     return "i386";
     38   case x86_64:  return "x86_64";
     39   case xcore:   return "xcore";
     40   case mblaze:  return "mblaze";
     41   case ptx32:   return "ptx32";
     42   case ptx64:   return "ptx64";
     43   case le32:    return "le32";
     44   case amdil:   return "amdil";
     45   }
     46 
     47   return "<invalid>";
     48 }
     49 
     50 const char *Triple::getArchTypePrefix(ArchType Kind) {
     51   switch (Kind) {
     52   default:
     53     return 0;
     54 
     55   case alpha:   return "alpha";
     56 
     57   case arm:
     58   case thumb:   return "arm";
     59 
     60   case bfin:    return "bfin";
     61 
     62   case cellspu: return "spu";
     63 
     64   case ppc64:
     65   case ppc:     return "ppc";
     66 
     67   case mblaze:  return "mblaze";
     68 
     69   case sparcv9:
     70   case sparc:   return "sparc";
     71 
     72   case x86:
     73   case x86_64:  return "x86";
     74 
     75   case xcore:   return "xcore";
     76 
     77   case ptx32:   return "ptx";
     78   case ptx64:   return "ptx";
     79   case le32:    return "le32";
     80   case amdil:   return "amdil";
     81   }
     82 }
     83 
     84 const char *Triple::getVendorTypeName(VendorType Kind) {
     85   switch (Kind) {
     86   case UnknownVendor: return "unknown";
     87 
     88   case Apple: return "apple";
     89   case PC: return "pc";
     90   case SCEI: return "scei";
     91   }
     92 
     93   return "<invalid>";
     94 }
     95 
     96 const char *Triple::getOSTypeName(OSType Kind) {
     97   switch (Kind) {
     98   case UnknownOS: return "unknown";
     99 
    100   case AuroraUX: return "auroraux";
    101   case Cygwin: return "cygwin";
    102   case Darwin: return "darwin";
    103   case DragonFly: return "dragonfly";
    104   case FreeBSD: return "freebsd";
    105   case IOS: return "ios";
    106   case KFreeBSD: return "kfreebsd";
    107   case Linux: return "linux";
    108   case Lv2: return "lv2";
    109   case MacOSX: return "macosx";
    110   case MinGW32: return "mingw32";
    111   case NetBSD: return "netbsd";
    112   case OpenBSD: return "openbsd";
    113   case Psp: return "psp";
    114   case Solaris: return "solaris";
    115   case Win32: return "win32";
    116   case Haiku: return "haiku";
    117   case Minix: return "minix";
    118   case RTEMS: return "rtems";
    119   case NativeClient: return "nacl";
    120   }
    121 
    122   return "<invalid>";
    123 }
    124 
    125 const char *Triple::getEnvironmentTypeName(EnvironmentType Kind) {
    126   switch (Kind) {
    127   case UnknownEnvironment: return "unknown";
    128   case GNU: return "gnu";
    129   case GNUEABI: return "gnueabi";
    130   case EABI: return "eabi";
    131   case MachO: return "macho";
    132   }
    133 
    134   return "<invalid>";
    135 }
    136 
    137 Triple::ArchType Triple::getArchTypeForLLVMName(StringRef Name) {
    138   if (Name == "alpha")
    139     return alpha;
    140   if (Name == "arm")
    141     return arm;
    142   if (Name == "bfin")
    143     return bfin;
    144   if (Name == "cellspu")
    145     return cellspu;
    146   if (Name == "mips")
    147     return mips;
    148   if (Name == "mipsel")
    149     return mipsel;
    150   if (Name == "mips64")
    151     return mips64;
    152   if (Name == "mips64el")
    153     return mips64el;
    154   if (Name == "msp430")
    155     return msp430;
    156   if (Name == "ppc64")
    157     return ppc64;
    158   if (Name == "ppc32")
    159     return ppc;
    160   if (Name == "ppc")
    161     return ppc;
    162   if (Name == "mblaze")
    163     return mblaze;
    164   if (Name == "sparc")
    165     return sparc;
    166   if (Name == "sparcv9")
    167     return sparcv9;
    168   if (Name == "systemz")
    169     return systemz;
    170   if (Name == "tce")
    171     return tce;
    172   if (Name == "thumb")
    173     return thumb;
    174   if (Name == "x86")
    175     return x86;
    176   if (Name == "x86-64")
    177     return x86_64;
    178   if (Name == "xcore")
    179     return xcore;
    180   if (Name == "ptx32")
    181     return ptx32;
    182   if (Name == "ptx64")
    183     return ptx64;
    184   if (Name == "le32")
    185     return le32;
    186   if (Name == "amdil")
    187       return amdil;
    188 
    189   return UnknownArch;
    190 }
    191 
    192 Triple::ArchType Triple::getArchTypeForDarwinArchName(StringRef Str) {
    193   // See arch(3) and llvm-gcc's driver-driver.c. We don't implement support for
    194   // archs which Darwin doesn't use.
    195 
    196   // The matching this routine does is fairly pointless, since it is neither the
    197   // complete architecture list, nor a reasonable subset. The problem is that
    198   // historically the driver driver accepts this and also ties its -march=
    199   // handling to the architecture name, so we need to be careful before removing
    200   // support for it.
    201 
    202   // This code must be kept in sync with Clang's Darwin specific argument
    203   // translation.
    204 
    205   if (Str == "ppc" || Str == "ppc601" || Str == "ppc603" || Str == "ppc604" ||
    206       Str == "ppc604e" || Str == "ppc750" || Str == "ppc7400" ||
    207       Str == "ppc7450" || Str == "ppc970")
    208     return Triple::ppc;
    209 
    210   if (Str == "ppc64")
    211     return Triple::ppc64;
    212 
    213   if (Str == "i386" || Str == "i486" || Str == "i486SX" || Str == "pentium" ||
    214       Str == "i586" || Str == "pentpro" || Str == "i686" || Str == "pentIIm3" ||
    215       Str == "pentIIm5" || Str == "pentium4")
    216     return Triple::x86;
    217 
    218   if (Str == "x86_64")
    219     return Triple::x86_64;
    220 
    221   // This is derived from the driver driver.
    222   if (Str == "arm" || Str == "armv4t" || Str == "armv5" || Str == "xscale" ||
    223       Str == "armv6" || Str == "armv7" || Str == "armv7f" || Str == "armv7k" ||
    224       Str == "armv7s")
    225     return Triple::arm;
    226 
    227   if (Str == "ptx32")
    228     return Triple::ptx32;
    229   if (Str == "ptx64")
    230     return Triple::ptx64;
    231   if (Str == "amdil")
    232       return Triple::amdil;
    233 
    234   return Triple::UnknownArch;
    235 }
    236 
    237 // Returns architecture name that is understood by the target assembler.
    238 const char *Triple::getArchNameForAssembler() {
    239   if (!isOSDarwin() && getVendor() != Triple::Apple)
    240     return NULL;
    241 
    242   StringRef Str = getArchName();
    243   if (Str == "i386")
    244     return "i386";
    245   if (Str == "x86_64")
    246     return "x86_64";
    247   if (Str == "powerpc")
    248     return "ppc";
    249   if (Str == "powerpc64")
    250     return "ppc64";
    251   if (Str == "mblaze" || Str == "microblaze")
    252     return "mblaze";
    253   if (Str == "arm")
    254     return "arm";
    255   if (Str == "armv4t" || Str == "thumbv4t")
    256     return "armv4t";
    257   if (Str == "armv5" || Str == "armv5e" || Str == "thumbv5"
    258       || Str == "thumbv5e")
    259     return "armv5";
    260   if (Str == "armv6" || Str == "thumbv6")
    261     return "armv6";
    262   if (Str == "armv7" || Str == "thumbv7")
    263     return "armv7";
    264   if (Str == "ptx32")
    265     return "ptx32";
    266   if (Str == "ptx64")
    267     return "ptx64";
    268   if (Str == "le32")
    269     return "le32";
    270   if (Str == "amdil")
    271       return "amdil";
    272   return NULL;
    273 }
    274 
    275 //
    276 
    277 Triple::ArchType Triple::ParseArch(StringRef ArchName) {
    278   if (ArchName.size() == 4 && ArchName[0] == 'i' &&
    279       ArchName[2] == '8' && ArchName[3] == '6' &&
    280       ArchName[1] - '3' < 6) // i[3-9]86
    281     return x86;
    282   else if (ArchName == "amd64" || ArchName == "x86_64")
    283     return x86_64;
    284   else if (ArchName == "bfin")
    285     return bfin;
    286   else if (ArchName == "powerpc")
    287     return ppc;
    288   else if ((ArchName == "powerpc64") || (ArchName == "ppu"))
    289     return ppc64;
    290   else if (ArchName == "mblaze")
    291     return mblaze;
    292   else if (ArchName == "arm" ||
    293            ArchName.startswith("armv") ||
    294            ArchName == "xscale")
    295     return arm;
    296   else if (ArchName == "thumb" ||
    297            ArchName.startswith("thumbv"))
    298     return thumb;
    299   else if (ArchName.startswith("alpha"))
    300     return alpha;
    301   else if (ArchName == "spu" || ArchName == "cellspu")
    302     return cellspu;
    303   else if (ArchName == "msp430")
    304     return msp430;
    305   else if (ArchName == "mips" || ArchName == "mipseb" ||
    306            ArchName == "mipsallegrex")
    307     return mips;
    308   else if (ArchName == "mipsel" || ArchName == "mipsallegrexel" ||
    309            ArchName == "psp")
    310     return mipsel;
    311   else if (ArchName == "mips64" || ArchName == "mips64eb")
    312     return mips64;
    313   else if (ArchName == "mips64el")
    314     return mips64el;
    315   else if (ArchName == "sparc")
    316     return sparc;
    317   else if (ArchName == "sparcv9")
    318     return sparcv9;
    319   else if (ArchName == "s390x")
    320     return systemz;
    321   else if (ArchName == "tce")
    322     return tce;
    323   else if (ArchName == "xcore")
    324     return xcore;
    325   else if (ArchName == "ptx32")
    326     return ptx32;
    327   else if (ArchName == "ptx64")
    328     return ptx64;
    329   else if (ArchName == "le32")
    330     return le32;
    331   else if (ArchName == "amdil")
    332       return amdil;
    333   else
    334     return UnknownArch;
    335 }
    336 
    337 Triple::VendorType Triple::ParseVendor(StringRef VendorName) {
    338   if (VendorName == "apple")
    339     return Apple;
    340   else if (VendorName == "pc")
    341     return PC;
    342   else if (VendorName == "scei")
    343     return SCEI;
    344   else
    345     return UnknownVendor;
    346 }
    347 
    348 Triple::OSType Triple::ParseOS(StringRef OSName) {
    349   if (OSName.startswith("auroraux"))
    350     return AuroraUX;
    351   else if (OSName.startswith("cygwin"))
    352     return Cygwin;
    353   else if (OSName.startswith("darwin"))
    354     return Darwin;
    355   else if (OSName.startswith("dragonfly"))
    356     return DragonFly;
    357   else if (OSName.startswith("freebsd"))
    358     return FreeBSD;
    359   else if (OSName.startswith("ios"))
    360     return IOS;
    361   else if (OSName.startswith("kfreebsd"))
    362     return KFreeBSD;
    363   else if (OSName.startswith("linux"))
    364     return Linux;
    365   else if (OSName.startswith("lv2"))
    366     return Lv2;
    367   else if (OSName.startswith("macosx"))
    368     return MacOSX;
    369   else if (OSName.startswith("mingw32"))
    370     return MinGW32;
    371   else if (OSName.startswith("netbsd"))
    372     return NetBSD;
    373   else if (OSName.startswith("openbsd"))
    374     return OpenBSD;
    375   else if (OSName.startswith("psp"))
    376     return Psp;
    377   else if (OSName.startswith("solaris"))
    378     return Solaris;
    379   else if (OSName.startswith("win32"))
    380     return Win32;
    381   else if (OSName.startswith("haiku"))
    382     return Haiku;
    383   else if (OSName.startswith("minix"))
    384     return Minix;
    385   else if (OSName.startswith("rtems"))
    386     return RTEMS;
    387   else if (OSName.startswith("nacl"))
    388     return NativeClient;
    389   else
    390     return UnknownOS;
    391 }
    392 
    393 Triple::EnvironmentType Triple::ParseEnvironment(StringRef EnvironmentName) {
    394   if (EnvironmentName.startswith("eabi"))
    395     return EABI;
    396   else if (EnvironmentName.startswith("gnueabi"))
    397     return GNUEABI;
    398   else if (EnvironmentName.startswith("gnu"))
    399     return GNU;
    400   else if (EnvironmentName.startswith("macho"))
    401     return MachO;
    402   else
    403     return UnknownEnvironment;
    404 }
    405 
    406 void Triple::Parse() const {
    407   assert(!isInitialized() && "Invalid parse call.");
    408 
    409   Arch = ParseArch(getArchName());
    410   Vendor = ParseVendor(getVendorName());
    411   OS = ParseOS(getOSName());
    412   Environment = ParseEnvironment(getEnvironmentName());
    413 
    414   assert(isInitialized() && "Failed to initialize!");
    415 }
    416 
    417 std::string Triple::normalize(StringRef Str) {
    418   // Parse into components.
    419   SmallVector<StringRef, 4> Components;
    420   for (size_t First = 0, Last = 0; Last != StringRef::npos; First = Last + 1) {
    421     Last = Str.find('-', First);
    422     Components.push_back(Str.slice(First, Last));
    423   }
    424 
    425   // If the first component corresponds to a known architecture, preferentially
    426   // use it for the architecture.  If the second component corresponds to a
    427   // known vendor, preferentially use it for the vendor, etc.  This avoids silly
    428   // component movement when a component parses as (eg) both a valid arch and a
    429   // valid os.
    430   ArchType Arch = UnknownArch;
    431   if (Components.size() > 0)
    432     Arch = ParseArch(Components[0]);
    433   VendorType Vendor = UnknownVendor;
    434   if (Components.size() > 1)
    435     Vendor = ParseVendor(Components[1]);
    436   OSType OS = UnknownOS;
    437   if (Components.size() > 2)
    438     OS = ParseOS(Components[2]);
    439   EnvironmentType Environment = UnknownEnvironment;
    440   if (Components.size() > 3)
    441     Environment = ParseEnvironment(Components[3]);
    442 
    443   // Note which components are already in their final position.  These will not
    444   // be moved.
    445   bool Found[4];
    446   Found[0] = Arch != UnknownArch;
    447   Found[1] = Vendor != UnknownVendor;
    448   Found[2] = OS != UnknownOS;
    449   Found[3] = Environment != UnknownEnvironment;
    450 
    451   // If they are not there already, permute the components into their canonical
    452   // positions by seeing if they parse as a valid architecture, and if so moving
    453   // the component to the architecture position etc.
    454   for (unsigned Pos = 0; Pos != array_lengthof(Found); ++Pos) {
    455     if (Found[Pos])
    456       continue; // Already in the canonical position.
    457 
    458     for (unsigned Idx = 0; Idx != Components.size(); ++Idx) {
    459       // Do not reparse any components that already matched.
    460       if (Idx < array_lengthof(Found) && Found[Idx])
    461         continue;
    462 
    463       // Does this component parse as valid for the target position?
    464       bool Valid = false;
    465       StringRef Comp = Components[Idx];
    466       switch (Pos) {
    467       default:
    468         assert(false && "unexpected component type!");
    469       case 0:
    470         Arch = ParseArch(Comp);
    471         Valid = Arch != UnknownArch;
    472         break;
    473       case 1:
    474         Vendor = ParseVendor(Comp);
    475         Valid = Vendor != UnknownVendor;
    476         break;
    477       case 2:
    478         OS = ParseOS(Comp);
    479         Valid = OS != UnknownOS;
    480         break;
    481       case 3:
    482         Environment = ParseEnvironment(Comp);
    483         Valid = Environment != UnknownEnvironment;
    484         break;
    485       }
    486       if (!Valid)
    487         continue; // Nope, try the next component.
    488 
    489       // Move the component to the target position, pushing any non-fixed
    490       // components that are in the way to the right.  This tends to give
    491       // good results in the common cases of a forgotten vendor component
    492       // or a wrongly positioned environment.
    493       if (Pos < Idx) {
    494         // Insert left, pushing the existing components to the right.  For
    495         // example, a-b-i386 -> i386-a-b when moving i386 to the front.
    496         StringRef CurrentComponent(""); // The empty component.
    497         // Replace the component we are moving with an empty component.
    498         std::swap(CurrentComponent, Components[Idx]);
    499         // Insert the component being moved at Pos, displacing any existing
    500         // components to the right.
    501         for (unsigned i = Pos; !CurrentComponent.empty(); ++i) {
    502           // Skip over any fixed components.
    503           while (i < array_lengthof(Found) && Found[i]) ++i;
    504           // Place the component at the new position, getting the component
    505           // that was at this position - it will be moved right.
    506           std::swap(CurrentComponent, Components[i]);
    507         }
    508       } else if (Pos > Idx) {
    509         // Push right by inserting empty components until the component at Idx
    510         // reaches the target position Pos.  For example, pc-a -> -pc-a when
    511         // moving pc to the second position.
    512         do {
    513           // Insert one empty component at Idx.
    514           StringRef CurrentComponent(""); // The empty component.
    515           for (unsigned i = Idx; i < Components.size();) {
    516             // Place the component at the new position, getting the component
    517             // that was at this position - it will be moved right.
    518             std::swap(CurrentComponent, Components[i]);
    519             // If it was placed on top of an empty component then we are done.
    520             if (CurrentComponent.empty())
    521               break;
    522             // Advance to the next component, skipping any fixed components.
    523             while (++i < array_lengthof(Found) && Found[i])
    524               ;
    525           }
    526           // The last component was pushed off the end - append it.
    527           if (!CurrentComponent.empty())
    528             Components.push_back(CurrentComponent);
    529 
    530           // Advance Idx to the component's new position.
    531           while (++Idx < array_lengthof(Found) && Found[Idx]) {}
    532         } while (Idx < Pos); // Add more until the final position is reached.
    533       }
    534       assert(Pos < Components.size() && Components[Pos] == Comp &&
    535              "Component moved wrong!");
    536       Found[Pos] = true;
    537       break;
    538     }
    539   }
    540 
    541   // Special case logic goes here.  At this point Arch, Vendor and OS have the
    542   // correct values for the computed components.
    543 
    544   // Stick the corrected components back together to form the normalized string.
    545   std::string Normalized;
    546   for (unsigned i = 0, e = Components.size(); i != e; ++i) {
    547     if (i) Normalized += '-';
    548     Normalized += Components[i];
    549   }
    550   return Normalized;
    551 }
    552 
    553 StringRef Triple::getArchName() const {
    554   return StringRef(Data).split('-').first;           // Isolate first component
    555 }
    556 
    557 StringRef Triple::getVendorName() const {
    558   StringRef Tmp = StringRef(Data).split('-').second; // Strip first component
    559   return Tmp.split('-').first;                       // Isolate second component
    560 }
    561 
    562 StringRef Triple::getOSName() const {
    563   StringRef Tmp = StringRef(Data).split('-').second; // Strip first component
    564   Tmp = Tmp.split('-').second;                       // Strip second component
    565   return Tmp.split('-').first;                       // Isolate third component
    566 }
    567 
    568 StringRef Triple::getEnvironmentName() const {
    569   StringRef Tmp = StringRef(Data).split('-').second; // Strip first component
    570   Tmp = Tmp.split('-').second;                       // Strip second component
    571   return Tmp.split('-').second;                      // Strip third component
    572 }
    573 
    574 StringRef Triple::getOSAndEnvironmentName() const {
    575   StringRef Tmp = StringRef(Data).split('-').second; // Strip first component
    576   return Tmp.split('-').second;                      // Strip second component
    577 }
    578 
    579 static unsigned EatNumber(StringRef &Str) {
    580   assert(!Str.empty() && Str[0] >= '0' && Str[0] <= '9' && "Not a number");
    581   unsigned Result = 0;
    582 
    583   do {
    584     // Consume the leading digit.
    585     Result = Result*10 + (Str[0] - '0');
    586 
    587     // Eat the digit.
    588     Str = Str.substr(1);
    589   } while (!Str.empty() && Str[0] >= '0' && Str[0] <= '9');
    590 
    591   return Result;
    592 }
    593 
    594 void Triple::getOSVersion(unsigned &Major, unsigned &Minor,
    595                           unsigned &Micro) const {
    596   StringRef OSName = getOSName();
    597 
    598   // Assume that the OS portion of the triple starts with the canonical name.
    599   StringRef OSTypeName = getOSTypeName(getOS());
    600   if (OSName.startswith(OSTypeName))
    601     OSName = OSName.substr(OSTypeName.size());
    602 
    603   // Any unset version defaults to 0.
    604   Major = Minor = Micro = 0;
    605 
    606   // Parse up to three components.
    607   unsigned *Components[3] = { &Major, &Minor, &Micro };
    608   for (unsigned i = 0; i != 3; ++i) {
    609     if (OSName.empty() || OSName[0] < '0' || OSName[0] > '9')
    610       break;
    611 
    612     // Consume the leading number.
    613     *Components[i] = EatNumber(OSName);
    614 
    615     // Consume the separator, if present.
    616     if (OSName.startswith("."))
    617       OSName = OSName.substr(1);
    618   }
    619 }
    620 
    621 void Triple::setTriple(const Twine &Str) {
    622   Data = Str.str();
    623   Arch = InvalidArch;
    624 }
    625 
    626 void Triple::setArch(ArchType Kind) {
    627   setArchName(getArchTypeName(Kind));
    628 }
    629 
    630 void Triple::setVendor(VendorType Kind) {
    631   setVendorName(getVendorTypeName(Kind));
    632 }
    633 
    634 void Triple::setOS(OSType Kind) {
    635   setOSName(getOSTypeName(Kind));
    636 }
    637 
    638 void Triple::setEnvironment(EnvironmentType Kind) {
    639   setEnvironmentName(getEnvironmentTypeName(Kind));
    640 }
    641 
    642 void Triple::setArchName(StringRef Str) {
    643   // Work around a miscompilation bug for Twines in gcc 4.0.3.
    644   SmallString<64> Triple;
    645   Triple += Str;
    646   Triple += "-";
    647   Triple += getVendorName();
    648   Triple += "-";
    649   Triple += getOSAndEnvironmentName();
    650   setTriple(Triple.str());
    651 }
    652 
    653 void Triple::setVendorName(StringRef Str) {
    654   setTriple(getArchName() + "-" + Str + "-" + getOSAndEnvironmentName());
    655 }
    656 
    657 void Triple::setOSName(StringRef Str) {
    658   if (hasEnvironment())
    659     setTriple(getArchName() + "-" + getVendorName() + "-" + Str +
    660               "-" + getEnvironmentName());
    661   else
    662     setTriple(getArchName() + "-" + getVendorName() + "-" + Str);
    663 }
    664 
    665 void Triple::setEnvironmentName(StringRef Str) {
    666   setTriple(getArchName() + "-" + getVendorName() + "-" + getOSName() +
    667             "-" + Str);
    668 }
    669 
    670 void Triple::setOSAndEnvironmentName(StringRef Str) {
    671   setTriple(getArchName() + "-" + getVendorName() + "-" + Str);
    672 }
    673