diff options
Diffstat (limited to 'clang')
-rw-r--r-- | clang/include/clang/Driver/Multilib.h | 163 | ||||
-rw-r--r-- | clang/include/clang/Driver/ToolChain.h | 5 | ||||
-rw-r--r-- | clang/lib/Driver/CMakeLists.txt | 1 | ||||
-rw-r--r-- | clang/lib/Driver/Driver.cpp | 61 | ||||
-rw-r--r-- | clang/lib/Driver/Multilib.cpp | 347 | ||||
-rw-r--r-- | clang/lib/Driver/ToolChains.cpp | 537 | ||||
-rw-r--r-- | clang/lib/Driver/ToolChains.h | 55 | ||||
-rw-r--r-- | clang/lib/Driver/Tools.cpp | 36 | ||||
-rw-r--r-- | clang/lib/Driver/Tools.h | 4 | ||||
-rw-r--r-- | clang/unittests/CMakeLists.txt | 1 | ||||
-rw-r--r-- | clang/unittests/Driver/CMakeLists.txt | 11 | ||||
-rw-r--r-- | clang/unittests/Driver/Makefile | 16 | ||||
-rw-r--r-- | clang/unittests/Driver/MultilibTest.cpp | 356 | ||||
-rw-r--r-- | clang/unittests/Makefile | 2 |
14 files changed, 247 insertions, 1348 deletions
diff --git a/clang/include/clang/Driver/Multilib.h b/clang/include/clang/Driver/Multilib.h deleted file mode 100644 index ad59d8a57fb..00000000000 --- a/clang/include/clang/Driver/Multilib.h +++ /dev/null @@ -1,163 +0,0 @@ -//===--- Multilib.h ---------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef CLANG_LIB_DRIVER_MULTILIB_H_ -#define CLANG_LIB_DRIVER_MULTILIB_H_ - -#include "clang/Basic/LLVM.h" -#include "llvm/ADT/Triple.h" -#include "llvm/Option/Option.h" -#include <string> -#include <vector> - -namespace clang { -namespace driver { - -/// This corresponds to a single GCC Multilib, or a segment of one controlled -/// by a command line flag -class Multilib { -public: - typedef std::vector<std::string> flags_list; - -private: - std::string GCCSuffix; - std::string OSSuffix; - std::string IncludeSuffix; - flags_list Flags; - -public: - Multilib(StringRef GCCSuffix = "", StringRef OSSuffix = "", - StringRef IncludeSuffix = ""); - - /// \brief Get the detected GCC installation path suffix for the multi-arch - /// target variant. Always starts with a '/', unless empty - const std::string &gccSuffix() const { - assert(GCCSuffix.empty() || - (StringRef(GCCSuffix).front() == '/' && GCCSuffix.size() > 1)); - return GCCSuffix; - } - /// Set the GCC installation path suffix. - Multilib &gccSuffix(StringRef S); - - /// \brief Get the detected os path suffix for the multi-arch - /// target variant. Always starts with a '/', unless empty - const std::string &osSuffix() const { - assert(OSSuffix.empty() || - (StringRef(OSSuffix).front() == '/' && OSSuffix.size() > 1)); - return OSSuffix; - } - /// Set the os path suffix. - Multilib &osSuffix(StringRef S); - - /// \brief Get the include directory suffix. Always starts with a '/', unless - /// empty - const std::string &includeSuffix() const { - assert(IncludeSuffix.empty() || - (StringRef(IncludeSuffix).front() == '/' && IncludeSuffix.size() > 1)); - return IncludeSuffix; - } - /// Set the include directory suffix - Multilib &includeSuffix(StringRef S); - - /// \brief Get the flags that indicate or contraindicate this multilib's use - /// All elements begin with either '+' or '-' - const flags_list &flags() const { return Flags; } - flags_list &flags() { return Flags; } - /// Add a flag to the flags list - Multilib &flag(StringRef F) { - assert(F.front() == '+' || F.front() == '-'); - Flags.push_back(F); - return *this; - } - - /// \brief print summary of the Multilib - void print(raw_ostream &OS) const; - - /// Check whether any of the 'against' flags contradict the 'for' flags. - bool isValid() const; - - bool operator==(const Multilib &Other) const; -}; - -raw_ostream &operator<<(raw_ostream &OS, const Multilib &M); - -class MultilibSet { -public: - typedef std::vector<Multilib> multilib_list; - typedef multilib_list::iterator iterator; - typedef multilib_list::const_iterator const_iterator; - - struct FilterCallback { - virtual ~FilterCallback() {}; - /// \return true iff the filter should remove the Multilib from the set - virtual bool operator()(const Multilib &M) const = 0; - }; - -private: - multilib_list Multilibs; - -public: - MultilibSet() {} - - /// Add an optional Multilib segment - MultilibSet &Maybe(const Multilib &M); - - /// Add a set of mutually incompatible Multilib segments - MultilibSet &Either(const Multilib &M1, const Multilib &M2); - MultilibSet &Either(const Multilib &M1, const Multilib &M2, - const Multilib &M3); - MultilibSet &Either(const Multilib &M1, const Multilib &M2, - const Multilib &M3, const Multilib &M4); - MultilibSet &Either(const Multilib &M1, const Multilib &M2, - const Multilib &M3, const Multilib &M4, - const Multilib &M5); - MultilibSet &Either(const std::vector<Multilib> &Ms); - - /// Filter out some subset of the Multilibs using a user defined callback - MultilibSet &FilterOut(const FilterCallback &F); - /// Filter out those Multilibs whose gccSuffix matches the given expression - MultilibSet &FilterOut(std::string Regex); - - /// Add a completed Multilib to the set - void push_back(const Multilib &M); - - /// Union this set of multilibs with another - void combineWith(const MultilibSet &MS); - - /// Remove all of thie multilibs from the set - void clear() { Multilibs.clear(); } - - iterator begin() { return Multilibs.begin(); } - const_iterator begin() const { return Multilibs.begin(); } - - iterator end() { return Multilibs.end(); } - const_iterator end() const { return Multilibs.end(); } - - /// Pick the best multilib in the set, \returns false if none are compatible - bool select(const Multilib::flags_list &Flags, Multilib &M) const; - - unsigned size() const { return Multilibs.size(); } - - void print(raw_ostream &OS) const; - -private: - /// Apply the filter to Multilibs and return the subset that remains - static multilib_list filterCopy(const FilterCallback &F, - const multilib_list &Ms); - - /// Apply the filter to the multilib_list, removing those that don't match - static void filterInPlace(const FilterCallback &F, multilib_list &Ms); -}; - -raw_ostream &operator<<(raw_ostream &OS, const MultilibSet &MS); -} -} - -#endif - diff --git a/clang/include/clang/Driver/ToolChain.h b/clang/include/clang/Driver/ToolChain.h index e8f2c78b733..e775f630e10 100644 --- a/clang/include/clang/Driver/ToolChain.h +++ b/clang/include/clang/Driver/ToolChain.h @@ -11,7 +11,6 @@ #define CLANG_DRIVER_TOOLCHAIN_H_ #include "clang/Driver/Action.h" -#include "clang/Driver/Multilib.h" #include "clang/Driver/Types.h" #include "clang/Driver/Util.h" #include "llvm/ADT/OwningPtr.h" @@ -77,8 +76,6 @@ private: mutable OwningPtr<SanitizerArgs> SanitizerArguments; protected: - MultilibSet Multilibs; - ToolChain(const Driver &D, const llvm::Triple &T, const llvm::opt::ArgList &Args); @@ -133,8 +130,6 @@ public: path_list &getProgramPaths() { return ProgramPaths; } const path_list &getProgramPaths() const { return ProgramPaths; } - const MultilibSet &getMultilibs() const { return Multilibs; } - const SanitizerArgs& getSanitizerArgs() const; // Tool access. diff --git a/clang/lib/Driver/CMakeLists.txt b/clang/lib/Driver/CMakeLists.txt index 818d554d4ec..e874ab8a8b3 100644 --- a/clang/lib/Driver/CMakeLists.txt +++ b/clang/lib/Driver/CMakeLists.txt @@ -11,7 +11,6 @@ add_clang_library(clangDriver Driver.cpp DriverOptions.cpp Job.cpp - Multilib.cpp Phases.cpp SanitizerArgs.cpp Tool.cpp diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index dd650ae8338..898bdc94e29 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -748,34 +748,51 @@ bool Driver::HandleImmediateArgs(const Compilation &C) { } if (C.getArgs().hasArg(options::OPT_print_multi_lib)) { - const MultilibSet &Multilibs = TC.getMultilibs(); + // FIXME: We need tool chain support for this. + llvm::outs() << ".;\n"; - for (MultilibSet::const_iterator I = Multilibs.begin(), E = Multilibs.end(); - I != E; ++I) { - llvm::outs() << *I << "\n"; - } - return false; - } + switch (C.getDefaultToolChain().getTriple().getArch()) { + default: + break; - if (C.getArgs().hasArg(options::OPT_print_multi_directory)) { - const MultilibSet &Multilibs = TC.getMultilibs(); - for (MultilibSet::const_iterator I = Multilibs.begin(), E = Multilibs.end(); - I != E; ++I) { - if (I->gccSuffix().empty()) - llvm::outs() << ".\n"; - else { - StringRef Suffix(I->gccSuffix()); - assert(Suffix.front() == '/'); - llvm::outs() << Suffix.substr(1) << "\n"; - } + case llvm::Triple::x86_64: + llvm::outs() << "x86_64;@m64" << "\n"; + break; + + case llvm::Triple::ppc64: + llvm::outs() << "ppc64;@m64" << "\n"; + break; + + case llvm::Triple::ppc64le: + llvm::outs() << "ppc64le;@m64" << "\n"; + break; } return false; } - if (C.getArgs().hasArg(options::OPT_print_multi_os_directory)) { - // FIXME: This should print out "lib/../lib", "lib/../lib64", or - // "lib/../lib32" as appropriate for the toolchain. For now, print - // nothing because it's not supported yet. + // FIXME: What is the difference between print-multi-directory and + // print-multi-os-directory? + if (C.getArgs().hasArg(options::OPT_print_multi_directory) || + C.getArgs().hasArg(options::OPT_print_multi_os_directory)) { + switch (C.getDefaultToolChain().getTriple().getArch()) { + default: + case llvm::Triple::x86: + case llvm::Triple::ppc: + llvm::outs() << "." << "\n"; + break; + + case llvm::Triple::x86_64: + llvm::outs() << "x86_64" << "\n"; + break; + + case llvm::Triple::ppc64: + llvm::outs() << "ppc64" << "\n"; + break; + + case llvm::Triple::ppc64le: + llvm::outs() << "ppc64le" << "\n"; + break; + } return false; } diff --git a/clang/lib/Driver/Multilib.cpp b/clang/lib/Driver/Multilib.cpp deleted file mode 100644 index 6d68517e83f..00000000000 --- a/clang/lib/Driver/Multilib.cpp +++ /dev/null @@ -1,347 +0,0 @@ -//===--- Multilib.cpp - Multilib Implementation ---------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "clang/Driver/Multilib.h" -#include "Tools.h" -#include "clang/Driver/Options.h" -#include "llvm/ADT/StringMap.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/ADT/StringSet.h" -#include "llvm/ADT/Triple.h" -#include "llvm/Option/Arg.h" -#include "llvm/Option/ArgList.h" -#include "llvm/Option/OptTable.h" -#include "llvm/Option/Option.h" -#include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/Path.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/Support/Regex.h" -#include "llvm/Support/YAMLParser.h" -#include "llvm/Support/YAMLTraits.h" -#include <algorithm> - -using namespace clang::driver; -using namespace clang; -using namespace llvm::opt; - -static void normalizePathSegment(std::string &Segment) { - StringRef SRS(Segment); - if (SRS.empty() || SRS == "/." || SRS == "/" || SRS == ".") { - SRS = ""; - } else { - if (SRS.back() == '/') - SRS = SRS.drop_back(); - if (SRS.front() != '/') - SRS = ("/" + SRS).str(); - } - Segment = SRS; -} - -Multilib::Multilib(StringRef GCCSuffix, StringRef OSSuffix, - StringRef IncludeSuffix) - : GCCSuffix(GCCSuffix), OSSuffix(OSSuffix), IncludeSuffix(IncludeSuffix) { - normalizePathSegment(this->GCCSuffix); - normalizePathSegment(this->OSSuffix); - normalizePathSegment(this->IncludeSuffix); -} - -Multilib &Multilib::gccSuffix(StringRef S) { - GCCSuffix = S; - normalizePathSegment(GCCSuffix); - return *this; -} - -Multilib &Multilib::osSuffix(StringRef S) { - OSSuffix = S; - normalizePathSegment(OSSuffix); - return *this; -} - -Multilib &Multilib::includeSuffix(StringRef S) { - IncludeSuffix = S; - normalizePathSegment(IncludeSuffix); - return *this; -} - -void Multilib::print(raw_ostream &OS) const { - assert(GCCSuffix.empty() || (StringRef(GCCSuffix).front() == '/')); - if (GCCSuffix.empty()) - OS << "."; - else { - OS << StringRef(GCCSuffix).drop_front(); - } - OS << ";"; - for (flags_list::const_iterator I = Flags.begin(), E = Flags.end(); I != E; - ++I) { - if (StringRef(*I).front() == '+') - OS << "@" << I->substr(1); - } -} - -bool Multilib::isValid() const { - llvm::StringMap<int> FlagSet; - for (unsigned I = 0, N = Flags.size(); I != N; ++I) { - StringRef Flag(Flags[I]); - llvm::StringMap<int>::iterator SI = FlagSet.find(Flag.substr(1)); - - assert(StringRef(Flag).front() == '+' || StringRef(Flag).front() == '-'); - - if (SI == FlagSet.end()) - FlagSet[Flag.substr(1)] = I; - else if (Flags[I] != Flags[SI->getValue()]) - return false; - } - return true; -} - -bool Multilib::operator==(const Multilib &Other) const { - // Check whether the flags sets match - // allowing for the match to be order invariant - llvm::StringSet<> MyFlags; - for (flags_list::const_iterator I = Flags.begin(), E = Flags.end(); I != E; - ++I) { - MyFlags.insert(*I); - } - for (flags_list::const_iterator I = Other.Flags.begin(), - E = Other.Flags.end(); - I != E; ++I) { - if (MyFlags.find(*I) == MyFlags.end()) - return false; - } - - if (osSuffix() != Other.osSuffix()) - return false; - - if (gccSuffix() != Other.gccSuffix()) - return false; - - if (includeSuffix() != Other.includeSuffix()) - return false; - - return true; -} - -raw_ostream &clang::driver::operator<<(raw_ostream &OS, const Multilib &M) { - M.print(OS); - return OS; -} - -MultilibSet &MultilibSet::Maybe(const Multilib &M) { - Multilib Opposite; - // Negate any '+' flags - for (Multilib::flags_list::const_iterator I = M.flags().begin(), - E = M.flags().end(); - I != E; ++I) { - StringRef Flag(*I); - if (Flag.front() == '+') - Opposite.flags().push_back(("-" + Flag.substr(1)).str()); - } - return Either(M, Opposite); -} - -MultilibSet &MultilibSet::Either(const Multilib &M1, const Multilib &M2) { - std::vector<Multilib> Ms; - Ms.push_back(M1); - Ms.push_back(M2); - return Either(Ms); -} - -MultilibSet &MultilibSet::Either(const Multilib &M1, const Multilib &M2, - const Multilib &M3) { - std::vector<Multilib> Ms; - Ms.push_back(M1); - Ms.push_back(M2); - Ms.push_back(M3); - return Either(Ms); -} - -MultilibSet &MultilibSet::Either(const Multilib &M1, const Multilib &M2, - const Multilib &M3, const Multilib &M4) { - std::vector<Multilib> Ms; - Ms.push_back(M1); - Ms.push_back(M2); - Ms.push_back(M3); - Ms.push_back(M4); - return Either(Ms); -} - -MultilibSet &MultilibSet::Either(const Multilib &M1, const Multilib &M2, - const Multilib &M3, const Multilib &M4, - const Multilib &M5) { - std::vector<Multilib> Ms; - Ms.push_back(M1); - Ms.push_back(M2); - Ms.push_back(M3); - Ms.push_back(M4); - Ms.push_back(M5); - return Either(Ms); -} - -static Multilib compose(const Multilib &Base, const Multilib &New) { - SmallString<128> GCCSuffix; - llvm::sys::path::append(GCCSuffix, "/", Base.gccSuffix(), New.gccSuffix()); - SmallString<128> OSSuffix; - llvm::sys::path::append(OSSuffix, "/", Base.osSuffix(), New.osSuffix()); - SmallString<128> IncludeSuffix; - llvm::sys::path::append(IncludeSuffix, "/", Base.includeSuffix(), - New.includeSuffix()); - - Multilib Composed(GCCSuffix.str(), OSSuffix.str(), IncludeSuffix.str()); - - Multilib::flags_list &Flags = Composed.flags(); - - Flags.insert(Flags.end(), Base.flags().begin(), Base.flags().end()); - Flags.insert(Flags.end(), New.flags().begin(), New.flags().end()); - - return Composed; -} - -MultilibSet & -MultilibSet::Either(const std::vector<Multilib> &MultilibSegments) { - multilib_list Composed; - - if (Multilibs.empty()) - Multilibs.insert(Multilibs.end(), MultilibSegments.begin(), - MultilibSegments.end()); - else { - for (std::vector<Multilib>::const_iterator NewI = MultilibSegments.begin(), - NewE = MultilibSegments.end(); - NewI != NewE; ++NewI) { - for (const_iterator BaseI = begin(), BaseE = end(); BaseI != BaseE; - ++BaseI) { - Multilib MO = compose(*BaseI, *NewI); - if (MO.isValid()) - Composed.push_back(MO); - } - } - - Multilibs = Composed; - } - - return *this; -} - -MultilibSet &MultilibSet::FilterOut(const MultilibSet::FilterCallback &F) { - filterInPlace(F, Multilibs); - return *this; -} - -MultilibSet &MultilibSet::FilterOut(std::string Regex) { - class REFilter : public MultilibSet::FilterCallback { - mutable llvm::Regex R; - - public: - REFilter(std::string Regex) : R(Regex) {} - bool operator()(const Multilib &M) const LLVM_OVERRIDE { - std::string Error; - if (!R.isValid(Error)) { - llvm::errs() << Error; - assert(false); - return false; - } - return R.match(M.gccSuffix()); - } - }; - - REFilter REF(Regex); - filterInPlace(REF, Multilibs); - return *this; -} - -void MultilibSet::push_back(const Multilib &M) { Multilibs.push_back(M); } - -void MultilibSet::combineWith(const MultilibSet &Other) { - Multilibs.insert(Multilibs.end(), Other.begin(), Other.end()); -} - -bool MultilibSet::select(const Multilib::flags_list &Flags, Multilib &M) const { - class FilterFlagsMismatch : public MultilibSet::FilterCallback { - llvm::StringMap<bool> FlagSet; - - public: - FilterFlagsMismatch(const std::vector<std::string> &Flags) { - // Stuff all of the flags into the FlagSet such that a true mappend - // indicates the flag was enabled, and a false mappend indicates the - // flag was disabled - for (Multilib::flags_list::const_iterator I = Flags.begin(), - E = Flags.end(); - I != E; ++I) { - FlagSet[StringRef(*I).substr(1)] = isFlagEnabled(*I); - } - } - bool operator()(const Multilib &M) const LLVM_OVERRIDE { - for (Multilib::flags_list::const_iterator I = M.flags().begin(), - E = M.flags().end(); - I != E; ++I) { - StringRef Flag(*I); - llvm::StringMap<bool>::const_iterator SI = FlagSet.find(Flag.substr(1)); - if (SI != FlagSet.end()) - if ((*SI).getValue() != isFlagEnabled(Flag)) - return true; - } - return false; - } - private: - bool isFlagEnabled(StringRef Flag) const { - char Indicator = Flag.front(); - assert(Indicator == '+' || Indicator == '-'); - return Indicator == '+'; - } - }; - - FilterFlagsMismatch FlagsMismatch(Flags); - - multilib_list Filtered = filterCopy(FlagsMismatch, Multilibs); - - if (Filtered.size() == 0) { - return false; - } else if (Filtered.size() == 1) { - M = Filtered[0]; - return true; - } - - // TODO: pick the "best" multlib when more than one is suitable - assert(false); - - return false; -} - -void MultilibSet::print(raw_ostream &OS) const { - for (const_iterator I = begin(), E = end(); I != E; ++I) - OS << *I << "\n"; -} - -MultilibSet::multilib_list -MultilibSet::filterCopy(const MultilibSet::FilterCallback &F, - const multilib_list &Ms) { - multilib_list Copy(Ms); - filterInPlace(F, Copy); - return Copy; -} - -namespace { -// Wrapper for FilterCallback to make operator() nonvirtual so it -// can be passed by value to std::remove_if -class FilterWrapper { - const MultilibSet::FilterCallback &F; -public: - FilterWrapper(const MultilibSet::FilterCallback &F) : F(F) {} - bool operator()(const Multilib &M) const { return F(M); } -}; -} // end anonymous namespace - -void MultilibSet::filterInPlace(const MultilibSet::FilterCallback &F, - multilib_list &Ms) { - Ms.erase(std::remove_if(Ms.begin(), Ms.end(), FilterWrapper(F)), Ms.end()); -} - -raw_ostream &clang::driver::operator<<(raw_ostream &OS, const MultilibSet &MS) { - MS.print(OS); - return OS; -} diff --git a/clang/lib/Driver/ToolChains.cpp b/clang/lib/Driver/ToolChains.cpp index 60ca7ea195a..f2155947586 100644 --- a/clang/lib/Driver/ToolChains.cpp +++ b/clang/lib/Driver/ToolChains.cpp @@ -139,11 +139,11 @@ static const char *GetArmArchForMCpu(StringRef Value) { } static bool isSoftFloatABI(const ArgList &Args) { - Arg *A = Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float, + Arg *A = Args.getLastArg(options::OPT_msoft_float, + options::OPT_mhard_float, options::OPT_mfloat_abi_EQ); - if (!A) - return false; - + if (!A) return false; + return A->getOption().matches(options::OPT_msoft_float) || (A->getOption().matches(options::OPT_mfloat_abi_EQ) && A->getValue() == StringRef("soft")); @@ -1175,7 +1175,7 @@ bool Generic_GCC::GCCVersion::isOlderThan(int RHSMajor, int RHSMinor, return false; } -static llvm::StringRef getGCCToolchainDir(const ArgList &Args) { +static StringRef getGCCToolchainDir(const ArgList &Args) { const Arg *A = Args.getLastArg(options::OPT_gcc_toolchain); if (A) return A->getValue(); @@ -1197,6 +1197,7 @@ Generic_GCC::GCCInstallationDetector::init( llvm::Triple BiarchVariantTriple = TargetTriple.isArch32Bit() ? TargetTriple.get64BitArchVariant() : TargetTriple.get32BitArchVariant(); + llvm::Triple::ArchType TargetArch = TargetTriple.getArch(); // The library directories which may contain GCC installations. SmallVector<StringRef, 4> CandidateLibDirs, CandidateBiarchLibDirs; // The compatible GCC triples for this particular architecture. @@ -1242,7 +1243,7 @@ Generic_GCC::GCCInstallationDetector::init( if (!llvm::sys::fs::exists(LibDir)) continue; for (unsigned k = 0, ke = CandidateTripleAliases.size(); k < ke; ++k) - ScanLibDirForGCCTriple(TargetTriple, Args, LibDir, + ScanLibDirForGCCTriple(TargetArch, Args, LibDir, CandidateTripleAliases[k]); } for (unsigned j = 0, je = CandidateBiarchLibDirs.size(); j < je; ++j) { @@ -1251,7 +1252,7 @@ Generic_GCC::GCCInstallationDetector::init( continue; for (unsigned k = 0, ke = CandidateBiarchTripleAliases.size(); k < ke; ++k) - ScanLibDirForGCCTriple(TargetTriple, Args, LibDir, + ScanLibDirForGCCTriple(TargetArch, Args, LibDir, CandidateBiarchTripleAliases[k], /*NeedsBiarchSuffix=*/ true); } @@ -1266,19 +1267,6 @@ void Generic_GCC::GCCInstallationDetector::print(raw_ostream &OS) const { OS << "Found candidate GCC installation: " << *I << "\n"; OS << "Selected GCC installation: " << GCCInstallPath << "\n"; - for (MultilibSet::const_iterator I = Multilibs.begin(), E = Multilibs.end(); - I != E; ++I) { - OS << "Candidate multiilb: " << *I << "\n"; - } - OS << "Selected multilib: " << SelectedMultilib << "\n"; -} - -bool Generic_GCC::GCCInstallationDetector::getBiarchSibling(Multilib &M) const { - if (BiarchSibling.hasValue()) { - M = BiarchSibling.getValue(); - return true; - } - return false; } /*static*/ void Generic_GCC::GCCInstallationDetector::CollectLibDirsAndTriples( @@ -1514,45 +1502,11 @@ bool Generic_GCC::GCCInstallationDetector::getBiarchSibling(Multilib &M) const { BiarchTripleAliases.push_back(BiarchTriple.str()); } -namespace { -// Filter to remove Multilibs that don't exist as a suffix to Path -class FilterNonExistant : public MultilibSet::FilterCallback { - std::string Base; -public: - FilterNonExistant(std::string Base) : Base(Base) {} - bool operator()(const Multilib &M) const LLVM_OVERRIDE { - return !llvm::sys::fs::exists(Base + M.gccSuffix() + "/crtbegin.o"); - } -}; -} // end anonymous namespace - -static void addMultilibFlag(bool Enabled, const char *const Flag, - std::vector<std::string> &Flags) { - if (Enabled) - Flags.push_back(std::string("+") + Flag); - else - Flags.push_back(std::string("-") + Flag); -} - static bool isMipsArch(llvm::Triple::ArchType Arch) { - return Arch == llvm::Triple::mips || Arch == llvm::Triple::mipsel || - Arch == llvm::Triple::mips64 || Arch == llvm::Triple::mips64el; -} - -static bool isMips32(llvm::Triple::ArchType Arch) { - return Arch == llvm::Triple::mips || Arch == llvm::Triple::mipsel; -} - -static bool isMips64(llvm::Triple::ArchType Arch) { - return Arch == llvm::Triple::mips64 || Arch == llvm::Triple::mips64el; -} - -static bool isMipsEL(llvm::Triple::ArchType Arch) { - return Arch == llvm::Triple::mipsel || Arch == llvm::Triple::mips64el; -} - -static bool isMipsEB(llvm::Triple::ArchType Arch) { - return Arch == llvm::Triple::mips || Arch == llvm::Triple::mips64; + return Arch == llvm::Triple::mips || + Arch == llvm::Triple::mipsel || + Arch == llvm::Triple::mips64 || + Arch == llvm::Triple::mips64el; } static bool isMips16(const ArgList &Args) { @@ -1591,8 +1545,39 @@ static bool isMipsNan2008(const ArgList &Args) { return A && A->getValue() == StringRef("2008"); } -bool Generic_GCC::GCCInstallationDetector::findMIPSMultilibs( - const llvm::Triple &TargetTriple, StringRef Path, +// FIXME: There is the same routine in the Tools.cpp. +static bool hasMipsABIArg(const ArgList &Args, const char *Value) { + Arg *A = Args.getLastArg(options::OPT_mabi_EQ); + return A && (A->getValue() == StringRef(Value)); +} + +static bool hasCrtBeginObj(Twine Path) { + return llvm::sys::fs::exists(Path + "/crtbegin.o"); +} + +static bool findTargetBiarchSuffix(std::string &Suffix, StringRef Path, + llvm::Triple::ArchType TargetArch, + const ArgList &Args) { + // FIXME: This routine was only intended to model bi-arch toolchains which + // use -m32 and -m64 to swap between variants of a target. It shouldn't be + // doing ABI-based builtin location for MIPS. + if (hasMipsABIArg(Args, "n32")) + Suffix = "/n32"; + else if (TargetArch == llvm::Triple::x86_64 || + TargetArch == llvm::Triple::ppc64 || + TargetArch == llvm::Triple::sparcv9 || + TargetArch == llvm::Triple::systemz || + TargetArch == llvm::Triple::mips64 || + TargetArch == llvm::Triple::mips64el) + Suffix = "/64"; + else + Suffix = "/32"; + + return hasCrtBeginObj(Path + Suffix); +} + +void Generic_GCC::GCCInstallationDetector::findMIPSABIDirSuffix( + std::string &Suffix, llvm::Triple::ArchType TargetArch, StringRef Path, const llvm::opt::ArgList &Args) { // Some MIPS toolchains put libraries and object files compiled // using different options in to the sub-directoris which names @@ -1619,286 +1604,69 @@ bool Generic_GCC::GCCInstallationDetector::findMIPSMultilibs( // /usr // /lib <= crt*.o files compiled with '-mips32' - FilterNonExistant NonExistant(Path); - - // Check for FSF toolchain multilibs - MultilibSet FSFMipsMultilibs; - { - Multilib MArchMips32 = Multilib() - .gccSuffix("/mips32") - .osSuffix("/mips32") - .includeSuffix("/mips32") - .flag("+m32").flag("-m64").flag("-mmicromips").flag("-march=mips32r2"); - - Multilib MArchMicroMips = Multilib() - .gccSuffix("/micromips") - .osSuffix("/micromips") - .includeSuffix("/micromips") - .flag("+m32").flag("-m64").flag("+mmicromips"); - - Multilib MArchMips64r2 = Multilib() - .gccSuffix("/mips64r2") - .osSuffix("/mips64r2") - .includeSuffix("/mips64r2") - .flag("-m32").flag("+m64").flag("+march=mips64r2"); - - Multilib MArchMips64 = Multilib() - .gccSuffix("/mips64") - .osSuffix("/mips64") - .includeSuffix("/mips64") - .flag("-m32").flag("+m64").flag("-march=mips64r2"); - - Multilib MArchDefault = Multilib() - .flag("+m32").flag("-m64").flag("+march=mips32r2"); - - Multilib Mips16 = Multilib() - .gccSuffix("/mips16") - .osSuffix("/mips16") - .includeSuffix("/mips16") - .flag("+mips16"); - - Multilib MAbi64 = Multilib() - .gccSuffix("/64") - .osSuffix("/64") - .includeSuffix("/64") - .flag("+mabi=64").flag("-mabi=n32").flag("-m32"); - - Multilib LittleEndian = Multilib() - .gccSuffix("/el") - .osSuffix("/el") - .includeSuffix("/el") - .flag("+EL").flag("-EB"); - - Multilib SoftFloat = Multilib() - .gccSuffix("/sof") - .osSuffix("/sof") - .includeSuffix("/sof") - .flag("+msoft-float"); - - Multilib FP64 = Multilib() - .gccSuffix("/fp64") - .osSuffix("/fp64") - .includeSuffix("/fp64") - .flag("+mfp64"); - - Multilib Nan2008 = Multilib() - .gccSuffix("/nan2008") - .osSuffix("/nan2008") - .includeSuffix("/nan2008") - .flag("+mnan=2008"); - - FSFMipsMultilibs = MultilibSet() - .Either(MArchMips32, MArchMicroMips, - MArchMips64r2, MArchMips64, MArchDefault) - .Maybe(Mips16) - .FilterOut("/mips64/mips16") - .FilterOut("/mips64r2/mips16") - .FilterOut("/micromips/mips16") - .Maybe(MAbi64) - .FilterOut("/micromips/64") - .FilterOut("/mips32/64") - .FilterOut("^/64") - .FilterOut("/mips16/64") - .Maybe(LittleEndian) - .Maybe(SoftFloat) - .Maybe(FP64) - .Maybe(Nan2008) - .FilterOut(".*sof/nan2008") - .FilterOut(".*sof/fp64") - .FilterOut(NonExistant); - } - - // Check for Code Sourcery toolchain multilibs - MultilibSet CSMipsMultilibs; - { - Multilib MArchMips16 = Multilib() - .gccSuffix("/mips16") - .osSuffix("/mips16") - .includeSuffix("/mips16") - .flag("+m32").flag("+mips16"); - - Multilib MArchMicroMips = Multilib() - .gccSuffix("/micromips") - .osSuffix("/micromips") - .includeSuffix("/micromips") - .flag("+m32").flag("+mmicromips"); - - Multilib MArchDefault = Multilib() - .flag("-mips16").flag("-mmicromips"); - - Multilib SoftFloat = Multilib() - .gccSuffix("/soft-float") - .osSuffix("/soft-float") - .includeSuffix("/soft-float") - .flag("+msoft-float"); - - Multilib Nan2008 = Multilib() - .gccSuffix("/nan2008") - .osSuffix("/nan2008") - .includeSuffix("/nan2008") - .flag("+mnan=2008"); - - Multilib DefaultFloat = Multilib() - .flag("-msoft-float").flag("-mnan=2008"); - - Multilib LittleEndian = Multilib() - .gccSuffix("/el") - .osSuffix("/el") - .includeSuffix("/el") - .flag("+EL").flag("-EB"); - - // Note that this one's osSuffix is "" - Multilib MAbi64 = Multilib() - .gccSuffix("/64") - .includeSuffix("/64") - .flag("+mabi=64").flag("-mabi=n32").flag("-m32"); - - CSMipsMultilibs = MultilibSet() - .Either(MArchMips16, MArchMicroMips, MArchDefault) - .Either(SoftFloat, Nan2008, DefaultFloat) - .FilterOut("/micromips/nan2008") - .FilterOut("/mips16/nan2008") - .Maybe(LittleEndian) - .Maybe(MAbi64) - .FilterOut("/mips16.*/64") - .FilterOut("/micromips.*/64") - .FilterOut(NonExistant); - } - - MultilibSet AndroidMipsMultilibs = MultilibSet() - .Maybe(Multilib("/mips-r2").flag("+march=mips32r2")) - .FilterOut(NonExistant); - - MultilibSet DebianMipsMultilibs; - { - Multilib MAbiN32 = Multilib() - .gccSuffix("/n32") - .includeSuffix("/n32") - .flag("+mabi=n32"); - - Multilib M64 = Multilib() - .gccSuffix("/64") - .includeSuffix("/64") - .flag("+m64").flag("-m32").flag("-mabi=n32"); - - Multilib M32 = Multilib() - .flag("-m64").flag("+m32").flag("-mabi=n32"); - - DebianMipsMultilibs = MultilibSet() - .Either(M32, M64, MAbiN32) - .FilterOut(NonExistant); - } - - Multilibs.clear(); - - // Decide which MultilibSet matches best for the given path - // (we do this rather than combining them all because there is a - // a bit of overlap in the directories that each specifies) - if (TargetTriple.getEnvironment() == llvm::Triple::Android) - Multilibs.combineWith(AndroidMipsMultilibs); - else if (DebianMipsMultilibs.size() == 3) { - Multilibs.combineWith(DebianMipsMultilibs); - BiarchSibling = Multilib(); - } else if (FSFMipsMultilibs.size() > CSMipsMultilibs.size()) - Multilibs.combineWith(FSFMipsMultilibs); - else - Multilibs.combineWith(CSMipsMultilibs); + // Check FSF Toolchain path + Suffix.clear(); + if (TargetArch == llvm::Triple::mips || + TargetArch == llvm::Triple::mipsel) { + if (isMicroMips(Args)) + Suffix += "/micromips"; + else if (isMips32r2(Args)) + Suffix += ""; + else + Suffix += "/mips32"; - llvm::Triple::ArchType TargetArch = TargetTriple.getArch(); + if (isMips16(Args)) + Suffix += "/mips16"; + } else { + if (isMips64r2(Args)) + Suffix += hasMipsABIArg(Args, "n32") ? "/mips64r2" : "/mips64r2/64"; + else + Suffix += hasMipsABIArg(Args, "n32") ? "/mips64" : "/mips64/64"; + } - Multilib::flags_list Flags; - addMultilibFlag(isMips32(TargetArch), "m32", Flags); - addMultilibFlag(isMips64(TargetArch), "m64", Flags); - addMultilibFlag(isMips16(Args), "mips16", Flags); - addMultilibFlag(isMips32r2(Args), "march=mips32r2", Flags); - addMultilibFlag(isMips64r2(Args), "march=mips64r2", Flags); - addMultilibFlag(isMicroMips(Args), "mmicromips", Flags); - addMultilibFlag(isMipsFP64(Args), "mfp64", Flags); - addMultilibFlag(!isMipsFP64(Args), "mfp32", Flags); - addMultilibFlag(isMipsNan2008(Args), "mnan=2008", Flags); - addMultilibFlag(tools::mips::hasMipsAbiArg(Args, "n32"), "mabi=n32", Flags); - // Default is to assume mabi=64 - bool IsMABI64 = - tools::mips::hasMipsAbiArg(Args, "64") || - (!tools::mips::hasMipsAbiArg(Args, "n32") && isMips64(TargetArch)); - addMultilibFlag(IsMABI64, "mabi=64", Flags); - addMultilibFlag(isSoftFloatABI(Args), "msoft-float", Flags); - addMultilibFlag(isSoftFloatABI(Args), "mfloat-abi=soft", Flags); - addMultilibFlag(!isSoftFloatABI(Args), "mhard-float", Flags); - addMultilibFlag(!isSoftFloatABI(Args), "mfloat-abi=hard", Flags); - addMultilibFlag(isMipsEL(TargetArch), "EL", Flags); - addMultilibFlag(isMipsEB(TargetArch), "EB", Flags); - - return Multilibs.select(Flags, SelectedMultilib); -} - -bool Generic_GCC::GCCInstallationDetector::findBiarchMultilibs( - const llvm::Triple &TargetTriple, StringRef Path, const ArgList &Args, - bool NeedsBiarchSuffix) { + if (TargetArch == llvm::Triple::mipsel || + TargetArch == llvm::Triple::mips64el) + Suffix += "/el"; - // 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. 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 biarch triple alias, we look for - // crtbegin.o without the subdirectory. - - Multilib Default; - Multilib Alt64 = Multilib() - .gccSuffix("/64") - .includeSuffix("/64") - .flag("-m32").flag("+m64"); - Multilib Alt32 = Multilib() - .gccSuffix("/32") - .includeSuffix("/32") - .flag("+m32").flag("-m64"); - - FilterNonExistant NonExistant(Path); - - // Decide whether the default multilib is 32bit, correcting for - // when the default multilib and the alternate appear backwards - bool DefaultIs32Bit; - if (TargetTriple.isArch32Bit() && !NonExistant(Alt32)) - DefaultIs32Bit = false; - else if (TargetTriple.isArch64Bit() && !NonExistant(Alt64)) - DefaultIs32Bit = true; + if (isSoftFloatABI(Args)) + Suffix += "/sof"; else { - if (NeedsBiarchSuffix) - DefaultIs32Bit = TargetTriple.isArch64Bit(); - else - DefaultIs32Bit = TargetTriple.isArch32Bit(); - } + if (isMipsFP64(Args)) + Suffix += "/fp64"; - if (DefaultIs32Bit) - Default.flag("+m32").flag("-m64"); - else - Default.flag("-m32").flag("+m64"); + if (isMipsNan2008(Args)) + Suffix += "/nan2008"; + } - Multilibs.push_back(Default); - Multilibs.push_back(Alt64); - Multilibs.push_back(Alt32); + if (hasCrtBeginObj(Path + Suffix)) + return; - Multilibs.FilterOut(NonExistant); + // Check Code Sourcery Toolchain path + Suffix.clear(); + if (isMips16(Args)) + Suffix += "/mips16"; + else if (isMicroMips(Args)) + Suffix += "/micromips"; - Multilib::flags_list Flags; - addMultilibFlag(TargetTriple.isArch64Bit(), "m64", Flags); - addMultilibFlag(TargetTriple.isArch32Bit(), "m32", Flags); + if (isSoftFloatABI(Args)) + Suffix += "/soft-float"; + else if (isMipsNan2008(Args)) + Suffix += "/nan2008"; - if (!Multilibs.select(Flags, SelectedMultilib)) - return false; + if (TargetArch == llvm::Triple::mipsel || + TargetArch == llvm::Triple::mips64el) + Suffix += "/el"; - if (SelectedMultilib == Alt64 || SelectedMultilib == Alt32) { - BiarchSibling = Default; - } + if (hasCrtBeginObj(Path + Suffix)) + return; - return true; + Suffix.clear(); } void Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple( - const llvm::Triple &TargetTriple, const ArgList &Args, + llvm::Triple::ArchType TargetArch, const ArgList &Args, const std::string &LibDir, StringRef CandidateTriple, bool NeedsBiarchSuffix) { - llvm::Triple::ArchType TargetArch = TargetTriple.getArch(); // 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. @@ -1943,18 +1711,28 @@ void Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple( if (CandidateVersion <= Version) continue; - Multilibs.clear(); - SelectedMultilib = Multilib(); - BiarchSibling.reset(); - - // Debian mips multilibs behave more like the rest of the biarch ones, - // so handle them there - if (isMipsArch(TargetArch)) { - if (!findMIPSMultilibs(TargetTriple, LI->path(), Args)) - continue; - } else if (!findBiarchMultilibs(TargetTriple, LI->path(), Args, - NeedsBiarchSuffix)) + std::string MIPSABIDirSuffix; + if (isMipsArch(TargetArch)) + findMIPSABIDirSuffix(MIPSABIDirSuffix, TargetArch, LI->path(), Args); + + // 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. 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 biarch triple alias, we look for + // crtbegin.o without the subdirectory. + + std::string BiarchSuffix; + if (findTargetBiarchSuffix(BiarchSuffix, + LI->path() + MIPSABIDirSuffix, + TargetArch, Args)) { + GCCBiarchSuffix = BiarchSuffix; + } else if (NeedsBiarchSuffix || + !hasCrtBeginObj(LI->path() + MIPSABIDirSuffix)) { continue; + } else { + GCCBiarchSuffix.clear(); + } Version = CandidateVersion; GCCTriple.setTriple(CandidateTriple); @@ -1963,6 +1741,7 @@ void Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple( // Linux. GCCInstallPath = LibDir + LibSuffixes[i] + "/" + VersionText.str(); GCCParentLibPath = GCCInstallPath + InstallSuffixes[i]; + GCCMIPSABIDirSuffix = MIPSABIDirSuffix; IsValid = true; } } @@ -2471,9 +2250,9 @@ NetBSD::NetBSD(const Driver &D, const llvm::Triple& Triple, const ArgList &Args) break; case llvm::Triple::mips64: case llvm::Triple::mips64el: - if (tools::mips::hasMipsAbiArg(Args, "o32")) + if (hasMipsABIArg(Args, "o32")) getFilePaths().push_back("=/usr/lib/o32"); - else if (tools::mips::hasMipsAbiArg(Args, "64")) + else if (hasMipsABIArg(Args, "64")) getFilePaths().push_back("=/usr/lib/64"); break; default: @@ -2787,24 +2566,25 @@ static void addPathIfExists(Twine Path, ToolChain::path_list &Paths) { if (llvm::sys::fs::exists(Path)) Paths.push_back(Path.str()); } -static StringRef getOSLibDir(const llvm::Triple &Triple, const ArgList &Args) { +static StringRef getMultilibDir(const llvm::Triple &Triple, + const ArgList &Args) { if (isMipsArch(Triple.getArch())) { // lib32 directory has a special meaning on MIPS targets. // It contains N32 ABI binaries. Use this folder if produce // code for N32 ABI only. - if (tools::mips::hasMipsAbiArg(Args, "n32")) + if (hasMipsABIArg(Args, "n32")) return "lib32"; return Triple.isArch32Bit() ? "lib" : "lib64"; } - // It happens that only x86 and PPC use the 'lib32' variant of oslibdir, and + // It happens that only x86 and PPC use the 'lib32' variant of multilib, and // using that variant while targeting other architectures causes problems // because the libraries are laid out in shared system roots that can't cope - // with a 'lib32' library search path being considered. So we only enable + // with a 'lib32' multilib search path being considered. So we only enable // them when we know we may need it. // // FIXME: This is a bit of a hack. We should really unify this code for - // reasoning about oslibdir spellings with the lib dir spellings in the + // reasoning about multilib spellings with the lib dir spellings in the // GCCInstallationDetector, but that is a more significant refactoring. if (Triple.getArch() == llvm::Triple::x86 || Triple.getArch() == llvm::Triple::ppc) @@ -2816,7 +2596,6 @@ static StringRef getOSLibDir(const llvm::Triple &Triple, const ArgList &Args) { Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) : Generic_ELF(D, Triple, Args) { GCCInstallation.init(D, Triple, Args); - Multilibs = GCCInstallation.getMultilibs(); llvm::Triple::ArchType Arch = Triple.getArch(); std::string SysRoot = computeSysRoot(); @@ -2884,20 +2663,29 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) // to the link paths. path_list &Paths = getFilePaths(); - const std::string OSLibDir = getOSLibDir(Triple, Args); + const std::string Multilib = getMultilibDir(Triple, Args); const std::string MultiarchTriple = getMultiarchTriple(Triple, SysRoot); // Add the multilib suffixed paths where they are available. if (GCCInstallation.isValid()) { const llvm::Triple &GCCTriple = GCCInstallation.getTriple(); const std::string &LibPath = GCCInstallation.getParentLibPath(); - const Multilib &Multilib = GCCInstallation.getMultilib(); // Sourcery CodeBench MIPS toolchain holds some libraries under // a biarch-like suffix of the GCC installation. - addPathIfExists((GCCInstallation.getInstallPath() + - Multilib.gccSuffix()), - Paths); + // + // FIXME: It would be cleaner to model this as a variant of bi-arch. IE, + // instead of a '64' biarch suffix it would be 'el' or something. + if (IsAndroid && IsMips && isMips32r2(Args)) { + assert(GCCInstallation.getBiarchSuffix().empty() && + "Unexpected bi-arch suffix"); + addPathIfExists(GCCInstallation.getInstallPath() + "/mips-r2", Paths); + } else { + addPathIfExists((GCCInstallation.getInstallPath() + + GCCInstallation.getMIPSABIDirSuffix() + + GCCInstallation.getBiarchSuffix()), + Paths); + } // GCC cross compiling toolchains will install target libraries which ship // as part of the toolchain under <prefix>/<triple>/<libdir> rather than as @@ -2917,8 +2705,8 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) // // Note that this matches the GCC behavior. See the below comment for where // Clang diverges from GCC's behavior. - addPathIfExists(LibPath + "/../" + GCCTriple.str() + "/lib/../" + OSLibDir + - Multilib.osSuffix(), + addPathIfExists(LibPath + "/../" + GCCTriple.str() + "/lib/../" + Multilib + + GCCInstallation.getMIPSABIDirSuffix(), Paths); // If the GCC installation we found is inside of the sysroot, we want to @@ -2932,45 +2720,42 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) // a bug. if (StringRef(LibPath).startswith(SysRoot)) { addPathIfExists(LibPath + "/" + MultiarchTriple, Paths); - addPathIfExists(LibPath + "/../" + OSLibDir, Paths); + addPathIfExists(LibPath + "/../" + Multilib, Paths); } } // Similar to the logic for GCC above, if we currently running Clang inside - // of the requested system root, add its parent library paths to + // of the requested system root, add its parent multilib library paths to // those searched. // FIXME: It's not clear whether we should use the driver's installed // directory ('Dir' below) or the ResourceDir. if (StringRef(D.Dir).startswith(SysRoot)) { addPathIfExists(D.Dir + "/../lib/" + MultiarchTriple, Paths); - addPathIfExists(D.Dir + "/../" + OSLibDir, Paths); + addPathIfExists(D.Dir + "/../" + Multilib, Paths); } addPathIfExists(SysRoot + "/lib/" + MultiarchTriple, Paths); - addPathIfExists(SysRoot + "/lib/../" + OSLibDir, Paths); + addPathIfExists(SysRoot + "/lib/../" + Multilib, Paths); addPathIfExists(SysRoot + "/usr/lib/" + MultiarchTriple, Paths); - addPathIfExists(SysRoot + "/usr/lib/../" + OSLibDir, Paths); + addPathIfExists(SysRoot + "/usr/lib/../" + Multilib, Paths); // Try walking via the GCC triple path in case of biarch or multiarch GCC // installations with strange symlinks. if (GCCInstallation.isValid()) { addPathIfExists(SysRoot + "/usr/lib/" + GCCInstallation.getTriple().str() + - "/../../" + OSLibDir, Paths); + "/../../" + Multilib, Paths); - // Add the 'other' biarch variant path - Multilib BiarchSibling; - if (GCCInstallation.getBiarchSibling(BiarchSibling)) { + // Add the non-multilib suffixed paths (if potentially different). + const std::string &LibPath = GCCInstallation.getParentLibPath(); + const llvm::Triple &GCCTriple = GCCInstallation.getTriple(); + if (!GCCInstallation.getBiarchSuffix().empty()) addPathIfExists(GCCInstallation.getInstallPath() + - BiarchSibling.gccSuffix(), Paths); - } + GCCInstallation.getMIPSABIDirSuffix(), Paths); // See comments above on the multilib variant for details of why this is // included even from outside the sysroot. - const std::string &LibPath = GCCInstallation.getParentLibPath(); - const llvm::Triple &GCCTriple = GCCInstallation.getTriple(); - const Multilib &Multilib = GCCInstallation.getMultilib(); addPathIfExists(LibPath + "/../" + GCCTriple.str() + - "/lib" + Multilib.osSuffix(), Paths); + "/lib" + GCCInstallation.getMIPSABIDirSuffix(), Paths); // See comments above on the multilib variant for details of why this is // only included from within the sysroot. @@ -3019,15 +2804,15 @@ std::string Linux::computeSysRoot() const { const StringRef InstallDir = GCCInstallation.getInstallPath(); const StringRef TripleStr = GCCInstallation.getTriple().str(); - const Multilib &Multilib = GCCInstallation.getMultilib(); + const StringRef MIPSABIDirSuffix = GCCInstallation.getMIPSABIDirSuffix(); std::string Path = (InstallDir + "/../../../../" + TripleStr + "/libc" + - Multilib.osSuffix()).str(); + MIPSABIDirSuffix).str(); if (llvm::sys::fs::exists(Path)) return Path; - Path = (InstallDir + "/../../../../sysroot" + Multilib.osSuffix()).str(); + Path = (InstallDir + "/../../../../sysroot" + MIPSABIDirSuffix).str(); if (llvm::sys::fs::exists(Path)) return Path; @@ -3183,16 +2968,17 @@ void Linux::AddClangSystemIncludeArgs(const ArgList &DriverArgs, /// libstdc++ installation. /*static*/ bool Linux::addLibStdCXXIncludePaths(Twine Base, Twine Suffix, Twine TargetArchDir, - Twine IncludeSuffix, + Twine BiarchSuffix, + Twine MIPSABIDirSuffix, const ArgList &DriverArgs, ArgStringList &CC1Args) { if (!addLibStdCXXIncludePaths(Base + Suffix, - TargetArchDir + IncludeSuffix, + TargetArchDir + MIPSABIDirSuffix + BiarchSuffix, DriverArgs, CC1Args)) return false; addSystemInclude(DriverArgs, CC1Args, Base + "/" + TargetArchDir + Suffix - + IncludeSuffix); + + MIPSABIDirSuffix + BiarchSuffix); return true; } @@ -3236,12 +3022,13 @@ void Linux::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs, StringRef LibDir = GCCInstallation.getParentLibPath(); StringRef InstallDir = GCCInstallation.getInstallPath(); StringRef TripleStr = GCCInstallation.getTriple().str(); - const Multilib &Multilib = GCCInstallation.getMultilib(); + StringRef MIPSABIDirSuffix = GCCInstallation.getMIPSABIDirSuffix(); + StringRef BiarchSuffix = GCCInstallation.getBiarchSuffix(); const GCCVersion &Version = GCCInstallation.getVersion(); if (addLibStdCXXIncludePaths(LibDir.str() + "/../include", - "/c++/" + Version.Text, TripleStr, - Multilib.includeSuffix(), DriverArgs, CC1Args)) + "/c++/" + Version.Text, TripleStr, BiarchSuffix, + MIPSABIDirSuffix, DriverArgs, CC1Args)) return; const std::string LibStdCXXIncludePathCandidates[] = { @@ -3260,7 +3047,7 @@ void Linux::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs, for (unsigned i = 0; i < llvm::array_lengthof(LibStdCXXIncludePathCandidates); ++i) { if (addLibStdCXXIncludePaths(LibStdCXXIncludePathCandidates[i], - TripleStr + Multilib.includeSuffix(), + TripleStr + MIPSABIDirSuffix + BiarchSuffix, DriverArgs, CC1Args)) break; } diff --git a/clang/lib/Driver/ToolChains.h b/clang/lib/Driver/ToolChains.h index 6c3b084bf72..d5d058161f9 100644 --- a/clang/lib/Driver/ToolChains.h +++ b/clang/lib/Driver/ToolChains.h @@ -13,10 +13,8 @@ #include "Tools.h" #include "clang/Basic/VersionTuple.h" #include "clang/Driver/Action.h" -#include "clang/Driver/Multilib.h" #include "clang/Driver/ToolChain.h" #include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/Optional.h" #include "llvm/Support/Compiler.h" #include <set> #include <vector> @@ -69,6 +67,7 @@ protected: bool operator>=(const GCCVersion &RHS) const { return !(*this < RHS); } }; + /// \brief This is a class to find a viable GCC installation for Clang to /// use. /// @@ -81,13 +80,9 @@ protected: // FIXME: These might be better as path objects. std::string GCCInstallPath; + std::string GCCBiarchSuffix; std::string GCCParentLibPath; - - /// The primary multilib appropriate for the given flags. - Multilib SelectedMultilib; - /// On Biarch systems, this corresponds to the default multilib when - /// targeting the non-default multilib. Otherwise, it is empty. - llvm::Optional<Multilib> BiarchSibling; + std::string GCCMIPSABIDirSuffix; GCCVersion Version; @@ -95,9 +90,6 @@ protected: // order to print out detailed information in verbose mode. std::set<std::string> CandidateGCCInstallPaths; - /// The set of multilibs that the detected installation supports. - MultilibSet Multilibs; - public: GCCInstallationDetector() : IsValid(false) {} void init(const Driver &D, const llvm::Triple &TargetTriple, @@ -112,18 +104,26 @@ protected: /// \brief Get the detected GCC installation path. StringRef getInstallPath() const { return GCCInstallPath; } + /// \brief Get the detected GCC installation path suffix for the bi-arch + /// target variant. + StringRef getBiarchSuffix() const { return GCCBiarchSuffix; } + /// \brief Get the detected GCC parent lib path. StringRef getParentLibPath() const { return GCCParentLibPath; } - /// \brief Get the detected Multilib - const Multilib &getMultilib() const { return SelectedMultilib; } - - /// \brief Get the whole MultilibSet - const MultilibSet &getMultilibs() const { return Multilibs; } - - /// Get the biarch sibling multilib (if it exists). - /// \return true iff such a sibling exists - bool getBiarchSibling(Multilib &M) const; + /// \brief Get the detected GCC MIPS ABI directory suffix. + /// + /// This is used as a suffix both to the install directory of GCC and as + /// a suffix to its parent lib path in order to select a MIPS ABI-specific + /// subdirectory. + /// + /// This will always be empty for any non-MIPS target. + /// + // FIXME: This probably shouldn't exist at all, and should be factored + // into the multiarch and/or biarch support. Please don't add more uses of + // this interface, it is meant as a legacy crutch for the MIPS driver + // logic. + StringRef getMIPSABIDirSuffix() const { return GCCMIPSABIDirSuffix; } /// \brief Get the detected GCC version string. const GCCVersion &getVersion() const { return Version; } @@ -140,18 +140,15 @@ protected: SmallVectorImpl<StringRef> &BiarchLibDirs, SmallVectorImpl<StringRef> &BiarchTripleAliases); - void ScanLibDirForGCCTriple(const llvm::Triple &TargetArch, + void ScanLibDirForGCCTriple(llvm::Triple::ArchType TargetArch, const llvm::opt::ArgList &Args, const std::string &LibDir, StringRef CandidateTriple, bool NeedsBiarchSuffix = false); - bool findMIPSMultilibs(const llvm::Triple &TargetArch, StringRef Path, - const llvm::opt::ArgList &Args); - - bool findBiarchMultilibs(const llvm::Triple &TargetArch, StringRef Path, - const llvm::opt::ArgList &Args, - bool NeedsBiarchSuffix); + void findMIPSABIDirSuffix(std::string &Suffix, + llvm::Triple::ArchType TargetArch, StringRef Path, + const llvm::opt::ArgList &Args); }; GCCInstallationDetector GCCInstallation; @@ -668,7 +665,9 @@ protected: private: static bool addLibStdCXXIncludePaths(Twine Base, Twine Suffix, - Twine TargetArchDir, Twine IncludeSuffix, + Twine TargetArchDir, + Twine BiarchSuffix, + Twine MIPSABIDirSuffix, const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args); static bool addLibStdCXXIncludePaths(Twine Base, Twine TargetArchDir, diff --git a/clang/lib/Driver/Tools.cpp b/clang/lib/Driver/Tools.cpp index 5087ce6816c..b3a2b865441 100644 --- a/clang/lib/Driver/Tools.cpp +++ b/clang/lib/Driver/Tools.cpp @@ -44,6 +44,11 @@ using namespace clang::driver::tools; using namespace clang; using namespace llvm::opt; +static bool hasMipsABIArg(const ArgList &Args, const char *Value) { + Arg *A = Args.getLastArg(options::OPT_mabi_EQ); + return A && (A->getValue() == StringRef(Value)); +} + /// CheckPreprocessingOptions - Perform some validation of preprocessing /// arguments that is shared with gcc. static void CheckPreprocessingOptions(const Driver &D, const ArgList &Args) { @@ -475,7 +480,7 @@ static bool isSignedCharDefault(const llvm::Triple &Triple) { case llvm::Triple::arm: case llvm::Triple::ppc: case llvm::Triple::ppc64: - if (Triple.isOSDarwin()) + if (Triple.isOSBinFormatMachO()) return true; return false; @@ -746,7 +751,7 @@ void Clang::AddARMTargetArgs(const ArgList &Args, const char *ABIName = 0; if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) { ABIName = A->getValue(); - } else if (Triple.isOSDarwin()) { + } else if (Triple.isOSBinFormatMachO()) { // The backend is hardwired to assume AAPCS for M-class processors, ensure // the frontend matches that. if (Triple.getEnvironment() == llvm::Triple::EABI || @@ -1192,7 +1197,7 @@ static const char *getX86TargetCPU(const ArgList &Args, const llvm::Triple &Triple) { if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) { if (StringRef(A->getValue()) != "native") { - if (Triple.isOSDarwin() && Triple.getArchName() == "x86_64h") + if (Triple.isOSBinFormatMachO() && Triple.getArchName() == "x86_64h") return "core-avx2"; return A->getValue(); @@ -1217,7 +1222,7 @@ static const char *getX86TargetCPU(const ArgList &Args, bool Is64Bit = Triple.getArch() == llvm::Triple::x86_64; // FIXME: Need target hooks. - if (Triple.isOSDarwin()) { + if (Triple.isOSBinFormatMachO()) { if (Triple.getArchName() == "x86_64h") return "core-avx2"; return Is64Bit ? "core2" : "yonah"; @@ -2619,7 +2624,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // -gline-tables-only. CmdArgs.push_back("-gline-tables-only"); // Default is dwarf-2 for darwin. - if (getToolChain().getTriple().isOSDarwin()) + if (getToolChain().getTriple().isOSBinFormatMachO()) CmdArgs.push_back("-gdwarf-2"); } else if (A->getOption().matches(options::OPT_gdwarf_2)) CmdArgs.push_back("-gdwarf-2"); @@ -2630,7 +2635,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, else if (!A->getOption().matches(options::OPT_g0) && !A->getOption().matches(options::OPT_ggdb0)) { // Default is dwarf-2 for darwin. - if (getToolChain().getTriple().isOSDarwin()) + if (getToolChain().getTriple().isOSBinFormatMachO()) CmdArgs.push_back("-gdwarf-2"); else CmdArgs.push_back("-g"); @@ -3944,7 +3949,7 @@ ObjCRuntime Clang::AddObjCRuntimeArgs(const ArgList &args, // -fnext-runtime } else if (runtimeArg->getOption().matches(options::OPT_fnext_runtime)) { // On Darwin, make this use the default behavior for the toolchain. - if (getToolChain().getTriple().isOSDarwin()) { + if (getToolChain().getTriple().isOSBinFormatMachO()) { runtime = getToolChain().getDefaultObjCRuntime(isNonFragile); // Otherwise, build for a generic macosx port. @@ -4218,7 +4223,7 @@ void gcc::Common::ConstructJob(Compilation &C, const JobAction &JA, // If using a driver driver, force the arch. llvm::Triple::ArchType Arch = getToolChain().getArch(); - if (getToolChain().getTriple().isOSDarwin()) { + if (getToolChain().getTriple().isOSBinFormatMachO()) { CmdArgs.push_back("-arch"); // FIXME: Remove these special cases. @@ -4713,11 +4718,6 @@ const char *arm::getLLVMArchSuffixForARM(StringRef CPU) { .Default(""); } -bool mips::hasMipsAbiArg(const ArgList &Args, const char *Value) { - Arg *A = Args.getLastArg(options::OPT_mabi_EQ); - return A && (A->getValue() == StringRef(Value)); -} - llvm::Triple::ArchType darwin::getArchTypeForMachOArchName(StringRef Str) { // See arch(3) and llvm-gcc's driver-driver.c. We don't implement support for // archs which Darwin doesn't use. @@ -6192,13 +6192,13 @@ void netbsd::Link::ConstructJob(Compilation &C, const JobAction &JA, break; case llvm::Triple::mips64: case llvm::Triple::mips64el: - if (mips::hasMipsAbiArg(Args, "32")) { + if (hasMipsABIArg(Args, "32")) { CmdArgs.push_back("-m"); if (getToolChain().getArch() == llvm::Triple::mips64) CmdArgs.push_back("elf32btsmip"); else CmdArgs.push_back("elf32ltsmip"); - } else if (mips::hasMipsAbiArg(Args, "64")) { + } else if (hasMipsABIArg(Args, "64")) { CmdArgs.push_back("-m"); if (getToolChain().getArch() == llvm::Triple::mips64) CmdArgs.push_back("elf64btsmip"); @@ -6502,7 +6502,7 @@ static StringRef getLinuxDynamicLinker(const ArgList &Args, return "/lib/ld.so.1"; else if (ToolChain.getArch() == llvm::Triple::mips64 || ToolChain.getArch() == llvm::Triple::mips64el) { - if (mips::hasMipsAbiArg(Args, "n32")) + if (hasMipsABIArg(Args, "n32")) return "/lib32/ld.so.1"; else return "/lib64/ld.so.1"; @@ -6585,13 +6585,13 @@ void gnutools::Link::ConstructJob(Compilation &C, const JobAction &JA, else if (ToolChain.getArch() == llvm::Triple::mipsel) CmdArgs.push_back("elf32ltsmip"); else if (ToolChain.getArch() == llvm::Triple::mips64) { - if (mips::hasMipsAbiArg(Args, "n32")) + if (hasMipsABIArg(Args, "n32")) CmdArgs.push_back("elf32btsmipn32"); else CmdArgs.push_back("elf64btsmip"); } else if (ToolChain.getArch() == llvm::Triple::mips64el) { - if (mips::hasMipsAbiArg(Args, "n32")) + if (hasMipsABIArg(Args, "n32")) CmdArgs.push_back("elf32ltsmipn32"); else CmdArgs.push_back("elf64ltsmip"); diff --git a/clang/lib/Driver/Tools.h b/clang/lib/Driver/Tools.h index 4fe42b87cd2..873969b4d78 100644 --- a/clang/lib/Driver/Tools.h +++ b/clang/lib/Driver/Tools.h @@ -209,10 +209,6 @@ namespace arm { const char* getLLVMArchSuffixForARM(StringRef CPU); } -namespace mips { - bool hasMipsAbiArg(const llvm::opt::ArgList &Args, const char *Value); -} - namespace darwin { llvm::Triple::ArchType getArchTypeForMachOArchName(StringRef Str); void setTripleTypeForMachOArchName(llvm::Triple &T, StringRef Str); diff --git a/clang/unittests/CMakeLists.txt b/clang/unittests/CMakeLists.txt index f00008e0407..479b36f84c5 100644 --- a/clang/unittests/CMakeLists.txt +++ b/clang/unittests/CMakeLists.txt @@ -11,7 +11,6 @@ endfunction() add_subdirectory(Basic) add_subdirectory(Lex) -add_subdirectory(Driver) if(CLANG_ENABLE_STATIC_ANALYZER) add_subdirectory(Frontend) endif() diff --git a/clang/unittests/Driver/CMakeLists.txt b/clang/unittests/Driver/CMakeLists.txt deleted file mode 100644 index 154197a8566..00000000000 --- a/clang/unittests/Driver/CMakeLists.txt +++ /dev/null @@ -1,11 +0,0 @@ -set(LLVM_LINK_COMPONENTS - Support - ) - -add_clang_unittest(DriverTests - MultilibTest.cpp - ) - -target_link_libraries(DriverTests - clangDriver - ) diff --git a/clang/unittests/Driver/Makefile b/clang/unittests/Driver/Makefile deleted file mode 100644 index 21d19f34f63..00000000000 --- a/clang/unittests/Driver/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -##===- unittests/Driver/Makefile ---------------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -CLANG_LEVEL = ../.. -TESTNAME = Multilib -include $(CLANG_LEVEL)/../../Makefile.config -LINK_COMPONENTS := $(TARGETS_TO_BUILD) support option -USEDLIBS = clangDriver.a clangBasic.a - -include $(CLANG_LEVEL)/unittests/Makefile diff --git a/clang/unittests/Driver/MultilibTest.cpp b/clang/unittests/Driver/MultilibTest.cpp deleted file mode 100644 index c036290c028..00000000000 --- a/clang/unittests/Driver/MultilibTest.cpp +++ /dev/null @@ -1,356 +0,0 @@ -//===- unittests/Driver/MultilibTest.cpp --- Multilib tests ---------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Unit tests for Multilib and MultilibSet -// -//===----------------------------------------------------------------------===// - -#include "clang/Driver/Multilib.h" -#include "clang/Basic/LLVM.h" -#include "gtest/gtest.h" -#include "llvm/ADT/StringSwitch.h" -#include "llvm/ADT/StringRef.h" - -using namespace clang::driver; -using namespace clang; - -TEST(MultilibTest, MultilibValidity) { - - ASSERT_TRUE(Multilib().isValid()) << "Empty multilib is not valid"; - - ASSERT_TRUE(Multilib().flag("+foo").isValid()) - << "Single indicative flag is not valid"; - - ASSERT_TRUE(Multilib().flag("-foo").isValid()) - << "Single contraindicative flag is not valid"; - - ASSERT_FALSE(Multilib().flag("+foo").flag("-foo").isValid()) - << "Conflicting flags should invalidate the Multilib"; - - ASSERT_TRUE(Multilib().flag("+foo").flag("+foo").isValid()) - << "Multilib should be valid even if it has the same flag twice"; - - ASSERT_TRUE(Multilib().flag("+foo").flag("-foobar").isValid()) - << "Seemingly conflicting prefixes shouldn't actually conflict"; -} - -TEST(MultilibTest, OpEqReflexivity1) { - Multilib M; - ASSERT_TRUE(M == M) << "Multilib::operator==() is not reflexive"; -} - -TEST(MultilibTest, OpEqReflexivity2) { - ASSERT_TRUE(Multilib() == Multilib()) - << "Separately constructed default multilibs are not equal"; -} - -TEST(MultilibTest, OpEqReflexivity3) { - Multilib M1, M2; - M1.flag("+foo"); - M2.flag("+foo"); - ASSERT_TRUE(M1 == M2) << "Multilibs with the same flag should be the same"; -} - -TEST(MultilibTest, OpEqInequivalence1) { - Multilib M1, M2; - M1.flag("+foo"); - M2.flag("-foo"); - ASSERT_FALSE(M1 == M2) << "Multilibs with conflicting flags are not the same"; - ASSERT_FALSE(M2 == M1) - << "Multilibs with conflicting flags are not the same (commuted)"; -} - -TEST(MultilibTest, OpEqInequivalence2) { - Multilib M1, M2; - M2.flag("+foo"); - ASSERT_FALSE(M1 == M2) << "Flags make Multilibs different"; -} - -TEST(MultilibTest, OpEqEquivalence1) { - Multilib M1, M2; - M1.flag("+foo"); - M2.flag("+foo").flag("+foo"); - ASSERT_TRUE(M1 == M2) << "Flag duplication shouldn't affect equivalence"; - ASSERT_TRUE(M2 == M1) - << "Flag duplication shouldn't affect equivalence (commuted)"; -} - -TEST(MultilibTest, OpEqEquivalence2) { - Multilib M1("64"); - Multilib M2; - M2.gccSuffix("/64"); - ASSERT_TRUE(M1 == M2) - << "Constructor argument must match Multilib::gccSuffix()"; - ASSERT_TRUE(M2 == M1) - << "Constructor argument must match Multilib::gccSuffix() (commuted)"; -} - -TEST(MultilibTest, OpEqEquivalence3) { - Multilib M1("", "32"); - Multilib M2; - M2.osSuffix("/32"); - ASSERT_TRUE(M1 == M2) - << "Constructor argument must match Multilib::osSuffix()"; - ASSERT_TRUE(M2 == M1) - << "Constructor argument must match Multilib::osSuffix() (commuted)"; -} - -TEST(MultilibTest, OpEqEquivalence4) { - Multilib M1("", "", "16"); - Multilib M2; - M2.includeSuffix("/16"); - ASSERT_TRUE(M1 == M2) - << "Constructor argument must match Multilib::includeSuffix()"; - ASSERT_TRUE(M2 == M1) - << "Constructor argument must match Multilib::includeSuffix() (commuted)"; -} - -TEST(MultilibTest, OpEqInequivalence3) { - Multilib M1("foo"); - Multilib M2("bar"); - ASSERT_FALSE(M1 == M2) << "Differing gccSuffixes should be different"; - ASSERT_FALSE(M2 == M1) - << "Differing gccSuffixes should be different (commuted)"; -} - -TEST(MultilibTest, OpEqInequivalence4) { - Multilib M1("", "foo"); - Multilib M2("", "bar"); - ASSERT_FALSE(M1 == M2) << "Differing osSuffixes should be different"; - ASSERT_FALSE(M2 == M1) - << "Differing osSuffixes should be different (commuted)"; -} - -TEST(MultilibTest, OpEqInequivalence5) { - Multilib M1("", "", "foo"); - Multilib M2("", "", "bar"); - ASSERT_FALSE(M1 == M2) << "Differing includeSuffixes should be different"; - ASSERT_FALSE(M2 == M1) - << "Differing includeSuffixes should be different (commuted)"; -} - -TEST(MultilibTest, Construction1) { - Multilib M("gcc64", "os64", "inc64"); - ASSERT_TRUE(M.gccSuffix() == "/gcc64"); - ASSERT_TRUE(M.osSuffix() == "/os64"); - ASSERT_TRUE(M.includeSuffix() == "/inc64"); -} - -TEST(MultilibTest, Construction2) { - Multilib M1; - Multilib M2(""); - Multilib M3("", ""); - Multilib M4("", "", ""); - ASSERT_TRUE(M1 == M2) - << "Default arguments to Multilib constructor broken (first argument)"; - ASSERT_TRUE(M1 == M3) - << "Default arguments to Multilib constructor broken (second argument)"; - ASSERT_TRUE(M1 == M4) - << "Default arguments to Multilib constructor broken (third argument)"; -} - -TEST(MultilibTest, Construction3) { - Multilib M = Multilib().flag("+f1").flag("+f2").flag("-f3"); - for (Multilib::flags_list::const_iterator I = M.flags().begin(), - E = M.flags().end(); - I != E; ++I) { - ASSERT_TRUE(llvm::StringSwitch<bool>(*I) - .Cases("+f1", "+f2", "-f3", true) - .Default(false)); - } -} - -static bool hasFlag(const Multilib &M, StringRef Flag) { - for (Multilib::flags_list::const_iterator I = M.flags().begin(), - E = M.flags().end(); - I != E; ++I) { - if (*I == Flag) - return true; - else if (StringRef(*I).substr(1) == Flag.substr(1)) - return false; - } - return false; -} - -TEST(MultilibTest, SetConstruction1) { - // Single maybe - MultilibSet MS; - ASSERT_TRUE(MS.size() == 0); - MS.Maybe(Multilib("64").flag("+m64")); - ASSERT_TRUE(MS.size() == 2); - for (MultilibSet::const_iterator I = MS.begin(), E = MS.end(); I != E; ++I) { - if (I->gccSuffix() == "/64") - ASSERT_TRUE(I->flags()[0] == "+m64"); - else if (I->gccSuffix() == "") - ASSERT_TRUE(I->flags()[0] == "-m64"); - else - FAIL() << "Unrecognized gccSufix: " << I->gccSuffix(); - } -} - -TEST(MultilibTest, SetConstruction2) { - // Double maybe - MultilibSet MS; - MS.Maybe(Multilib("sof").flag("+sof")); - MS.Maybe(Multilib("el").flag("+EL")); - ASSERT_TRUE(MS.size() == 4); - for (MultilibSet::const_iterator I = MS.begin(), E = MS.end(); I != E; ++I) { - ASSERT_TRUE(I->isValid()) << "Multilb " << *I << " should be valid"; - ASSERT_TRUE(llvm::StringSwitch<bool>(I->gccSuffix()) - .Cases("", "/sof", "/el", "/sof/el", true) - .Default(false)) - << "Multilib " << *I << " wasn't expected"; - ASSERT_TRUE(llvm::StringSwitch<bool>(I->gccSuffix()) - .Case("", hasFlag(*I, "-sof")) - .Case("/sof", hasFlag(*I, "+sof")) - .Case("/el", hasFlag(*I, "-sof")) - .Case("/sof/el", hasFlag(*I, "+sof")) - .Default(false)) - << "Multilib " << *I << " didn't have the appropriate {+,-}sof flag"; - ASSERT_TRUE(llvm::StringSwitch<bool>(I->gccSuffix()) - .Case("", hasFlag(*I, "-EL")) - .Case("/sof", hasFlag(*I, "-EL")) - .Case("/el", hasFlag(*I, "+EL")) - .Case("/sof/el", hasFlag(*I, "+EL")) - .Default(false)) - << "Multilib " << *I << " didn't have the appropriate {+,-}EL flag"; - } -} - -TEST(MultilibTest, SetPushback) { - MultilibSet MS; - MS.push_back(Multilib("one")); - MS.push_back(Multilib("two")); - ASSERT_TRUE(MS.size() == 2); - for (MultilibSet::const_iterator I = MS.begin(), E = MS.end(); I != E; ++I) { - ASSERT_TRUE(llvm::StringSwitch<bool>(I->gccSuffix()) - .Cases("/one", "/two", true) - .Default(false)); - } - MS.clear(); - ASSERT_TRUE(MS.size() == 0); -} - -TEST(MultilibTest, SetRegexFilter) { - MultilibSet MS; - MS.Maybe(Multilib("one")); - MS.Maybe(Multilib("two")); - MS.Maybe(Multilib("three")); - ASSERT_EQ(MS.size(), (unsigned)2 * 2 * 2) - << "Size before filter was incorrect. Contents:\n" << MS; - MS.FilterOut("/one/two/three"); - ASSERT_EQ(MS.size(), (unsigned)2 * 2 * 2 - 1) - << "Size after filter was incorrect. Contents:\n" << MS; - for (MultilibSet::const_iterator I = MS.begin(), E = MS.end(); I != E; ++I) { - ASSERT_TRUE(I->gccSuffix() != "/one/two/three") - << "The filter should have removed " << *I; - } -} - -TEST(MultilibTest, SetFilterObject) { - // Filter object - struct StartsWithP : public MultilibSet::FilterCallback { - bool operator()(const Multilib &M) const LLVM_OVERRIDE { - return StringRef(M.gccSuffix()).startswith("/p"); - } - }; - MultilibSet MS; - MS.Maybe(Multilib("orange")); - MS.Maybe(Multilib("pear")); - MS.Maybe(Multilib("plum")); - ASSERT_EQ((int)MS.size(), 1 /* Default */ + - 1 /* pear */ + - 1 /* plum */ + - 1 /* pear/plum */ + - 1 /* orange */ + - 1 /* orange/pear */ + - 1 /* orange/plum */ + - 1 /* orange/pear/plum */ ) - << "Size before filter was incorrect. Contents:\n" << MS; - MS.FilterOut(StartsWithP()); - ASSERT_EQ((int)MS.size(), 1 /* Default */ + - 1 /* orange */ + - 1 /* orange/pear */ + - 1 /* orange/plum */ + - 1 /* orange/pear/plum */ ) - << "Size after filter was incorrect. Contents:\n" << MS; - for (MultilibSet::const_iterator I = MS.begin(), E = MS.end(); I != E; ++I) { - ASSERT_FALSE(StringRef(I->gccSuffix()).startswith("/p")) - << "The filter should have removed " << *I; - } -} - -TEST(MultilibTest, SetSelection1) { - MultilibSet MS1 = MultilibSet() - .Maybe(Multilib("64").flag("+m64")); - - Multilib::flags_list FlagM64; - FlagM64.push_back("+m64"); - Multilib SelectionM64; - ASSERT_TRUE(MS1.select(FlagM64, SelectionM64)) - << "Flag set was {\"+m64\"}, but selection not found"; - ASSERT_TRUE(SelectionM64.gccSuffix() == "/64") - << "Selection picked " << SelectionM64 << " which was not expected"; - - Multilib::flags_list FlagNoM64; - FlagNoM64.push_back("-m64"); - Multilib SelectionNoM64; - ASSERT_TRUE(MS1.select(FlagNoM64, SelectionNoM64)) - << "Flag set was {\"-m64\"}, but selection not found"; - ASSERT_TRUE(SelectionNoM64.gccSuffix() == "") - << "Selection picked " << SelectionNoM64 << " which was not expected"; -} - -TEST(MultilibTest, SetSelection2) { - MultilibSet MS2 = MultilibSet() - .Maybe(Multilib("el").flag("+EL")) - .Maybe(Multilib("sf").flag("+SF")); - - for (unsigned I = 0; I < 4; ++I) { - bool IsEL = I & 0x1; - bool IsSF = I & 0x2; - Multilib::flags_list Flags; - if (IsEL) - Flags.push_back("+EL"); - else - Flags.push_back("-EL"); - - if (IsSF) - Flags.push_back("+SF"); - else - Flags.push_back("-SF"); - - Multilib Selection; - ASSERT_TRUE(MS2.select(Flags, Selection)) << "Selection failed for " - << (IsEL ? "+EL" : "-EL") << " " - << (IsSF ? "+SF" : "-SF"); - - std::string Suffix; - if (IsEL) - Suffix += "/el"; - if (IsSF) - Suffix += "/sf"; - - ASSERT_EQ(Selection.gccSuffix(), Suffix) << "Selection picked " << Selection - << " which was not expected "; - } -} - -TEST(MultilibTest, SetCombineWith) { - MultilibSet Coffee; - Coffee.push_back(Multilib("coffee")); - MultilibSet Milk; - Milk.push_back(Multilib("milk")); - MultilibSet Latte; - ASSERT_EQ(Latte.size(), (unsigned)0); - Latte.combineWith(Coffee); - ASSERT_EQ(Latte.size(), (unsigned)1); - Latte.combineWith(Milk); - ASSERT_EQ(Latte.size(), (unsigned)2); -} diff --git a/clang/unittests/Makefile b/clang/unittests/Makefile index e4fbe584da1..d0dfe471d15 100644 --- a/clang/unittests/Makefile +++ b/clang/unittests/Makefile @@ -14,7 +14,7 @@ ifndef CLANG_LEVEL IS_UNITTEST_LEVEL := 1 CLANG_LEVEL := .. -PARALLEL_DIRS = Basic Lex Driver +PARALLEL_DIRS = Basic Lex include $(CLANG_LEVEL)/../..//Makefile.config |