diff options
Diffstat (limited to 'clang/lib')
| -rw-r--r-- | clang/lib/Driver/ToolChains.cpp | 322 | ||||
| -rw-r--r-- | clang/lib/Driver/ToolChains.h | 23 |
2 files changed, 213 insertions, 132 deletions
diff --git a/clang/lib/Driver/ToolChains.cpp b/clang/lib/Driver/ToolChains.cpp index b62be8b..428f37ca 100644 --- a/clang/lib/Driver/ToolChains.cpp +++ b/clang/lib/Driver/ToolChains.cpp @@ -1093,15 +1093,31 @@ bool Generic_GCC::GCCVersion::operator<(const GCCVersion &RHS) const { return false; } +// FIXME: Factor this helper into llvm::Triple itself. +static llvm::Triple getMultiarchAlternateTriple(llvm::Triple Triple) { + switch (Triple.getArch()) { + default: break; + case llvm::Triple::x86: Triple.setArchName("x86_64"); break; + case llvm::Triple::x86_64: Triple.setArchName("i386"); break; + case llvm::Triple::ppc: Triple.setArchName("powerpc64"); break; + case llvm::Triple::ppc64: Triple.setArchName("powerpc"); break; + } + return Triple; +} + /// \brief Construct a GCCInstallationDetector from the driver. /// /// This performs all of the autodetection and sets up the various paths. /// Once constructed, a GCCInstallation is esentially immutable. -Generic_GCC::GCCInstallationDetector::GCCInstallationDetector(const Driver &D) - : IsValid(false), - // FIXME: GCCTriple is using the target triple as both the target and host - // triple here. - GCCTriple(D.TargetTriple) { +/// +/// FIXME: We shouldn't need an explicit TargetTriple parameter here, and +/// should instead pull the target out of the driver. This is currently +/// necessary because the driver doesn't store the final version of the target +/// triple. +Generic_GCC::GCCInstallationDetector::GCCInstallationDetector( + const Driver &D, + const llvm::Triple &TargetTriple) + : IsValid(false) { // FIXME: Using CXX_INCLUDE_ROOT is here is a bit of a hack, but // avoids adding yet another option to configure/cmake. // It would probably be cleaner to break it in two variables @@ -1130,17 +1146,17 @@ Generic_GCC::GCCInstallationDetector::GCCInstallationDetector(const Driver &D) return; } - llvm::Triple::ArchType HostArch = GCCTriple.getArch(); + llvm::Triple MultiarchTriple = getMultiarchAlternateTriple(TargetTriple); + llvm::Triple::ArchType TargetArch = TargetTriple.getArch(); // The library directories which may contain GCC installations. - SmallVector<StringRef, 4> CandidateLibDirs; + SmallVector<StringRef, 4> CandidateLibDirs, CandidateMultiarchLibDirs; // The compatible GCC triples for this particular architecture. - SmallVector<StringRef, 10> CandidateTriples; - CollectLibDirsAndTriples(HostArch, CandidateLibDirs, CandidateTriples); - - // Always include the default host triple as the final fallback if no - // specific triple is detected. - // FIXME: This is using the Driver's target triple as the host triple! - CandidateTriples.push_back(D.TargetTriple.str()); + SmallVector<StringRef, 10> CandidateTripleAliases; + SmallVector<StringRef, 10> CandidateMultiarchTripleAliases; + CollectLibDirsAndTriples(TargetTriple, MultiarchTriple, CandidateLibDirs, + CandidateTripleAliases, + CandidateMultiarchLibDirs, + CandidateMultiarchTripleAliases); // Compute the set of prefixes for our search. SmallVector<std::string, 8> Prefixes(D.PrefixDirs.begin(), @@ -1159,99 +1175,162 @@ Generic_GCC::GCCInstallationDetector::GCCInstallationDetector(const Driver &D) const std::string LibDir = Prefixes[i] + CandidateLibDirs[j].str(); if (!llvm::sys::fs::exists(LibDir)) continue; - for (unsigned k = 0, ke = CandidateTriples.size(); k < ke; ++k) - ScanLibDirForGCCTriple(HostArch, LibDir, CandidateTriples[k]); + for (unsigned k = 0, ke = CandidateTripleAliases.size(); k < ke; ++k) + ScanLibDirForGCCTriple(TargetArch, LibDir, CandidateTripleAliases[k]); + } + for (unsigned j = 0, je = CandidateMultiarchLibDirs.size(); j < je; ++j) { + const std::string LibDir + = Prefixes[i] + CandidateMultiarchLibDirs[j].str(); + if (!llvm::sys::fs::exists(LibDir)) + continue; + for (unsigned k = 0, ke = CandidateMultiarchTripleAliases.size(); k < ke; + ++k) + ScanLibDirForGCCTriple(TargetArch, LibDir, + CandidateMultiarchTripleAliases[k], + /*NeedsMultiarchSuffix=*/true); } } } /*static*/ void Generic_GCC::GCCInstallationDetector::CollectLibDirsAndTriples( - llvm::Triple::ArchType HostArch, SmallVectorImpl<StringRef> &LibDirs, - SmallVectorImpl<StringRef> &Triples) { - if (HostArch == llvm::Triple::arm || HostArch == llvm::Triple::thumb) { - static const char *const ARMLibDirs[] = { "/lib" }; - static const char *const ARMTriples[] = { - "arm-linux-gnueabi", - "arm-linux-androideabi" - }; + const llvm::Triple &TargetTriple, + const llvm::Triple &MultiarchTriple, + SmallVectorImpl<StringRef> &LibDirs, + SmallVectorImpl<StringRef> &TripleAliases, + SmallVectorImpl<StringRef> &MultiarchLibDirs, + SmallVectorImpl<StringRef> &MultiarchTripleAliases) { + // Declare a bunch of static data sets that we'll select between below. These + // are specifically designed to always refer to string literals to avoid any + // lifetime or initialization issues. + static const char *const ARMLibDirs[] = { "/lib" }; + static const char *const ARMTriples[] = { + "arm-linux-gnueabi", + "arm-linux-androideabi" + }; + + static const char *const X86_64LibDirs[] = { "/lib64", "/lib" }; + static const char *const X86_64Triples[] = { + "x86_64-linux-gnu", + "x86_64-unknown-linux-gnu", + "x86_64-pc-linux-gnu", + "x86_64-redhat-linux6E", + "x86_64-redhat-linux", + "x86_64-suse-linux", + "x86_64-manbo-linux-gnu", + "x86_64-linux-gnu", + "x86_64-slackware-linux" + }; + static const char *const X86LibDirs[] = { "/lib32", "/lib" }; + static const char *const X86Triples[] = { + "i686-linux-gnu", + "i686-pc-linux-gnu", + "i486-linux-gnu", + "i386-linux-gnu", + "i686-redhat-linux", + "i586-redhat-linux", + "i386-redhat-linux", + "i586-suse-linux", + "i486-slackware-linux" + }; + + static const char *const MIPSLibDirs[] = { "/lib" }; + static const char *const MIPSTriples[] = { "mips-linux-gnu" }; + static const char *const MIPSELLibDirs[] = { "/lib" }; + static const char *const MIPSELTriples[] = { "mipsel-linux-gnu" }; + + static const char *const PPCLibDirs[] = { "/lib32", "/lib" }; + static const char *const PPCTriples[] = { + "powerpc-linux-gnu", + "powerpc-unknown-linux-gnu", + "powerpc-suse-linux" + }; + static const char *const PPC64LibDirs[] = { "/lib64", "/lib" }; + static const char *const PPC64Triples[] = { + "powerpc64-unknown-linux-gnu", + "powerpc64-suse-linux", + "ppc64-redhat-linux" + }; + + switch (TargetTriple.getArch()) { + case llvm::Triple::arm: + case llvm::Triple::thumb: LibDirs.append(ARMLibDirs, ARMLibDirs + llvm::array_lengthof(ARMLibDirs)); - Triples.append(ARMTriples, ARMTriples + llvm::array_lengthof(ARMTriples)); - } else if (HostArch == llvm::Triple::x86_64) { - static const char *const X86_64LibDirs[] = { "/lib64", "/lib" }; - static const char *const X86_64Triples[] = { - "x86_64-linux-gnu", - "x86_64-unknown-linux-gnu", - "x86_64-pc-linux-gnu", - "x86_64-redhat-linux6E", - "x86_64-redhat-linux", - "x86_64-suse-linux", - "x86_64-manbo-linux-gnu", - "x86_64-linux-gnu", - "x86_64-slackware-linux" - }; - LibDirs.append(X86_64LibDirs, - X86_64LibDirs + llvm::array_lengthof(X86_64LibDirs)); - Triples.append(X86_64Triples, - X86_64Triples + llvm::array_lengthof(X86_64Triples)); - } else if (HostArch == llvm::Triple::x86) { - static const char *const X86LibDirs[] = { "/lib32", "/lib" }; - static const char *const X86Triples[] = { - "i686-linux-gnu", - "i686-pc-linux-gnu", - "i486-linux-gnu", - "i386-linux-gnu", - "i686-redhat-linux", - "i586-redhat-linux", - "i386-redhat-linux", - "i586-suse-linux", - "i486-slackware-linux" - }; + TripleAliases.append( + ARMTriples, ARMTriples + llvm::array_lengthof(ARMTriples)); + break; + case llvm::Triple::x86_64: + LibDirs.append( + X86_64LibDirs, X86_64LibDirs + llvm::array_lengthof(X86_64LibDirs)); + TripleAliases.append( + X86_64Triples, X86_64Triples + llvm::array_lengthof(X86_64Triples)); + MultiarchLibDirs.append( + X86LibDirs, X86LibDirs + llvm::array_lengthof(X86LibDirs)); + MultiarchTripleAliases.append( + X86Triples, X86Triples + llvm::array_lengthof(X86Triples)); + break; + case llvm::Triple::x86: LibDirs.append(X86LibDirs, X86LibDirs + llvm::array_lengthof(X86LibDirs)); - Triples.append(X86Triples, X86Triples + llvm::array_lengthof(X86Triples)); - } else if (HostArch == llvm::Triple::mips) { - static const char *const MIPSLibDirs[] = { "/lib" }; - static const char *const MIPSTriples[] = { "mips-linux-gnu" }; - LibDirs.append(MIPSLibDirs, - MIPSLibDirs + llvm::array_lengthof(MIPSLibDirs)); - Triples.append(MIPSTriples, - MIPSTriples + llvm::array_lengthof(MIPSTriples)); - } else if (HostArch == llvm::Triple::mipsel) { - static const char *const MIPSELLibDirs[] = { "/lib" }; - static const char *const MIPSELTriples[] = { "mipsel-linux-gnu" }; - LibDirs.append(MIPSELLibDirs, - MIPSELLibDirs + llvm::array_lengthof(MIPSELLibDirs)); - Triples.append(MIPSELTriples, - MIPSELTriples + llvm::array_lengthof(MIPSELTriples)); - } else if (HostArch == llvm::Triple::ppc) { - static const char *const PPCLibDirs[] = { "/lib32", "/lib" }; - static const char *const PPCTriples[] = { - "powerpc-linux-gnu", - "powerpc-unknown-linux-gnu", - "powerpc-suse-linux" - }; + TripleAliases.append( + X86Triples, X86Triples + llvm::array_lengthof(X86Triples)); + MultiarchLibDirs.append( + X86_64LibDirs, X86_64LibDirs + llvm::array_lengthof(X86_64LibDirs)); + MultiarchTripleAliases.append( + X86_64Triples, X86_64Triples + llvm::array_lengthof(X86_64Triples)); + break; + case llvm::Triple::mips: + LibDirs.append( + MIPSLibDirs, MIPSLibDirs + llvm::array_lengthof(MIPSLibDirs)); + TripleAliases.append( + MIPSTriples, MIPSTriples + llvm::array_lengthof(MIPSTriples)); + break; + case llvm::Triple::mipsel: + LibDirs.append( + MIPSELLibDirs, MIPSELLibDirs + llvm::array_lengthof(MIPSELLibDirs)); + TripleAliases.append( + MIPSELTriples, MIPSELTriples + llvm::array_lengthof(MIPSELTriples)); + break; + case llvm::Triple::ppc: LibDirs.append(PPCLibDirs, PPCLibDirs + llvm::array_lengthof(PPCLibDirs)); - Triples.append(PPCTriples, PPCTriples + llvm::array_lengthof(PPCTriples)); - } else if (HostArch == llvm::Triple::ppc64) { - static const char *const PPC64LibDirs[] = { "/lib64", "/lib" }; - static const char *const PPC64Triples[] = { - "powerpc64-unknown-linux-gnu", - "powerpc64-suse-linux", - "ppc64-redhat-linux" - }; - LibDirs.append(PPC64LibDirs, - PPC64LibDirs + llvm::array_lengthof(PPC64LibDirs)); - Triples.append(PPC64Triples, - PPC64Triples + llvm::array_lengthof(PPC64Triples)); + TripleAliases.append( + PPCTriples, PPCTriples + llvm::array_lengthof(PPCTriples)); + MultiarchLibDirs.append( + PPC64LibDirs, PPC64LibDirs + llvm::array_lengthof(PPC64LibDirs)); + MultiarchTripleAliases.append( + PPC64Triples, PPC64Triples + llvm::array_lengthof(PPC64Triples)); + break; + case llvm::Triple::ppc64: + LibDirs.append( + PPC64LibDirs, PPC64LibDirs + llvm::array_lengthof(PPC64LibDirs)); + TripleAliases.append( + PPC64Triples, PPC64Triples + llvm::array_lengthof(PPC64Triples)); + MultiarchLibDirs.append( + PPCLibDirs, PPCLibDirs + llvm::array_lengthof(PPCLibDirs)); + MultiarchTripleAliases.append( + PPCTriples, PPCTriples + llvm::array_lengthof(PPCTriples)); + break; + + default: + // By default, just rely on the standard lib directories and the original + // triple. + break; } + + // Always append the drivers target triple to the end, in case it doesn't + // match any of our aliases. + TripleAliases.push_back(TargetTriple.str()); + + // Also include the multiarch variant if it's different. + if (TargetTriple.str() != MultiarchTriple.str()) + MultiarchTripleAliases.push_back(MultiarchTriple.str()); } void Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple( - llvm::Triple::ArchType HostArch, const std::string &LibDir, - StringRef CandidateTriple) { + llvm::Triple::ArchType TargetArch, const std::string &LibDir, + StringRef CandidateTriple, bool NeedsMultiarchSuffix) { // There are various different suffixes involving the triple we // check for. We also record what is necessary to walk from each back // up to the lib directory. - const std::string Suffixes[] = { + const std::string LibSuffixes[] = { "/gcc/" + CandidateTriple.str(), "/" + CandidateTriple.str() + "/gcc/" + CandidateTriple.str(), @@ -1267,12 +1346,12 @@ void Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple( "/../../../.." }; // Only look at the final, weird Ubuntu suffix for i386-linux-gnu. - const unsigned NumSuffixes = (llvm::array_lengthof(Suffixes) - - (HostArch != llvm::Triple::x86)); - for (unsigned i = 0; i < NumSuffixes; ++i) { - StringRef Suffix = Suffixes[i]; + const unsigned NumLibSuffixes = (llvm::array_lengthof(LibSuffixes) - + (TargetArch != llvm::Triple::x86)); + for (unsigned i = 0; i < NumLibSuffixes; ++i) { + StringRef LibSuffix = LibSuffixes[i]; llvm::error_code EC; - for (llvm::sys::fs::directory_iterator LI(LibDir + Suffix, EC), LE; + for (llvm::sys::fs::directory_iterator LI(LibDir + LibSuffix, EC), LE; !EC && LI != LE; LI = LI.increment(EC)) { StringRef VersionText = llvm::sys::path::filename(LI->path()); GCCVersion CandidateVersion = GCCVersion::Parse(VersionText); @@ -1284,31 +1363,36 @@ void Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple( // Some versions of SUSE and Fedora on ppc64 put 32-bit libs // in what would normally be GCCInstallPath and put the 64-bit - // libs in a subdirectory named 64. We need the 64-bit libs - // for linking. - bool UseSlash64 = false; - if (HostArch == llvm::Triple::ppc64 && - llvm::sys::fs::exists(LI->path() + "/64/crtbegin.o")) - UseSlash64 = true; - - if (!llvm::sys::fs::exists(LI->path() + "/crtbegin.o")) - continue; + // libs in a subdirectory named 64. The simple logic we follow is that + // *if* there is a subdirectory of the right name with crtbegin.o in it, + // we use that. If not, and if not a multiarch triple, we look for + // crtbegin.o without the subdirectory. + StringRef MultiarchSuffix + = (TargetArch == llvm::Triple::x86_64 || + TargetArch == llvm::Triple::ppc64) ? "/64" : "/32"; + if (llvm::sys::fs::exists(LI->path() + MultiarchSuffix + "/crtbegin.o")) { + GCCMultiarchSuffix = MultiarchSuffix.str(); + } else { + if (NeedsMultiarchSuffix || + !llvm::sys::fs::exists(LI->path() + "/crtbegin.o")) + continue; + GCCMultiarchSuffix.clear(); + } Version = CandidateVersion; GCCTriple.setTriple(CandidateTriple); // FIXME: We hack together the directory name here instead of // using LI to ensure stable path separators across Windows and // Linux. - GCCInstallPath = LibDir + Suffixes[i] + "/" + VersionText.str(); + GCCInstallPath = LibDir + LibSuffixes[i] + "/" + VersionText.str(); GCCParentLibPath = GCCInstallPath + InstallSuffixes[i]; - if (UseSlash64) GCCInstallPath = GCCInstallPath + "/64"; IsValid = true; } } } Generic_GCC::Generic_GCC(const HostInfo &Host, const llvm::Triple& Triple) - : ToolChain(Host, Triple), GCCInstallation(getDriver()) { + : ToolChain(Host, Triple), GCCInstallation(getDriver(), Triple) { getProgramPaths().push_back(getDriver().getInstalledDir()); if (getDriver().getInstalledDir() != getDriver().Dir) getProgramPaths().push_back(getDriver().Dir); @@ -1970,24 +2054,12 @@ Linux::Linux(const HostInfo &Host, const llvm::Triple &Triple) const std::string MultiarchTriple = getMultiarchTriple(Triple, SysRoot); // Add the multilib suffixed paths where they are available. - bool SuffixedGCCInstallation = false; if (GCCInstallation.isValid()) { - StringRef Suffix32; - StringRef Suffix64; const llvm::Triple &GCCTriple = GCCInstallation.getTriple(); - if (GCCTriple.getArch() == llvm::Triple::x86_64 || - GCCTriple.getArch() == llvm::Triple::ppc64) { - Suffix32 = "/32"; - Suffix64 = ""; - } else { - Suffix32 = ""; - Suffix64 = "/64"; - } - const std::string Suffix = Is32Bits ? Suffix32 : Suffix64; - SuffixedGCCInstallation = !Suffix.empty(); - const std::string &LibPath = GCCInstallation.getParentLibPath(); - addPathIfExists(GCCInstallation.getInstallPath() + Suffix, Paths); + addPathIfExists((GCCInstallation.getInstallPath() + + GCCInstallation.getMultiarchSuffix()), + Paths); addPathIfExists(LibPath + "/../" + GCCTriple.str() + "/lib/../" + Multilib, Paths); addPathIfExists(LibPath + "/" + MultiarchTriple, Paths); @@ -2008,7 +2080,7 @@ Linux::Linux(const HostInfo &Host, const llvm::Triple &Triple) if (GCCInstallation.isValid()) { const std::string &LibPath = GCCInstallation.getParentLibPath(); const llvm::Triple &GCCTriple = GCCInstallation.getTriple(); - if (SuffixedGCCInstallation) + if (!GCCInstallation.getMultiarchSuffix().empty()) addPathIfExists(GCCInstallation.getInstallPath(), Paths); addPathIfExists(LibPath + "/../" + GCCTriple.str() + "/lib", Paths); addPathIfExists(LibPath, Paths); diff --git a/clang/lib/Driver/ToolChains.h b/clang/lib/Driver/ToolChains.h index 6b152f4..2b7c432 100644 --- a/clang/lib/Driver/ToolChains.h +++ b/clang/lib/Driver/ToolChains.h @@ -73,12 +73,13 @@ protected: // FIXME: These might be better as path objects. std::string GCCInstallPath; + std::string GCCMultiarchSuffix; std::string GCCParentLibPath; GCCVersion Version; public: - GCCInstallationDetector(const Driver &D); + GCCInstallationDetector(const Driver &D, const llvm::Triple &TargetTriple); /// \brief Check whether we detected a valid GCC install. bool isValid() const { return IsValid; } @@ -89,6 +90,9 @@ protected: /// \brief Get the detected GCC installation path. StringRef getInstallPath() const { return GCCInstallPath; } + /// \brief Get the detected GCC installation path suffix for multiarch GCCs. + StringRef getMultiarchSuffix() const { return GCCMultiarchSuffix; } + /// \brief Get the detected GCC parent lib path. StringRef getParentLibPath() const { return GCCParentLibPath; } @@ -96,13 +100,18 @@ protected: StringRef getVersion() const { return Version.Text; } private: - static void CollectLibDirsAndTriples(llvm::Triple::ArchType HostArch, - SmallVectorImpl<StringRef> &LibDirs, - SmallVectorImpl<StringRef> &Triples); - - void ScanLibDirForGCCTriple(llvm::Triple::ArchType HostArch, + static void CollectLibDirsAndTriples( + const llvm::Triple &TargetTriple, + const llvm::Triple &MultiarchTriple, + SmallVectorImpl<StringRef> &LibDirs, + SmallVectorImpl<StringRef> &TripleAliases, + SmallVectorImpl<StringRef> &MultiarchLibDirs, + SmallVectorImpl<StringRef> &MultiarchTripleAliases); + + void ScanLibDirForGCCTriple(llvm::Triple::ArchType TargetArch, const std::string &LibDir, - StringRef CandidateTriple); + StringRef CandidateTriple, + bool NeedsMultiarchSuffix = false); }; GCCInstallationDetector GCCInstallation; |
