Driver: support exherbo's multiarch support

Exherbo has an alternative file system layout to accommodate multiarch.  The
loader is located at /usr/${triple}/lib/${loader}.  Adjust the Linux toolchain
to support that on exherbo.

llvm-svn: 270392
diff --git a/clang/lib/Driver/ToolChains.cpp b/clang/lib/Driver/ToolChains.cpp
index 7929021..2f1420e 100644
--- a/clang/lib/Driver/ToolChains.cpp
+++ b/clang/lib/Driver/ToolChains.cpp
@@ -4037,69 +4037,102 @@
   const llvm::Triple::ArchType Arch = getArch();
   const llvm::Triple &Triple = getTriple();
 
+  const enum Distro Distro = DetectDistro(getDriver(), Arch);
+
   if (Triple.isAndroid())
     return Triple.isArch64Bit() ? "/system/bin/linker64" : "/system/bin/linker";
 
+  std::string LibDir;
+  std::string Loader;
+
   switch (Arch) {
-  default: llvm_unreachable("unsupported architecture");
+  default:
+    llvm_unreachable("unsupported architecture");
 
   case llvm::Triple::aarch64:
-    return "/lib/ld-linux-aarch64.so.1";
+    LibDir = "lib";
+    Loader = "ld-linux-aarch64.so.1";
+    break;
   case llvm::Triple::aarch64_be:
-    return "/lib/ld-linux-aarch64_be.so.1";
+    LibDir = "lib";
+    Loader = "ld-linux-aarch64_be.so.1";
+    break;
   case llvm::Triple::arm:
   case llvm::Triple::thumb:
   case llvm::Triple::armeb:
   case llvm::Triple::thumbeb: {
-    const bool IsHardFloat =
+    const bool HF =
         Triple.getEnvironment() == llvm::Triple::GNUEABIHF ||
         tools::arm::getARMFloatABI(*this, Args) == tools::arm::FloatABI::Hard;
 
-    return IsHardFloat ? "/lib/ld-linux-armhf.so.3" : "/lib/ld-linux.so.3";
+    LibDir = "lib";
+    Loader = HF ? "ld-linux-armhf.so.3" : "ld-linux.so.3";
+    break;
   }
   case llvm::Triple::mips:
   case llvm::Triple::mipsel:
   case llvm::Triple::mips64:
   case llvm::Triple::mips64el: {
-    bool IsNaN2008 = tools::mips::isNaN2008(Args, Triple);
     bool LE = (Triple.getArch() == llvm::Triple::mipsel) ||
               (Triple.getArch() == llvm::Triple::mips64el);
+    bool IsNaN2008 = tools::mips::isNaN2008(Args, Triple);
 
-    std::string LibDir =
-        "/lib" + tools::mips::getMipsABILibSuffix(Args, Triple);
-    StringRef LibName;
+    LibDir = "lib" + tools::mips::getMipsABILibSuffix(Args, Triple);
+
     if (tools::mips::isUCLibc(Args))
-      LibName = IsNaN2008 ? "ld-uClibc-mipsn8.so.0" : "ld-uClibc.so.0";
+      Loader = IsNaN2008 ? "ld-uClibc-mipsn8.so.0" : "ld-uClibc.so.0";
     else if (!Triple.hasEnvironment() &&
              Triple.getVendor() == llvm::Triple::VendorType::MipsTechnologies)
-      LibName = LE ? "ld-musl-mipsel.so.1" : "ld-musl-mips.so.1";
+      Loader = LE ? "ld-musl-mipsel.so.1" : "ld-musl-mips.so.1";
     else
-      LibName = IsNaN2008 ? "ld-linux-mipsn8.so.1" : "ld.so.1";
+      Loader = IsNaN2008 ? "ld-linux-mipsn8.so.1" : "ld.so.1";
 
-    return (LibDir + "/" + LibName).str();
+    break;
   }
   case llvm::Triple::ppc:
-    return "/lib/ld.so.1";
+    LibDir = "lib";
+    Loader = "ld.so.1";
+    break;
   case llvm::Triple::ppc64:
-    return (tools::ppc::hasPPCAbiArg(Args, "elfv2")) ? "/lib64/ld64.so.2"
-                                                     : "/lib64/ld64.so.1";
+    LibDir = "lib64";
+    Loader =
+        (tools::ppc::hasPPCAbiArg(Args, "elfv2")) ? "ld64.so.2" : "ld64.so.1";
+    break;
   case llvm::Triple::ppc64le:
-    return (tools::ppc::hasPPCAbiArg(Args, "elfv1")) ? "/lib64/ld64.so.1"
-                                                     : "/lib64/ld64.so.2";
+    LibDir = "lib64";
+    Loader =
+        (tools::ppc::hasPPCAbiArg(Args, "elfv1")) ? "ld64.so.1" : "ld64.so.2";
+    break;
   case llvm::Triple::sparc:
   case llvm::Triple::sparcel:
-    return "/lib/ld-linux.so.2";
+    LibDir = "lib";
+    Loader = "ld-linux.so.2";
+    break;
   case llvm::Triple::sparcv9:
-    return "/lib64/ld-linux.so.2";
+    LibDir = "lib64";
+    Loader = "ld-linux.so.2";
+    break;
   case llvm::Triple::systemz:
-    return "/lib/ld64.so.1";
+    LibDir = "lib";
+    Loader = "ld64.so.1";
+    break;
   case llvm::Triple::x86:
-    return "/lib/ld-linux.so.2";
-  case llvm::Triple::x86_64:
-    return (Triple.getEnvironment() == llvm::Triple::GNUX32)
-               ? "/libx32/ld-linux-x32.so.2"
-               : "/lib64/ld-linux-x86-64.so.2";
+    LibDir = "lib";
+    Loader = "ld-linux.so.2";
+    break;
+  case llvm::Triple::x86_64: {
+    bool X32 = Triple.getEnvironment() == llvm::Triple::GNUX32;
+
+    LibDir = X32 ? "libx32" : "lib64";
+    Loader = X32 ? "ld-linux-x32.so.2" : "ld-linux-x86-64.so.2";
+    break;
   }
+  }
+
+  if (Distro == Exherbo && (Triple.getVendor() == llvm::Triple::UnknownVendor ||
+                            Triple.getVendor() == llvm::Triple::PC))
+    return "/usr/" + Triple.str() + "/lib/" + Loader;
+  return "/" + LibDir + "/" + Loader;
 }
 
 void Linux::AddClangSystemIncludeArgs(const ArgList &DriverArgs,