diff --git a/include/llvm/ADT/Triple.h b/include/llvm/ADT/Triple.h index 9238f5af7a1..0eb0420f564 100644 --- a/include/llvm/ADT/Triple.h +++ b/include/llvm/ADT/Triple.h @@ -124,9 +124,14 @@ public: CODE16, EABI, EABIHF, - MachO, Android, - ELF + }; + enum ObjectFormatType { + UnknownObjectFormat, + + COFF, + ELF, + MachO, }; private: @@ -144,13 +149,16 @@ private: /// The parsed Environment type. EnvironmentType Environment; + /// The object format type. + ObjectFormatType ObjectFormat; + public: /// @name Constructors /// @{ /// \brief Default constructor is the same as an empty string and leaves all /// triple fields unknown. - Triple() : Data(), Arch(), Vendor(), OS(), Environment() {} + Triple() : Data(), Arch(), Vendor(), OS(), Environment(), ObjectFormat() {} explicit Triple(const Twine &Str); Triple(const Twine &ArchStr, const Twine &VendorStr, const Twine &OSStr); @@ -189,6 +197,9 @@ public: /// getEnvironment - Get the parsed environment type of this triple. EnvironmentType getEnvironment() const { return Environment; } + /// getFormat - Get the object format for this triple. + ObjectFormatType getObjectFormat() const { return ObjectFormat; } + /// getOSVersion - Parse the version number from the OS name component of the /// triple, if present. /// @@ -344,18 +355,17 @@ public: /// \brief Tests whether the OS uses the ELF binary format. bool isOSBinFormatELF() const { - return !isOSBinFormatMachO() && !isOSBinFormatCOFF(); + return getObjectFormat() == Triple::ELF; } /// \brief Tests whether the OS uses the COFF binary format. bool isOSBinFormatCOFF() const { - return getEnvironment() != Triple::ELF && - getEnvironment() != Triple::MachO && isOSWindows(); + return getObjectFormat() == Triple::COFF; } /// \brief Tests whether the environment is MachO. bool isOSBinFormatMachO() const { - return getEnvironment() == Triple::MachO || isOSDarwin(); + return getObjectFormat() == Triple::MachO; } /// @} @@ -378,6 +388,9 @@ public: /// to a known type. void setEnvironment(EnvironmentType Kind); + /// setObjectFormat - Set the object file format + void setObjectFormat(ObjectFormatType Kind); + /// setTriple - Set all components to the new triple \p Str. void setTriple(const Twine &Str); diff --git a/lib/MC/MCObjectFileInfo.cpp b/lib/MC/MCObjectFileInfo.cpp index 9a512d561fe..6b21cd3dd1c 100644 --- a/lib/MC/MCObjectFileInfo.cpp +++ b/lib/MC/MCObjectFileInfo.cpp @@ -736,10 +736,10 @@ void MCObjectFileInfo::InitMCObjectFileInfo(StringRef TT, Reloc::Model relocm, Arch == Triple::arm || Arch == Triple::thumb || Arch == Triple::ppc || Arch == Triple::ppc64 || Arch == Triple::UnknownArch) && - (T.isOSDarwin() || T.getEnvironment() == Triple::MachO)) { + (T.isOSDarwin() || T.isOSBinFormatMachO())) { Env = IsMachO; InitMachOMCObjectFileInfo(T); - } else if (T.isOSWindows() && T.getEnvironment() != Triple::ELF) { + } else if (T.isOSWindows() && !T.isOSBinFormatELF()) { assert((Arch == Triple::x86 || Arch == Triple::x86_64) && "expected x86 or x86_64"); Env = IsCOFF; diff --git a/lib/Support/Triple.cpp b/lib/Support/Triple.cpp index e7bb1accd10..d09931a3456 100644 --- a/lib/Support/Triple.cpp +++ b/lib/Support/Triple.cpp @@ -154,9 +154,7 @@ const char *Triple::getEnvironmentTypeName(EnvironmentType Kind) { case CODE16: return "code16"; case EABI: return "eabi"; case EABIHF: return "eabihf"; - case MachO: return "macho"; case Android: return "android"; - case ELF: return "elf"; } llvm_unreachable("Invalid EnvironmentType!"); @@ -310,12 +308,36 @@ static Triple::EnvironmentType parseEnvironment(StringRef EnvironmentName) { .StartsWith("gnux32", Triple::GNUX32) .StartsWith("code16", Triple::CODE16) .StartsWith("gnu", Triple::GNU) - .StartsWith("macho", Triple::MachO) .StartsWith("android", Triple::Android) - .StartsWith("elf", Triple::ELF) .Default(Triple::UnknownEnvironment); } +static Triple::ObjectFormatType parseFormat(StringRef EnvironmentName) { + return StringSwitch(EnvironmentName) + .EndsWith("coff", Triple::COFF) + .EndsWith("elf", Triple::ELF) + .EndsWith("macho", Triple::MachO) + .Default(Triple::UnknownObjectFormat); +} + +static const char *getObjectFormatTypeName(Triple::ObjectFormatType Kind) { + switch (Kind) { + case Triple::UnknownObjectFormat: return ""; + case Triple::COFF: return "coff"; + case Triple::ELF: return "elf"; + case Triple::MachO: return "macho"; + } + llvm_unreachable("unknown object format type"); +} + +static Triple::ObjectFormatType getDefaultFormat(const Triple &T) { + if (T.isOSDarwin()) + return Triple::MachO; + else if (T.isOSWindows()) + return Triple::COFF; + return Triple::ELF; +} + /// \brief Construct a triple from the string representation provided. /// /// This stores the string representation and parses the various pieces into @@ -325,7 +347,10 @@ Triple::Triple(const Twine &Str) Arch(parseArch(getArchName())), Vendor(parseVendor(getVendorName())), OS(parseOS(getOSName())), - Environment(parseEnvironment(getEnvironmentName())) { + Environment(parseEnvironment(getEnvironmentName())), + ObjectFormat(parseFormat(getEnvironmentName())) { + if (ObjectFormat == Triple::UnknownObjectFormat) + ObjectFormat = getDefaultFormat(*this); } /// \brief Construct a triple from string representations of the architecture, @@ -339,7 +364,8 @@ Triple::Triple(const Twine &ArchStr, const Twine &VendorStr, const Twine &OSStr) Arch(parseArch(ArchStr.str())), Vendor(parseVendor(VendorStr.str())), OS(parseOS(OSStr.str())), - Environment() { + Environment(), ObjectFormat(Triple::UnknownObjectFormat) { + ObjectFormat = getDefaultFormat(*this); } /// \brief Construct a triple from string representations of the architecture, @@ -354,7 +380,10 @@ Triple::Triple(const Twine &ArchStr, const Twine &VendorStr, const Twine &OSStr, Arch(parseArch(ArchStr.str())), Vendor(parseVendor(VendorStr.str())), OS(parseOS(OSStr.str())), - Environment(parseEnvironment(EnvironmentStr.str())) { + Environment(parseEnvironment(EnvironmentStr.str())), + ObjectFormat(parseFormat(EnvironmentStr.str())) { + if (ObjectFormat == Triple::UnknownObjectFormat) + ObjectFormat = getDefaultFormat(*this); } std::string Triple::normalize(StringRef Str) { @@ -379,6 +408,7 @@ std::string Triple::normalize(StringRef Str) { EnvironmentType Environment = UnknownEnvironment; if (Components.size() > 3) Environment = parseEnvironment(Components[3]); + ObjectFormatType ObjectFormat = UnknownObjectFormat; // Note which components are already in their final position. These will not // be moved. @@ -420,6 +450,10 @@ std::string Triple::normalize(StringRef Str) { case 3: Environment = parseEnvironment(Comp); Valid = Environment != UnknownEnvironment; + if (!Valid) { + ObjectFormat = parseFormat(Comp); + Valid = ObjectFormat != UnknownObjectFormat; + } break; } if (!Valid) @@ -641,6 +675,10 @@ void Triple::setEnvironment(EnvironmentType Kind) { setEnvironmentName(getEnvironmentTypeName(Kind)); } +void Triple::setObjectFormat(ObjectFormatType Kind) { + setEnvironmentName(getObjectFormatTypeName(Kind)); +} + void Triple::setArchName(StringRef Str) { // Work around a miscompilation bug for Twines in gcc 4.0.3. SmallString<64> Triple; diff --git a/lib/Target/ARM/ARMSubtarget.cpp b/lib/Target/ARM/ARMSubtarget.cpp index 8c5847777e8..d510e7ebf10 100644 --- a/lib/Target/ARM/ARMSubtarget.cpp +++ b/lib/Target/ARM/ARMSubtarget.cpp @@ -196,11 +196,12 @@ void ARMSubtarget::resetSubtargetFeatures(StringRef CPU, StringRef FS) { case Triple::EABIHF: case Triple::GNUEABI: case Triple::GNUEABIHF: - case Triple::MachO: TargetABI = ARM_ABI_AAPCS; break; default: - if (isTargetIOS() && isMClass()) + if ((isTargetIOS() && isMClass()) || + (TargetTriple.isOSBinFormatMachO() && + TargetTriple.getOS() == Triple::UnknownOS)) TargetABI = ARM_ABI_AAPCS; else TargetABI = ARM_ABI_APCS; diff --git a/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp b/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp index a80be99bad9..5311e429294 100644 --- a/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp +++ b/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp @@ -801,7 +801,7 @@ MCAsmBackend *llvm::createX86_32AsmBackend(const Target &T, TheTriple.isMacOSX() && !TheTriple.isMacOSXVersionLT(10, 7)); - if (TheTriple.isOSWindows() && TheTriple.getEnvironment() != Triple::ELF) + if (TheTriple.isOSWindows() && !TheTriple.isOSBinFormatELF()) return new WindowsX86AsmBackend(T, false, CPU); uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(TheTriple.getOS()); @@ -824,7 +824,7 @@ MCAsmBackend *llvm::createX86_64AsmBackend(const Target &T, !TheTriple.isMacOSXVersionLT(10, 7), CS); } - if (TheTriple.isOSWindows() && TheTriple.getEnvironment() != Triple::ELF) + if (TheTriple.isOSWindows() && !TheTriple.isOSBinFormatELF()) return new WindowsX86AsmBackend(T, true, CPU); uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(TheTriple.getOS()); diff --git a/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp b/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp index 81ac4ad47e4..8deba94c80e 100644 --- a/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp +++ b/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp @@ -276,7 +276,7 @@ static MCAsmInfo *createX86MCAsmInfo(const MCRegisterInfo &MRI, StringRef TT) { MAI = new X86_64MCAsmInfoDarwin(TheTriple); else MAI = new X86MCAsmInfoDarwin(TheTriple); - } else if (TheTriple.getEnvironment() == Triple::ELF) { + } else if (TheTriple.isOSBinFormatELF()) { // Force the use of an ELF container. MAI = new X86ELFMCAsmInfo(TheTriple); } else if (TheTriple.getOS() == Triple::Win32) { @@ -370,7 +370,7 @@ static MCStreamer *createMCStreamer(const Target &T, StringRef TT, if (TheTriple.isOSBinFormatMachO()) return createMachOStreamer(Ctx, MAB, _OS, _Emitter, RelaxAll); - if (TheTriple.isOSWindows() && TheTriple.getEnvironment() != Triple::ELF) + if (TheTriple.isOSWindows() && !TheTriple.isOSBinFormatELF()) return createWinCOFFStreamer(Ctx, MAB, *_Emitter, _OS, RelaxAll); return createELFStreamer(Ctx, MAB, _OS, _Emitter, RelaxAll, NoExecStack); diff --git a/tools/llvm-jitlistener/llvm-jitlistener.cpp b/tools/llvm-jitlistener/llvm-jitlistener.cpp index a9bbc702a90..c159aa506d6 100644 --- a/tools/llvm-jitlistener/llvm-jitlistener.cpp +++ b/tools/llvm-jitlistener/llvm-jitlistener.cpp @@ -138,8 +138,8 @@ protected: if (Tuple.getTriple().empty()) Tuple.setTriple(sys::getProcessTriple()); - if (Tuple.isOSWindows() && Triple::ELF != Tuple.getEnvironment()) { - Tuple.setEnvironment(Triple::ELF); + if (Tuple.isOSWindows() && !Tuple.isOSBinFormatELF()) { + Tuple.setObjectFormat(Triple::ELF); TheModule->setTargetTriple(Tuple.getTriple()); } diff --git a/tools/llvm-objdump/llvm-objdump.cpp b/tools/llvm-objdump/llvm-objdump.cpp index 7a3d0e29d96..d93e477b5c1 100644 --- a/tools/llvm-objdump/llvm-objdump.cpp +++ b/tools/llvm-objdump/llvm-objdump.cpp @@ -166,7 +166,7 @@ static const Target *getTarget(const ObjectFile *Obj = NULL) { // TheTriple defaults to ELF, and COFF doesn't have an environment: // the best we can do here is indicate that it is mach-o. if (Obj->isMachO()) - TheTriple.setEnvironment(Triple::MachO); + TheTriple.setObjectFormat(Triple::MachO); } } else TheTriple.setTriple(Triple::normalize(TripleName)); diff --git a/unittests/ADT/TripleTest.cpp b/unittests/ADT/TripleTest.cpp index a32a2312986..efd09157a47 100644 --- a/unittests/ADT/TripleTest.cpp +++ b/unittests/ADT/TripleTest.cpp @@ -201,7 +201,7 @@ TEST(TripleTest, Normalization) { EXPECT_EQ(E, Triple::normalize(Join(C[2], C[0], C[1]))); EXPECT_EQ(E, Triple::normalize(Join(C[2], C[1], C[0]))); - for (int Env = 1+Triple::UnknownEnvironment; Env <= Triple::MachO; + for (int Env = 1 + Triple::UnknownEnvironment; Env <= Triple::Android; ++Env) { C[3] = Triple::getEnvironmentTypeName(Triple::EnvironmentType(Env)); @@ -497,4 +497,22 @@ TEST(TripleTest, getOSVersion) { EXPECT_EQ((unsigned)0, Micro); } +TEST(TripleTest, FileFormat) { + EXPECT_EQ(Triple::ELF, Triple("i686-unknown-linux-gnu").getObjectFormat()); + EXPECT_EQ(Triple::ELF, Triple("i686-unknown-freebsd").getObjectFormat()); + EXPECT_EQ(Triple::ELF, Triple("i686-unknown-netbsd").getObjectFormat()); + EXPECT_EQ(Triple::ELF, Triple("i686--win32-elf").getObjectFormat()); + EXPECT_EQ(Triple::ELF, Triple("i686---elf").getObjectFormat()); + + EXPECT_EQ(Triple::MachO, Triple("i686-apple-macosx").getObjectFormat()); + EXPECT_EQ(Triple::MachO, Triple("i686-apple-ios").getObjectFormat()); + EXPECT_EQ(Triple::MachO, Triple("i686---macho").getObjectFormat()); + + EXPECT_EQ(Triple::COFF, Triple("i686--win32").getObjectFormat()); + + Triple T = Triple(""); + T.setObjectFormat(Triple::ELF); + EXPECT_EQ(Triple::ELF, T.getObjectFormat()); +} + }