[Driver] Do not lose already detected set of toolchain's multilibs while

iterating over different library path suffixes and different library versions.

To find the most appropriate library for the given command line flags we
iterate over a set of disk paths. Before probe each path the already
detected set of multilibs are cleared. If the set of paths contains
existing paths which do not satisfy command line flags or do not contain
necessary libraries and object files at all we might lose found multilibs.

The patch updates variables which hold detected multilibs if we really find
a new multilib matches command line flags.

The patch reviewed by Jon Roelofs.

llvm-svn: 208523
This commit is contained in:
Simon Atanasyan 2014-05-12 07:37:51 +00:00
parent 8e8fde8e93
commit 60280b4e65
9 changed files with 55 additions and 33 deletions

View File

@ -1646,9 +1646,21 @@ static bool isMipsNan2008(const ArgList &Args) {
return A && A->getValue() == StringRef("2008");
}
bool Generic_GCC::GCCInstallationDetector::findMIPSMultilibs(
const llvm::Triple &TargetTriple, StringRef Path,
const llvm::opt::ArgList &Args) {
struct DetectedMultilibs {
/// The set of multilibs that the detected installation supports.
MultilibSet Multilibs;
/// 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;
};
static bool findMIPSMultilibs(const llvm::Triple &TargetTriple, StringRef Path,
const llvm::opt::ArgList &Args,
DetectedMultilibs &Result) {
// Some MIPS toolchains put libraries and object files compiled
// using different options in to the sub-directoris which names
// reflects the flags used for compilation. For example sysroot
@ -1877,9 +1889,11 @@ bool Generic_GCC::GCCInstallationDetector::findMIPSMultilibs(
if (TargetTriple.getEnvironment() == llvm::Triple::Android) {
// Select Android toolchain. It's the only choice in that case.
Multilibs.clear();
Multilibs.combineWith(AndroidMipsMultilibs);
return Multilibs.select(Flags, SelectedMultilib);
if (AndroidMipsMultilibs.select(Flags, Result.SelectedMultilib)) {
Result.Multilibs = AndroidMipsMultilibs;
return true;
}
return false;
}
// Sort candidates. Toolchain that best meets the directories goes first.
@ -1890,11 +1904,10 @@ bool Generic_GCC::GCCInstallationDetector::findMIPSMultilibs(
std::begin(candidates), std::end(candidates),
[](MultilibSet *a, MultilibSet *b) { return a->size() > b->size(); });
for (const auto &candidate : candidates) {
Multilibs.clear();
Multilibs.combineWith(*candidate);
if (Multilibs.select(Flags, SelectedMultilib)) {
if (candidate->select(Flags, Result.SelectedMultilib)) {
if (candidate == &DebianMipsMultilibs)
BiarchSibling = Multilib();
Result.BiarchSibling = Multilib();
Result.Multilibs = *candidate;
return true;
}
}
@ -1902,9 +1915,10 @@ bool Generic_GCC::GCCInstallationDetector::findMIPSMultilibs(
return false;
}
bool Generic_GCC::GCCInstallationDetector::findBiarchMultilibs(
const llvm::Triple &TargetTriple, StringRef Path, const ArgList &Args,
bool NeedsBiarchSuffix) {
static bool findBiarchMultilibs(const llvm::Triple &TargetTriple,
StringRef Path, const ArgList &Args,
bool NeedsBiarchSuffix,
DetectedMultilibs &Result) {
// Some versions of SUSE and Fedora on ppc64 put 32-bit libs
// in what would normally be GCCInstallPath and put the 64-bit
@ -1944,22 +1958,21 @@ bool Generic_GCC::GCCInstallationDetector::findBiarchMultilibs(
else
Default.flag("-m32").flag("+m64");
Multilibs.push_back(Default);
Multilibs.push_back(Alt64);
Multilibs.push_back(Alt32);
Result.Multilibs.push_back(Default);
Result.Multilibs.push_back(Alt64);
Result.Multilibs.push_back(Alt32);
Multilibs.FilterOut(NonExistent);
Result.Multilibs.FilterOut(NonExistent);
Multilib::flags_list Flags;
addMultilibFlag(TargetTriple.isArch64Bit(), "m64", Flags);
addMultilibFlag(TargetTriple.isArch32Bit(), "m32", Flags);
if (!Multilibs.select(Flags, SelectedMultilib))
if (!Result.Multilibs.select(Flags, Result.SelectedMultilib))
return false;
if (SelectedMultilib == Alt64 || SelectedMultilib == Alt32) {
BiarchSibling = Default;
}
if (Result.SelectedMultilib == Alt64 || Result.SelectedMultilib == Alt32)
Result.BiarchSibling = Default;
return true;
}
@ -2013,19 +2026,21 @@ void Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple(
if (CandidateVersion <= Version)
continue;
Multilibs.clear();
SelectedMultilib = Multilib();
BiarchSibling.reset();
DetectedMultilibs Detected;
// 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))
if (!findMIPSMultilibs(TargetTriple, LI->path(), Args, Detected))
continue;
} else if (!findBiarchMultilibs(TargetTriple, LI->path(), Args,
NeedsBiarchSuffix))
NeedsBiarchSuffix, Detected)) {
continue;
}
Multilibs = Detected.Multilibs;
SelectedMultilib = Detected.SelectedMultilib;
BiarchSibling = Detected.BiarchSibling;
Version = CandidateVersion;
GCCTriple.setTriple(CandidateTriple);
// FIXME: We hack together the directory name here instead of

View File

@ -145,13 +145,6 @@ protected:
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);
};
GCCInstallationDetector GCCInstallation;

View File

@ -81,6 +81,20 @@
// CHECK-UBUNTU-13-04-M32: "-internal-isystem" "[[SYSROOT]]/usr/lib/gcc/x86_64-linux-gnu/4.7/../../../../include/c++/4.7/backward"
// CHECK-UBUNTU-13-04-M32: "-internal-isystem" "[[SYSROOT]]/usr/lib/gcc/x86_64-linux-gnu/4.7/../../../../include/x86_64-linux-gnu/c++/4.7/32"
//
// Test Ubuntu/Debian's Ubuntu 14.04 config variant, with -m32
// and an empty 4.9 directory.
// RUN: %clang -no-canonical-prefixes %s -### -fsyntax-only 2>&1 \
// RUN: -target x86_64-unknown-linux-gnu -m32 \
// RUN: --sysroot=%S/Inputs/ubuntu_14.04_multiarch_tree \
// RUN: | FileCheck --check-prefix=CHECK-UBUNTU-14-04-M32 %s
// CHECK-UBUNTU-14-04-M32: "{{[^"]*}}clang{{[^"]*}}" "-cc1"
// CHECK-UBUNTU-14-04-M32: "-triple" "i386-unknown-linux-gnu"
// CHECK-UBUNTU-14-04-M32: "-isysroot" "[[SYSROOT:[^"]+]]"
// CHECK-UBUNTU-14-04-M32: "-internal-isystem" "[[SYSROOT]]/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8"
// CHECK-UBUNTU-14-04-M32: "-internal-isystem" "[[SYSROOT]]/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/x86_64-linux-gnu/32"
// CHECK-UBUNTU-14-04-M32: "-internal-isystem" "[[SYSROOT]]/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/backward"
// CHECK-UBUNTU-14-04-M32: "-internal-isystem" "[[SYSROOT]]/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../include/x86_64-linux-gnu/c++/4.8/32"
//
// Thoroughly exercise the Debian multiarch environment.
// RUN: %clang -no-canonical-prefixes %s -### -fsyntax-only 2>&1 \
// RUN: -target i686-linux-gnu \