diff --git a/include/llvm/ADT/Triple.h b/include/llvm/ADT/Triple.h index 0b80bb5a33a..60f622d2dea 100644 --- a/include/llvm/ADT/Triple.h +++ b/include/llvm/ADT/Triple.h @@ -95,6 +95,9 @@ public: Haiku, Minix }; + enum EnvironmentType { + UnknownEnvironment + }; private: std::string Data; @@ -108,10 +111,14 @@ private: /// The parsed OS type. mutable OSType OS; + /// The parsed Environment type. + mutable EnvironmentType Environment; + bool isInitialized() const { return Arch != InvalidArch; } static ArchType ParseArch(StringRef ArchName); static VendorType ParseVendor(StringRef VendorName); static OSType ParseOS(StringRef OSName); + static EnvironmentType ParseEnvironment(StringRef EnvironmentName); void Parse() const; public: @@ -128,6 +135,17 @@ public: Data += OSStr; } + explicit Triple(StringRef ArchStr, StringRef VendorStr, StringRef OSStr, + StringRef EnvironmentStr) + : Data(ArchStr), Arch(InvalidArch) { + Data += '-'; + Data += VendorStr; + Data += '-'; + Data += OSStr; + Data += '-'; + Data += EnvironmentStr; + } + /// @} /// @name Normalization /// @{ @@ -166,6 +184,12 @@ public: return getEnvironmentName() != ""; } + /// getEnvironment - Get the parsed environment type of this triple. + EnvironmentType getEnvironment() const { + if (!isInitialized()) Parse(); + return Environment; + } + /// @} /// @name Direct Component Access /// @{ @@ -225,6 +249,10 @@ public: /// to a known type. void setOS(OSType Kind); + /// setEnvironment - Set the environment (fourth) component of the triple + /// to a known type. + void setEnvironment(EnvironmentType Kind); + /// setTriple - Set all components to the new triple \arg Str. void setTriple(const Twine &Str); @@ -272,9 +300,14 @@ public: /// vendor. static const char *getVendorTypeName(VendorType Kind); - /// getOSTypeName - Get the canonical name for the \arg Kind vendor. + /// getOSTypeName - Get the canonical name for the \arg Kind operating + /// system. static const char *getOSTypeName(OSType Kind); + /// getEnvironmentTypeName - Get the canonical name for the \arg Kind + /// environment. + static const char *getEnvironmentTypeName(EnvironmentType Kind); + /// @} /// @name Static helpers for converting alternate architecture names. /// @{ diff --git a/lib/Support/Triple.cpp b/lib/Support/Triple.cpp index 365c0836953..24f83e2f6fb 100644 --- a/lib/Support/Triple.cpp +++ b/lib/Support/Triple.cpp @@ -10,6 +10,7 @@ #include "llvm/ADT/Triple.h" #include "llvm/ADT/SmallString.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/Twine.h" #include #include @@ -114,6 +115,14 @@ const char *Triple::getOSTypeName(OSType Kind) { return ""; } +const char *Triple::getEnvironmentTypeName(EnvironmentType Kind) { + switch (Kind) { + case UnknownEnvironment: return "unknown"; + } + + return ""; +} + Triple::ArchType Triple::getArchTypeForLLVMName(StringRef Name) { if (Name == "alpha") return alpha; @@ -329,12 +338,17 @@ Triple::OSType Triple::ParseOS(StringRef OSName) { return UnknownOS; } +Triple::EnvironmentType Triple::ParseEnvironment(StringRef EnvironmentName) { + return UnknownEnvironment; +} + void Triple::Parse() const { assert(!isInitialized() && "Invalid parse call."); Arch = ParseArch(getArchName()); Vendor = ParseVendor(getVendorName()); OS = ParseOS(getOSName()); + Environment = ParseEnvironment(getEnvironmentName()); assert(isInitialized() && "Failed to initialize!"); } @@ -361,24 +375,28 @@ std::string Triple::normalize(StringRef Str) { OSType OS = UnknownOS; if (Components.size() > 2) OS = ParseOS(Components[2]); + EnvironmentType Environment = UnknownEnvironment; + if (Components.size() > 3) + Environment = ParseEnvironment(Components[3]); // Note which components are already in their final position. These will not // be moved. - bool Found[3]; + bool Found[4]; Found[0] = Arch != UnknownArch; Found[1] = Vendor != UnknownVendor; Found[2] = OS != UnknownOS; + Found[3] = Environment != UnknownEnvironment; // 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) { + for (unsigned Pos = 0; Pos != array_lengthof(Found); ++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]) + if (Idx < array_lengthof(Found) && Found[Idx]) continue; // Does this component parse as valid for the target position? @@ -399,6 +417,10 @@ std::string Triple::normalize(StringRef Str) { OS = ParseOS(Comp); Valid = OS != UnknownOS; break; + case 3: + Environment = ParseEnvironment(Comp); + Valid = Environment != UnknownEnvironment; + break; } if (!Valid) continue; // Nope, try the next component. @@ -417,7 +439,7 @@ std::string Triple::normalize(StringRef Str) { // components to the right. for (unsigned i = Pos; !CurrentComponent.empty(); ++i) { // Skip over any fixed components. - while (i < 3 && Found[i]) ++i; + while (i < array_lengthof(Found) && 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]); @@ -431,7 +453,7 @@ std::string Triple::normalize(StringRef Str) { StringRef CurrentComponent(""); // The empty component. for (unsigned i = Idx; i < Components.size(); ++i) { // Skip over any fixed components. - while (i < 3 && Found[i]) ++i; + while (i < array_lengthof(Found) && 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]); @@ -444,7 +466,7 @@ std::string Triple::normalize(StringRef Str) { Components.push_back(CurrentComponent); // Advance Idx to the component's new position. - while (++Idx < 3 && Found[Idx]) {} + while (++Idx < array_lengthof(Found) && Found[Idx]) {} } while (Idx < Pos); // Add more until the final position is reached. } assert(Pos < Components.size() && Components[Pos] == Comp && @@ -574,6 +596,10 @@ void Triple::setOS(OSType Kind) { setOSName(getOSTypeName(Kind)); } +void Triple::setEnvironment(EnvironmentType Kind) { + setEnvironmentName(getEnvironmentTypeName(Kind)); +} + void Triple::setArchName(StringRef Str) { // Work around a miscompilation bug for Twines in gcc 4.0.3. SmallString<64> Triple; diff --git a/unittests/ADT/TripleTest.cpp b/unittests/ADT/TripleTest.cpp index 067f5e5116c..bcc71968fe2 100644 --- a/unittests/ADT/TripleTest.cpp +++ b/unittests/ADT/TripleTest.cpp @@ -79,16 +79,21 @@ TEST(TripleTest, ParsedIDs) { EXPECT_EQ(Triple::x86, T.getArch()); EXPECT_EQ(Triple::Apple, T.getVendor()); EXPECT_EQ(Triple::Darwin, T.getOS()); + EXPECT_EQ(Triple::UnknownEnvironment, T.getEnvironment()); T = Triple("x86_64-pc-linux-gnu"); EXPECT_EQ(Triple::x86_64, T.getArch()); EXPECT_EQ(Triple::PC, T.getVendor()); EXPECT_EQ(Triple::Linux, T.getOS()); + // When environments are defined, change this test to verify the "gnu" + // environment. + EXPECT_EQ(Triple::UnknownEnvironment, T.getEnvironment()); T = Triple("powerpc-dunno-notsure"); EXPECT_EQ(Triple::ppc, T.getArch()); EXPECT_EQ(Triple::UnknownVendor, T.getVendor()); EXPECT_EQ(Triple::UnknownOS, T.getOS()); + EXPECT_EQ(Triple::UnknownEnvironment, T.getEnvironment()); T = Triple("huh"); EXPECT_EQ(Triple::UnknownArch, T.getArch()); @@ -119,10 +124,12 @@ TEST(TripleTest, Normalization) { EXPECT_EQ("i386-b-c", Triple::normalize("i386-b-c")); EXPECT_EQ("i386-a-c", Triple::normalize("a-i386-c")); EXPECT_EQ("i386-a-b", Triple::normalize("a-b-i386")); + EXPECT_EQ("i386-a-b-c", Triple::normalize("a-b-c-i386")); EXPECT_EQ("a-pc-c", Triple::normalize("a-pc-c")); EXPECT_EQ("-pc-b-c", Triple::normalize("pc-b-c")); EXPECT_EQ("a-pc-b", Triple::normalize("a-b-pc")); + EXPECT_EQ("a-pc-b-c", Triple::normalize("a-b-c-pc")); EXPECT_EQ("a-b-linux", Triple::normalize("a-b-linux")); EXPECT_EQ("--linux-b-c", Triple::normalize("linux-b-c")); @@ -210,6 +217,7 @@ TEST(TripleTest, MutateName) { EXPECT_EQ(Triple::UnknownArch, T.getArch()); EXPECT_EQ(Triple::UnknownVendor, T.getVendor()); EXPECT_EQ(Triple::UnknownOS, T.getOS()); + EXPECT_EQ(Triple::UnknownEnvironment, T.getEnvironment()); T.setArchName("i386"); EXPECT_EQ(Triple::x86, T.getArch());