--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/components/llvm/patches/012-solaris-clang-libclangDriver.patch Thu Jul 28 16:25:34 2016 -0700
@@ -0,0 +1,2506 @@
+# 23701635 clang produces amd64 opcodes, but calls 32-bit assembler by default
+# 23854357 clang should check for GNU ld
+# 22778650 clang should support OpenMP because it can
+# 24314745 clang should support PIE executables in Solaris
+# 3.9.X for upstream.
+--- tools/clang/include/clang/Driver/Options.td 2016-01-06 16:27:42.000000000 -0500
++++ tools/clang/include/clang/Driver/Options.td 2016-05-08 23:19:20.553431263 -0400
+@@ -669,6 +669,9 @@
+ Flags<[CC1Option]>, HelpText<"Form fused FP ops (e.g. FMAs): fast (everywhere)"
+ " | on (according to FP_CONTRACT pragma, default) | off (never fuse)">;
+
++def fabi_version_EQ : Joined<["-"], "fabi-version=">, Group<f_Group>,
++ Flags<[CC1Option]>, HelpText<"Use specified GNU C++ ABI version">;
++
+ def ffor_scope : Flag<["-"], "ffor-scope">, Group<f_Group>;
+ def fno_for_scope : Flag<["-"], "fno-for-scope">, Group<f_Group>;
+
+@@ -1312,6 +1315,12 @@
+ def meabi : Separate<["-"], "meabi">, Group<m_Group>, Flags<[CC1Option]>,
+ HelpText<"Set EABI type, e.g. 4, 5 or gnu (default depends on triple)">;
+
++// SPARC-only options.
++def mvis : Flag<["-"], "mvis">, Group<m_Group>;
++def mvis2 : Flag<["-"], "mvis2">, Group<m_Group>;
++def mvis3 : Flag<["-"], "mvis3">, Group<m_Group>;
++def mimpure_text: Flag<["-"], "mimpure-text">, Group<m_Group>;
++
+ def mmmx : Flag<["-"], "mmmx">, Group<m_x86_Features_Group>;
+ def mno_3dnowa : Flag<["-"], "mno-3dnowa">, Group<m_x86_Features_Group>;
+ def mno_3dnow : Flag<["-"], "mno-3dnow">, Group<m_x86_Features_Group>;
+@@ -1954,6 +1963,7 @@
+
+ def fprofile_dir : Joined<["-"], "fprofile-dir=">, Group<clang_ignored_gcc_optimization_f_Group>;
+
++def fuse_as_EQ : Joined<["-"], "fuse-as=">, Group<f_Group>;
+ def fuse_ld_EQ : Joined<["-"], "fuse-ld=">, Group<f_Group>;
+
+ defm align_functions : BooleanFFlag<"align-functions">, Group<clang_ignored_gcc_optimization_f_Group>;
+###
+--- tools/clang/lib/Driver/Multilib.cpp 2015-10-12 10:32:57.000000000 -0400
++++ tools/clang/lib/Driver/Multilib.cpp 2016-05-08 23:19:20.569431652 -0400
+@@ -171,11 +171,11 @@
+ }
+
+ static Multilib compose(const Multilib &Base, const Multilib &New) {
+- SmallString<128> GCCSuffix;
++ SmallString<PATH_MAX> GCCSuffix;
+ llvm::sys::path::append(GCCSuffix, "/", Base.gccSuffix(), New.gccSuffix());
+- SmallString<128> OSSuffix;
++ SmallString<PATH_MAX> OSSuffix;
+ llvm::sys::path::append(OSSuffix, "/", Base.osSuffix(), New.osSuffix());
+- SmallString<128> IncludeSuffix;
++ SmallString<PATH_MAX> IncludeSuffix;
+ llvm::sys::path::append(IncludeSuffix, "/", Base.includeSuffix(),
+ New.includeSuffix());
+
+###
+--- tools/clang/lib/Driver/ToolChains.cpp 2016-02-16 10:56:48.000000000 -0900
++++ tools/clang/lib/Driver/ToolChains.cpp 2016-06-30 09:27:01.031173505 -0800
+@@ -28,12 +28,15 @@
+ #include "llvm/ProfileData/InstrProf.h"
+ #include "llvm/Support/ErrorHandling.h"
+ #include "llvm/Support/FileSystem.h"
++#include "llvm/Support/Host.h"
+ #include "llvm/Support/MemoryBuffer.h"
+ #include "llvm/Support/Path.h"
+ #include "llvm/Support/Program.h"
+ #include "llvm/Support/TargetParser.h"
+ #include "llvm/Support/raw_ostream.h"
+ #include <cstdlib> // ::getenv
++#include <cstring>
++#include <cctype>
+ #include <system_error>
+
+ using namespace clang::driver;
+@@ -41,6 +44,15 @@
+ using namespace clang;
+ using namespace llvm::opt;
+
++#if defined(LLVM_ON_UNIX)
++#include <cstring>
++#include <cctype>
++#include <sys/types.h>
++#include <sys/stat.h>
++#include <dirent.h>
++#include <unistd.h>
++#endif
++
+ MachO::MachO(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
+ : ToolChain(D, Triple, Args) {
+ // We expect 'as', 'ld', etc. to be adjacent to our install dir.
+@@ -1347,6 +1359,11 @@
+ // If we have a SysRoot, try that first.
+ if (!D.SysRoot.empty()) {
+ Prefixes.push_back(D.SysRoot);
++
++ // Add Solaris-specific GCC locations.
++ if (TargetTriple.getOS() == llvm::Triple::Solaris)
++ Prefixes.push_back("/usr/gcc");
++
+ Prefixes.push_back(D.SysRoot + "/usr");
+ }
+
+@@ -1434,14 +1451,17 @@
+ static const char *const ARMebHFTriples[] = {
+ "armeb-linux-gnueabihf", "armebv7hl-redhat-linux-gnueabi"};
+
+- static const char *const X86_64LibDirs[] = {"/lib64", "/lib"};
++ static const char *const X86_64LibDirs[] = {"/lib64", "/lib/amd64",
++ "/lib/64", "/lib"};
+ static const char *const X86_64Triples[] = {
+ "x86_64-linux-gnu", "x86_64-unknown-linux-gnu",
+ "x86_64-pc-linux-gnu", "x86_64-redhat-linux6E",
+ "x86_64-redhat-linux", "x86_64-suse-linux",
+ "x86_64-manbo-linux-gnu", "x86_64-linux-gnu",
+ "x86_64-slackware-linux", "x86_64-linux-android",
+- "x86_64-unknown-linux"};
++ "x86_64-unknown-linux", "x86_64-pc-solaris2.11",
++ "x86_64-pc-solaris2.12", "x86_64-pc-solaris2.13" };
++
+ static const char *const X32LibDirs[] = {"/libx32"};
+ static const char *const X86LibDirs[] = {"/lib32", "/lib"};
+ static const char *const X86Triples[] = {
+@@ -1449,7 +1469,8 @@
+ "i386-linux-gnu", "i386-redhat-linux6E", "i686-redhat-linux",
+ "i586-redhat-linux", "i386-redhat-linux", "i586-suse-linux",
+ "i486-slackware-linux", "i686-montavista-linux", "i686-linux-android",
+- "i586-linux-gnu"};
++ "i586-linux-gnu", "i386-pc-solaris2.11", "i386-pc-solaris2.12",
++ "i386-pc-solaris2.13" };
+
+ static const char *const MIPSLibDirs[] = {"/lib"};
+ static const char *const MIPSTriples[] = {"mips-linux-gnu", "mips-mti-linux",
+@@ -1483,30 +1504,28 @@
+
+ static const char *const SPARCv8LibDirs[] = {"/lib32", "/lib"};
+ static const char *const SPARCv8Triples[] = {"sparc-linux-gnu",
+- "sparcv8-linux-gnu"};
+- static const char *const SPARCv9LibDirs[] = {"/lib64", "/lib"};
++ "sparcv8-linux-gnu",
++ "sparc-sun-solaris2.11",
++ "sparc-sun-solaris2.12",
++ "sparc-sun-solaris2.13" };
++
++ static const char *const SPARCv9LibDirs[] = {"/lib64", "/lib/sparcv9",
++ "/lib/64", "/lib" };
++
+ static const char *const SPARCv9Triples[] = {"sparc64-linux-gnu",
+- "sparcv9-linux-gnu"};
++ "sparcv9-linux-gnu",
++ "sparcv9-sun-solaris2.11",
++ "sparcv9-sun-solaris2.12",
++ "sparcv9-sun-solaris2.13" };
+
+ static const char *const SystemZLibDirs[] = {"/lib64", "/lib"};
+ static const char *const SystemZTriples[] = {
+ "s390x-linux-gnu", "s390x-unknown-linux-gnu", "s390x-ibm-linux-gnu",
+ "s390x-suse-linux", "s390x-redhat-linux"};
+
+- // Solaris.
+- static const char *const SolarisSPARCLibDirs[] = {"/gcc"};
+- static const char *const SolarisSPARCTriples[] = {"sparc-sun-solaris2.11",
+- "i386-pc-solaris2.11"};
+-
+ using std::begin;
+ using std::end;
+
+- if (TargetTriple.getOS() == llvm::Triple::Solaris) {
+- LibDirs.append(begin(SolarisSPARCLibDirs), end(SolarisSPARCLibDirs));
+- TripleAliases.append(begin(SolarisSPARCTriples), end(SolarisSPARCTriples));
+- return;
+- }
+-
+ switch (TargetTriple.getArch()) {
+ case llvm::Triple::aarch64:
+ LibDirs.append(begin(AArch64LibDirs), end(AArch64LibDirs));
+@@ -3302,69 +3321,783 @@
+ }
+
+ /// Solaris - Solaris tool chain which can call as(1) and ld(1) directly.
++bool Solaris::SupportsClangLibCPlusPlus = false;
+
+ Solaris::Solaris(const Driver &D, const llvm::Triple &Triple,
+- const ArgList &Args)
+- : Generic_GCC(D, Triple, Args) {
++ const llvm::opt::ArgList &Args)
++ : Generic_ELF(D, Triple, Args),
++ UseGnuAs(true),
++ UseGnuLd(false),
++ UseGoldLd(false),
++ UseSunLd(true),
++ UseMediatedGCCToolChainPath(false),
++ UseSpecifiedGCCToolChainPath(false),
++ IsValid(false),
++ GCCInstallDir("/usr/gcc/"),
++ GCCMajorMinor(""),
++ GCCMajorMinorMicro(""),
++ GCCInternalLibDir(""),
++ GCCInternalMultiLibDir(""),
++ GCCIncludeDirs(),
++ Assembler("/usr/gnu/bin/as"),
++ Linker("/usr/bin/ld"),
++ mtune(""),
++ march(""),
++ mcpu(""),
++ ExtraOpts() {
++ if (Arg *A = Args.getLastArg(options::OPT_gcc_toolchain)) {
++ GCCInstallDir = A->getValue();
++ if (!llvm::sys::fs::exists(GCCInstallDir))
++ D.Diag(diag::err_drv_no_such_file) << GCCInstallDir;
++ else {
++ findSpecifiedGCCToolchain(GCCInstallDir.c_str(), Triple, Args);
++
++ if (!UseSpecifiedGCCToolChainPath) {
++ D.Diag(diag::err_drv_unsupported_rtlib_for_platform)
++ << GCCInstallDir << Triple.getTriple();
++ } else {
++ findGCCIncludeDirs(Triple, Args);
++ findGCCInternalLibDir(Triple, Args);
++ }
++ }
++ } else {
++ findGCCMajorMinor();
++ findGCCMajorMinorMicro(Triple);
++ findGCCIncludeDirs(Triple, Args);
++ findGCCInternalLibDir(Triple, Args);
++ }
+
+- GCCInstallation.init(Triple, Args);
++ if (Arg *A = Args.getLastArg(options::OPT_fuse_ld_EQ)) {
++ Linker = A->getValue();
++ if (Linker == "bfd")
++ Linker = "/usr/gnu/bin/ld";
++ else if (Linker == "gold")
++ Linker = "/usr/gnu/bin/ld.gold";
++
++ if ((Linker == "/usr/gnu/bin/ld") || (Linker == "/usr/gnu/bin/ld.bfd") ||
++ (Linker == "/usr/bin/gld") || (Linker == "/usr/bin/gld.bfd")) {
++ UseGnuLd = true;
++ UseGoldLd = false;
++ UseSunLd = false;
++ } else if ((Linker == "/usr/gnu/bin/ld.gold") ||
++ (Linker == "/usr/bin/gld.gold") ||
++ (Linker == "/usr/bin/ld.gold")) {
++ UseGnuLd = false;
++ UseSunLd = false;
++ UseGoldLd = true;
++ }
++ }
+
+- path_list &Paths = getFilePaths();
+- if (GCCInstallation.isValid())
+- addPathIfExists(D, GCCInstallation.getInstallPath(), Paths);
++ if (Arg *A = Args.getLastArg(options::OPT_fuse_as_EQ)) {
++ Assembler = A->getValue();
++ if (Assembler == "llvm")
++ UseGnuAs = false;
++ else if ((Assembler == "/usr/gnu/bin/as") ||
++ (Assembler == "/usr/bin/gas"))
++ UseGnuAs = true;
++ else if (Assembler == "gas") {
++ Assembler = "/usr/gnu/bin/as";
++ UseGnuAs = true;
++ } else if ((Assembler == "/usr/bin/as") || (Assembler == "sun") ||
++ (Assembler == "solaris"))
++ D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args);
++ }
++
++ getProgramPaths().push_back(GCCInstallDir);
+
+- addPathIfExists(D, getDriver().getInstalledDir(), Paths);
+ if (getDriver().getInstalledDir() != getDriver().Dir)
+- addPathIfExists(D, getDriver().Dir, Paths);
++ getProgramPaths().push_back(getDriver().Dir);
+
+- addPathIfExists(D, getDriver().SysRoot + getDriver().Dir + "/../lib", Paths);
++ llvm::Triple::ArchType Arch = Triple.getArch();
+
+- std::string LibPath = "/usr/lib/";
+- switch (Triple.getArch()) {
++ switch (Arch) {
+ case llvm::Triple::x86:
++ getFilePaths().push_back(getDriver().Dir + "/../lib");
++ getFilePaths().push_back("/usr/lib");
++ march = mtune = "i686";
++ break;
+ case llvm::Triple::sparc:
++ getFilePaths().push_back(getDriver().Dir + "/../lib");
++ getFilePaths().push_back("/usr/lib");
++ mcpu = "ultrasparc";
++ mtune = "ultrasparc";
++ march = "v8plusa";
+ break;
+ case llvm::Triple::x86_64:
+- LibPath += "amd64/";
++ getFilePaths().push_back(getDriver().Dir + "/../lib/amd64");
++ getFilePaths().push_back("/usr/lib/amd64");
++ march = mtune = "opteron";
+ break;
+ case llvm::Triple::sparcv9:
+- LibPath += "sparcv9/";
++ getFilePaths().push_back(getDriver().Dir + "/../lib/sparcv9");
++ getFilePaths().push_back("/usr/lib/sparcv9");
++ mcpu = "ultrasparc";
++ mtune = "ultrasparc";
++ march = "v9a";
+ break;
+ default:
+- llvm_unreachable("Unsupported architecture");
++ getFilePaths().push_back(getDriver().Dir + "/../lib");
++ getFilePaths().push_back("/usr/lib");
++ break;
+ }
+
+- addPathIfExists(D, getDriver().SysRoot + LibPath, Paths);
++ validate();
++
++ if (Args.hasArg(options::OPT_v))
++ this->print(llvm::errs());
+ }
+
+-Tool *Solaris::buildAssembler() const {
+- return new tools::solaris::Assembler(*this);
++std::string Solaris::computeSysRoot() const {
++ if (!getDriver().SysRoot.empty())
++ return getDriver().SysRoot;
++
++ return std::string("/");
+ }
+
+-Tool *Solaris::buildLinker() const { return new tools::solaris::Linker(*this); }
++bool
++Solaris::addLibStdCXXIncludePaths(Twine Base, Twine Suffix,
++ StringRef GCCTriple,
++ StringRef GCCMultiarchTriple,
++ StringRef TargetMultiarchTriple,
++ Twine IncludeSuffix,
++ const llvm::opt::ArgList &DriverArgs,
++ llvm::opt::ArgStringList &CC1Args) const {
++ if (!llvm::sys::fs::exists(Base + Suffix))
++ return false;
+
+-void Solaris::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
+- ArgStringList &CC1Args) const {
++ addSystemInclude(DriverArgs, CC1Args, Base);
++ addSystemInclude(DriverArgs, CC1Args, Base + Suffix);
++
++ if ((GCCMultiarchTriple.empty() && TargetMultiarchTriple.empty()) ||
++ llvm::sys::fs::exists(Base + Suffix + "/" + GCCTriple + IncludeSuffix)) {
++ addSystemInclude(DriverArgs,
++ CC1Args, Base + Suffix + "/" + GCCTriple + IncludeSuffix);
++ } else {
++ addSystemInclude(DriverArgs, CC1Args,
++ Base + "/" + GCCMultiarchTriple + Suffix + IncludeSuffix);
++ addSystemInclude(DriverArgs, CC1Args,
++ Base + "/" + TargetMultiarchTriple + Suffix);
++ }
++
++ addSystemInclude(DriverArgs, CC1Args, Base + "/backward");
++ addSystemInclude(DriverArgs, CC1Args, Base + Suffix + "/backward");
++ return true;
++}
++
++void
++Solaris::AddClangCXXStdlibIncludeArgs(const llvm::opt::ArgList &DriverArgs,
++ llvm::opt::ArgStringList &CC1Args) const {
+ if (DriverArgs.hasArg(options::OPT_nostdlibinc) ||
+ DriverArgs.hasArg(options::OPT_nostdincxx))
+ return;
+
+- // Include the support directory for things like xlocale and fudged system
+- // headers.
+- addSystemInclude(DriverArgs, CC1Args, "/usr/include/c++/v1/support/solaris");
++ const Driver &D = getDriver();
+
+- if (GCCInstallation.isValid()) {
+- GCCVersion Version = GCCInstallation.getVersion();
+- addSystemInclude(DriverArgs, CC1Args,
+- getDriver().SysRoot + "/usr/gcc/" +
+- Version.MajorStr + "." +
+- Version.MinorStr +
+- "/include/c++/" + Version.Text);
+- addSystemInclude(DriverArgs, CC1Args,
+- getDriver().SysRoot + "/usr/gcc/" + Version.MajorStr +
+- "." + Version.MinorStr + "/include/c++/" +
+- Version.Text + "/" +
+- GCCInstallation.getTriple().str());
++ // Check for Clang libc++
++ if (GetCXXStdlibType(DriverArgs) == ToolChain::CST_Libcxx) {
++ if (!Solaris::SupportsClangLibCPlusPlus) {
++ D.Diag(diag::err_drv_invalid_stdlib_name) << "libc++";
++ return;
++ }
++
++ StringRef IncludePath = "/usr/include/libc++/v1";
++ if (!llvm::sys::fs::exists(IncludePath)) {
++ D.Diag(diag::err_drv_no_such_file) << IncludePath;
++ return;
++ }
++
++ addSystemInclude(DriverArgs, CC1Args, IncludePath);
++ return;
++ }
++
++ for (std::vector<std::string>::const_iterator B =
++ getGCCIncludeDirs().begin(), E = getGCCIncludeDirs().end();
++ B != E; ++B) {
++ llvm::Twine IncludePath((*B));
++ addSystemInclude(DriverArgs, CC1Args, IncludePath);
++ }
++}
++
++void
++Solaris::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
++ ArgStringList &CC1Args) const {
++ const Driver &D = getDriver();
++
++ if (DriverArgs.hasArg(options::OPT_nostdinc))
++ return;
++
++ std::string SysRoot = computeSysRoot();
++
++ if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
++ SmallString<PATH_MAX> P(D.ResourceDir);
++ llvm::sys::path::append(P, "/include");
++ addSystemInclude(DriverArgs, CC1Args, P.str());
++ }
++
++ if (DriverArgs.hasArg(options::OPT_nostdlibinc))
++ return;
++
++ StringRef CIncludeDirs(C_INCLUDE_DIRS);
++ if (CIncludeDirs != "") {
++ SmallVector<StringRef, 5> dirs;
++ CIncludeDirs.split(dirs, ":");
++ for (SmallVectorImpl<StringRef>::iterator I = dirs.begin(), E = dirs.end();
++ I != E; ++I) {
++ StringRef Prefix =
++ llvm::sys::path::is_absolute(*I) ? StringRef(SysRoot) : "";
++ addExternCSystemInclude(DriverArgs, CC1Args, Prefix + *I);
++ }
++ }
++
++ addExternCSystemInclude(DriverArgs, CC1Args, "/usr/include");
++}
++
++void
++Solaris::addClangTargetOptions(const ArgList &DriverArgs,
++ ArgStringList &CC1Args) const {
++ const llvm::Triple& TT = getTriple();
++ llvm::Triple::ArchType Arch = TT.getArch();
++
++ if (Arg *A = DriverArgs.getLastArg(options::OPT_fuse_init_array))
++ DriverArgs.ClaimAllArgs(options::OPT_fuse_init_array);
++
++ // Always use .init_array/.fini_array on Solaris. The Solaris
++ // linker can't do .ctors/.dtors or .init/.fini for that matter.
++ CC1Args.push_back("-fuse-init-array");
++
++ if (Arg *A = DriverArgs.getLastArg(options::OPT_fabi_version_EQ)) {
++ StringRef V = A->getValue();
++ if (!V.empty()) {
++ std::string fabi_version = "-fabi-version=";
++ fabi_version += V.str();
++ CC1Args.push_back(DriverArgs.MakeArgString(fabi_version.c_str()));
++ } else {
++ std::string fabi_version = "-fabi-version=4";
++ CC1Args.push_back(DriverArgs.MakeArgString(fabi_version.c_str()));
++ }
++ } else {
++ CC1Args.push_back(DriverArgs.MakeArgString("-fabi-version=4"));
++ }
++
++ DriverArgs.ClaimAllArgs(options::OPT_fabi_version_EQ);
++
++ if (Arch == llvm::Triple::sparc || Arch == llvm::Triple::sparcv9) {
++ CC1Args.push_back(DriverArgs.MakeArgString("-target-feature"));
++ CC1Args.push_back(DriverArgs.MakeArgString("+hwcap"));
++ }
++
++ bool SeenVIS = false;
++ bool SeenVIS2 = false;
++ bool SeenVIS3 = false;
++
++ bool DoneVIS = false;
++ bool DoneVIS2 = false;
++ bool DoneVIS3 = false;
++
++ bool DoneMTune = false;
++
++ if (Arg *A = DriverArgs.getLastArg(options::OPT_mtune_EQ)) {
++ StringRef V = A->getValue();
++ if (!V.empty())
++ mtune = V.str();
++ else
++ mtune = "ultrasparc";
++
++ if (Arch == llvm::Triple::sparc || Arch == llvm::Triple::sparcv9) {
++ if ((mtune == "ultrasparc") || (mtune == "ultrasparc2") ||
++ (mtune == "vis")) {
++ SeenVIS = true;
++ } else if ((mtune == "ultrasparc3") || (mtune == "vis2")) {
++ SeenVIS = true;
++ SeenVIS2 = true;
++ } else {
++ SeenVIS = true;
++ SeenVIS2 = true;
++ SeenVIS3 = true;
++ }
++
++ if (!DoneMTune) {
++ if (SeenVIS3 && !DoneVIS3) {
++ CC1Args.push_back(DriverArgs.MakeArgString("-target-feature"));
++ CC1Args.push_back(DriverArgs.MakeArgString("+vis3"));
++ DoneVIS3 = true;
++ DoneVIS2 = true;
++ DoneVIS = true;
++ }
++
++ if (SeenVIS2 && !DoneVIS2) {
++ CC1Args.push_back(DriverArgs.MakeArgString("-target-feature"));
++ CC1Args.push_back(DriverArgs.MakeArgString("+vis2"));
++ DoneVIS2 = true;
++ DoneVIS = true;
++ }
++
++ if (SeenVIS && !DoneVIS) {
++ CC1Args.push_back(DriverArgs.MakeArgString("-target-feature"));
++ CC1Args.push_back(DriverArgs.MakeArgString("+vis"));
++ DoneVIS = true;
++ }
++
++ DoneMTune = true;
++ }
++ }
++ }
++
++ if (Arch == llvm::Triple::sparc || Arch == llvm::Triple::sparcv9) {
++ if (Arg *A = DriverArgs.getLastArg(options::OPT_mvis)) {
++ SeenVIS = !DoneVIS;
++ if (!DoneVIS) {
++ CC1Args.push_back(DriverArgs.MakeArgString("-target-feature"));
++ CC1Args.push_back(DriverArgs.MakeArgString("+vis"));
++ DoneVIS = true;
++ }
++ }
++
++ if (Arg *A = DriverArgs.getLastArg(options::OPT_mvis2)) {
++ SeenVIS2 = !DoneVIS2;
++ if (!DoneVIS2) {
++ CC1Args.push_back(DriverArgs.MakeArgString("-target-feature"));
++ CC1Args.push_back(DriverArgs.MakeArgString("+vis2"));
++ DoneVIS2 = true;
++ DoneVIS = true;
++ }
++ }
++
++ if (Arg *A = DriverArgs.getLastArg(options::OPT_mvis3)) {
++ SeenVIS3 = !DoneVIS3;
++ if (!DoneVIS3) {
++ CC1Args.push_back(DriverArgs.MakeArgString("-target-feature"));
++ CC1Args.push_back(DriverArgs.MakeArgString("+vis3"));
++ DoneVIS3 = true;
++ DoneVIS2 = true;
++ DoneVIS = true;
++ }
++ }
++ }
++}
++
++void
++Solaris::findGCCMajorMinor() const {
++ // FIXME: Add 5.X after testing the ABI.
++ static const char* const GCCMM[] = { "4.8", "4.9" };
++
++ const char* P;
++ std::string Path;
++
++ Path.reserve(std::string::size_type(PATH_MAX));
++
++ for (int I = (llvm::array_lengthof(GCCMM) - 1); I >= 0; --I) {
++ if ((P = GCCMM[I]) != NULL) {
++ Path = GCCInstallDir;
++ Path.append(P);
++ Path.append("/");
++
++ if (llvm::sys::fs::exists(Path.c_str())) {
++ GCCMajorMinor = P;
++ break;
++ }
++ }
++ }
++}
++
++void
++Solaris::findGCCMajorMinorMicro(const llvm::Triple& T) const {
++ // FIXME: Add 5.X after testing the ABI.
++ static const char* const GCCMMM[] = { "4.8.2", "4.9.3", "4.9.4" };
++
++ const char* P;
++ std::string Path;
++ std::string TripleString = llvm::sys::getDefaultTargetTriple();
++ llvm::Triple::ArchType Arch = T.getArch();
++
++ // GCC4 on Solaris is multilib 32/64.
++ // GCC5 (not supported here yet) on Solaris is multilib 64/32.
++ if (GCCMajorMinor[0] == '4') {
++ if (TripleString.find("x86_64") != std::string::npos)
++ TripleString.replace(0U, 6U, std::string("i386"));
++ else if (TripleString.find("sparcv9") != std::string::npos)
++ TripleString.replace(0U, 7U, std::string("sparc"));
++ }
++
++ Path.reserve(std::string::size_type(PATH_MAX));
++
++ for (int I = (llvm::array_lengthof(GCCMMM) - 1); I >= 0; --I) {
++ if ((P = GCCMMM[I]) != NULL) {
++ if ((P[0] == GCCMajorMinor[0]) && (P[2] == GCCMajorMinor[2])) {
++ Path = GCCInstallDir;
++ Path.append("/");
++ Path.append(GCCMajorMinor);
++ Path.append("/lib/gcc/");
++ Path.append(TripleString);
++ Path.append("/");
++ Path.append(P);
++
++ if (llvm::sys::fs::exists(Path.c_str())) {
++ std::string Test;
++ // Check if this is a real GCC installation and not just
++ // an empty directory tree
++ switch (Arch) {
++ case llvm::Triple::x86:
++ case llvm::Triple::sparc:
++ Test = Path + "/crtbegin.o";
++ break;
++ case llvm::Triple::x86_64:
++ Test = Path + "/amd64/crtbegin.o";
++ break;
++ case llvm::Triple::sparcv9:
++ Test = Path + "/sparcv9/crtbegin.o";
++ break;
++ default:
++ break;
++ }
++
++ if (llvm::sys::fs::exists(Test.c_str())) {
++ GCCMajorMinorMicro = P;
++ break;
++ }
++ }
++ }
++ }
++ }
++}
++
++void
++Solaris::findSpecifiedGCCToolchain(const char *StartingPath,
++ const llvm::Triple &Triple,
++ const llvm::opt::ArgList &Args) const {
++ DIR *TopLD = 0;
++ DIR *LibLD = 0;
++ DIR *GccLD = 0;
++ DIR *TripleLD = 0;
++ struct dirent *TopDE = 0;
++ struct dirent *LibDE = 0;
++ struct dirent *GccDE = 0;
++ struct dirent *TripleDE = 0;
++ std::string LibDir;
++ std::string GccDir;
++ std::string TripleDir;
++ std::string TripleVersionDir;
++ const char *DName;
++
++ assert(StartingPath && "Invalid GCC Toolchain starting search path!");
++
++ GCCMajorMinor = "";
++ GCCMajorMinorMicro = "";
++ UseSpecifiedGCCToolChainPath = false;
++
++ LibDir.reserve(std::string::size_type(PATH_MAX));
++ GccDir.reserve(std::string::size_type(PATH_MAX));
++ TripleDir.reserve(std::string::size_type(PATH_MAX));
++ TripleVersionDir.reserve(std::string::size_type(PATH_MAX));
++
++ if (llvm::sys::fs::exists(StartingPath) &&
++ llvm::sys::fs::is_directory(StartingPath)) {
++ TopLD = opendir(StartingPath);
++ assert(TopLD && "Cannot obtain a valid toplevel DIR handle!");
++
++ while ((TopDE = readdir(TopLD)) != NULL) {
++ if (TopDE->d_name[0] == '.')
++ continue;
++
++ DName = static_cast<const char*>(&TopDE->d_name[0]);
++ if (std::strcmp(DName, "lib") == 0) {
++ LibDir = StartingPath;
++ LibDir.append("/");
++ LibDir.append(DName);
++
++ if (!llvm::sys::fs::is_directory(LibDir.c_str()))
++ continue;
++
++ LibLD = opendir(LibDir.c_str());
++ assert(LibLD && "Could not obtain a valid lib DIR handle!");
++
++ while ((LibDE = readdir(LibLD)) != NULL) {
++ if (LibDE->d_name[0] == '.')
++ continue;
++
++ DName = static_cast<const char*>(&LibDE->d_name[0]);
++ if (std::strcmp(DName, "gcc") == 0) {
++ GccDir = LibDir;
++ GccDir.append("/");
++ GccDir.append(DName);
++
++ if (!llvm::sys::fs::is_directory(GccDir.c_str()))
++ continue;
++
++ GccLD = opendir(GccDir.c_str());
++ assert(GccLD && "Could not obtain a valid gcc DIR handle!");
++
++ while ((GccDE = readdir(GccLD)) != NULL) {
++ if (GccDE->d_name[0] == '.')
++ continue;
++
++ DName = static_cast<const char*>(&GccDE->d_name[0]);
++ TripleDir = GccDir;
++ TripleDir.append("/");
++ TripleDir.append(DName);
++
++ if (!llvm::sys::fs::is_directory(TripleDir.c_str()))
++ continue;
++
++ if ((std::strncmp(DName, "sparc", 5) == 0) ||
++ (std::strncmp(DName, "i386", 4) == 0) ||
++ (std::strncmp(DName, "sparcv9", 7) == 0) ||
++ (std::strncmp(DName, "x86_64", 6) == 0)) {
++ TripleLD = opendir(TripleDir.c_str());
++ assert(TripleLD &&
++ "Could not obtain a valid Triple DIR handle!");
++
++ while ((TripleDE = readdir(TripleLD)) != NULL) {
++ if (TripleDE->d_name[0] == '.')
++ continue;
++
++ DName = static_cast<const char*>(&TripleDE->d_name[0]);
++ TripleVersionDir = TripleDir;
++ TripleVersionDir.append("/");
++ TripleVersionDir.append(DName);
++
++ if (!llvm::sys::fs::is_directory(TripleVersionDir.c_str()))
++ continue;
++
++ if ((std::isdigit(DName[0])) && (DName[1] == '.') &&
++ (std::isdigit(DName[2])) && (DName[3] == '.') &&
++ (std::isdigit(DName[4])) && (DName[5] == '\0')) {
++ GCCMajorMinorMicro = DName;
++ GCCMajorMinor = GCCMajorMinorMicro.substr(0, 3);
++ UseSpecifiedGCCToolChainPath = true;
++ goto done;
++ }
++ }
++ }
++ }
++ }
++ }
++ }
++ }
++ }
++
++done:
++ if (TripleLD) {
++ rewinddir(TripleLD);
++ closedir(TripleLD);
++ }
++
++ if (GccLD) {
++ rewinddir(GccLD);
++ closedir(GccLD);
++ }
++
++ if (LibLD) {
++ rewinddir(LibLD);
++ closedir(LibLD);
++ }
++
++ if (TopLD) {
++ rewinddir(TopLD);
++ closedir(TopLD);
++ }
++}
++
++void
++Solaris::findGCCIncludeDirs(const llvm::Triple &Triple,
++ const llvm::opt::ArgList &Args) const {
++ std::string GCCInstallPath;
++ if (UseSpecifiedGCCToolChainPath)
++ GCCInstallPath = GCCInstallDir;
++ else
++ GCCInstallPath = GCCInstallDir + GCCMajorMinor;
++
++ std::string GCCIncludeDir =
++ GCCInstallPath + "/include/c++/" + GCCMajorMinorMicro;
++ GCCIncludeDirs.push_back(GCCIncludeDir);
++
++ llvm::Triple::ArchType Arch = Triple.getArch();
++ GCCIncludeDir += "/";
++
++ switch (Arch) {
++ case llvm::Triple::x86:
++ GCCIncludeDir += Triple.getTriple();
++ if (Arg *A = Args.getLastArg(options::OPT_m64))
++ GCCIncludeDir += "/amd64";
++ break;
++ case llvm::Triple::sparc:
++ GCCIncludeDir += Triple.getTriple();
++ if (Arg *A = Args.getLastArg(options::OPT_m64))
++ GCCIncludeDir += "/sparcv9";
++ break;
++ case llvm::Triple::x86_64:
++ GCCIncludeDir += "i386-pc-";
++ GCCIncludeDir += Triple.getOSName();
++ if (Arg *A = Args.getLastArg(options::OPT_m64))
++ GCCIncludeDir += "/amd64";
++ break;
++ case llvm::Triple::sparcv9:
++ GCCIncludeDir += "sparc-sun-";
++ GCCIncludeDir += Triple.getOSName();
++ if (Arg *A = Args.getLastArg(options::OPT_m64))
++ GCCIncludeDir += "/sparcv9";
++ break;
++ default:
++ getDriver().Diag(diag::err_target_unsupported_arch)
++ << Triple.getArchName() << Triple.getTriple();
++ break;
++ }
++
++ GCCIncludeDirs.push_back(GCCIncludeDir);
++
++ GCCIncludeDir = GCCInstallPath + "/include/c++/" +
++ GCCMajorMinorMicro + "/backward";
++
++ GCCIncludeDirs.push_back(GCCIncludeDir);
++}
++
++void
++Solaris::findGCCInternalLibDir(const llvm::Triple &Triple,
++ const llvm::opt::ArgList &Args) const {
++ std::string GCCInstallPath;
++ if (UseSpecifiedGCCToolChainPath)
++ GCCInstallPath = GCCInstallDir;
++ else
++ GCCInstallPath = GCCInstallDir + GCCMajorMinor;
++
++ GCCInternalLibDir = GCCInstallPath + "/lib/gcc/";
++
++ llvm::Triple::ArchType Arch = Triple.getArch();
++
++ switch (Arch) {
++ case llvm::Triple::x86:
++ GCCInternalLibDir += Triple.getTriple();
++ GCCInternalLibDir += "/";
++ GCCInternalLibDir += GCCMajorMinorMicro;
++ if (Arg *A = Args.getLastArg(options::OPT_m64)) {
++ GCCInternalMultiLibDir = GCCInternalLibDir;
++ GCCInternalLibDir += "/amd64";
++ } else if (Arg *A = Args.getLastArg(options::OPT_m32)) {
++ GCCInternalMultiLibDir = GCCInternalLibDir;
++ GCCInternalMultiLibDir += "/amd64";
++ } else {
++ GCCInternalMultiLibDir = GCCInternalLibDir;
++ GCCInternalMultiLibDir += "/amd64";
++ }
++
++ break;
++ case llvm::Triple::sparc:
++ GCCInternalLibDir += Triple.getTriple();
++ GCCInternalLibDir += "/";
++ GCCInternalLibDir += GCCMajorMinorMicro;
++ if (Arg *A = Args.getLastArg(options::OPT_m64)) {
++ GCCInternalMultiLibDir = GCCInternalLibDir;
++ GCCInternalLibDir += "/sparcv9";
++ } else if (Arg *A = Args.getLastArg(options::OPT_m32)) {
++ GCCInternalMultiLibDir = GCCInternalLibDir;
++ GCCInternalMultiLibDir += "/sparcv9";
++ } else {
++ GCCInternalMultiLibDir = GCCInternalLibDir;
++ GCCInternalMultiLibDir += "/sparcv9";
++ }
++ break;
++ case llvm::Triple::x86_64:
++ GCCInternalLibDir += "i386-pc-";
++ GCCInternalLibDir += Triple.getOSName();
++ GCCInternalLibDir += "/";
++ GCCInternalLibDir += GCCMajorMinorMicro;
++ GCCInternalMultiLibDir = GCCInternalLibDir;
++ if (Arg *A = Args.getLastArg(options::OPT_m64))
++ GCCInternalLibDir += "/amd64";
++ else if (Arg *A = Args.getLastArg(options::OPT_m32))
++ GCCInternalMultiLibDir += "/amd64";
++ else
++ GCCInternalLibDir += "/amd64";
++ break;
++ case llvm::Triple::sparcv9:
++ GCCInternalLibDir += "sparc-sun-";
++ GCCInternalLibDir += Triple.getOSName();
++ GCCInternalLibDir += "/";
++ GCCInternalLibDir += GCCMajorMinorMicro;
++ GCCInternalMultiLibDir = GCCInternalLibDir;
++ if (Arg *A = Args.getLastArg(options::OPT_m64))
++ GCCInternalLibDir += "/sparcv9";
++ else if (Arg *A = Args.getLastArg(options::OPT_m32))
++ GCCInternalMultiLibDir += "/sparcv9";
++ else
++ GCCInternalLibDir += "/sparcv9";
++ break;
++ default:
++ getDriver().Diag(diag::err_target_unsupported_arch)
++ << Triple.getArchName() << Triple.getTriple();
++ break;
++ }
++}
++
++
++void
++Solaris::print(raw_ostream &OS) const {
++ OS << "UseGnuAs: " << (UseGnuAs ? "true" : "false") << "\n";
++ OS << "UseGnuLd: " << (UseGnuLd ? "true" : "false") << "\n";
++ OS << "UseGoldLd: " << (UseGoldLd ? "true" : "false") << "\n";
++ OS << "UseSunLd: " << (UseSunLd ? "true" : "false") << "\n";
++ OS << "UseMediatedGCCToolChainPath: "
++ << (UseMediatedGCCToolChainPath ? "true" : "false") << "\n";
++ OS << "UseSpecifiedGCCToolChainPath: "
++ << (UseSpecifiedGCCToolChainPath ? "true" : "false") << "\n";
++ OS << "GCCInstallDir: " << GCCInstallDir.c_str() << "\n";
++ OS << "GCCMajorMinor: " << GCCMajorMinor.c_str() << "\n";
++ OS << "GCCMajorMinorMicro: " << GCCMajorMinorMicro.c_str() << "\n";
++ OS << "GCCInternalLibDir: " << GCCInternalLibDir.c_str() << "\n";
++ OS << "GCCInternalMultiLibDir: " << GCCInternalMultiLibDir.c_str() << "\n";
++ OS << "GCCIncludeDirs: ";
++
++ if (GCCIncludeDirs.size()) {
++ std::string IncludePath;
++ for (std::vector<std::string>::const_iterator B = GCCIncludeDirs.begin(),
++ E = GCCIncludeDirs.end(); B != E; ++B) {
++ IncludePath = "-I";
++ IncludePath += (*B);
++ OS << IncludePath.c_str() << " ";
++ }
++
++ OS << "\n";
++ }
++
++ OS << "Assembler: " << Assembler.c_str() << "\n";
++ OS << "Linker: " << Linker.c_str() << "\n";
++ OS << "mtune: " << mtune.c_str() << "\n";
++ OS << "march: " << march.c_str() << "\n";
++ OS << "mcpu: " << mcpu.c_str() << "\n";
++
++ if (ExtraOpts.size()) {
++ OS << "ExtraOpts: ";
++ for (std::vector<std::string>::const_iterator B = ExtraOpts.begin(),
++ E = ExtraOpts.end(); B != E; ++B) {
++ OS << (*B).c_str() << " ";
++ }
++
++ OS << "\n";
++ }
++
++ OS << "Valid: " << (IsValid ? "true" : "false") << "\n";
++}
++
++Tool *Solaris::buildAssembler() const {
++ return new tools::solaris::Assembler(*this);
++}
++
++Tool *Solaris::buildLinker() const {
++ return new tools::solaris::Linker(*this);
++}
++
++void Solaris::validate() {
++ IsValid = llvm::sys::fs::exists(GCCInstallDir.c_str());
++ if (!IsValid) return;
++ IsValid = llvm::sys::fs::exists(GCCInternalLibDir.c_str());
++ if (!IsValid) return;
++ IsValid = llvm::sys::fs::exists(GCCInternalMultiLibDir.c_str());
++ if (!IsValid) return;
++
++ for (std::vector<std::string>::const_iterator B = GCCIncludeDirs.begin(),
++ E = GCCIncludeDirs.end(); B != E; ++B) {
++ IsValid = llvm::sys::fs::exists((*B).c_str());
++ if (!IsValid) return;
+ }
+ }
+
+@@ -3404,6 +4137,27 @@
+ UbuntuVivid,
+ UbuntuWily,
+ UbuntuXenial,
++ Solaris_11,
++ Solaris_11_1,
++ Solaris_11_2,
++ Solaris_11_3,
++ Solaris_11_4,
++ Solaris_11_5,
++ Solaris_11_6,
++ Solaris_11_7,
++ Solaris_11_8,
++ Solaris_11_9,
++ Solaris_12,
++ Solaris_12_1,
++ Solaris_12_2,
++ Solaris_12_3,
++ Solaris_12_4,
++ Solaris_12_5,
++ Solaris_12_6,
++ Solaris_12_7,
++ Solaris_12_8,
++ Solaris_12_9,
++ Solaris_13,
+ UnknownDistro
+ };
+
+@@ -3421,6 +4175,10 @@
+ return Distro >= UbuntuHardy && Distro <= UbuntuXenial;
+ }
+
++static bool IsSolaris(enum Distro Distro) {
++ return Distro >= Solaris_11 && Distro <= Solaris_13;
++}
++
+ static Distro DetectDistro(const Driver &D, llvm::Triple::ArchType Arch) {
+ llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> File =
+ llvm::MemoryBuffer::getFile("/etc/lsb-release");
+@@ -3488,6 +4246,59 @@
+ return UnknownDistro;
+ }
+
++ File = llvm::MemoryBuffer::getFile("/etc/release");
++ if (File) {
++ StringRef Data = File.get()->getBuffer();
++ SmallVector<StringRef, 8> Lines;
++ Data.split(Lines, "\n");
++ for (unsigned I = 0, S = Lines.size(); I != S; ++I) {
++ if (Lines[I].find("Oracle Solaris") != std::string::npos) {
++ if (Lines[I].find("Solaris 11.0") != std::string::npos)
++ return Solaris_11;
++ else if (Lines[I].find("Solaris 11.1") != std::string::npos)
++ return Solaris_11_1;
++ else if (Lines[I].find("Solaris 11.2") != std::string::npos)
++ return Solaris_11_2;
++ else if (Lines[I].find("Solaris 11.3") != std::string::npos)
++ return Solaris_11_3;
++ else if (Lines[I].find("Solaris 11.4") != std::string::npos)
++ return Solaris_11_4;
++ else if (Lines[I].find("Solaris 11.5") != std::string::npos)
++ return Solaris_11_5;
++ else if (Lines[I].find("Solaris 11.6") != std::string::npos)
++ return Solaris_11_6;
++ else if (Lines[I].find("Solaris 11.7") != std::string::npos)
++ return Solaris_11_7;
++ else if (Lines[I].find("Solaris 11.8") != std::string::npos)
++ return Solaris_11_8;
++ else if (Lines[I].find("Solaris 11.9") != std::string::npos)
++ return Solaris_11_9;
++ else if (Lines[I].find("Solaris 12.0") != std::string::npos)
++ return Solaris_12;
++ else if (Lines[I].find("Solaris 12.1") != std::string::npos)
++ return Solaris_12_1;
++ else if (Lines[I].find("Solaris 12.2") != std::string::npos)
++ return Solaris_12_2;
++ else if (Lines[I].find("Solaris 12.3") != std::string::npos)
++ return Solaris_12_3;
++ else if (Lines[I].find("Solaris 12.4") != std::string::npos)
++ return Solaris_12_4;
++ else if (Lines[I].find("Solaris 12.5") != std::string::npos)
++ return Solaris_12_5;
++ else if (Lines[I].find("Solaris 12.6") != std::string::npos)
++ return Solaris_12_6;
++ else if (Lines[I].find("Solaris 12.7") != std::string::npos)
++ return Solaris_12_7;
++ else if (Lines[I].find("Solaris 12.8") != std::string::npos)
++ return Solaris_12_8;
++ else if (Lines[I].find("Solaris 12.9") != std::string::npos)
++ return Solaris_12_9;
++ }
++ }
++
++ return UnknownDistro;
++ }
++
+ if (D.getVFS().exists("/etc/SuSE-release"))
+ return OpenSUSE;
+
+###
+--- tools/clang/lib/Driver/ToolChains.h 2016-02-16 14:56:48.000000000 -0500
++++ tools/clang/lib/Driver/ToolChains.h 2016-05-08 23:19:20.571431701 -0400
+@@ -615,24 +615,111 @@
+ Tool *buildLinker() const override;
+ };
+
+-class LLVM_LIBRARY_VISIBILITY Solaris : public Generic_GCC {
++class LLVM_LIBRARY_VISIBILITY Solaris : public Generic_ELF {
+ public:
+ Solaris(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args);
+
+- bool IsIntegratedAssemblerDefault() const override { return true; }
++ bool IsIntegratedAssemblerDefault() const override { return !UseGnuAs; }
+
+- void AddClangCXXStdlibIncludeArgs(
+- const llvm::opt::ArgList &DriverArgs,
+- llvm::opt::ArgStringList &CC1Args) const override;
++ std::string computeSysRoot() const;
+
+- unsigned GetDefaultDwarfVersion() const override { return 2; }
++ bool addLibStdCXXIncludePaths(Twine Base, Twine Suffix,
++ StringRef GCCTriple,
++ StringRef GCCMultiarchTriple,
++ StringRef TargetMultiarchTriple,
++ Twine IncludeSuffix,
++ const llvm::opt::ArgList &DriverArgs,
++ llvm::opt::ArgStringList &CC1Args) const;
++
++ void addLibStdCXXIncludePaths(Twine Base, Twine TargetArchDir,
++ const llvm::opt::ArgList &DriverArgs,
++ llvm::opt::ArgStringList &CC1Args) const;
++
++ void AddClangCXXStdlibIncludeArgs(const llvm::opt::ArgList &DriverArgs,
++ llvm::opt::ArgStringList &CC1Args) const override;
++
++ void AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
++ llvm::opt::ArgStringList &CC1Args) const override;
++
++ void addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
++ llvm::opt::ArgStringList &CC1Args) const override;
++
++ void findGCCMajorMinor() const;
++ void findGCCMajorMinorMicro(const llvm::Triple &Triple) const;
++ void findGCCIncludeDirs(const llvm::Triple &Triple,
++ const llvm::opt::ArgList &Args) const;
++ void findGCCInternalLibDir(const llvm::Triple &Triple,
++ const llvm::opt::ArgList &Args) const;
++ void findSpecifiedGCCToolchain(const char *StartingPath,
++ const llvm::Triple &Triple,
++ const llvm::opt::ArgList &Args) const;
++
++ StringRef getAssembler() const { return Assembler.c_str(); }
++ StringRef getLinker() const { return Linker.c_str(); }
++ StringRef getGCCInstallDir() const { return GCCInstallDir.c_str(); }
++ StringRef getGCCMajorMinor() const { return GCCMajorMinor.c_str(); }
++ StringRef getMArch() const { return march.c_str(); }
++ StringRef getMTune() const { return mtune.c_str(); }
++ StringRef getMCpu() const { return mcpu.c_str(); }
++ StringRef getGCCInternalLibDir() const { return GCCInternalLibDir; }
++
++ StringRef getGCCInternalMultiLibDir() const {
++ return GCCInternalMultiLibDir;
++ }
++
++ StringRef getGCCMajorMinorMicro() const {
++ return GCCMajorMinorMicro.c_str();
++ }
++
++ const std::vector<std::string> &getGCCIncludeDirs() const {
++ return GCCIncludeDirs;
++ }
++
++ const std::vector<std::string> &getExtraOpts() const {
++ return ExtraOpts;
++ }
++
++ bool isValid() const { return IsValid; }
++
++ void print(raw_ostream &OS) const;
++
++ unsigned GetDefaultDwarfVersion() const override { return 4; }
+
+ protected:
+ Tool *buildAssembler() const override;
+ Tool *buildLinker() const override;
++ void validate();
++
++private:
++ bool UseGnuAs;
++ bool UseGnuLd;
++ bool UseGoldLd;
++ bool UseSunLd;
++ mutable bool UseMediatedGCCToolChainPath;
++ mutable bool UseSpecifiedGCCToolChainPath;
++ bool IsValid;
++
++protected:
++ mutable std::string GCCInstallDir;
++ mutable std::string GCCMajorMinor;
++ mutable std::string GCCMajorMinorMicro;
++ mutable std::string GCCInternalLibDir;
++ mutable std::string GCCInternalMultiLibDir;
++ mutable std::vector<std::string> GCCIncludeDirs;
++
++ mutable std::string Assembler;
++ mutable std::string Linker;
++ mutable std::string mtune;
++ mutable std::string march;
++ mutable std::string mcpu;
++
++ mutable std::vector<std::string> ExtraOpts;
++ static const char *MediatedGCCToolChainPath;
++ static bool SupportsClangLibCPlusPlus;
+ };
+
++
+ class LLVM_LIBRARY_VISIBILITY MinGW : public ToolChain {
+ public:
+ MinGW(const Driver &D, const llvm::Triple &Triple,
+###
+--- tools/clang/lib/Driver/Tools.cpp 2016-02-12 14:51:41.000000000 -0800
++++ tools/clang/lib/Driver/Tools.cpp 2016-07-18 19:13:48.364415520 -0700
+@@ -43,15 +43,22 @@
+ #include "llvm/Support/raw_ostream.h"
+ #include "llvm/Support/TargetParser.h"
+
+-#ifdef LLVM_ON_UNIX
+-#include <unistd.h> // For getuid().
+-#endif
+-
+ using namespace clang::driver;
+ using namespace clang::driver::tools;
+ using namespace clang;
+ using namespace llvm::opt;
+
++#ifdef LLVM_ON_UNIX
++#include <unistd.h> // For getuid().
++#endif
++
++#include <cstdlib>
++#include <climits>
++
++static std::tuple<llvm::Reloc::Model, unsigned, bool>
++ParsePICArgs(const ToolChain &ToolChain, const llvm::Triple &Triple,
++ const ArgList &Args);
++
+ static void handleTargetFeaturesGroup(const ArgList &Args,
+ std::vector<const char *> &Features,
+ OptSpecifier Group) {
+@@ -74,11 +81,15 @@
+ const llvm::Triple &Triple) {
+ if (Triple.getArch() == llvm::Triple::sparcv9) {
+ return llvm::StringSwitch<const char *>(Name)
++ .Case("v9", "-Av9")
++ .Case("ultrasparc", "-Av9a")
++ .Case("ultrasparc2", "-Av9a")
++ .Case("ultrasparc3", "-Av9b")
+ .Case("niagara", "-Av9b")
+ .Case("niagara2", "-Av9b")
+ .Case("niagara3", "-Av9d")
+ .Case("niagara4", "-Av9d")
+- .Default("-Av9");
++ .Default("-Av9a");
+ } else {
+ return llvm::StringSwitch<const char *>(Name)
+ .Case("v8", "-Av8")
+@@ -89,17 +100,23 @@
+ .Case("sparclite86x", "-Asparclite")
+ .Case("sparclet", "-Asparclet")
+ .Case("tsc701", "-Asparclet")
+- .Case("v9", "-Av8plus")
+- .Case("ultrasparc", "-Av8plus")
+- .Case("ultrasparc3", "-Av8plus")
++ .Case("ultrasparc", "-Av8plusa")
++ .Case("ultrasparc2", "-Av8plusa")
++ .Case("ultrasparc3", "-Av8plusb")
+ .Case("niagara", "-Av8plusb")
+ .Case("niagara2", "-Av8plusb")
+ .Case("niagara3", "-Av8plusd")
+ .Case("niagara4", "-Av8plusd")
+- .Default("-Av8");
++ .Default("-Av8plusa");
+ }
+ }
+
++static void AddLibgcc(const llvm::Triple &Triple, const Driver &D,
++ ArgStringList &CmdArgs, const ArgList &Args);
++
++static void AddLibgcc(const Driver &D, ArgStringList &CmdArgs,
++ const ArgList &Args, const std::string& Exec);
++
+ /// CheckPreprocessingOptions - Perform some validation of preprocessing
+ /// arguments that is shared with gcc.
+ static void CheckPreprocessingOptions(const Driver &D, const ArgList &Args) {
+@@ -266,6 +283,27 @@
+ addDirectoryList(Args, CmdArgs, "-L", "LIBRARY_PATH");
+ }
+
++static void AddAssemblerKPIC(const ToolChain &ToolChain, const ArgList &Args,
++ ArgStringList &CmdArgs) {
++ llvm::Reloc::Model RelocationModel;
++ unsigned PICLevel = 1;
++ bool IsPIE = false;
++
++ std::tie(RelocationModel, PICLevel, IsPIE) =
++ ParsePICArgs(ToolChain, ToolChain.getTriple(), Args);
++
++ if (ToolChain.getTriple().getOS() == llvm::Triple::Solaris) {
++ if ((RelocationModel != llvm::Reloc::Static) &&
++ (RelocationModel != llvm::Reloc::DynamicNoPIC))
++ CmdArgs.push_back("-KPIC");
++
++ return;
++ }
++
++ if (RelocationModel != llvm::Reloc::Static)
++ CmdArgs.push_back("-KPIC");
++}
++
+ /// \brief Determine whether Objective-C automated reference counting is
+ /// enabled.
+ static bool isObjCAutoRefCount(const ArgList &Args) {
+@@ -1601,8 +1639,127 @@
+ }
+ }
+
+-static const char *getX86TargetCPU(const ArgList &Args,
+- const llvm::Triple &Triple) {
++const char *sparc::getSparcTargetCPU(const llvm::opt::ArgList &Args,
++ const llvm::Triple &Triple) {
++ if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) {
++ StringRef AV = A->getValue();
++ if (AV == "native") {
++ std::string CPU = llvm::sys::getHostCPUName().str();
++ if (CPU.find("UltraSPARC-IV") != std::string::npos)
++ return Triple.getArch() == llvm::Triple::sparcv9 ? "v9c" : "v8plusc";
++ else if (CPU.find("UltraSPARC-III") != std::string::npos)
++ return Triple.getArch() == llvm::Triple::sparcv9 ? "v9b" : "v8plusb";
++ else if (CPU.find("UltraSPARC-II") != std::string::npos)
++ return Triple.getArch() == llvm::Triple::sparcv9 ? "v9a" : "v8plusa";
++ else if (CPU.find("UltraSPARC-I") != std::string::npos)
++ return Triple.getArch() == llvm::Triple::sparcv9 ? "v9" : "v8plus";
++ else if (CPU.find("SPARC-T4") != std::string::npos)
++ return Triple.getArch() == llvm::Triple::sparcv9 ? "v9v" : "v8plusv";
++ else if (CPU.find("SPARC-T5") != std::string::npos)
++ return Triple.getArch() == llvm::Triple::sparcv9 ? "v9v" : "v8plusv";
++ else if (CPU.find("SPARC-T6") != std::string::npos)
++ return Triple.getArch() == llvm::Triple::sparcv9 ? "v9v" : "v8plusv";
++ else if (CPU.find("SPARC-T7") != std::string::npos)
++ return Triple.getArch() == llvm::Triple::sparcv9 ? "v9v" : "v8plusv";
++ else if (CPU.find("SPARC-M4") != std::string::npos)
++ return Triple.getArch() == llvm::Triple::sparcv9 ? "v9v" : "v8plusv";
++ else if (CPU.find("SPARC-M5") != std::string::npos)
++ return Triple.getArch() == llvm::Triple::sparcv9 ? "v9m" : "v8plusm";
++ else if (CPU.find("SPARC-M6") != std::string::npos)
++ return Triple.getArch() == llvm::Triple::sparcv9 ? "v9m" : "v8plusm";
++ else if (CPU.find("SPARC-M7") != std::string::npos)
++ return Triple.getArch() == llvm::Triple::sparcv9 ? "v9m" : "v8plusm";
++ } else if (AV == "ultrasparc") {
++ return Triple.getArch() == llvm::Triple::sparcv9 ? "v9a" : "v8plusa";
++ } else if (AV == "ultrasparc2") {
++ return Triple.getArch() == llvm::Triple::sparcv9 ? "v9a" : "v8plusa";
++ } else if (AV == "ultrasparc3") {
++ return Triple.getArch() == llvm::Triple::sparcv9 ? "v9b" : "v8plusb";
++ } else if (AV == "ultrasparc4") {
++ return Triple.getArch() == llvm::Triple::sparcv9 ? "v9c" : "v8plusc";
++ } else if (AV == "niagara") {
++ return Triple.getArch() == llvm::Triple::sparcv9 ? "v9b" : "v8plusb";
++ } else if (AV == "niagara2") {
++ return Triple.getArch() == llvm::Triple::sparcv9 ? "v9b" : "v8plusb";
++ } else if (AV == "niagara3") {
++ return Triple.getArch() == llvm::Triple::sparcv9 ? "v9b" : "v8plusb";
++ } else if (AV == "niagara4") {
++ return Triple.getArch() == llvm::Triple::sparcv9 ? "v9b" : "v8plusb";
++ } else if (AV == "sparc4") {
++ return "sparc4";
++ } else if (AV == "sparc5") {
++ return "sparc5";
++ } else if (AV == "generic") {
++ return Triple.getArch() == llvm::Triple::sparcv9 ? "v9a" : "v8plusa";
++ } else if (AV == "generic32") {
++ return "v8plusa";
++ } else if (AV == "generic64") {
++ return "v9a";
++ }
++ }
++
++ if (const Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) {
++ StringRef AV = A->getValue();
++ if (AV == "native") {
++ std::string CPU = llvm::sys::getHostCPUName().str();
++ if (CPU.find("UltraSPARC-IV") != std::string::npos)
++ return Triple.getArch() == llvm::Triple::sparcv9 ? "v9c" : "v8plusc";
++ else if (CPU.find("UltraSPARC-III") != std::string::npos)
++ return Triple.getArch() == llvm::Triple::sparcv9 ? "v9b" : "v8plusb";
++ else if (CPU.find("UltraSPARC-II") != std::string::npos)
++ return Triple.getArch() == llvm::Triple::sparcv9 ? "v9a" : "v8plusa";
++ else if (CPU.find("UltraSPARC-I") != std::string::npos)
++ return Triple.getArch() == llvm::Triple::sparcv9 ? "v9" : "v8plus";
++ else if (CPU.find("SPARC-T4") != std::string::npos)
++ return Triple.getArch() == llvm::Triple::sparcv9 ? "v9v" : "v8plusv";
++ else if (CPU.find("SPARC-T5") != std::string::npos)
++ return Triple.getArch() == llvm::Triple::sparcv9 ? "v9m" : "v8plusm";
++ else if (CPU.find("SPARC-T6") != std::string::npos)
++ return Triple.getArch() == llvm::Triple::sparcv9 ? "v9m" : "v8plusm";
++ else if (CPU.find("SPARC-T7") != std::string::npos)
++ return Triple.getArch() == llvm::Triple::sparcv9 ? "v9m" : "v8plusm";
++ else if (CPU.find("SPARC-M4") != std::string::npos)
++ return Triple.getArch() == llvm::Triple::sparcv9 ? "v9v" : "v8plusv";
++ else if (CPU.find("SPARC-M5") != std::string::npos)
++ return Triple.getArch() == llvm::Triple::sparcv9 ? "v9m" : "v8plusm";
++ else if (CPU.find("SPARC-M6") != std::string::npos)
++ return Triple.getArch() == llvm::Triple::sparcv9 ? "v9m" : "v8plusm";
++ else if (CPU.find("SPARC-M7") != std::string::npos)
++ return Triple.getArch() == llvm::Triple::sparcv9 ? "v9m" : "v8plusm";
++ } else if (AV == "ultrasparc") {
++ return Triple.getArch() == llvm::Triple::sparcv9 ? "v9a" : "v8plusa";
++ } else if (AV == "ultrasparc2") {
++ return Triple.getArch() == llvm::Triple::sparcv9 ? "v9a" : "v8plusa";
++ } else if (AV == "ultrasparc3") {
++ return Triple.getArch() == llvm::Triple::sparcv9 ? "v9b" : "v8plusb";
++ } else if (AV == "ultrasparc4") {
++ return Triple.getArch() == llvm::Triple::sparcv9 ? "v9c" : "v8plusc";
++ } else if (AV == "niagara") {
++ return Triple.getArch() == llvm::Triple::sparcv9 ? "v9b" : "v8plusb";
++ } else if (AV == "niagara2") {
++ return Triple.getArch() == llvm::Triple::sparcv9 ? "v9b" : "v8plusb";
++ } else if (AV == "niagara3") {
++ return Triple.getArch() == llvm::Triple::sparcv9 ? "v9b" : "v8plusb";
++ } else if (AV == "niagara4") {
++ return Triple.getArch() == llvm::Triple::sparcv9 ? "v9b" : "v8plusb";
++ } else if (AV == "sparc4") {
++ return "sparc4";
++ } else if (AV == "sparc5") {
++ return "sparc5";
++ } else if (AV == "generic") {
++ return Triple.getArch() == llvm::Triple::sparcv9 ? "v9a" : "v8plusa";
++ } else if (AV == "generic32") {
++ return "v8plusa";
++ } else if (AV == "generic64") {
++ return "v9a";
++ }
++ }
++
++ return Triple.getArch() == llvm::Triple::sparcv9 ? "v9a" : "v8plusa";
++}
++
++const char *x86::getX86TargetCPU(const llvm::opt::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")
+@@ -1616,7 +1773,7 @@
+ //
+ // FIXME: We should also incorporate the detected target features for use
+ // with -native.
+- std::string CPU = llvm::sys::getHostCPUName();
++ std::string CPU = llvm::sys::getHostCPUName().str();
+ if (!CPU.empty() && CPU != "generic")
+ return Args.MakeArgString(CPU);
+ }
+@@ -1666,6 +1823,10 @@
+ if (Triple.isAndroid())
+ return Is64Bit ? "x86-64" : "i686";
+
++ // On Solaris return a target compatible with gas.
++ if (Triple.isOSSolaris())
++ return Is64Bit ? "opteron" : "pentium4";
++
+ // Everything else goes to x86-64 in 64-bit mode.
+ if (Is64Bit)
+ return "x86-64";
+@@ -1757,15 +1918,17 @@
+ }
+
+ case llvm::Triple::sparc:
+- case llvm::Triple::sparcel:
+ case llvm::Triple::sparcv9:
++ return sparc::getSparcTargetCPU(Args, T);
++
++ case llvm::Triple::sparcel:
+ if (const Arg *A = Args.getLastArg(options::OPT_mcpu_EQ))
+ return A->getValue();
+ return "";
+
+ case llvm::Triple::x86:
+ case llvm::Triple::x86_64:
+- return getX86TargetCPU(Args, T);
++ return x86::getX86TargetCPU(Args, T);
+
+ case llvm::Triple::hexagon:
+ return "hexagon" +
+@@ -3084,7 +3247,7 @@
+
+ // Fallback to user id.
+ #ifdef LLVM_ON_UNIX
+- std::string UID = llvm::utostr(getuid());
++ std::string UID = std::to_string(static_cast<unsigned int>(getuid()));
+ #else
+ // FIXME: Windows seems to have an 'SID' that might work.
+ std::string UID = "9999";
+@@ -3263,10 +3426,12 @@
+ // ToolChain.getTriple() and Triple?
+ bool PIE = ToolChain.isPIEDefault();
+ bool PIC = PIE || ToolChain.isPICDefault();
++
+ // The Darwin/MachO default to use PIC does not apply when using -static.
+ if (ToolChain.getTriple().isOSBinFormatMachO() &&
+ Args.hasArg(options::OPT_static))
+ PIE = PIC = false;
++
+ bool IsPICLevelTwo = PIC;
+
+ bool KernelOrKext =
+@@ -3320,6 +3485,24 @@
+ }
+ }
+
++ // Solaris-specific defaults for PIE
++ if (ToolChain.getTriple().getOS() == llvm::Triple::Solaris) {
++ switch (ToolChain.getTriple().getArch()) {
++ case llvm::Triple::x86:
++ IsPICLevelTwo = false; // "-fpie"
++ break;
++ case llvm::Triple::sparc:
++ case llvm::Triple::x86_64:
++ case llvm::Triple::sparcv9:
++ IsPICLevelTwo = true; // "-fPIE"
++ break;
++
++ default:
++ break;
++ }
++ }
++
++
+ // The last argument relating to either PIC or PIE wins, and no
+ // other argument is used. If the last argument is any flavor of the
+ // '-fno-...' arguments, both PIC and PIE are disabled. Any PIE
+@@ -3336,8 +3519,8 @@
+ if (O.matches(options::OPT_fPIC) || O.matches(options::OPT_fpic) ||
+ O.matches(options::OPT_fPIE) || O.matches(options::OPT_fpie)) {
+ PIE = O.matches(options::OPT_fPIE) || O.matches(options::OPT_fpie);
+- PIC =
+- PIE || O.matches(options::OPT_fPIC) || O.matches(options::OPT_fpic);
++ PIC = PIE || O.matches(options::OPT_fPIC) ||
++ O.matches(options::OPT_fpic);
+ IsPICLevelTwo =
+ O.matches(options::OPT_fPIE) || O.matches(options::OPT_fPIC);
+ } else {
+@@ -3367,10 +3550,37 @@
+ !Triple.isWatchOS()))
+ PIC = PIE = false;
+
++ if (ToolChain.getTriple().getOS() == llvm::Triple::Solaris) {
++ unsigned PICLevel = IsPICLevelTwo ? 2 : 1;
++ if (Arg *A = Args.getLastArg(options::OPT_shared)) {
++ PIC = true;
++ PIE = false;
++ return std::make_tuple(llvm::Reloc::PIC_, PICLevel, PIE);
++ } else if (PIE) {
++ PIC = PIE = true;
++ return std::make_tuple(llvm::Reloc::PIC_, PICLevel, PIE);
++ } else if (PIC) {
++ PIC = true;
++ PIE = IsPICLevelTwo;
++ return std::make_tuple(llvm::Reloc::PIC_, PICLevel, PIE);
++ } else if (Args.hasArg(options::OPT_static)) {
++ // Solaris doesn't to static relocations.
++ PIC = PIE = false;
++ return std::make_tuple(llvm::Reloc::DynamicNoPIC, PICLevel, PIE);
++ } else {
++ // This is a Solaris non-PIE executable.
++ // Solaris doesn't to static relocations.
++ PIC = PIE = false;
++ PICLevel = 0;
++ return std::make_tuple(llvm::Reloc::DynamicNoPIC, PICLevel, PIE);
++ }
++ }
++
+ if (Arg *A = Args.getLastArg(options::OPT_mdynamic_no_pic)) {
+ // This is a very special mode. It trumps the other modes, almost no one
+ // uses it, and it isn't even valid on any OS but Darwin.
+- if (!ToolChain.getTriple().isOSDarwin())
++ if (!ToolChain.getTriple().isOSDarwin() &&
++ !ToolChain.getTriple().isOSSolaris())
+ ToolChain.getDriver().Diag(diag::err_drv_unsupported_opt_for_target)
+ << A->getSpelling() << ToolChain.getTriple().str();
+
+@@ -3404,18 +3614,6 @@
+ llvm_unreachable("Unknown Reloc::Model kind");
+ }
+
+-static void AddAssemblerKPIC(const ToolChain &ToolChain, const ArgList &Args,
+- ArgStringList &CmdArgs) {
+- llvm::Reloc::Model RelocationModel;
+- unsigned PICLevel;
+- bool IsPIE;
+- std::tie(RelocationModel, PICLevel, IsPIE) =
+- ParsePICArgs(ToolChain, ToolChain.getTriple(), Args);
+-
+- if (RelocationModel != llvm::Reloc::Static)
+- CmdArgs.push_back("-KPIC");
+-}
+-
+ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output, const InputInfoList &Inputs,
+ const ArgList &Args, const char *LinkingOutput) const {
+@@ -3713,6 +3911,14 @@
+ CmdArgs.push_back(A->getValue());
+ }
+
++ if (Arg *A = Args.getLastArg(options::OPT_fabi_version_EQ)) {
++ StringRef V = A->getValue();
++ CmdArgs.push_back(Args.MakeArgString("-fabi-version=" + V));
++ A->claim();
++ } else {
++ CmdArgs.push_back(Args.MakeArgString("-fabi-version=4"));
++ }
++
+ if (Arg *A = Args.getLastArg(options::OPT_fpcc_struct_return,
+ options::OPT_freg_struct_return)) {
+ if (getToolChain().getArch() != llvm::Triple::x86) {
+@@ -4522,6 +4728,7 @@
+ // If -fmessage-length=N was not specified, determine whether this is a
+ // terminal and, if so, implicitly define -fmessage-length appropriately.
+ unsigned N = llvm::sys::Process::StandardErrColumns();
++ if (N == 0U) N = 72U;
+ CmdArgs.push_back(Args.MakeArgString(Twine(N)));
+ }
+
+@@ -4707,6 +4914,10 @@
+ if (Args.hasArg(options::OPT_mstack_alignment)) {
+ StringRef alignment = Args.getLastArgValue(options::OPT_mstack_alignment);
+ CmdArgs.push_back(Args.MakeArgString("-mstack-alignment=" + alignment));
++ } else {
++ if ((getToolChain().getArch() == llvm::Triple::sparc) ||
++ (getToolChain().getArch() == llvm::Triple::sparcv9))
++ CmdArgs.push_back("-mstack-alignment=16");
+ }
+
+ if (Args.hasArg(options::OPT_mstack_probe_size)) {
+@@ -4963,16 +5174,16 @@
+ }
+
+ // -fuse-cxa-atexit is default.
+- if (!Args.hasFlag(
++ if ((!Args.hasFlag(
+ options::OPT_fuse_cxa_atexit, options::OPT_fno_use_cxa_atexit,
+ !IsWindowsCygnus && !IsWindowsGNU &&
+- getToolChain().getTriple().getOS() != llvm::Triple::Solaris &&
+ getToolChain().getArch() != llvm::Triple::hexagon &&
+ getToolChain().getArch() != llvm::Triple::xcore &&
+ ((getToolChain().getTriple().getVendor() !=
+ llvm::Triple::MipsTechnologies) ||
+ getToolChain().getTriple().hasEnvironment())) ||
+- KernelOrKext)
++ KernelOrKext) &&
++ !getToolChain().getTriple().getOS() == llvm::Triple::Solaris)
+ CmdArgs.push_back("-fno-use-cxa-atexit");
+
+ // -fms-extensions=0 is default.
+@@ -5425,8 +5636,10 @@
+ // nice to enable this when doing a crashdump for modules as well.
+ if (Args.hasFlag(options::OPT_frewrite_includes,
+ options::OPT_fno_rewrite_includes, false) ||
+- (C.isForDiagnostics() && !HaveModules))
++ (C.isForDiagnostics() && !HaveModules)) {
++ if (getToolChain().getTriple().getOS() != llvm::Triple::Solaris)
+ CmdArgs.push_back("-frewrite-includes");
++ }
+
+ // Only allow -traditional or -traditional-cpp outside in preprocessing modes.
+ if (Arg *A = Args.getLastArg(options::OPT_traditional,
+@@ -6155,7 +6368,10 @@
+ CmdArgs.push_back("-fsyntax-only");
+ }
+
+- Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
++ Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,
++ options::OPT_Xassembler);
++ Args.ClaimAllArgs(options::OPT_Wa_COMMA);
++ Args.ClaimAllArgs(options::OPT_Xassembler);
+
+ // Only pass -x if gcc will understand it; otherwise hope gcc
+ // understands the suffix correctly. The main use case this would go
+@@ -7383,44 +7599,362 @@
+ claimNoWarnArgs(Args);
+ ArgStringList CmdArgs;
+
+- Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
++ const toolchains::Solaris &TC =
++ static_cast<const toolchains::Solaris&>(getToolChain());
++
++ if (!TC.isValid()) {
++ llvm::errs() << "Invalid GCC installation!\n";
++ return;
++ }
+
++ std::string EffectiveTriple = TC.ComputeLLVMTriple(Args, types::ID(0));
++ llvm::Triple ET(EffectiveTriple);
++
++ const Driver &D = TC.getDriver();
++ llvm::Triple::ArchType Arch = ET.getArch();
++ StringRef AS = TC.getAssembler();
++ bool m32 = !!Args.getLastArg(options::OPT_m32);
++
++ std::string march;
++ std::string mtune;
++ std::string mcpu;
++
++ if (Arg *A = Args.getLastArg(options::OPT_march_EQ))
++ march = A->getValue();
++ else
++ march = TC.getMArch();
++
++ if (Arg *A = Args.getLastArg(options::OPT_mtune_EQ))
++ mtune = A->getValue();
++ else
++ mtune = TC.getMTune();
++
++ if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ))
++ mcpu = A->getValue();
++ else
++ mcpu = TC.getMCpu();
++
++ if (Args.hasArg(options::OPT_v))
++ CmdArgs.push_back("-V");
++
++ switch (Arch) {
++ case llvm::Triple::x86:
++ case llvm::Triple::x86_64:
++ if (m32)
++ CmdArgs.push_back("--32");
++ else
++ CmdArgs.push_back("--64");
++ break;
++ case llvm::Triple::sparc:
++ case llvm::Triple::sparcv9:
++ if (m32) {
++ CmdArgs.push_back("-32");
++ if (march.empty())
++ march="v8plusa";
++ if (mcpu.empty())
++ mcpu="v8plusa";
++ } else {
++ CmdArgs.push_back("-64");
++ if (march.empty())
++ march="v9a";
++ if (mcpu.empty())
++ mcpu="v9a";
++ }
++ break;
++ default:
++ D.Diag(diag::err_target_unsupported_arch) << ET.getArchName()
++ << ET.getTriple();
++ break;
++ }
++
++ std::string xarch;
++
++ switch (Arch) {
++ case llvm::Triple::sparc:
++ case llvm::Triple::sparcv9:
++ xarch = "-xarch=";
++ xarch += clang::driver::tools::sparc::getSparcTargetCPU(Args, ET);
++ CmdArgs.push_back(Args.MakeArgString(xarch.c_str()));
++ AddAssemblerKPIC(TC, Args, CmdArgs);
++ CmdArgs.push_back("-no-undeclared-regs");
++ if (Args.hasArg(options::OPT_mstrict_align))
++ CmdArgs.push_back("--enforce-aligned-data");
++ break;
++ case llvm::Triple::x86:
++ case llvm::Triple::x86_64:
++ xarch = "-march=";
++ xarch += clang::driver::tools::x86::getX86TargetCPU(Args, ET);
++ CmdArgs.push_back(Args.MakeArgString(xarch.c_str()));
++ break;
++ default:
++ D.Diag(diag::err_target_unsupported_arch) << ET.getArchName()
++ << ET.getTriple();
++ break;
++ }
++
++ if (Args.hasArg(options::OPT_g_Flag) || Args.hasArg(options::OPT_g0) ||
++ Args.hasArg(options::OPT_g1) || Args.hasArg(options::OPT_g2) ||
++ Args.hasArg(options::OPT_g3))
++ CmdArgs.push_back("--gen-debug");
++
++ if (Output.isFilename()) {
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back(Output.getFilename());
++ } else {
++ D.Diag(diag::err_drv_invalid_gcc_output_type) << "<unspecified>";
++ CmdArgs.push_back("-fsyntax-only");
++ }
+
+- for (const auto &II : Inputs)
++ Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,
++ options::OPT_Xassembler);
++
++ for (const auto &II : Inputs) {
++ if (II.isFilename())
+ CmdArgs.push_back(II.getFilename());
++ else
++ II.getInputArg().render(Args, CmdArgs);
++ }
+
+- const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as"));
++ const char *Exec = AS.data();
+ C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
+ }
+
++void
++solaris::Assembler::RenderExtraToolArgs(const JobAction &JA,
++ llvm::opt::ArgStringList &CmdArgs) const {
++ // FIXME: IMPLEMENT
++}
++
++bool solaris::Linker::checkGnuLd(StringRef Path) const {
++ if (Path.empty()) return false;
++
++ char Buf[_POSIX_PATH_MAX+1];
++ std::string CMD = Path.str();
++ CMD += " -v 2>&1";
++
++ std::FILE *FP = ::popen(CMD.c_str(), "r");
++ if (!FP) return false;
++
++ (void) std::memset(Buf, 0, sizeof(Buf));
++ (void) std::fgets(Buf, _POSIX_PATH_MAX, FP);
++ ::pclose(FP);
++
++ return !!std::strstr(Buf, "GNU");
++}
++
+ void solaris::Linker::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
++ const toolchains::Solaris& TC =
++ static_cast<const toolchains::Solaris&>(getToolChain());
++
++ if (!TC.isValid()) {
++ llvm::errs() << "Invalid GCC installation!\n";
++ return;
++ }
++
++ llvm::Triple TT = TC.getTriple();
++ std::string EffectiveTriple = TC.ComputeLLVMTriple(Args, types::ID(0));
++ llvm::Triple ET(EffectiveTriple);
++
++ const Driver &D = TC.getDriver();
++ llvm::Triple::ArchType Arch = TT.getArch();
++ bool m32 = !!Args.getLastArg(options::OPT_m32);
++
++ StringRef LD = TC.getLinker();
++ bool UseGnuLd = checkGnuLd(LD);
++
++ std::string GCCLibPath;
++ std::string YPPath;
++ GCCLibPath += "/lib/gcc/";
++ std::string LibPath = "/usr/lib/";
++ std::string ShortLibPath = "/lib/";
++ std::string ClangLibPath;
++ const char* moption;
++ std::string gldm;
++
++ if (UseGnuLd) {
++ switch (Arch) {
++ case llvm::Triple::x86:
++ if (m32)
++ gldm = "elf_i386_sol2";
++ else
++ gldm = "elf_x86_64_sol2";
++ break;
++ case llvm::Triple::x86_64:
++ if (m32)
++ gldm = "elf_i386_sol2";
++ else
++ gldm = "elf_x86_64_sol2";
++ break;
++ case llvm::Triple::sparc:
++ if (m32)
++ gldm = "elf32_sparc_sol2";
++ else
++ gldm = "elf64_sparc_sol2";
++ break;
++ case llvm::Triple::sparcv9:
++ if (m32)
++ gldm = "elf32_sparc_sol2";
++ else
++ gldm = "elf64_sparc_sol2";
++ break;
++ default:
++ break;
++ }
++ }
++
++ switch (Arch) {
++ case llvm::Triple::x86:
++ if (m32) {
++ GCCLibPath = TC.getGCCInternalLibDir().str();
++ GCCLibPath += "/";
++ moption = "-32";
++ YPPath = "/lib:/usr/lib";
++ ClangLibPath = "/usr/lib/clang/";
++ } else {
++ GCCLibPath = TC.getGCCInternalMultiLibDir().str();
++ GCCLibPath += "/";
++ LibPath += "amd64/";
++ ShortLibPath += "amd64/";
++ moption = "-64";
++ YPPath = "/lib/amd64:/usr/lib/amd64";
++ ClangLibPath = "/usr/lib/amd64/clang/";
++ }
++ break;
++ case llvm::Triple::sparc:
++ if (m32) {
++ GCCLibPath = TC.getGCCInternalLibDir().str();
++ GCCLibPath += "/";
++ moption = "-32";
++ YPPath = "/lib:/usr/lib";
++ ClangLibPath = "/usr/lib/clang/";
++ } else {
++ GCCLibPath = TC.getGCCInternalMultiLibDir().str();
++ GCCLibPath += "/";
++ LibPath += "sparcv9/";
++ ShortLibPath += "sparcv9/";
++ moption = "-64";
++ YPPath = "/lib/sparcv9:/usr/lib/sparcv9";
++ ClangLibPath = "/usr/lib/sparcv9/clang/";
++ }
++ break;
++ case llvm::Triple::x86_64:
++ if (m32) {
++ GCCLibPath = TC.getGCCInternalMultiLibDir().str();
++ GCCLibPath += "/";
++ moption = "-32";
++ YPPath = "/lib:/usr/lib";
++ ClangLibPath = "/usr/lib/clang/";
++ } else {
++ GCCLibPath = TC.getGCCInternalLibDir().str();
++ GCCLibPath += "/";
++ LibPath += "amd64/";
++ ShortLibPath += "amd64/";
++ moption = "-64";
++ YPPath = "/lib/amd64:/usr/lib/amd64";
++ ClangLibPath = "/usr/lib/amd64/clang/";
++ }
++ break;
++ case llvm::Triple::sparcv9:
++ if (m32) {
++ GCCLibPath = TC.getGCCInternalMultiLibDir().str();
++ GCCLibPath += "/";
++ moption = "-32";
++ YPPath = "/lib:/usr/lib";
++ ClangLibPath = "/usr/lib/clang/";
++ } else {
++ GCCLibPath = TC.getGCCInternalLibDir().str();
++ GCCLibPath += "/";
++ LibPath += "sparcv9/";
++ ShortLibPath += "sparcv9/";
++ moption = "-64";
++ YPPath = "/lib/sparcv9:/usr/lib/sparcv9";
++ ClangLibPath = "/usr/lib/sparcv9/clang/";
++ }
++ break;
++ default:
++ D.Diag(diag::err_target_unsupported_arch) << ET.getArchName()
++ << ET.getTriple();
++ break;
++ }
++
+ ArgStringList CmdArgs;
+
+- // Demangle C++ names in errors
+- CmdArgs.push_back("-C");
++ // THe -m flag to GNU ld is positional dependent.
++ // Do not change this ordering of options for the GNU ld.
++ if (!gldm.empty()) {
++ CmdArgs.push_back(Args.MakeArgString("-m"));
++ CmdArgs.push_back(Args.MakeArgString(gldm.c_str()));
++ }
+
+- if (!Args.hasArg(options::OPT_nostdlib, options::OPT_shared)) {
+- CmdArgs.push_back("-e");
+- CmdArgs.push_back("_start");
++ if (UseGnuLd) {
++ if (Args.hasArg(options::OPT_v))
++ CmdArgs.push_back(Args.MakeArgString("-v"));
++ CmdArgs.push_back(Args.MakeArgString("--as-needed"));
++ } else {
++ if (D.CCCIsCXX())
++ CmdArgs.push_back(Args.MakeArgString("-zrelax=comdat"));
+ }
+
++ Arg *PIEArg = Args.getLastArg(options::OPT_fPIE, options::OPT_fpie);
++ if (PIEArg) {
++ if (PIEArg->getOption().matches(options::OPT_fPIE) ||
++ PIEArg->getOption().matches(options::OPT_fpie)) {
++ CmdArgs.push_back(Args.MakeArgString("-Qy"));
++
++ if (UseGnuLd) {
++ CmdArgs.push_back(Args.MakeArgString("--pic-executable"));
++ } else {
++ CmdArgs.push_back(Args.MakeArgString("-zdirect"));
++ CmdArgs.push_back(Args.MakeArgString("-ztextwarn"));
++ CmdArgs.push_back(Args.MakeArgString("-ztype=pie"));
++ CmdArgs.push_back(Args.MakeArgString("-zaslr=enable"));
++ }
++ }
++ }
++
++ // Silence 'argument not used during compilation: -g' warning.
++ Args.ClaimAllArgs(options::OPT_g_Group);
++
++ // Silence 'argument unused during compilation: -pthread' warning.
++ Args.ClaimAllArgs(options::OPT_pthread);
++
++ // Language options
++ Args.ClaimAllArgs(options::OPT_emit_llvm);
++ Args.ClaimAllArgs(options::OPT_w);
++
++ if (Args.hasArg(options::OPT_s))
++ CmdArgs.push_back("-s");
++
++ const std::vector<std::string> &ExtraOpts = TC.getExtraOpts();
++
++ // Handle extra options
++ if (ExtraOpts.size()) {
++ for (std::vector<std::string>::const_iterator I = ExtraOpts.begin(),
++ E = ExtraOpts.end(); I != E; ++I)
++ CmdArgs.push_back((*I).c_str());
++ }
++
++ // Demangle C++ names
++ if (UseGnuLd)
++ CmdArgs.push_back("--demangle");
++ else
++ CmdArgs.push_back("-C");
++
+ if (Args.hasArg(options::OPT_static)) {
+ CmdArgs.push_back("-Bstatic");
+ CmdArgs.push_back("-dn");
+ } else {
+ CmdArgs.push_back("-Bdynamic");
++ CmdArgs.push_back("-dy");
+ if (Args.hasArg(options::OPT_shared)) {
+ CmdArgs.push_back("-shared");
+ } else {
+ CmdArgs.push_back("--dynamic-linker");
+- CmdArgs.push_back(
+- Args.MakeArgString(getToolChain().GetFilePath("ld.so.1")));
++ CmdArgs.push_back(Args.MakeArgString(LibPath + "ld.so.1"));
+ }
+ }
+
+@@ -7431,48 +7965,264 @@
+ assert(Output.isNothing() && "Invalid output.");
+ }
+
+- if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
+- if (!Args.hasArg(options::OPT_shared))
+- CmdArgs.push_back(
+- Args.MakeArgString(getToolChain().GetFilePath("crt1.o")));
++ const char* Values = "values-Xa.o";
++ const char* Xpg = "values-xpg4.o";
+
+- CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath("crti.o")));
+- CmdArgs.push_back(
+- Args.MakeArgString(getToolChain().GetFilePath("values-Xa.o")));
+- CmdArgs.push_back(
+- Args.MakeArgString(getToolChain().GetFilePath("crtbegin.o")));
++ Arg *STDArg = Args.getLastArg(options::OPT_std_EQ);
++ if (STDArg) {
++ if (STDArg->getOption().matches(options::OPT_std_EQ)) {
++ std::string Lang = STDArg->getValue();
++ if ((Lang == "c99") || (Lang == "c11") ||
++ (Lang == "c++11") || (Lang == "c++14")) {
++ Values = "values-Xc.o";
++ Xpg = "values-xpg6.o";
++ }
++ }
+ }
+
+- getToolChain().AddFilePathLibArgs(Args, CmdArgs);
++ if (UseGnuLd) {
++ if (LD == "/usr/gnu/bin/ld.gold") {
++ if (Args.hasArg(options::OPT_O))
++ Args.AddAllArgs(CmdArgs, options::OPT_O);
++ } else
++ CmdArgs.push_back(Args.MakeArgString("-O"));
++ }
+
+- Args.AddAllArgs(CmdArgs, {options::OPT_L, options::OPT_T_Group,
+- options::OPT_e, options::OPT_r});
++ if (Args.hasArg(options::OPT_v))
++ CmdArgs.push_back(Args.MakeArgString(StringRef("-V")));
+
+- AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);
++ CmdArgs.push_back(Args.MakeArgString(StringRef("-Qy")));
+
+- if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
+- if (getToolChain().getDriver().CCCIsCXX())
+- getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
+- CmdArgs.push_back("-lgcc_s");
+- CmdArgs.push_back("-lc");
++ if (LD == "/usr/bin/ld") {
++ CmdArgs.push_back(Args.MakeArgString(StringRef("-Y")));
++ CmdArgs.push_back(Args.MakeArgString(StringRef("P," + YPPath)));
++ } else {
++ CmdArgs.push_back(Args.MakeArgString(StringRef("-Y")));
++ CmdArgs.push_back(Args.MakeArgString(StringRef(YPPath)));
++ }
++
++ CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + LibPath));
++
++ std::string P = GCCLibPath;
++ P += "../../..";
++ CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + P));
++
++ std::string crt1o;
++ bool S12OrHigher = false;
++
++ // We're not backporting this to S10. Until we do, that is.
++ if (EffectiveTriple.find("solaris2.11") == std::string::npos)
++ S12OrHigher = true;
++
++ if (!Args.hasArg(options::OPT_nostdlib) &&
++ !Args.hasArg(options::OPT_nostartfiles)) {
+ if (!Args.hasArg(options::OPT_shared)) {
+- CmdArgs.push_back("-lgcc");
++ switch (Arch) {
++ case llvm::Triple::sparc:
++ case llvm::Triple::sparcv9:
++ if (S12OrHigher)
++ crt1o = LibPath;
++ else
++ crt1o = GCCLibPath;
++ case llvm::Triple::x86:
++ case llvm::Triple::x86_64:
++ crt1o = LibPath;
++ break;
++ default:
++ D.Diag(diag::err_target_unsupported_arch) << ET.getArchName()
++ << ET.getTriple();
++ break;
++ }
++
++ crt1o += "/crt1.o";
++
++ CmdArgs.push_back(Args.MakeArgString(crt1o.c_str()));
++ CmdArgs.push_back(Args.MakeArgString(LibPath + "crti.o"));
++ CmdArgs.push_back(Args.MakeArgString(LibPath + Values));
++ CmdArgs.push_back(Args.MakeArgString(LibPath + Xpg));
++ CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + GCCLibPath));
++ CmdArgs.push_back(Args.MakeArgString("-L" + P));
++ CmdArgs.push_back(Args.MakeArgString(GCCLibPath + "crtbegin.o"));
++ } else {
++ CmdArgs.push_back(Args.MakeArgString(LibPath + "crti.o"));
++ CmdArgs.push_back(Args.MakeArgString(LibPath + Values));
++ CmdArgs.push_back(Args.MakeArgString(LibPath + Xpg));
++ CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + GCCLibPath));
++ CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + P));
++ CmdArgs.push_back(Args.MakeArgString(GCCLibPath + "crtbegin.o"));
++ }
++ } else if (Args.hasArg(options::OPT_nostdlib) &&
++ !Args.hasArg(options::OPT_nostartfiles)) {
++ if (Args.hasArg(options::OPT_shared)) {
++ CmdArgs.push_back(Args.MakeArgString(LibPath + "crti.o"));
++ CmdArgs.push_back(Args.MakeArgString(LibPath + Values));
++ CmdArgs.push_back(Args.MakeArgString(LibPath + Xpg));
++ CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + GCCLibPath));
++ CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + P));
++ CmdArgs.push_back(Args.MakeArgString(GCCLibPath + "crtbegin.o"));
++ } else {
++ CmdArgs.push_back(Args.MakeArgString(crt1o.c_str()));
++ CmdArgs.push_back(Args.MakeArgString(LibPath + "crti.o"));
++ CmdArgs.push_back(Args.MakeArgString(LibPath + Values));
++ CmdArgs.push_back(Args.MakeArgString(LibPath + Xpg));
++ CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + GCCLibPath));
++ CmdArgs.push_back(Args.MakeArgString("-L" + P));
++ }
++ } else if (!Args.hasArg(options::OPT_nostdlib) &&
++ Args.hasArg(options::OPT_nostartfiles)) {
++ if (Args.hasArg(options::OPT_shared)) {
++ CmdArgs.push_back(Args.MakeArgString(GCCLibPath + "crtend.o"));
++ }
++ }
++
++ // Itanium C++ ABI.
++ std::string CXAFinalize;
++ bool HasSystemCXAFinalize = !S12OrHigher;
++
++ if (!Args.hasArg(options::OPT_shared)) {
++ if (PIEArg) {
++ if (PIEArg->getOption().matches(options::OPT_fPIE) ||
++ PIEArg->getOption().matches(options::OPT_fpie)) {
++ CXAFinalize = ClangLibPath + "cxa_finalize_pic.o";
++ }
++ } else {
++ CXAFinalize = ClangLibPath + "cxa_finalize.o";
++ }
++
++ HasSystemCXAFinalize = llvm::sys::fs::exists(CXAFinalize.c_str());
++
++ if (D.CCCIsCXX() && HasSystemCXAFinalize)
++ CmdArgs.push_back(Args.MakeArgString(CXAFinalize.c_str()));
++ }
++
++ CmdArgs.push_back(Args.MakeArgString(StringRef("-L" + GCCLibPath)));
++ CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + LibPath));
++ CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + ShortLibPath));
++
++ Args.AddAllArgs(CmdArgs, options::OPT_L);
++ const ToolChain::path_list Paths = TC.getFilePaths();
++ for (ToolChain::path_list::const_iterator B = Paths.begin(), E = Paths.end();
++ B != E; ++B) {
++ CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + *B));
++
++ // Itanium C++ ABI.
++ if (!Args.hasArg(options::OPT_shared)) {
++ if (D.CCCIsCXX() && !HasSystemCXAFinalize) {
++ if (PIEArg) {
++ if (PIEArg->getOption().matches(options::OPT_fPIE) ||
++ PIEArg->getOption().matches(options::OPT_fpie)) {
++ CXAFinalize = *B + "/cxa_finalize_pic.o";
++ }
++ } else {
++ CXAFinalize = *B + "/cxa_finalize.o";
++ }
++
++ if (llvm::sys::fs::exists(CXAFinalize.c_str()))
++ CmdArgs.push_back(Args.MakeArgString(CXAFinalize.c_str()));
++ }
++ }
++ }
++
++ Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
++ Args.AddAllArgs(CmdArgs, options::OPT_e);
++ Args.AddAllArgs(CmdArgs, options::OPT_s);
++ Args.AddAllArgs(CmdArgs, options::OPT_t);
++ Args.AddAllArgs(CmdArgs, options::OPT_r);
++
++ std::vector<std::string> zoptions = Args.getAllArgValues(options::OPT_z);
++ std::string zoption;
++
++ for (std::vector<std::string>::const_iterator B = zoptions.begin(),
++ E = zoptions.end(); B != E; ++B) {
++ zoption = "-z";
++ zoption += *B;
++ CmdArgs.push_back(Args.MakeArgString(StringRef(zoption)));
++ }
++
++ if (!Args.hasArg(options::OPT_mimpure_text) &&
++ !Args.hasArg(options::OPT_fpie) &&
++ !Args.hasArg(options::OPT_fPIE))
++ CmdArgs.push_back(Args.MakeArgString(StringRef("-ztext")));
++
++ // Itanium C++ ABI.
++ if (D.CCCIsCXX()) {
++ if (!Args.hasArg(options::OPT_shared)) {
++ if (HasSystemCXAFinalize) {
++ const char* zfiniarray = "-zfiniarray=__cxa_finalize";
++ CmdArgs.push_back(Args.MakeArgString(zfiniarray));
++ }
++ }
++ }
++
++ if (LD == "/usr/gnu/bin/ld.gold") {
++ CmdArgs.push_back("-plugin");
++ std::string Plugin = D.Dir + "/../lib/LLVMgold.so";
++ CmdArgs.push_back(Args.MakeArgString(Plugin));
++ }
++
++ if (!UseGnuLd) {
++ CmdArgs.push_back(moption);
++ }
++
++ if (Arg *A = Args.getLastArg(options::OPT_rpath)) {
++ StringRef V = A->getValue();
++ if (UseGnuLd) {
++ CmdArgs.push_back(Args.MakeArgString("-rpath"));
++ CmdArgs.push_back(Args.MakeArgString(V));
++ } else {
++ CmdArgs.push_back(Args.MakeArgString("-R"));
++ CmdArgs.push_back(Args.MakeArgString(V));
++ }
++ }
++
++ AddLinkerInputs(TC, Inputs, Args, CmdArgs);
++ AddLibgcc(D, CmdArgs, Args, LD.str());
++
++ if (!Args.hasArg(options::OPT_nostdlib) &&
++ !Args.hasArg(options::OPT_nodefaultlibs)) {
++ addOpenMPRuntime(CmdArgs, TC, Args);
++
++ if (D.CCCIsCXX())
++ TC.AddCXXStdlibLibArgs(Args, CmdArgs);
++
++ CmdArgs.push_back("-lc");
+ CmdArgs.push_back("-lm");
++ CmdArgs.push_back("-lgcc_s");
++
++ if (Args.hasArg(options::OPT_static)) {
++ CmdArgs.push_back("-lgcc");
++ CmdArgs.push_back("-lgcc_eh");
+ }
++ } else if (Args.hasArg(options::OPT_nostdlib) &&
++ (!Args.hasArg(options::OPT_nodefaultlibs))) {
++ CmdArgs.push_back("-lgcc_s");
++
++ if (Args.hasArg(options::OPT_static))
++ CmdArgs.push_back("-lgcc_eh");
+ }
+
+- if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
+- CmdArgs.push_back(
+- Args.MakeArgString(getToolChain().GetFilePath("crtend.o")));
++ if (!Args.hasArg(options::OPT_nostdlib) &&
++ !Args.hasArg(options::OPT_nostartfiles)) {
++ CmdArgs.push_back(Args.MakeArgString(GCCLibPath + "crtend.o"));
+ }
+- CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath("crtn.o")));
+
+- getToolChain().addProfileRTLibs(Args, CmdArgs);
++ CmdArgs.push_back(Args.MakeArgString(LibPath + "crtn.o"));
+
+- const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath());
++ TC.addProfileRTLibs(Args, CmdArgs);
++
++ Args.ClaimAllArgs(options::OPT_Wl_COMMA);
++ Args.ClaimAllArgs(options::OPT_Xlinker);
++
++ const char *Exec = LD.data();
+ C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
+ }
+
++void
++solaris::Linker::RenderExtraToolArgs(const JobAction &JA,
++ llvm::opt::ArgStringList &CmdArgs) const {
++ // FIXME: IMPLEMENT
++}
++
+ void openbsd::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+@@ -8623,6 +9373,41 @@
+ CmdArgs.push_back("-ldl");
+ }
+
++static void AddLibgcc(const Driver &D, ArgStringList &CmdArgs,
++ const ArgList &Args, const std::string& Exec) {
++ bool StaticLibgcc = Args.hasArg(options::OPT_static) ||
++ Args.hasArg(options::OPT_static_libgcc);
++ if (!D.CCCIsCXX())
++ CmdArgs.push_back("-lgcc");
++
++ if (StaticLibgcc) {
++ if (D.CCCIsCXX())
++ CmdArgs.push_back("-lgcc");
++ } else {
++ if ((!D.CCCIsCXX()) && ((Exec == "/usr/bin/gld") ||
++ (Exec == "/usr/gnu/bin/ld") ||
++ (Exec == "/usr/gnu/bin/ld.bfd") ||
++ (Exec == "/usr/gnu/bin/ld.gold")))
++ CmdArgs.push_back("--as-needed");
++
++ CmdArgs.push_back("-lgcc_s");
++ if ((!D.CCCIsCXX()) && ((Exec == "/usr/bin/gld") ||
++ (Exec == "/usr/gnu/bin/ld") ||
++ (Exec == "/usr/gnu/bin/ld.bfd") ||
++ (Exec == "/usr/gnu/bin/ld.gold")))
++ CmdArgs.push_back("--no-as-needed");
++ }
++
++ if (StaticLibgcc)
++ CmdArgs.push_back("-lgcc_eh");
++ else if (!Args.hasArg(options::OPT_shared) && D.CCCIsCXX())
++ CmdArgs.push_back("-lgcc");
++
++ if (!StaticLibgcc)
++ CmdArgs.push_back("-ldl");
++}
++
++
+ static std::string getLinuxDynamicLinker(const ArgList &Args,
+ const toolchains::Linux &ToolChain) {
+ const llvm::Triple::ArchType Arch = ToolChain.getArch();
+###
+--- tools/clang/lib/Driver/Tools.h 2016-01-08 06:14:31.000000000 -0900
++++ tools/clang/lib/Driver/Tools.h 2016-07-04 11:21:03.646553390 -0800
+@@ -17,6 +17,8 @@
+ #include "clang/Frontend/CodeGenOptions.h"
+ #include "llvm/ADT/Triple.h"
+ #include "llvm/Option/Option.h"
++#include "llvm/Option/Arg.h"
++#include "llvm/Option/ArgList.h"
+ #include "llvm/Support/Compiler.h"
+
+ namespace clang {
+@@ -38,9 +40,10 @@
+
+ using llvm::opt::ArgStringList;
+
+-SmallString<128> getCompilerRT(const ToolChain &TC,
++SmallString<PATH_MAX> getCompilerRT(const ToolChain &TC,
+ const llvm::opt::ArgList &Args,
+- StringRef Component, bool Shared = false);
++ StringRef Component,
++ bool Shared = false);
+
+ /// \brief Clang compiler tool.
+ class LLVM_LIBRARY_VISIBILITY Clang : public Tool {
+@@ -308,6 +311,16 @@
+ bool hasPPCAbiArg(const llvm::opt::ArgList &Args, const char *Value);
+ } // end namespace ppc
+
++namespace sparc {
++ const char *getSparcTargetCPU(const llvm::opt::ArgList &Args,
++ const llvm::Triple &Triple);
++} // end namespace sparc
++
++namespace x86 {
++ const char *getX86TargetCPU(const llvm::opt::ArgList &Args,
++ const llvm::Triple &Triple);
++} // end namespace x86
++
+ /// cloudabi -- Directly call GNU Binutils linker
+ namespace cloudabi {
+ class LLVM_LIBRARY_VISIBILITY Linker : public GnuTool {
+@@ -622,25 +635,32 @@
+
+ /// solaris -- Directly call Solaris assembler and linker
+ namespace solaris {
+-class LLVM_LIBRARY_VISIBILITY Assembler : public Tool {
++class LLVM_LIBRARY_VISIBILITY Assembler : public GnuTool {
+ public:
+ Assembler(const ToolChain &TC)
+- : Tool("solaris::Assembler", "assembler", TC) {}
++ : GnuTool("solaris::Assembler", "assembler", TC) {}
+
+ bool hasIntegratedCPP() const override { return false; }
+
++ virtual void RenderExtraToolArgs(const JobAction &JA,
++ llvm::opt::ArgStringList &CmdArgs) const;
++
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+ };
+
+-class LLVM_LIBRARY_VISIBILITY Linker : public Tool {
++class LLVM_LIBRARY_VISIBILITY Linker : public GnuTool {
+ public:
+- Linker(const ToolChain &TC) : Tool("solaris::Linker", "linker", TC) {}
++ Linker(const ToolChain &TC)
++ : GnuTool("solaris::Linker", "linker", TC) {}
+
+ bool hasIntegratedCPP() const override { return false; }
+ bool isLinkJob() const override { return true; }
++ bool checkGnuLd(StringRef Path) const;
++ virtual void RenderExtraToolArgs(const JobAction &JA,
++ llvm::opt::ArgStringList &CmdArgs) const;
+
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output, const InputInfoList &Inputs,
+###
+--- tools/clang/lib/Driver/ToolChain.cpp 2015-11-25 16:02:07.000000000 -0900
++++ tools/clang/lib/Driver/ToolChain.cpp 2016-06-30 20:26:09.406980255 -0800
+@@ -408,6 +408,34 @@
+
+ std::string ToolChain::ComputeLLVMTriple(const ArgList &Args,
+ types::ID InputType) const {
++ llvm::Triple T = getTriple();
++ if (T.isOSSolaris()) {
++ if ((!Args.getLastArg(options::OPT_m32)) &&
++ (!Args.getLastArg(options::OPT_m64))) {
++ StringRef ArchName;
++
++ switch (T.getArch()) {
++ case llvm::Triple::x86_64:
++ case llvm::Triple::sparcv9:
++ return getTripleString();
++ break;
++ case llvm::Triple::sparc:
++ ArchName = "sparcv9";
++ T.setArchName(ArchName);
++ return T.getTriple();
++ break;
++ case llvm::Triple::x86:
++ ArchName = "x86_64";
++ T.setArchName(ArchName);
++ return T.getTriple();
++ break;
++ default:
++ llvm_unreachable("Unknonwn Solaris Target Triple!");
++ break;
++ }
++ }
++ }
++
+ switch (getTriple().getArch()) {
+ default:
+ return getTripleString();
+###
+