summaryrefslogtreecommitdiff
path: root/lib/Support/Triple.cpp
diff options
context:
space:
mode:
authorDuncan Sands <baldrick@free.fr>2010-08-12 11:31:39 +0000
committerDuncan Sands <baldrick@free.fr>2010-08-12 11:31:39 +0000
commit335db223926931db204bf54d4accac6677b8e6b1 (patch)
tree897faf4c7a1ae316baa853b1e08de7781d4648bb /lib/Support/Triple.cpp
parent74862789001b62350fa1a316150fdab04689a0bc (diff)
downloadllvm-335db223926931db204bf54d4accac6677b8e6b1.tar.gz
llvm-335db223926931db204bf54d4accac6677b8e6b1.tar.bz2
llvm-335db223926931db204bf54d4accac6677b8e6b1.tar.xz
Add a 'normalize' method to the Triple class, which takes a mucked up
target triple and straightens it out. This does less than gcc's script config.sub, for example it turns i386-mingw32 into i386--mingw32 not i386-pc-mingw32, but it does a decent job of turning funky triples into something that the rest of the Triple class can understand. The plan is to use this to canonicalize triple's when they are first provided by users, and have the rest of LLVM only deal with canonical triples. Once this is done the special case workarounds in the Triple constructor can be removed, making the class more regular and easier to use. The comments and unittests for the Triple class are already adjusted in this patch appropriately for this brave new world of increased uniformity. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@110909 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Support/Triple.cpp')
-rw-r--r--lib/Support/Triple.cpp259
1 files changed, 196 insertions, 63 deletions
diff --git a/lib/Support/Triple.cpp b/lib/Support/Triple.cpp
index 6a70449b56..7806aec16c 100644
--- a/lib/Support/Triple.cpp
+++ b/lib/Support/Triple.cpp
@@ -221,121 +221,254 @@ const char *Triple::getArchNameForAssembler() {
//
-void Triple::Parse() const {
- assert(!isInitialized() && "Invalid parse call.");
-
- StringRef ArchName = getArchName();
- StringRef VendorName = getVendorName();
- StringRef OSName = getOSName();
-
+Triple::ArchType Triple::ParseArch(StringRef ArchName) {
if (ArchName.size() == 4 && ArchName[0] == 'i' &&
ArchName[2] == '8' && ArchName[3] == '6' &&
ArchName[1] - '3' < 6) // i[3-9]86
- Arch = x86;
+ return x86;
else if (ArchName == "amd64" || ArchName == "x86_64")
- Arch = x86_64;
+ return x86_64;
else if (ArchName == "bfin")
- Arch = bfin;
+ return bfin;
else if (ArchName == "pic16")
- Arch = pic16;
+ return pic16;
else if (ArchName == "powerpc")
- Arch = ppc;
+ return ppc;
else if ((ArchName == "powerpc64") || (ArchName == "ppu"))
- Arch = ppc64;
+ return ppc64;
else if (ArchName == "mblaze")
- Arch = mblaze;
+ return mblaze;
else if (ArchName == "arm" ||
ArchName.startswith("armv") ||
ArchName == "xscale")
- Arch = arm;
+ return arm;
else if (ArchName == "thumb" ||
ArchName.startswith("thumbv"))
- Arch = thumb;
+ return thumb;
else if (ArchName.startswith("alpha"))
- Arch = alpha;
+ return alpha;
else if (ArchName == "spu" || ArchName == "cellspu")
- Arch = cellspu;
+ return cellspu;
else if (ArchName == "msp430")
- Arch = msp430;
+ return msp430;
else if (ArchName == "mips" || ArchName == "mipsallegrex")
- Arch = mips;
+ return mips;
else if (ArchName == "mipsel" || ArchName == "mipsallegrexel" ||
ArchName == "psp")
- Arch = mipsel;
+ return mipsel;
else if (ArchName == "sparc")
- Arch = sparc;
+ return sparc;
else if (ArchName == "sparcv9")
- Arch = sparcv9;
+ return sparcv9;
else if (ArchName == "s390x")
- Arch = systemz;
+ return systemz;
else if (ArchName == "tce")
- Arch = tce;
+ return tce;
else if (ArchName == "xcore")
- Arch = xcore;
+ return xcore;
else
- Arch = UnknownArch;
-
-
- // Handle some exceptional cases where the OS / environment components are
- // stuck into the vendor field.
- if (StringRef(getTriple()).count('-') == 1) {
- StringRef VendorName = getVendorName();
-
- if (VendorName.startswith("mingw32")) { // 'i386-mingw32', etc.
- Vendor = PC;
- OS = MinGW32;
- return;
- }
-
- // arm-elf is another example, but we don't currently parse anything about
- // the environment.
- }
+ return UnknownArch;
+}
+Triple::VendorType Triple::ParseVendor(StringRef VendorName) {
if (VendorName == "apple")
- Vendor = Apple;
+ return Apple;
else if (VendorName == "pc")
- Vendor = PC;
+ return PC;
else
- Vendor = UnknownVendor;
+ return UnknownVendor;
+}
+Triple::OSType Triple::ParseOS(StringRef OSName) {
if (OSName.startswith("auroraux"))
- OS = AuroraUX;
+ return AuroraUX;
else if (OSName.startswith("cygwin"))
- OS = Cygwin;
+ return Cygwin;
else if (OSName.startswith("darwin"))
- OS = Darwin;
+ return Darwin;
else if (OSName.startswith("dragonfly"))
- OS = DragonFly;
+ return DragonFly;
else if (OSName.startswith("freebsd"))
- OS = FreeBSD;
+ return FreeBSD;
else if (OSName.startswith("linux"))
- OS = Linux;
+ return Linux;
else if (OSName.startswith("lv2"))
- OS = Lv2;
+ return Lv2;
else if (OSName.startswith("mingw32"))
- OS = MinGW32;
+ return MinGW32;
else if (OSName.startswith("mingw64"))
- OS = MinGW64;
+ return MinGW64;
else if (OSName.startswith("netbsd"))
- OS = NetBSD;
+ return NetBSD;
else if (OSName.startswith("openbsd"))
- OS = OpenBSD;
+ return OpenBSD;
else if (OSName.startswith("psp"))
- OS = Psp;
+ return Psp;
else if (OSName.startswith("solaris"))
- OS = Solaris;
+ return Solaris;
else if (OSName.startswith("win32"))
- OS = Win32;
+ return Win32;
else if (OSName.startswith("haiku"))
- OS = Haiku;
+ return Haiku;
else if (OSName.startswith("minix"))
- OS = Minix;
+ return Minix;
else
- OS = UnknownOS;
+ return UnknownOS;
+}
+
+void Triple::Parse() const {
+ assert(!isInitialized() && "Invalid parse call.");
+
+ Arch = ParseArch(getArchName());
+ Vendor = ParseVendor(getVendorName());
+ OS = ParseOS(getOSName());
+
+ // Handle some exceptional cases where the OS / environment components are
+ // stuck into the vendor field.
+ // TODO: Remove this logic and have places that need it use 'normalize'.
+ if (StringRef(getTriple()).count('-') == 1) {
+ StringRef VendorName = getVendorName();
+
+ if (VendorName.startswith("mingw32")) { // 'i386-mingw32', etc.
+ Vendor = PC;
+ OS = MinGW32;
+ return;
+ }
+
+ // arm-elf is another example, but we don't currently parse anything about
+ // the environment.
+ }
assert(isInitialized() && "Failed to initialize!");
}
+std::string Triple::normalize(StringRef Str) {
+ // Parse into components.
+ SmallVector<StringRef, 4> Components;
+ for (size_t First = 0, Last = 0; Last != StringRef::npos; First = Last + 1) {
+ Last = Str.find('-', First);
+ Components.push_back(Str.slice(First, Last));
+ }
+
+ // If the first component corresponds to a known architecture, preferentially
+ // use it for the architecture. If the second component corresponds to a
+ // known vendor, preferentially use it for the vendor, etc. This avoids silly
+ // component movement when a component parses as (eg) both a valid arch and a
+ // valid os.
+ ArchType Arch = UnknownArch;
+ if (Components.size() > 0)
+ Arch = ParseArch(Components[0]);
+ VendorType Vendor = UnknownVendor;
+ if (Components.size() > 1)
+ Vendor = ParseVendor(Components[1]);
+ OSType OS = UnknownOS;
+ if (Components.size() > 2)
+ OS = ParseOS(Components[2]);
+
+ // Note which components are already in their final position. These will not
+ // be moved.
+ bool Found[3];
+ Found[0] = Arch != UnknownArch;
+ Found[1] = Vendor != UnknownVendor;
+ Found[2] = OS != UnknownOS;
+
+ // If they are not there already, permute the components into their canonical
+ // positions by seeing if they parse as a valid architecture, and if so moving
+ // the component to the architecture position etc.
+ for (unsigned Pos = 0; Pos != 3; ++Pos) {
+ if (Found[Pos])
+ continue; // Already in the canonical position.
+
+ for (unsigned Idx = 0; Idx != Components.size(); ++Idx) {
+ // Do not reparse any components that already matched.
+ if (Idx < 3 && Found[Idx])
+ continue;
+
+ // Does this component parse as valid for the target position?
+ bool Valid = false;
+ StringRef Comp = Components[Idx];
+ switch (Pos) {
+ default:
+ assert(false && "unexpected component type!");
+ case 0:
+ Arch = ParseArch(Comp);
+ Valid = Arch != UnknownArch;
+ break;
+ case 1:
+ Vendor = ParseVendor(Comp);
+ Valid = Vendor != UnknownVendor;
+ break;
+ case 2:
+ OS = ParseOS(Comp);
+ Valid = OS != UnknownOS;
+ break;
+ }
+ if (!Valid)
+ continue; // Nope, try the next component.
+
+ // Move the component to the target position, pushing any non-fixed
+ // components that are in the way to the right. This tends to give
+ // good results in the common cases of a forgotten vendor component
+ // or a wrongly positioned environment.
+ if (Pos < Idx) {
+ // Insert left, pushing the existing components to the right. For
+ // example, a-b-i386 -> i386-a-b when moving i386 to the front.
+ StringRef CurrentComponent(""); // The empty component.
+ // Replace the component we are moving with an empty component.
+ std::swap(CurrentComponent, Components[Idx]);
+ // Insert the component being moved at Pos, displacing any existing
+ // components to the right.
+ for (unsigned i = Pos; !CurrentComponent.empty(); ++i) {
+ // Skip over any fixed components.
+ while (i < 3 && Found[i]) ++i;
+ // Place the component at the new position, getting the component
+ // that was at this position - it will be moved right.
+ std::swap(CurrentComponent, Components[i]);
+ }
+ } else if (Pos > Idx) {
+ // Push right by inserting empty components until the component at Idx
+ // reaches the target position Pos. For example, pc-a -> -pc-a when
+ // moving pc to the second position.
+ do {
+ // Insert one empty component at Idx.
+ StringRef CurrentComponent(""); // The empty component.
+ for (unsigned i = Idx; i < Components.size(); ++i) {
+ // Skip over any fixed components.
+ while (i < 3 && Found[i]) ++i;
+ // Place the component at the new position, getting the component
+ // that was at this position - it will be moved right.
+ std::swap(CurrentComponent, Components[i]);
+ // If it was placed on top of an empty component then we are done.
+ if (CurrentComponent.empty())
+ break;
+ }
+ // The last component was pushed off the end - append it.
+ if (!CurrentComponent.empty())
+ Components.push_back(CurrentComponent);
+
+ // Advance Idx to the component's new position.
+ while (++Idx < 3 && Found[Idx]) {}
+ } while (Idx < Pos); // Add more until the final position is reached.
+ }
+ assert(Pos < Components.size() && Components[Pos] == Comp &&
+ "Component moved wrong!");
+ Found[Pos] = true;
+ break;
+ }
+ }
+
+ // Special case logic goes here. At this point Arch, Vendor and OS have the
+ // correct values for the computed components.
+
+ // Stick the corrected components back together to form the normalized string.
+ std::string Normalized;
+ for (unsigned i = 0, e = Components.size(); i != e; ++i) {
+ if (i) Normalized += '-';
+ Normalized += Components[i];
+ }
+ return Normalized;
+}
+
StringRef Triple::getArchName() const {
return StringRef(Data).split('-').first; // Isolate first component
}