gollvm: support --gcc-toolchain flag

For explicitly specify GCC toolchain directory, similar to what
clang does.

Change-Id: I5afa14caff8768205040a001cd2cc2761d5453ce
Reviewed-on: https://go-review.googlesource.com/116219
Reviewed-by: Than McIntosh <thanm@google.com>
diff --git a/driver/Driver.cpp b/driver/Driver.cpp
index 39e3683..cc1be39 100644
--- a/driver/Driver.cpp
+++ b/driver/Driver.cpp
@@ -35,6 +35,8 @@
 {
   if (const opt::Arg *arg = args.getLastArg(gollvm::options::OPT_sysroot_EQ))
     sysroot_ = arg->getValue();
+  if (const opt::Arg *arg = args.getLastArg(gollvm::options::OPT_gcc_toolchain_EQ))
+    gccToolchainDir_ = arg->getValue();
 
   // Establish executable path and installation dir.
   executablePath_ = argv0;
diff --git a/driver/Driver.h b/driver/Driver.h
index 748b43c..e6185ca 100644
--- a/driver/Driver.h
+++ b/driver/Driver.h
@@ -88,6 +88,9 @@
   // Sysroot (or empty string if not present)
   std::string sysRoot() { return sysroot_; }
 
+  // gccToolchainDir (or empty string if not present)
+  std::string gccToolchainDir() { return gccToolchainDir_; }
+
   // Install directory of compiler binary.
   std::string installDir() { return installDir_; }
 
@@ -115,6 +118,7 @@
   llvm::opt::OptTable *opts_;
   const char *progname_;
   std::string sysroot_;
+  std::string gccToolchainDir_;
   std::string installDir_;
   std::string executablePath_;
   // maps target to toolchain for that target
diff --git a/driver/GccUtils.cpp b/driver/GccUtils.cpp
index 28077b7..858731f 100644
--- a/driver/GccUtils.cpp
+++ b/driver/GccUtils.cpp
@@ -124,9 +124,11 @@
 
 GCCInstallationDetector::
 GCCInstallationDetector(const llvm::Triple &targetTriple,
+                        const std::string &gccToolchainDir,
                         const std::string &sysroot,
                         InspectFS &inspector)
     : triple_(targetTriple),
+      gccToolchainDir_(gccToolchainDir),
       sysroot_(sysroot),
       inspector_(inspector),
       version_(new GCCVersion())
@@ -245,8 +247,11 @@
   if (!selectLibDirs(s))
     return;
 
-  // If sysroot is non-empty, then perform a search there first.
-  if (!sysroot_.empty()) {
+  if (!gccToolchainDir_.empty())
+    scanPrefix(s, gccToolchainDir_);
+
+  if (!s.version.valid() && !sysroot_.empty()) {
+    // If sysroot is non-empty, then perform a search there first.
     std::string srp(sysroot_);
     srp += "/usr";
     scanPrefix(s, srp);
diff --git a/driver/GccUtils.h b/driver/GccUtils.h
index f33520f..e3f68f4 100644
--- a/driver/GccUtils.h
+++ b/driver/GccUtils.h
@@ -57,6 +57,7 @@
 class GCCInstallationDetector {
  public:
   GCCInstallationDetector(const llvm::Triple &targetTriple,
+                          const std::string &gccToolchainDir,
                           const std::string &sysroot,
                           InspectFS &inspector);
 
@@ -89,6 +90,7 @@
  private:
   llvm::Triple triple_; // target for which we looked
   llvm::Triple foundTriple_; // target we found (taking into account aliases)
+  std::string gccToolchainDir_;
   std::string sysroot_;
   InspectFS &inspector_;
   std::unique_ptr<GCCVersion> version_;
diff --git a/driver/GollvmOptions.td b/driver/GollvmOptions.td
index 4a199ee..d4d8199 100644
--- a/driver/GollvmOptions.td
+++ b/driver/GollvmOptions.td
@@ -410,3 +410,6 @@
 def disable_llvm_passes : Flag<["-"], "disable-llvm-passes">,
   HelpText<"Use together with -emit-llvm to get pristine LLVM IR from the "
            "frontend by not running any LLVM passes at all">;
+
+def gcc_toolchain_EQ : Joined<["--"], "gcc-toolchain=">, Flags<[DriverOption]>,
+  HelpText<"Use the gcc toolchain at the given directory">;
diff --git a/driver/LinuxToolChain.cpp b/driver/LinuxToolChain.cpp
index 65769f5..64af934 100644
--- a/driver/LinuxToolChain.cpp
+++ b/driver/LinuxToolChain.cpp
@@ -45,6 +45,7 @@
     : ToolChain(driver, targetTriple),
       inspectFS_(gnutools::gccdetect::InspectRealFS()),
       gccDetector_(targetTriple,
+                   driver.gccToolchainDir(),
                    driver.sysRoot(),
                    inspectFS_)
 {