Keep track of the original target the user specified before
normalization. This used to be captured in DefaultTargetTriple and is
used for the (optional) $triple-$tool lookup for cross-compilation.
Do this properly by making it an attribute of the toolchain and use it
in combination with the computed triple as index for the toolchain
lookup.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@149083 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/Driver/ToolChain.h b/include/clang/Driver/ToolChain.h
index 4f3a3be..7f03356 100644
--- a/include/clang/Driver/ToolChain.h
+++ b/include/clang/Driver/ToolChain.h
@@ -46,6 +46,9 @@
 private:
   const Driver &D;
   const llvm::Triple Triple;
+  /// The target triple originally requested by the user
+  /// before modifications due to -m32 and without normalization.
+  const std::string UserTriple;
 
   /// The list of toolchain specific path prefixes to search for
   /// files.
@@ -56,7 +59,7 @@
   path_list ProgramPaths;
 
 protected:
-  ToolChain(const Driver &D, const llvm::Triple &T);
+  ToolChain(const Driver &D, const llvm::Triple &T, const std::string &UT);
 
   /// \name Utilities for implementing subclasses.
   ///@{
@@ -87,6 +90,9 @@
   std::string getTripleString() const {
     return Triple.getTriple();
   }
+  const std::string &getUserTriple() const {
+    return UserTriple;
+  }
 
   path_list &getFilePaths() { return FilePaths; }
   const path_list &getFilePaths() const { return FilePaths; }
diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp
index 7c26a0e..10e2fd9 100644
--- a/lib/Driver/Driver.cpp
+++ b/lib/Driver/Driver.cpp
@@ -1507,7 +1507,7 @@
 
 std::string Driver::GetProgramPath(const char *Name, const ToolChain &TC,
                                    bool WantFile) const {
-  std::string TargetSpecificExecutable(DefaultTargetTriple + "-" + Name);
+  std::string TargetSpecificExecutable(TC.getUserTriple() + "-" + Name);
   // Respect a limited subset of the '-Bprefix' functionality in GCC by
   // attempting to use this prefix when lokup up program paths.
   for (Driver::prefix_list::const_iterator it = PrefixDirs.begin(),
@@ -1574,13 +1574,10 @@
 ///
 /// This routine provides the logic to compute a target triple from various
 /// args passed to the driver and the default triple string.
-static llvm::Triple computeTargetTriple(StringRef DefaultTargetTriple,
+static llvm::Triple computeTargetTriple(StringRef TargetTriple,
                                         const ArgList &Args,
                                         StringRef DarwinArchName) {
-  if (const Arg *A = Args.getLastArg(options::OPT_target))
-    DefaultTargetTriple = A->getValue(Args);
-
-  llvm::Triple Target(llvm::Triple::normalize(DefaultTargetTriple));
+  llvm::Triple Target(llvm::Triple::normalize(TargetTriple));
 
   // Handle Darwin-specific options available here.
   if (Target.isOSDarwin()) {
@@ -1627,14 +1624,19 @@
 
 const ToolChain &Driver::getToolChain(const ArgList &Args,
                                       StringRef DarwinArchName) const {
-  llvm::Triple Target = computeTargetTriple(DefaultTargetTriple, Args,
-                                            DarwinArchName);
+  std::string TargetTriple(DefaultTargetTriple);
+  if (const Arg *A = Args.getLastArg(options::OPT_target))
+    TargetTriple = A->getValue(Args);
 
-  ToolChain *&TC = ToolChains[Target.str()];
+  llvm::Triple Target = computeTargetTriple(TargetTriple, Args, DarwinArchName);
+
+  std::string TargetIndex = TargetTriple + "::" + Target.str();
+
+  ToolChain *&TC = ToolChains[TargetIndex];
   if (!TC) {
     switch (Target.getOS()) {
     case llvm::Triple::AuroraUX:
-      TC = new toolchains::AuroraUX(*this, Target);
+      TC = new toolchains::AuroraUX(*this, Target, TargetTriple);
       break;
     case llvm::Triple::Darwin:
     case llvm::Triple::MacOSX:
@@ -1643,44 +1645,44 @@
           Target.getArch() == llvm::Triple::x86_64 ||
           Target.getArch() == llvm::Triple::arm ||
           Target.getArch() == llvm::Triple::thumb)
-        TC = new toolchains::DarwinClang(*this, Target);
+        TC = new toolchains::DarwinClang(*this, Target, TargetTriple);
       else
-        TC = new toolchains::Darwin_Generic_GCC(*this, Target);
+        TC = new toolchains::Darwin_Generic_GCC(*this, Target, TargetTriple);
       break;
     case llvm::Triple::DragonFly:
-      TC = new toolchains::DragonFly(*this, Target);
+      TC = new toolchains::DragonFly(*this, Target, TargetTriple);
       break;
     case llvm::Triple::OpenBSD:
-      TC = new toolchains::OpenBSD(*this, Target);
+      TC = new toolchains::OpenBSD(*this, Target, TargetTriple);
       break;
     case llvm::Triple::NetBSD:
-      TC = new toolchains::NetBSD(*this, Target);
+      TC = new toolchains::NetBSD(*this, Target, TargetTriple);
       break;
     case llvm::Triple::FreeBSD:
-      TC = new toolchains::FreeBSD(*this, Target);
+      TC = new toolchains::FreeBSD(*this, Target, TargetTriple);
       break;
     case llvm::Triple::Minix:
-      TC = new toolchains::Minix(*this, Target);
+      TC = new toolchains::Minix(*this, Target, TargetTriple);
       break;
     case llvm::Triple::Linux:
       if (Target.getArch() == llvm::Triple::hexagon)
-        TC = new toolchains::Hexagon_TC(*this, Target);
+        TC = new toolchains::Hexagon_TC(*this, Target, TargetTriple);
       else
-        TC = new toolchains::Linux(*this, Target);
+        TC = new toolchains::Linux(*this, Target, TargetTriple);
       break;
     case llvm::Triple::Win32:
-      TC = new toolchains::Windows(*this, Target);
+      TC = new toolchains::Windows(*this, Target, TargetTriple);
       break;
     case llvm::Triple::MinGW32:
       // FIXME: We need a MinGW toolchain. Fallthrough for now.
     default:
       // TCE is an OSless target
       if (Target.getArchName() == "tce") {
-        TC = new toolchains::TCEToolChain(*this, Target);
+        TC = new toolchains::TCEToolChain(*this, Target, TargetTriple);
         break;
       }
 
-      TC = new toolchains::Generic_GCC(*this, Target);
+      TC = new toolchains::Generic_GCC(*this, Target, TargetTriple);
       break;
     }
   }
diff --git a/lib/Driver/ToolChain.cpp b/lib/Driver/ToolChain.cpp
index c0c9c50..52038d2 100644
--- a/lib/Driver/ToolChain.cpp
+++ b/lib/Driver/ToolChain.cpp
@@ -20,8 +20,9 @@
 using namespace clang::driver;
 using namespace clang;
 
-ToolChain::ToolChain(const Driver &D, const llvm::Triple &T)
-  : D(D), Triple(T) {
+ToolChain::ToolChain(const Driver &D, const llvm::Triple &T,
+                     const std::string &UserTriple)
+  : D(D), Triple(T), UserTriple(UserTriple) {
 }
 
 ToolChain::~ToolChain() {
diff --git a/lib/Driver/ToolChains.cpp b/lib/Driver/ToolChains.cpp
index ad1c362..4e34dc5 100644
--- a/lib/Driver/ToolChains.cpp
+++ b/lib/Driver/ToolChains.cpp
@@ -45,8 +45,9 @@
 
 /// Darwin - Darwin tool chain for i386 and x86_64.
 
-Darwin::Darwin(const Driver &D, const llvm::Triple& Triple)
-  : ToolChain(D, Triple), TargetInitialized(false),
+Darwin::Darwin(const Driver &D, const llvm::Triple& Triple,
+               const std::string &UserTriple)
+  : ToolChain(D, Triple, UserTriple), TargetInitialized(false),
     ARCRuntimeForSimulator(ARCSimulator_None),
     LibCXXForSimulator(LibCXXSimulator_None)
 {
@@ -250,8 +251,9 @@
 }
 
 
-DarwinClang::DarwinClang(const Driver &D, const llvm::Triple& Triple)
-  : Darwin(D, Triple)
+DarwinClang::DarwinClang(const Driver &D, const llvm::Triple& Triple,
+                         const std::string &UserTriple)
+  : Darwin(D, Triple, UserTriple)
 {
   getProgramPaths().push_back(getDriver().getInstalledDir());
   if (getDriver().getInstalledDir() != getDriver().Dir)
@@ -1387,8 +1389,9 @@
   }
 }
 
-Generic_GCC::Generic_GCC(const Driver &D, const llvm::Triple& Triple)
-  : ToolChain(D, Triple), GCCInstallation(getDriver(), Triple) {
+Generic_GCC::Generic_GCC(const Driver &D, const llvm::Triple& Triple,
+                         const std::string &UserTriple)
+  : ToolChain(D, Triple, UserTriple), GCCInstallation(getDriver(), Triple) {
   getProgramPaths().push_back(getDriver().getInstalledDir());
   if (getDriver().getInstalledDir() != getDriver().Dir)
     getProgramPaths().push_back(getDriver().Dir);
@@ -1458,8 +1461,9 @@
 }
 /// Hexagon Toolchain
 
-Hexagon_TC::Hexagon_TC(const Driver &D, const llvm::Triple& Triple)
-  : ToolChain(D, Triple) {
+Hexagon_TC::Hexagon_TC(const Driver &D, const llvm::Triple& Triple,
+                       const std::string &UserTriple)
+  : ToolChain(D, Triple, UserTriple) {
   getProgramPaths().push_back(getDriver().getInstalledDir());
   if (getDriver().getInstalledDir() != getDriver().Dir.c_str())
     getProgramPaths().push_back(getDriver().Dir);
@@ -1528,8 +1532,9 @@
 /// all subcommands. See http://tce.cs.tut.fi for our peculiar target.
 /// Currently does not support anything else but compilation.
 
-TCEToolChain::TCEToolChain(const Driver &D, const llvm::Triple& Triple)
-  : ToolChain(D, Triple) {
+TCEToolChain::TCEToolChain(const Driver &D, const llvm::Triple& Triple,
+                          const std::string &UserTriple)
+  : ToolChain(D, Triple, UserTriple) {
   // Path mangling to find libexec
   std::string Path(getDriver().Dir);
 
@@ -1581,8 +1586,9 @@
 
 /// OpenBSD - OpenBSD tool chain which can call as(1) and ld(1) directly.
 
-OpenBSD::OpenBSD(const Driver &D, const llvm::Triple& Triple)
-  : Generic_ELF(D, Triple) {
+OpenBSD::OpenBSD(const Driver &D, const llvm::Triple& Triple,
+                 const std::string &UserTriple)
+  : Generic_ELF(D, Triple, UserTriple) {
   getFilePaths().push_back(getDriver().Dir + "/../lib");
   getFilePaths().push_back("/usr/lib");
 }
@@ -1621,8 +1627,9 @@
 
 /// FreeBSD - FreeBSD tool chain which can call as(1) and ld(1) directly.
 
-FreeBSD::FreeBSD(const Driver &D, const llvm::Triple& Triple)
-  : Generic_ELF(D, Triple) {
+FreeBSD::FreeBSD(const Driver &D, const llvm::Triple& Triple,
+                 const std::string &UserTriple)
+  : Generic_ELF(D, Triple, UserTriple) {
 
   // When targeting 32-bit platforms, look for '/usr/lib32/crt1.o' and fall
   // back to '/usr/lib' if it doesn't exist.
@@ -1667,8 +1674,9 @@
 
 /// NetBSD - NetBSD tool chain which can call as(1) and ld(1) directly.
 
-NetBSD::NetBSD(const Driver &D, const llvm::Triple& Triple)
-  : Generic_ELF(D, Triple) {
+NetBSD::NetBSD(const Driver &D, const llvm::Triple& Triple,
+               const std::string &UserTriple)
+  : Generic_ELF(D, Triple, UserTriple) {
 
   if (getDriver().UseStdLib) {
     // When targeting a 32-bit platform, try the special directory used on
@@ -1718,8 +1726,9 @@
 
 /// Minix - Minix tool chain which can call as(1) and ld(1) directly.
 
-Minix::Minix(const Driver &D, const llvm::Triple& Triple)
-  : Generic_ELF(D, Triple) {
+Minix::Minix(const Driver &D, const llvm::Triple& Triple,
+             const std::string &UserTriple)
+  : Generic_ELF(D, Triple, UserTriple) {
   getFilePaths().push_back(getDriver().Dir + "/../lib");
   getFilePaths().push_back("/usr/lib");
 }
@@ -1749,8 +1758,9 @@
 
 /// AuroraUX - AuroraUX tool chain which can call as(1) and ld(1) directly.
 
-AuroraUX::AuroraUX(const Driver &D, const llvm::Triple& Triple)
-  : Generic_GCC(D, Triple) {
+AuroraUX::AuroraUX(const Driver &D, const llvm::Triple& Triple,
+                   const std::string &UserTriple)
+  : Generic_GCC(D, Triple, UserTriple) {
 
   getProgramPaths().push_back(getDriver().getInstalledDir());
   if (getDriver().getInstalledDir() != getDriver().Dir)
@@ -1965,8 +1975,9 @@
   if (llvm::sys::fs::exists(Path)) Paths.push_back(Path.str());
 }
 
-Linux::Linux(const Driver &D, const llvm::Triple &Triple)
-  : Generic_ELF(D, Triple) {
+Linux::Linux(const Driver &D, const llvm::Triple &Triple,
+             const std::string &UserTriple)
+  : Generic_ELF(D, Triple, UserTriple) {
   llvm::Triple::ArchType Arch = Triple.getArch();
   const std::string &SysRoot = getDriver().SysRoot;
 
@@ -2274,8 +2285,9 @@
 
 /// DragonFly - DragonFly tool chain which can call as(1) and ld(1) directly.
 
-DragonFly::DragonFly(const Driver &D, const llvm::Triple& Triple)
-  : Generic_ELF(D, Triple) {
+DragonFly::DragonFly(const Driver &D, const llvm::Triple& Triple,
+                     const std::string &UserTriple)
+  : Generic_ELF(D, Triple, UserTriple) {
 
   // Path mangling to find libexec
   getProgramPaths().push_back(getDriver().getInstalledDir());
diff --git a/lib/Driver/ToolChains.h b/lib/Driver/ToolChains.h
index 071a367..7a39f9a 100644
--- a/lib/Driver/ToolChains.h
+++ b/lib/Driver/ToolChains.h
@@ -119,7 +119,8 @@
   mutable llvm::DenseMap<unsigned, Tool*> Tools;
 
 public:
-  Generic_GCC(const Driver &D, const llvm::Triple& Triple);
+  Generic_GCC(const Driver &D, const llvm::Triple& Triple,
+              const std::string &UserTriple);
   ~Generic_GCC();
 
   virtual Tool &SelectTool(const Compilation &C, const JobAction &JA,
@@ -150,7 +151,8 @@
   mutable llvm::DenseMap<unsigned, Tool*> Tools;
 
 public:
-  Hexagon_TC(const Driver &D, const llvm::Triple& Triple);
+  Hexagon_TC(const Driver &D, const llvm::Triple& Triple,
+             const std::string &UserTriple);
   ~Hexagon_TC();
 
   virtual Tool &SelectTool(const Compilation &C, const JobAction &JA,
@@ -212,7 +214,8 @@
   void AddDeploymentTarget(DerivedArgList &Args) const;
 
 public:
-  Darwin(const Driver &D, const llvm::Triple& Triple);
+  Darwin(const Driver &D, const llvm::Triple& Triple,
+         const std::string &UserTriple);
   ~Darwin();
 
   std::string ComputeEffectiveClangTriple(const ArgList &Args,
@@ -395,7 +398,8 @@
   void AddGCCLibexecPath(unsigned darwinVersion);
 
 public:
-  DarwinClang(const Driver &D, const llvm::Triple& Triple);
+  DarwinClang(const Driver &D, const llvm::Triple& Triple,
+              const std::string &UserTriple);
 
   /// @name Darwin ToolChain Implementation
   /// {
@@ -422,8 +426,9 @@
 /// Darwin_Generic_GCC - Generic Darwin tool chain using gcc.
 class LLVM_LIBRARY_VISIBILITY Darwin_Generic_GCC : public Generic_GCC {
 public:
-  Darwin_Generic_GCC(const Driver &D, const llvm::Triple& Triple)
-    : Generic_GCC(D, Triple) {}
+  Darwin_Generic_GCC(const Driver &D, const llvm::Triple& Triple,
+                     const std::string &UserTriple)
+    : Generic_GCC(D, Triple, UserTriple) {}
 
   std::string ComputeEffectiveClangTriple(const ArgList &Args,
                                           types::ID InputType) const;
@@ -434,8 +439,9 @@
 class LLVM_LIBRARY_VISIBILITY Generic_ELF : public Generic_GCC {
   virtual void anchor();
 public:
-  Generic_ELF(const Driver &D, const llvm::Triple& Triple)
-    : Generic_GCC(D, Triple) {}
+  Generic_ELF(const Driver &D, const llvm::Triple& Triple,
+              const std::string &UserTriple)
+    : Generic_GCC(D, Triple, UserTriple) {}
 
   virtual bool IsIntegratedAssemblerDefault() const {
     // Default integrated assembler to on for x86.
@@ -446,7 +452,8 @@
 
 class LLVM_LIBRARY_VISIBILITY AuroraUX : public Generic_GCC {
 public:
-  AuroraUX(const Driver &D, const llvm::Triple& Triple);
+  AuroraUX(const Driver &D, const llvm::Triple& Triple,
+           const std::string &UserTriple);
 
   virtual Tool &SelectTool(const Compilation &C, const JobAction &JA,
                            const ActionList &Inputs) const;
@@ -454,7 +461,8 @@
 
 class LLVM_LIBRARY_VISIBILITY OpenBSD : public Generic_ELF {
 public:
-  OpenBSD(const Driver &D, const llvm::Triple& Triple);
+  OpenBSD(const Driver &D, const llvm::Triple& Triple,
+          const std::string &UserTriple);
 
   virtual Tool &SelectTool(const Compilation &C, const JobAction &JA,
                            const ActionList &Inputs) const;
@@ -462,7 +470,8 @@
 
 class LLVM_LIBRARY_VISIBILITY FreeBSD : public Generic_ELF {
 public:
-  FreeBSD(const Driver &D, const llvm::Triple& Triple);
+  FreeBSD(const Driver &D, const llvm::Triple& Triple,
+          const std::string &UserTriple);
 
   virtual Tool &SelectTool(const Compilation &C, const JobAction &JA,
                            const ActionList &Inputs) const;
@@ -470,7 +479,8 @@
 
 class LLVM_LIBRARY_VISIBILITY NetBSD : public Generic_ELF {
 public:
-  NetBSD(const Driver &D, const llvm::Triple& Triple);
+  NetBSD(const Driver &D, const llvm::Triple& Triple,
+         const std::string &UserTriple);
 
   virtual Tool &SelectTool(const Compilation &C, const JobAction &JA,
                            const ActionList &Inputs) const;
@@ -478,7 +488,8 @@
 
 class LLVM_LIBRARY_VISIBILITY Minix : public Generic_ELF {
 public:
-  Minix(const Driver &D, const llvm::Triple& Triple);
+  Minix(const Driver &D, const llvm::Triple& Triple,
+        const std::string &UserTriple);
 
   virtual Tool &SelectTool(const Compilation &C, const JobAction &JA,
                            const ActionList &Inputs) const;
@@ -486,7 +497,8 @@
 
 class LLVM_LIBRARY_VISIBILITY DragonFly : public Generic_ELF {
 public:
-  DragonFly(const Driver &D, const llvm::Triple& Triple);
+  DragonFly(const Driver &D, const llvm::Triple& Triple,
+            const std::string &UserTriple);
 
   virtual Tool &SelectTool(const Compilation &C, const JobAction &JA,
                            const ActionList &Inputs) const;
@@ -494,7 +506,8 @@
 
 class LLVM_LIBRARY_VISIBILITY Linux : public Generic_ELF {
 public:
-  Linux(const Driver &D, const llvm::Triple& Triple);
+  Linux(const Driver &D, const llvm::Triple& Triple,
+        const std::string &UserTriple);
 
   virtual bool HasNativeLLVMSupport() const;
 
@@ -520,7 +533,8 @@
 /// all subcommands. See http://tce.cs.tut.fi for our peculiar target.
 class LLVM_LIBRARY_VISIBILITY TCEToolChain : public ToolChain {
 public:
-  TCEToolChain(const Driver &D, const llvm::Triple& Triple);
+  TCEToolChain(const Driver &D, const llvm::Triple& Triple,
+               const std::string &UserTriple);
   ~TCEToolChain();
 
   virtual Tool &SelectTool(const Compilation &C, const JobAction &JA,
@@ -539,7 +553,8 @@
   mutable llvm::DenseMap<unsigned, Tool*> Tools;
 
 public:
-  Windows(const Driver &D, const llvm::Triple& Triple);
+  Windows(const Driver &D, const llvm::Triple& Triple,
+          const std::string &UserTriple);
 
   virtual Tool &SelectTool(const Compilation &C, const JobAction &JA,
                            const ActionList &Inputs) const;
diff --git a/lib/Driver/WindowsToolChain.cpp b/lib/Driver/WindowsToolChain.cpp
index b951581..076dff9 100644
--- a/lib/Driver/WindowsToolChain.cpp
+++ b/lib/Driver/WindowsToolChain.cpp
@@ -35,8 +35,9 @@
 using namespace clang::driver::toolchains;
 using namespace clang;
 
-Windows::Windows(const Driver &D, const llvm::Triple& Triple)
-  : ToolChain(D, Triple) {
+Windows::Windows(const Driver &D, const llvm::Triple& Triple,
+                 const std::string &UserTriple)
+  : ToolChain(D, Triple, UserTriple) {
 }
 
 Tool &Windows::SelectTool(const Compilation &C, const JobAction &JA,
diff --git a/test/Driver/prefixed-tools.c b/test/Driver/prefixed-tools.c
new file mode 100644
index 0000000..1fc3d8f
--- /dev/null
+++ b/test/Driver/prefixed-tools.c
@@ -0,0 +1,14 @@
+// RUN: env PATH=%s-helper %clang -no-integrated-as -target x86_64--linux %s -o - > %t.log
+// RUN: env PATH=%s-helper %clang -no-integrated-as -m32 -target x86_64--linux %s -o - >> %t.log
+// RUN: FileCheck -input-file %t.log %s
+
+// CHECK: x86_64--linux-as called
+// CHECK: x86_64--linux-ld called
+// CHECK: x86_64--linux-as called
+// CHECK: x86_64--linux-ld called
+
+int
+main(void)
+{
+  return 0;
+}
\ No newline at end of file
diff --git a/test/Driver/prefixed-tools.c-helper/x86_64--linux-as b/test/Driver/prefixed-tools.c-helper/x86_64--linux-as
new file mode 100755
index 0000000..141e1fa
--- /dev/null
+++ b/test/Driver/prefixed-tools.c-helper/x86_64--linux-as
@@ -0,0 +1,2 @@
+#!/bin/sh
+echo "x86_64--linux-as called"
diff --git a/test/Driver/prefixed-tools.c-helper/x86_64--linux-ld b/test/Driver/prefixed-tools.c-helper/x86_64--linux-ld
new file mode 100755
index 0000000..129ba0a
--- /dev/null
+++ b/test/Driver/prefixed-tools.c-helper/x86_64--linux-ld
@@ -0,0 +1,2 @@
+#!/bin/sh
+echo "x86_64--linux-ld called"