summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/tools/clang/lib/Driver/Tools.cpp
diff options
context:
space:
mode:
authordim <dim@FreeBSD.org>2014-03-21 17:53:59 +0000
committerdim <dim@FreeBSD.org>2014-03-21 17:53:59 +0000
commit9cedb8bb69b89b0f0c529937247a6a80cabdbaec (patch)
treec978f0e9ec1ab92dc8123783f30b08a7fd1e2a39 /contrib/llvm/tools/clang/lib/Driver/Tools.cpp
parent03fdc2934eb61c44c049a02b02aa974cfdd8a0eb (diff)
downloadFreeBSD-src-9cedb8bb69b89b0f0c529937247a6a80cabdbaec.zip
FreeBSD-src-9cedb8bb69b89b0f0c529937247a6a80cabdbaec.tar.gz
MFC 261991:
Upgrade our copy of llvm/clang to 3.4 release. This version supports all of the features in the current working draft of the upcoming C++ standard, provisionally named C++1y. The code generator's performance is greatly increased, and the loop auto-vectorizer is now enabled at -Os and -O2 in addition to -O3. The PowerPC backend has made several major improvements to code generation quality and compile time, and the X86, SPARC, ARM32, Aarch64 and SystemZ backends have all seen major feature work. Release notes for llvm and clang can be found here: <http://llvm.org/releases/3.4/docs/ReleaseNotes.html> <http://llvm.org/releases/3.4/tools/clang/docs/ReleaseNotes.html> MFC 262121 (by emaste): Update lldb for clang/llvm 3.4 import This commit largely restores the lldb source to the upstream r196259 snapshot with the addition of threaded inferior support and a few bug fixes. Specific upstream lldb revisions restored include: SVN git 181387 779e6ac 181703 7bef4e2 182099 b31044e 182650 f2dcf35 182683 0d91b80 183862 15c1774 183929 99447a6 184177 0b2934b 184948 4dc3761 184954 007e7bc 186990 eebd175 Sponsored by: DARPA, AFRL MFC 262186 (by emaste): Fix mismerge in r262121 A break statement was lost in the merge. The error had no functional impact, but restore it to reduce the diff against upstream. MFC 262303: Pull in r197521 from upstream clang trunk (by rdivacky): Use the integrated assembler by default on FreeBSD/ppc and ppc64. Requested by: jhibbits MFC 262611: Pull in r196874 from upstream llvm trunk: Fix a crash that occurs when PWD is invalid. MCJIT needs to be able to run in hostile environments, even when PWD is invalid. There's no need to crash MCJIT in this case. The obvious fix is to simply leave MCContext's CompilationDir empty when PWD can't be determined. This way, MCJIT clients, and other clients that link with LLVM don't need a valid working directory. If we do want to guarantee valid CompilationDir, that should be done only for clients of getCompilationDir(). This is as simple as checking for an empty string. The only current use of getCompilationDir is EmitGenDwarfInfo, which won't conceivably run with an invalid working dir. However, in the purely hypothetically and untestable case that this happens, the AT_comp_dir will be omitted from the compilation_unit DIE. This should help fix assertions occurring with ports-mgmt/tinderbox, when it is using jails, and sometimes invalidates clang's current working directory. Reported by: decke MFC 262809: Pull in r203007 from upstream clang trunk: Don't produce an alias between destructors with different calling conventions. Fixes pr19007. (Please note that is an LLVM PR identifier, not a FreeBSD one.) This should fix Firefox and/or libxul crashes (due to problems with regparm/stdcall calling conventions) on i386. Reported by: multiple users on freebsd-current PR: bin/187103 MFC 263048: Repair recognition of "CC" as an alias for the C++ compiler, since it was silently broken by upstream for a Windows-specific use-case. Apparently some versions of CMake still rely on this archaic feature... Reported by: rakuco MFC 263049: Garbage collect the old way of adding the libstdc++ include directories in clang's InitHeaderSearch.cpp. This has been superseded by David Chisnall's commit in r255321. Moreover, if libc++ is used, the libstdc++ include directories should not be in the search path at all. These directories are now only used if you pass -stdlib=libstdc++.
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Driver/Tools.cpp')
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/Tools.cpp2230
1 files changed, 1452 insertions, 778 deletions
diff --git a/contrib/llvm/tools/clang/lib/Driver/Tools.cpp b/contrib/llvm/tools/clang/lib/Driver/Tools.cpp
index 26b69f3..3529fc7 100644
--- a/contrib/llvm/tools/clang/lib/Driver/Tools.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/Tools.cpp
@@ -7,43 +7,48 @@
//
//===----------------------------------------------------------------------===//
-#include <sys/stat.h>
#include "Tools.h"
#include "InputInfo.h"
-#include "SanitizerArgs.h"
#include "ToolChains.h"
#include "clang/Basic/ObjCRuntime.h"
#include "clang/Basic/Version.h"
#include "clang/Driver/Action.h"
-#include "clang/Driver/Arg.h"
-#include "clang/Driver/ArgList.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/Job.h"
-#include "clang/Driver/Option.h"
#include "clang/Driver/Options.h"
+#include "clang/Driver/SanitizerArgs.h"
#include "clang/Driver/ToolChain.h"
#include "clang/Driver/Util.h"
+#include "clang/Sema/SemaDiagnostic.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/Twine.h"
+#include "llvm/Option/Arg.h"
+#include "llvm/Option/ArgList.h"
+#include "llvm/Option/Option.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/Host.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/Program.h"
#include "llvm/Support/Process.h"
#include "llvm/Support/raw_ostream.h"
+#include <sys/stat.h>
using namespace clang::driver;
using namespace clang::driver::tools;
using namespace clang;
+using namespace llvm::opt;
/// CheckPreprocessingOptions - Perform some validation of preprocessing
/// arguments that is shared with gcc.
static void CheckPreprocessingOptions(const Driver &D, const ArgList &Args) {
if (Arg *A = Args.getLastArg(options::OPT_C, options::OPT_CC))
- if (!Args.hasArg(options::OPT_E) && !D.CCCIsCPP)
+ if (!Args.hasArg(options::OPT_E) && !D.CCCIsCPP())
D.Diag(diag::err_drv_argument_only_allowed_with)
<< A->getAsString(Args) << "-E";
}
@@ -107,7 +112,7 @@ static void addDirectoryList(const ArgList &Args,
return;
StringRef::size_type Delim;
- while ((Delim = Dirs.find(llvm::sys::PathSeparator)) != StringRef::npos) {
+ while ((Delim = Dirs.find(llvm::sys::EnvPathSeparator)) != StringRef::npos) {
if (Delim == 0) { // Leading colon.
if (CombinedArg) {
CmdArgs.push_back(Args.MakeArgString(std::string(ArgName) + "."));
@@ -223,7 +228,9 @@ static void addProfileRT(const ToolChain &TC, const ArgList &Args,
}
static bool forwardToGCC(const Option &O) {
- return !O.hasFlag(options::NoForward) &&
+ // Don't forward inputs from the original command line. They are added from
+ // InputInfoList.
+ return O.getKind() != Option::InputClass &&
!O.hasFlag(options::DriverOption) &&
!O.hasFlag(options::LinkerInput);
}
@@ -339,32 +346,28 @@ void Clang::AddPreprocessingOptions(Compilation &C,
bool FoundPTH = false;
bool FoundPCH = false;
- llvm::sys::Path P(A->getValue());
- bool Exists;
+ SmallString<128> P(A->getValue());
+ // We want the files to have a name like foo.h.pch. Add a dummy extension
+ // so that replace_extension does the right thing.
+ P += ".dummy";
if (UsePCH) {
- P.appendSuffix("pch");
- if (!llvm::sys::fs::exists(P.str(), Exists) && Exists)
+ llvm::sys::path::replace_extension(P, "pch");
+ if (llvm::sys::fs::exists(P.str()))
FoundPCH = true;
- else
- P.eraseSuffix();
}
if (!FoundPCH) {
- P.appendSuffix("pth");
- if (!llvm::sys::fs::exists(P.str(), Exists) && Exists)
+ llvm::sys::path::replace_extension(P, "pth");
+ if (llvm::sys::fs::exists(P.str()))
FoundPTH = true;
- else
- P.eraseSuffix();
}
if (!FoundPCH && !FoundPTH) {
- P.appendSuffix("gch");
- if (!llvm::sys::fs::exists(P.str(), Exists) && Exists) {
+ llvm::sys::path::replace_extension(P, "gch");
+ if (llvm::sys::fs::exists(P.str())) {
FoundPCH = UsePCH;
FoundPTH = !UsePCH;
}
- else
- P.eraseSuffix();
}
if (FoundPCH || FoundPTH) {
@@ -446,6 +449,7 @@ void Clang::AddPreprocessingOptions(Compilation &C,
// FIXME: tblgen this, or kill it!
static const char *getLLVMArchSuffixForARM(StringRef CPU) {
return llvm::StringSwitch<const char *>(CPU)
+ .Case("strongarm", "v4")
.Cases("arm7tdmi", "arm7tdmi-s", "arm710t", "v4t")
.Cases("arm720t", "arm9", "arm9tdmi", "v4t")
.Cases("arm920", "arm920t", "arm922t", "v4t")
@@ -458,13 +462,14 @@ static const char *getLLVMArchSuffixForARM(StringRef CPU) {
.Cases("arm1176jzf-s", "mpcorenovfp", "mpcore", "v6")
.Cases("arm1156t2-s", "arm1156t2f-s", "v6t2")
.Cases("cortex-a5", "cortex-a7", "cortex-a8", "v7")
- .Cases("cortex-a9", "cortex-a15", "v7")
- .Case("cortex-r5", "v7r")
+ .Cases("cortex-a9", "cortex-a12", "cortex-a15", "v7")
+ .Cases("cortex-r4", "cortex-r5", "v7r")
.Case("cortex-m0", "v6m")
.Case("cortex-m3", "v7m")
.Case("cortex-m4", "v7em")
.Case("cortex-a9-mp", "v7f")
.Case("swift", "v7s")
+ .Cases("cortex-a53", "cortex-a57", "v8")
.Default("");
}
@@ -494,6 +499,11 @@ static std::string getARMTargetCPU(const ArgList &Args,
MArch = Triple.getArchName();
}
+ if (Triple.getOS() == llvm::Triple::NetBSD) {
+ if (MArch == "armv6")
+ return "arm1176jzf-s";
+ }
+
// Handle -march=native.
std::string NativeMArch;
if (MArch == "native") {
@@ -510,7 +520,8 @@ static std::string getARMTargetCPU(const ArgList &Args,
.Cases("armv2", "armv2a","arm2")
.Case("armv3", "arm6")
.Case("armv3m", "arm7m")
- .Cases("armv4", "armv4t", "arm7tdmi")
+ .Case("armv4", "strongarm")
+ .Case("armv4t", "arm7tdmi")
.Cases("armv5", "armv5t", "arm10tdmi")
.Cases("armv5e", "armv5te", "arm1022e")
.Case("armv5tej", "arm926ej-s")
@@ -525,13 +536,35 @@ static std::string getARMTargetCPU(const ArgList &Args,
.Cases("armv7s", "armv7-s", "swift")
.Cases("armv7r", "armv7-r", "cortex-r4")
.Cases("armv7m", "armv7-m", "cortex-m3")
+ .Cases("armv8", "armv8a", "armv8-a", "cortex-a53")
.Case("ep9312", "ep9312")
.Case("iwmmxt", "iwmmxt")
.Case("xscale", "xscale")
- // If all else failed, return the most base CPU LLVM supports.
+ // If all else failed, return the most base CPU with thumb interworking
+ // supported by LLVM.
.Default("arm7tdmi");
}
+/// getAArch64TargetCPU - Get the (LLVM) name of the AArch64 cpu we are targeting.
+//
+// FIXME: tblgen this.
+static std::string getAArch64TargetCPU(const ArgList &Args,
+ const llvm::Triple &Triple) {
+ // FIXME: Warn on inconsistent use of -mcpu and -march.
+
+ // If we have -mcpu=, use that.
+ if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) {
+ StringRef MCPU = A->getValue();
+ // Handle -mcpu=native.
+ if (MCPU == "native")
+ return llvm::sys::getHostCPUName();
+ else
+ return MCPU;
+ }
+
+ return "generic";
+}
+
// FIXME: Move to target hook.
static bool isSignedCharDefault(const llvm::Triple &Triple) {
switch (Triple.getArch()) {
@@ -546,73 +579,117 @@ static bool isSignedCharDefault(const llvm::Triple &Triple) {
return true;
return false;
+ case llvm::Triple::ppc64le:
case llvm::Triple::systemz:
+ case llvm::Triple::xcore:
return false;
}
}
+static bool isNoCommonDefault(const llvm::Triple &Triple) {
+ switch (Triple.getArch()) {
+ default:
+ return false;
+
+ case llvm::Triple::xcore:
+ return true;
+ }
+}
+
+// Handle -mfpu=.
+//
+// FIXME: Centralize feature selection, defaulting shouldn't be also in the
+// frontend target.
+static void getAArch64FPUFeatures(const Driver &D, const Arg *A,
+ const ArgList &Args,
+ std::vector<const char *> &Features) {
+ StringRef FPU = A->getValue();
+ if (FPU == "fp-armv8") {
+ Features.push_back("+fp-armv8");
+ } else if (FPU == "neon-fp-armv8") {
+ Features.push_back("+fp-armv8");
+ Features.push_back("+neon");
+ } else if (FPU == "crypto-neon-fp-armv8") {
+ Features.push_back("+fp-armv8");
+ Features.push_back("+neon");
+ Features.push_back("+crypto");
+ } else if (FPU == "neon") {
+ Features.push_back("+neon");
+ } else if (FPU == "none") {
+ Features.push_back("-fp-armv8");
+ Features.push_back("-crypto");
+ Features.push_back("-neon");
+ } else
+ D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args);
+}
+
+// Handle -mhwdiv=.
+static void getARMHWDivFeatures(const Driver &D, const Arg *A,
+ const ArgList &Args,
+ std::vector<const char *> &Features) {
+ StringRef HWDiv = A->getValue();
+ if (HWDiv == "arm") {
+ Features.push_back("+hwdiv-arm");
+ Features.push_back("-hwdiv");
+ } else if (HWDiv == "thumb") {
+ Features.push_back("-hwdiv-arm");
+ Features.push_back("+hwdiv");
+ } else if (HWDiv == "arm,thumb" || HWDiv == "thumb,arm") {
+ Features.push_back("+hwdiv-arm");
+ Features.push_back("+hwdiv");
+ } else if (HWDiv == "none") {
+ Features.push_back("-hwdiv-arm");
+ Features.push_back("-hwdiv");
+ } else
+ D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args);
+}
+
// Handle -mfpu=.
//
// FIXME: Centralize feature selection, defaulting shouldn't be also in the
// frontend target.
-static void addFPUArgs(const Driver &D, const Arg *A, const ArgList &Args,
- ArgStringList &CmdArgs) {
+static void getARMFPUFeatures(const Driver &D, const Arg *A,
+ const ArgList &Args,
+ std::vector<const char *> &Features) {
StringRef FPU = A->getValue();
// Set the target features based on the FPU.
if (FPU == "fpa" || FPU == "fpe2" || FPU == "fpe3" || FPU == "maverick") {
// Disable any default FPU support.
- CmdArgs.push_back("-target-feature");
- CmdArgs.push_back("-vfp2");
- CmdArgs.push_back("-target-feature");
- CmdArgs.push_back("-vfp3");
- CmdArgs.push_back("-target-feature");
- CmdArgs.push_back("-neon");
+ Features.push_back("-vfp2");
+ Features.push_back("-vfp3");
+ Features.push_back("-neon");
} else if (FPU == "vfp3-d16" || FPU == "vfpv3-d16") {
- CmdArgs.push_back("-target-feature");
- CmdArgs.push_back("+vfp3");
- CmdArgs.push_back("-target-feature");
- CmdArgs.push_back("+d16");
- CmdArgs.push_back("-target-feature");
- CmdArgs.push_back("-neon");
+ Features.push_back("+vfp3");
+ Features.push_back("+d16");
+ Features.push_back("-neon");
} else if (FPU == "vfp") {
- CmdArgs.push_back("-target-feature");
- CmdArgs.push_back("+vfp2");
- CmdArgs.push_back("-target-feature");
- CmdArgs.push_back("-neon");
+ Features.push_back("+vfp2");
+ Features.push_back("-neon");
} else if (FPU == "vfp3" || FPU == "vfpv3") {
- CmdArgs.push_back("-target-feature");
- CmdArgs.push_back("+vfp3");
- CmdArgs.push_back("-target-feature");
- CmdArgs.push_back("-neon");
+ Features.push_back("+vfp3");
+ Features.push_back("-neon");
+ } else if (FPU == "fp-armv8") {
+ Features.push_back("+fp-armv8");
+ Features.push_back("-neon");
+ Features.push_back("-crypto");
+ } else if (FPU == "neon-fp-armv8") {
+ Features.push_back("+fp-armv8");
+ Features.push_back("+neon");
+ Features.push_back("-crypto");
+ } else if (FPU == "crypto-neon-fp-armv8") {
+ Features.push_back("+fp-armv8");
+ Features.push_back("+neon");
+ Features.push_back("+crypto");
} else if (FPU == "neon") {
- CmdArgs.push_back("-target-feature");
- CmdArgs.push_back("+neon");
- } else
- D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args);
-}
-
-// Handle -mfpmath=.
-static void addFPMathArgs(const Driver &D, const Arg *A, const ArgList &Args,
- ArgStringList &CmdArgs, StringRef CPU) {
- StringRef FPMath = A->getValue();
-
- // Set the target features based on the FPMath.
- if (FPMath == "neon") {
- CmdArgs.push_back("-target-feature");
- CmdArgs.push_back("+neonfp");
-
- if (CPU != "cortex-a5" && CPU != "cortex-a7" &&
- CPU != "cortex-a8" && CPU != "cortex-a9" &&
- CPU != "cortex-a9-mp" && CPU != "cortex-a15")
- D.Diag(diag::err_drv_invalid_feature) << "-mfpmath=neon" << CPU;
-
- } else if (FPMath == "vfp" || FPMath == "vfp2" || FPMath == "vfp3" ||
- FPMath == "vfp4") {
- CmdArgs.push_back("-target-feature");
- CmdArgs.push_back("-neonfp");
-
- // FIXME: Add warnings when disabling a feature not present for a given CPU.
+ Features.push_back("+neon");
+ } else if (FPU == "none") {
+ Features.push_back("-vfp2");
+ Features.push_back("-vfp3");
+ Features.push_back("-vfp4");
+ Features.push_back("-fp-armv8");
+ Features.push_back("-crypto");
+ Features.push_back("-neon");
} else
D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args);
}
@@ -697,6 +774,41 @@ static StringRef getARMFloatABI(const Driver &D,
return FloatABI;
}
+static void getARMTargetFeatures(const Driver &D, const llvm::Triple &Triple,
+ const ArgList &Args,
+ std::vector<const char *> &Features) {
+ StringRef FloatABI = getARMFloatABI(D, Args, Triple);
+ // FIXME: Note, this is a hack, the LLVM backend doesn't actually use these
+ // yet (it uses the -mfloat-abi and -msoft-float options), and it is
+ // stripped out by the ARM target.
+ // Use software floating point operations?
+ if (FloatABI == "soft")
+ Features.push_back("+soft-float");
+
+ // Use software floating point argument passing?
+ if (FloatABI != "hard")
+ Features.push_back("+soft-float-abi");
+
+ // Honor -mfpu=.
+ if (const Arg *A = Args.getLastArg(options::OPT_mfpu_EQ))
+ getARMFPUFeatures(D, A, Args, Features);
+ if (const Arg *A = Args.getLastArg(options::OPT_mhwdiv_EQ))
+ getARMHWDivFeatures(D, A, Args, Features);
+
+ // Setting -msoft-float effectively disables NEON because of the GCC
+ // implementation, although the same isn't true of VFP or VFP3.
+ if (FloatABI == "soft")
+ Features.push_back("-neon");
+
+ // En/disable crc
+ if (Arg *A = Args.getLastArg(options::OPT_mcrc,
+ options::OPT_mnocrc)) {
+ if (A->getOption().matches(options::OPT_mcrc))
+ Features.push_back("+crc");
+ else
+ Features.push_back("-crc");
+ }
+}
void Clang::AddARMTargetArgs(const ArgList &Args,
ArgStringList &CmdArgs,
@@ -716,7 +828,8 @@ void Clang::AddARMTargetArgs(const ArgList &Args,
} else if (Triple.isOSDarwin()) {
// The backend is hardwired to assume AAPCS for M-class processors, ensure
// the frontend matches that.
- if (StringRef(CPUName).startswith("cortex-m")) {
+ if (Triple.getEnvironment() == llvm::Triple::EABI ||
+ StringRef(CPUName).startswith("cortex-m")) {
ABIName = "aapcs";
} else {
ABIName = "apcs-gnu";
@@ -739,10 +852,6 @@ void Clang::AddARMTargetArgs(const ArgList &Args,
CmdArgs.push_back("-target-abi");
CmdArgs.push_back(ABIName);
- // Set the CPU based on -march= and -mcpu=.
- CmdArgs.push_back("-target-cpu");
- CmdArgs.push_back(Args.MakeArgString(CPUName));
-
// Determine floating point ABI from the options & target defaults.
StringRef FloatABI = getARMFloatABI(D, Args, Triple);
if (FloatABI == "soft") {
@@ -763,42 +872,9 @@ void Clang::AddARMTargetArgs(const ArgList &Args,
CmdArgs.push_back("hard");
}
- // Set appropriate target features for floating point mode.
- //
- // FIXME: Note, this is a hack, the LLVM backend doesn't actually use these
- // yet (it uses the -mfloat-abi and -msoft-float options above), and it is
- // stripped out by the ARM target.
-
- // Use software floating point operations?
- if (FloatABI == "soft") {
- CmdArgs.push_back("-target-feature");
- CmdArgs.push_back("+soft-float");
- }
-
- // Use software floating point argument passing?
- if (FloatABI != "hard") {
- CmdArgs.push_back("-target-feature");
- CmdArgs.push_back("+soft-float-abi");
- }
-
- // Honor -mfpu=.
- if (const Arg *A = Args.getLastArg(options::OPT_mfpu_EQ))
- addFPUArgs(D, A, Args, CmdArgs);
-
- // Honor -mfpmath=.
- if (const Arg *A = Args.getLastArg(options::OPT_mfpmath_EQ))
- addFPMathArgs(D, A, Args, CmdArgs, getARMTargetCPU(Args, Triple));
-
- // Setting -msoft-float effectively disables NEON because of the GCC
- // implementation, although the same isn't true of VFP or VFP3.
- if (FloatABI == "soft") {
- CmdArgs.push_back("-target-feature");
- CmdArgs.push_back("-neon");
- }
-
// Kernel code has more strict alignment requirements.
if (KernelOrKext) {
- if (Triple.getOS() != llvm::Triple::IOS || Triple.isOSVersionLT(6)) {
+ if (!Triple.isiOS() || Triple.isOSVersionLT(6)) {
CmdArgs.push_back("-backend-option");
CmdArgs.push_back("-arm-long-calls");
}
@@ -808,7 +884,7 @@ void Clang::AddARMTargetArgs(const ArgList &Args,
// The kext linker doesn't know how to deal with movw/movt.
CmdArgs.push_back("-backend-option");
- CmdArgs.push_back("-arm-darwin-use-movt=0");
+ CmdArgs.push_back("-arm-use-movt=0");
}
// Setting -mno-global-merge disables the codegen global merge pass. Setting
@@ -823,39 +899,28 @@ void Clang::AddARMTargetArgs(const ArgList &Args,
options::OPT_mno_implicit_float,
true))
CmdArgs.push_back("-no-implicit-float");
-}
-// Translate MIPS CPU name alias option to CPU name.
-static StringRef getMipsCPUFromAlias(const Arg &A) {
- if (A.getOption().matches(options::OPT_mips32))
- return "mips32";
- if (A.getOption().matches(options::OPT_mips32r2))
- return "mips32r2";
- if (A.getOption().matches(options::OPT_mips64))
- return "mips64";
- if (A.getOption().matches(options::OPT_mips64r2))
- return "mips64r2";
- llvm_unreachable("Unexpected option");
- return "";
+ // llvm does not support reserving registers in general. There is support
+ // for reserving r9 on ARM though (defined as a platform-specific register
+ // in ARM EABI).
+ if (Args.hasArg(options::OPT_ffixed_r9)) {
+ CmdArgs.push_back("-backend-option");
+ CmdArgs.push_back("-arm-reserve-r9");
+ }
}
// Get CPU and ABI names. They are not independent
// so we have to calculate them together.
static void getMipsCPUAndABI(const ArgList &Args,
- const ToolChain &TC,
+ const llvm::Triple &Triple,
StringRef &CPUName,
StringRef &ABIName) {
const char *DefMips32CPU = "mips32";
const char *DefMips64CPU = "mips64";
if (Arg *A = Args.getLastArg(options::OPT_march_EQ,
- options::OPT_mcpu_EQ,
- options::OPT_mips_CPUs_Group)) {
- if (A->getOption().matches(options::OPT_mips_CPUs_Group))
- CPUName = getMipsCPUFromAlias(*A);
- else
- CPUName = A->getValue();
- }
+ options::OPT_mcpu_EQ))
+ CPUName = A->getValue();
if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) {
ABIName = A->getValue();
@@ -869,7 +934,7 @@ static void getMipsCPUAndABI(const ArgList &Args,
// Setup default CPU and ABI names.
if (CPUName.empty() && ABIName.empty()) {
- switch (TC.getTriple().getArch()) {
+ switch (Triple.getArch()) {
default:
llvm_unreachable("Unexpected triple arch name");
case llvm::Triple::mips:
@@ -941,28 +1006,56 @@ static StringRef getMipsFloatABI(const Driver &D, const ArgList &Args) {
}
static void AddTargetFeature(const ArgList &Args,
- ArgStringList &CmdArgs,
- OptSpecifier OnOpt,
- OptSpecifier OffOpt,
+ std::vector<const char *> &Features,
+ OptSpecifier OnOpt, OptSpecifier OffOpt,
StringRef FeatureName) {
if (Arg *A = Args.getLastArg(OnOpt, OffOpt)) {
- CmdArgs.push_back("-target-feature");
if (A->getOption().matches(OnOpt))
- CmdArgs.push_back(Args.MakeArgString("+" + FeatureName));
+ Features.push_back(Args.MakeArgString("+" + FeatureName));
else
- CmdArgs.push_back(Args.MakeArgString("-" + FeatureName));
+ Features.push_back(Args.MakeArgString("-" + FeatureName));
}
}
+static void getMIPSTargetFeatures(const Driver &D, const ArgList &Args,
+ std::vector<const char *> &Features) {
+ StringRef FloatABI = getMipsFloatABI(D, Args);
+ bool IsMips16 = Args.getLastArg(options::OPT_mips16) != NULL;
+ if (FloatABI == "soft" || (FloatABI == "hard" && IsMips16)) {
+ // FIXME: Note, this is a hack. We need to pass the selected float
+ // mode to the MipsTargetInfoBase to define appropriate macros there.
+ // Now it is the only method.
+ Features.push_back("+soft-float");
+ }
+
+ if (Arg *A = Args.getLastArg(options::OPT_mnan_EQ)) {
+ if (StringRef(A->getValue()) == "2008")
+ Features.push_back("+nan2008");
+ }
+
+ AddTargetFeature(Args, Features, options::OPT_msingle_float,
+ options::OPT_mdouble_float, "single-float");
+ AddTargetFeature(Args, Features, options::OPT_mips16, options::OPT_mno_mips16,
+ "mips16");
+ AddTargetFeature(Args, Features, options::OPT_mmicromips,
+ options::OPT_mno_micromips, "micromips");
+ AddTargetFeature(Args, Features, options::OPT_mdsp, options::OPT_mno_dsp,
+ "dsp");
+ AddTargetFeature(Args, Features, options::OPT_mdspr2, options::OPT_mno_dspr2,
+ "dspr2");
+ AddTargetFeature(Args, Features, options::OPT_mmsa, options::OPT_mno_msa,
+ "msa");
+ AddTargetFeature(Args, Features, options::OPT_mfp64, options::OPT_mfp32,
+ "fp64");
+}
+
void Clang::AddMIPSTargetArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
const Driver &D = getToolChain().getDriver();
StringRef CPUName;
StringRef ABIName;
- getMipsCPUAndABI(Args, getToolChain(), CPUName, ABIName);
-
- CmdArgs.push_back("-target-cpu");
- CmdArgs.push_back(CPUName.data());
+ const llvm::Triple &Triple = getToolChain().getTriple();
+ getMipsCPUAndABI(Args, Triple, CPUName, ABIName);
CmdArgs.push_back("-target-abi");
CmdArgs.push_back(ABIName.data());
@@ -977,12 +1070,6 @@ void Clang::AddMIPSTargetArgs(const ArgList &Args,
CmdArgs.push_back("-mfloat-abi");
CmdArgs.push_back("soft");
- // FIXME: Note, this is a hack. We need to pass the selected float
- // mode to the MipsTargetInfoBase to define appropriate macros there.
- // Now it is the only method.
- CmdArgs.push_back("-target-feature");
- CmdArgs.push_back("+soft-float");
-
if (FloatABI == "hard" && IsMips16) {
CmdArgs.push_back("-mllvm");
CmdArgs.push_back("-mips16-hard-float");
@@ -995,22 +1082,6 @@ void Clang::AddMIPSTargetArgs(const ArgList &Args,
CmdArgs.push_back("hard");
}
- AddTargetFeature(Args, CmdArgs,
- options::OPT_msingle_float, options::OPT_mdouble_float,
- "single-float");
- AddTargetFeature(Args, CmdArgs,
- options::OPT_mips16, options::OPT_mno_mips16,
- "mips16");
- AddTargetFeature(Args, CmdArgs,
- options::OPT_mmicromips, options::OPT_mno_micromips,
- "micromips");
- AddTargetFeature(Args, CmdArgs,
- options::OPT_mdsp, options::OPT_mno_dsp,
- "dsp");
- AddTargetFeature(Args, CmdArgs,
- options::OPT_mdspr2, options::OPT_mno_dspr2,
- "dspr2");
-
if (Arg *A = Args.getLastArg(options::OPT_mxgot, options::OPT_mno_xgot)) {
if (A->getOption().matches(options::OPT_mxgot)) {
CmdArgs.push_back("-mllvm");
@@ -1018,6 +1089,22 @@ void Clang::AddMIPSTargetArgs(const ArgList &Args,
}
}
+ if (Arg *A = Args.getLastArg(options::OPT_mldc1_sdc1,
+ options::OPT_mno_ldc1_sdc1)) {
+ if (A->getOption().matches(options::OPT_mno_ldc1_sdc1)) {
+ CmdArgs.push_back("-mllvm");
+ CmdArgs.push_back("-mno-ldc1-sdc1");
+ }
+ }
+
+ if (Arg *A = Args.getLastArg(options::OPT_mcheck_zero_division,
+ options::OPT_mno_check_zero_division)) {
+ if (A->getOption().matches(options::OPT_mno_check_zero_division)) {
+ CmdArgs.push_back("-mllvm");
+ CmdArgs.push_back("-mno-check-zero-division");
+ }
+ }
+
if (Arg *A = Args.getLastArg(options::OPT_G)) {
StringRef v = A->getValue();
CmdArgs.push_back("-mllvm");
@@ -1081,62 +1168,48 @@ static std::string getPPCTargetCPU(const ArgList &Args) {
.Case("pwr7", "pwr7")
.Case("powerpc", "ppc")
.Case("powerpc64", "ppc64")
+ .Case("powerpc64le", "ppc64le")
.Default("");
}
return "";
}
-void Clang::AddPPCTargetArgs(const ArgList &Args,
- ArgStringList &CmdArgs) const {
- std::string TargetCPUName = getPPCTargetCPU(Args);
-
- // LLVM may default to generating code for the native CPU,
- // but, like gcc, we default to a more generic option for
- // each architecture. (except on Darwin)
- llvm::Triple Triple = getToolChain().getTriple();
- if (TargetCPUName.empty() && !Triple.isOSDarwin()) {
- if (Triple.getArch() == llvm::Triple::ppc64)
- TargetCPUName = "ppc64";
- else
- TargetCPUName = "ppc";
- }
-
- if (!TargetCPUName.empty()) {
- CmdArgs.push_back("-target-cpu");
- CmdArgs.push_back(Args.MakeArgString(TargetCPUName.c_str()));
- }
-
- // Allow override of the Altivec feature.
- AddTargetFeature(Args, CmdArgs,
- options::OPT_faltivec, options::OPT_fno_altivec,
- "altivec");
+static void getPPCTargetFeatures(const ArgList &Args,
+ std::vector<const char *> &Features) {
+ for (arg_iterator it = Args.filtered_begin(options::OPT_m_ppc_Features_Group),
+ ie = Args.filtered_end();
+ it != ie; ++it) {
+ StringRef Name = (*it)->getOption().getName();
+ (*it)->claim();
- AddTargetFeature(Args, CmdArgs,
- options::OPT_mfprnd, options::OPT_mno_fprnd,
- "fprnd");
+ // Skip over "-m".
+ assert(Name.startswith("m") && "Invalid feature name.");
+ Name = Name.substr(1);
- // Note that gcc calls this mfcrf and LLVM calls this mfocrf.
- AddTargetFeature(Args, CmdArgs,
- options::OPT_mmfcrf, options::OPT_mno_mfcrf,
- "mfocrf");
+ bool IsNegative = Name.startswith("no-");
+ if (IsNegative)
+ Name = Name.substr(3);
- AddTargetFeature(Args, CmdArgs,
- options::OPT_mpopcntd, options::OPT_mno_popcntd,
- "popcntd");
+ // Note that gcc calls this mfcrf and LLVM calls this mfocrf so we
+ // pass the correct option to the backend while calling the frontend
+ // option the same.
+ // TODO: Change the LLVM backend option maybe?
+ if (Name == "mfcrf")
+ Name = "mfocrf";
- // It is really only possible to turn qpx off because turning qpx on is tied
- // to using the a2q CPU.
- if (Args.hasFlag(options::OPT_mno_qpx, options::OPT_mqpx, false)) {
- CmdArgs.push_back("-target-feature");
- CmdArgs.push_back("-qpx");
+ Features.push_back(Args.MakeArgString((IsNegative ? "-" : "+") + Name));
}
+
+ // Altivec is a bit weird, allow overriding of the Altivec feature here.
+ AddTargetFeature(Args, Features, options::OPT_faltivec,
+ options::OPT_fno_altivec, "altivec");
}
/// Get the (LLVM) name of the R600 gpu we are targeting.
static std::string getR600TargetGPU(const ArgList &Args) {
if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) {
- std::string GPUName = A->getValue();
+ const char *GPUName = A->getValue();
return llvm::StringSwitch<const char *>(GPUName)
.Cases("rv630", "rv635", "r600")
.Cases("rv610", "rv620", "rs780", "rs880")
@@ -1145,27 +1218,27 @@ static std::string getR600TargetGPU(const ArgList &Args) {
.Cases("sumo", "sumo2", "sumo")
.Case("hemlock", "cypress")
.Case("aruba", "cayman")
- .Default(GPUName.c_str());
+ .Default(GPUName);
}
return "";
}
-void Clang::AddR600TargetArgs(const ArgList &Args,
- ArgStringList &CmdArgs) const {
- std::string TargetGPUName = getR600TargetGPU(Args);
- CmdArgs.push_back("-target-cpu");
- CmdArgs.push_back(Args.MakeArgString(TargetGPUName.c_str()));
+static void getSparcTargetFeatures(const ArgList &Args,
+ std::vector<const char *> Features) {
+ bool SoftFloatABI = true;
+ if (Arg *A =
+ Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float)) {
+ if (A->getOption().matches(options::OPT_mhard_float))
+ SoftFloatABI = false;
+ }
+ if (SoftFloatABI)
+ Features.push_back("+soft-float");
}
void Clang::AddSparcTargetArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
const Driver &D = getToolChain().getDriver();
- if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) {
- CmdArgs.push_back("-target-cpu");
- CmdArgs.push_back(A->getValue());
- }
-
// Select the float ABI as determined by -msoft-float, -mhard-float, and
StringRef FloatABI;
if (Arg *A = Args.getLastArg(options::OPT_msoft_float,
@@ -1178,13 +1251,9 @@ void Clang::AddSparcTargetArgs(const ArgList &Args,
// If unspecified, choose the default based on the platform.
if (FloatABI.empty()) {
- switch (getToolChain().getTriple().getOS()) {
- default:
- // Assume "soft", but warn the user we are guessing.
- FloatABI = "soft";
- D.Diag(diag::warn_drv_assuming_mfloat_abi_is) << "soft";
- break;
- }
+ // Assume "soft", but warn the user we are guessing.
+ FloatABI = "soft";
+ D.Diag(diag::warn_drv_assuming_mfloat_abi_is) << "soft";
}
if (FloatABI == "soft") {
@@ -1192,19 +1261,27 @@ void Clang::AddSparcTargetArgs(const ArgList &Args,
//
// FIXME: This changes CPP defines, we need -target-soft-float.
CmdArgs.push_back("-msoft-float");
- CmdArgs.push_back("-target-feature");
- CmdArgs.push_back("+soft-float");
} else {
assert(FloatABI == "hard" && "Invalid float abi!");
CmdArgs.push_back("-mhard-float");
}
}
+static const char *getSystemZTargetCPU(const ArgList &Args) {
+ if (const Arg *A = Args.getLastArg(options::OPT_march_EQ))
+ return A->getValue();
+ return "z10";
+}
+
static const char *getX86TargetCPU(const ArgList &Args,
const llvm::Triple &Triple) {
if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) {
- if (StringRef(A->getValue()) != "native")
+ if (StringRef(A->getValue()) != "native") {
+ if (Triple.isOSDarwin() && Triple.getArchName() == "x86_64h")
+ return "core-avx2";
+
return A->getValue();
+ }
// FIXME: Reject attempts to use -march=native unless the target matches
// the host.
@@ -1225,30 +1302,128 @@ static const char *getX86TargetCPU(const ArgList &Args,
bool Is64Bit = Triple.getArch() == llvm::Triple::x86_64;
// FIXME: Need target hooks.
- if (Triple.isOSDarwin())
+ if (Triple.isOSDarwin()) {
+ if (Triple.getArchName() == "x86_64h")
+ return "core-avx2";
return Is64Bit ? "core2" : "yonah";
+ }
+
+ // All x86 devices running Android have core2 as their common
+ // denominator. This makes a better choice than pentium4.
+ if (Triple.getEnvironment() == llvm::Triple::Android)
+ return "core2";
// Everything else goes to x86-64 in 64-bit mode.
if (Is64Bit)
return "x86-64";
- if (Triple.getOSName().startswith("haiku"))
- return "i586";
- if (Triple.getOSName().startswith("openbsd"))
+ switch (Triple.getOS()) {
+ case llvm::Triple::FreeBSD:
+ case llvm::Triple::NetBSD:
+ case llvm::Triple::OpenBSD:
return "i486";
- if (Triple.getOSName().startswith("bitrig"))
+ case llvm::Triple::Haiku:
+ return "i586";
+ case llvm::Triple::Bitrig:
return "i686";
- if (Triple.getOSName().startswith("freebsd"))
- return "i486";
- if (Triple.getOSName().startswith("netbsd"))
- return "i486";
- // All x86 devices running Android have core2 as their common
- // denominator. This makes a better choice than pentium4.
- if (Triple.getEnvironment() == llvm::Triple::Android)
- return "core2";
+ default:
+ // Fallback to p4.
+ return "pentium4";
+ }
+}
+
+static std::string getCPUName(const ArgList &Args, const llvm::Triple &T) {
+ switch(T.getArch()) {
+ default:
+ return "";
- // Fallback to p4.
- return "pentium4";
+ case llvm::Triple::aarch64:
+ return getAArch64TargetCPU(Args, T);
+
+ case llvm::Triple::arm:
+ case llvm::Triple::thumb:
+ return getARMTargetCPU(Args, T);
+
+ case llvm::Triple::mips:
+ case llvm::Triple::mipsel:
+ case llvm::Triple::mips64:
+ case llvm::Triple::mips64el: {
+ StringRef CPUName;
+ StringRef ABIName;
+ getMipsCPUAndABI(Args, T, CPUName, ABIName);
+ return CPUName;
+ }
+
+ case llvm::Triple::ppc:
+ case llvm::Triple::ppc64:
+ case llvm::Triple::ppc64le: {
+ std::string TargetCPUName = getPPCTargetCPU(Args);
+ // LLVM may default to generating code for the native CPU,
+ // but, like gcc, we default to a more generic option for
+ // each architecture. (except on Darwin)
+ if (TargetCPUName.empty() && !T.isOSDarwin()) {
+ if (T.getArch() == llvm::Triple::ppc64)
+ TargetCPUName = "ppc64";
+ else if (T.getArch() == llvm::Triple::ppc64le)
+ TargetCPUName = "ppc64le";
+ else
+ TargetCPUName = "ppc";
+ }
+ return TargetCPUName;
+ }
+
+ case llvm::Triple::sparc:
+ if (const Arg *A = Args.getLastArg(options::OPT_march_EQ))
+ return A->getValue();
+ return "";
+
+ case llvm::Triple::x86:
+ case llvm::Triple::x86_64:
+ return getX86TargetCPU(Args, T);
+
+ case llvm::Triple::hexagon:
+ return "hexagon" + toolchains::Hexagon_TC::GetTargetCPU(Args).str();
+
+ case llvm::Triple::systemz:
+ return getSystemZTargetCPU(Args);
+
+ case llvm::Triple::r600:
+ return getR600TargetGPU(Args);
+ }
+}
+
+static void getX86TargetFeatures(const llvm::Triple &Triple,
+ const ArgList &Args,
+ std::vector<const char *> &Features) {
+ if (Triple.getArchName() == "x86_64h") {
+ // x86_64h implies quite a few of the more modern subtarget features
+ // for Haswell class CPUs, but not all of them. Opt-out of a few.
+ Features.push_back("-rdrnd");
+ Features.push_back("-aes");
+ Features.push_back("-pclmul");
+ Features.push_back("-rtm");
+ Features.push_back("-hle");
+ Features.push_back("-fsgsbase");
+ }
+
+ // Now add any that the user explicitly requested on the command line,
+ // which may override the defaults.
+ for (arg_iterator it = Args.filtered_begin(options::OPT_m_x86_Features_Group),
+ ie = Args.filtered_end();
+ it != ie; ++it) {
+ StringRef Name = (*it)->getOption().getName();
+ (*it)->claim();
+
+ // Skip over "-m".
+ assert(Name.startswith("m") && "Invalid feature name.");
+ Name = Name.substr(1);
+
+ bool IsNegative = Name.startswith("no-");
+ if (IsNegative)
+ Name = Name.substr(3);
+
+ Features.push_back(Args.MakeArgString((IsNegative ? "-" : "+") + Name));
+ }
}
void Clang::AddX86TargetArgs(const ArgList &Args,
@@ -1274,45 +1449,6 @@ void Clang::AddX86TargetArgs(const ArgList &Args,
}
if (NoImplicitFloat)
CmdArgs.push_back("-no-implicit-float");
-
- if (const char *CPUName = getX86TargetCPU(Args, getToolChain().getTriple())) {
- CmdArgs.push_back("-target-cpu");
- CmdArgs.push_back(CPUName);
- }
-
- // The required algorithm here is slightly strange: the options are applied
- // in order (so -mno-sse -msse2 disables SSE3), but any option that gets
- // directly overridden later is ignored (so "-mno-sse -msse2 -mno-sse2 -msse"
- // is equivalent to "-mno-sse2 -msse"). The -cc1 handling deals with the
- // former correctly, but not the latter; handle directly-overridden
- // attributes here.
- llvm::StringMap<unsigned> PrevFeature;
- std::vector<const char*> Features;
- for (arg_iterator it = Args.filtered_begin(options::OPT_m_x86_Features_Group),
- ie = Args.filtered_end(); it != ie; ++it) {
- StringRef Name = (*it)->getOption().getName();
- (*it)->claim();
-
- // Skip over "-m".
- assert(Name.startswith("m") && "Invalid feature name.");
- Name = Name.substr(1);
-
- bool IsNegative = Name.startswith("no-");
- if (IsNegative)
- Name = Name.substr(3);
-
- unsigned& Prev = PrevFeature[Name];
- if (Prev)
- Features[Prev - 1] = 0;
- Prev = Features.size() + 1;
- Features.push_back(Args.MakeArgString((IsNegative ? "-" : "+") + Name));
- }
- for (unsigned i = 0; i < Features.size(); i++) {
- if (Features[i]) {
- CmdArgs.push_back("-target-feature");
- CmdArgs.push_back(Features[i]);
- }
- }
}
static inline bool HasPICArg(const ArgList &Args) {
@@ -1339,12 +1475,6 @@ static std::string GetHexagonSmallDataThresholdValue(const ArgList &Args) {
void Clang::AddHexagonTargetArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
- llvm::Triple Triple = getToolChain().getTriple();
-
- CmdArgs.push_back("-target-cpu");
- CmdArgs.push_back(Args.MakeArgString(
- "hexagon"
- + toolchains::Hexagon_TC::GetTargetCPU(Args)));
CmdArgs.push_back("-fno-signed-char");
CmdArgs.push_back("-mqdsp6-compat");
CmdArgs.push_back("-Wreturn-type");
@@ -1366,6 +1496,70 @@ void Clang::AddHexagonTargetArgs(const ArgList &Args,
CmdArgs.push_back ("-machine-sink-split=0");
}
+static void getAArch64TargetFeatures(const Driver &D, const ArgList &Args,
+ std::vector<const char *> &Features) {
+ // Honor -mfpu=.
+ if (const Arg *A = Args.getLastArg(options::OPT_mfpu_EQ))
+ getAArch64FPUFeatures(D, A, Args, Features);
+}
+
+static void getTargetFeatures(const Driver &D, const llvm::Triple &Triple,
+ const ArgList &Args, ArgStringList &CmdArgs) {
+ std::vector<const char *> Features;
+ switch (Triple.getArch()) {
+ default:
+ break;
+ case llvm::Triple::mips:
+ case llvm::Triple::mipsel:
+ case llvm::Triple::mips64:
+ case llvm::Triple::mips64el:
+ getMIPSTargetFeatures(D, Args, Features);
+ break;
+
+ case llvm::Triple::arm:
+ case llvm::Triple::thumb:
+ getARMTargetFeatures(D, Triple, Args, Features);
+ break;
+
+ case llvm::Triple::ppc:
+ case llvm::Triple::ppc64:
+ case llvm::Triple::ppc64le:
+ getPPCTargetFeatures(Args, Features);
+ break;
+ case llvm::Triple::sparc:
+ getSparcTargetFeatures(Args, Features);
+ break;
+ case llvm::Triple::aarch64:
+ getAArch64TargetFeatures(D, Args, Features);
+ break;
+ case llvm::Triple::x86:
+ case llvm::Triple::x86_64:
+ getX86TargetFeatures(Triple, Args, Features);
+ break;
+ }
+
+ // Find the last of each feature.
+ llvm::StringMap<unsigned> LastOpt;
+ for (unsigned I = 0, N = Features.size(); I < N; ++I) {
+ const char *Name = Features[I];
+ assert(Name[0] == '-' || Name[0] == '+');
+ LastOpt[Name + 1] = I;
+ }
+
+ for (unsigned I = 0, N = Features.size(); I < N; ++I) {
+ // If this feature was overridden, ignore it.
+ const char *Name = Features[I];
+ llvm::StringMap<unsigned>::iterator LastI = LastOpt.find(Name + 1);
+ assert(LastI != LastOpt.end());
+ unsigned Last = LastI->second;
+ if (Last != I)
+ continue;
+
+ CmdArgs.push_back("-target-feature");
+ CmdArgs.push_back(Name);
+ }
+}
+
static bool
shouldUseExceptionTablesForObjCExceptions(const ObjCRuntime &runtime,
const llvm::Triple &Triple) {
@@ -1532,117 +1726,75 @@ static bool UseRelaxAll(Compilation &C, const ArgList &Args) {
RelaxDefault);
}
-SanitizerArgs::SanitizerArgs(const ToolChain &TC, const ArgList &Args)
- : Kind(0), BlacklistFile(""), MsanTrackOrigins(false),
- AsanZeroBaseShadow(false) {
- unsigned AllKinds = 0; // All kinds of sanitizers that were turned on
- // at least once (possibly, disabled further).
- const Driver &D = TC.getDriver();
- for (ArgList::const_iterator I = Args.begin(), E = Args.end(); I != E; ++I) {
- unsigned Add, Remove;
- if (!parse(D, Args, *I, Add, Remove, true))
- continue;
- (*I)->claim();
- Kind |= Add;
- Kind &= ~Remove;
- AllKinds |= Add;
- }
+static void CollectArgsForIntegratedAssembler(Compilation &C,
+ const ArgList &Args,
+ ArgStringList &CmdArgs,
+ const Driver &D) {
+ if (UseRelaxAll(C, Args))
+ CmdArgs.push_back("-mrelax-all");
- UbsanTrapOnError =
- Args.hasArg(options::OPT_fcatch_undefined_behavior) ||
- Args.hasFlag(options::OPT_fsanitize_undefined_trap_on_error,
- options::OPT_fno_sanitize_undefined_trap_on_error, false);
+ // When passing -I arguments to the assembler we sometimes need to
+ // unconditionally take the next argument. For example, when parsing
+ // '-Wa,-I -Wa,foo' we need to accept the -Wa,foo arg after seeing the
+ // -Wa,-I arg and when parsing '-Wa,-I,foo' we need to accept the 'foo'
+ // arg after parsing the '-I' arg.
+ bool TakeNextArg = false;
- if (Args.hasArg(options::OPT_fcatch_undefined_behavior) &&
- !Args.hasFlag(options::OPT_fsanitize_undefined_trap_on_error,
- options::OPT_fno_sanitize_undefined_trap_on_error, true)) {
- D.Diag(diag::err_drv_argument_not_allowed_with)
- << "-fcatch-undefined-behavior"
- << "-fno-sanitize-undefined-trap-on-error";
- }
+ // When using an integrated assembler, translate -Wa, and -Xassembler
+ // options.
+ for (arg_iterator it = Args.filtered_begin(options::OPT_Wa_COMMA,
+ options::OPT_Xassembler),
+ ie = Args.filtered_end(); it != ie; ++it) {
+ const Arg *A = *it;
+ A->claim();
- // Warn about undefined sanitizer options that require runtime support.
- if (UbsanTrapOnError && notAllowedWithTrap()) {
- if (Args.hasArg(options::OPT_fcatch_undefined_behavior))
- D.Diag(diag::err_drv_argument_not_allowed_with)
- << lastArgumentForKind(D, Args, NotAllowedWithTrap)
- << "-fcatch-undefined-behavior";
- else if (Args.hasFlag(options::OPT_fsanitize_undefined_trap_on_error,
- options::OPT_fno_sanitize_undefined_trap_on_error,
- false))
- D.Diag(diag::err_drv_argument_not_allowed_with)
- << lastArgumentForKind(D, Args, NotAllowedWithTrap)
- << "-fsanitize-undefined-trap-on-error";
- }
-
- // Only one runtime library can be used at once.
- bool NeedsAsan = needsAsanRt();
- bool NeedsTsan = needsTsanRt();
- bool NeedsMsan = needsMsanRt();
- if (NeedsAsan && NeedsTsan)
- D.Diag(diag::err_drv_argument_not_allowed_with)
- << lastArgumentForKind(D, Args, NeedsAsanRt)
- << lastArgumentForKind(D, Args, NeedsTsanRt);
- if (NeedsAsan && NeedsMsan)
- D.Diag(diag::err_drv_argument_not_allowed_with)
- << lastArgumentForKind(D, Args, NeedsAsanRt)
- << lastArgumentForKind(D, Args, NeedsMsanRt);
- if (NeedsTsan && NeedsMsan)
- D.Diag(diag::err_drv_argument_not_allowed_with)
- << lastArgumentForKind(D, Args, NeedsTsanRt)
- << lastArgumentForKind(D, Args, NeedsMsanRt);
-
- // If -fsanitize contains extra features of ASan, it should also
- // explicitly contain -fsanitize=address (probably, turned off later in the
- // command line).
- if ((Kind & AddressFull) != 0 && (AllKinds & Address) == 0)
- D.Diag(diag::warn_drv_unused_sanitizer)
- << lastArgumentForKind(D, Args, AddressFull)
- << "-fsanitize=address";
-
- // Parse -f(no-)sanitize-blacklist options.
- if (Arg *BLArg = Args.getLastArg(options::OPT_fsanitize_blacklist,
- options::OPT_fno_sanitize_blacklist)) {
- if (BLArg->getOption().matches(options::OPT_fsanitize_blacklist)) {
- std::string BLPath = BLArg->getValue();
- bool BLExists = false;
- if (!llvm::sys::fs::exists(BLPath, BLExists) && BLExists)
- BlacklistFile = BLPath;
- else
- D.Diag(diag::err_drv_no_such_file) << BLPath;
- }
- } else {
- // If no -fsanitize-blacklist option is specified, try to look up for
- // blacklist in the resource directory.
- std::string BLPath;
- bool BLExists = false;
- if (getDefaultBlacklistForKind(D, Kind, BLPath) &&
- !llvm::sys::fs::exists(BLPath, BLExists) && BLExists)
- BlacklistFile = BLPath;
- }
-
- // Parse -f(no-)sanitize-memory-track-origins options.
- if (NeedsMsan)
- MsanTrackOrigins =
- Args.hasFlag(options::OPT_fsanitize_memory_track_origins,
- options::OPT_fno_sanitize_memory_track_origins,
- /* Default */false);
-
- // Parse -f(no-)sanitize-address-zero-base-shadow options.
- if (NeedsAsan) {
- bool IsAndroid = (TC.getTriple().getEnvironment() == llvm::Triple::Android);
- bool ZeroBaseShadowDefault = IsAndroid;
- AsanZeroBaseShadow =
- Args.hasFlag(options::OPT_fsanitize_address_zero_base_shadow,
- options::OPT_fno_sanitize_address_zero_base_shadow,
- ZeroBaseShadowDefault);
- // Zero-base shadow is a requirement on Android.
- if (IsAndroid && !AsanZeroBaseShadow) {
- D.Diag(diag::err_drv_argument_not_allowed_with)
- << "-fno-sanitize-address-zero-base-shadow"
- << lastArgumentForKind(D, Args, Address);
+ for (unsigned i = 0, e = A->getNumValues(); i != e; ++i) {
+ StringRef Value = A->getValue(i);
+ if (TakeNextArg) {
+ CmdArgs.push_back(Value.data());
+ TakeNextArg = false;
+ continue;
+ }
+
+ if (Value == "-force_cpusubtype_ALL") {
+ // Do nothing, this is the default and we don't support anything else.
+ } else if (Value == "-L") {
+ CmdArgs.push_back("-msave-temp-labels");
+ } else if (Value == "--fatal-warnings") {
+ CmdArgs.push_back("-mllvm");
+ CmdArgs.push_back("-fatal-assembler-warnings");
+ } else if (Value == "--noexecstack") {
+ CmdArgs.push_back("-mnoexecstack");
+ } else if (Value.startswith("-I")) {
+ CmdArgs.push_back(Value.data());
+ // We need to consume the next argument if the current arg is a plain
+ // -I. The next arg will be the include directory.
+ if (Value == "-I")
+ TakeNextArg = true;
+ } else {
+ D.Diag(diag::err_drv_unsupported_option_argument)
+ << A->getOption().getName() << Value;
+ }
+ }
}
- }
+}
+
+static void addProfileRTLinux(
+ const ToolChain &TC, const ArgList &Args, ArgStringList &CmdArgs) {
+ if (!(Args.hasArg(options::OPT_fprofile_arcs) ||
+ Args.hasArg(options::OPT_fprofile_generate) ||
+ Args.hasArg(options::OPT_fcreate_profile) ||
+ Args.hasArg(options::OPT_coverage)))
+ return;
+
+ // The profile runtime is located in the Linux library directory and has name
+ // "libclang_rt.profile-<ArchName>.a".
+ SmallString<128> LibProfile(TC.getDriver().ResourceDir);
+ llvm::sys::path::append(
+ LibProfile, "lib", "linux",
+ Twine("libclang_rt.profile-") + TC.getArchName() + ".a");
+
+ CmdArgs.push_back(Args.MakeArgString(LibProfile));
}
static void addSanitizerRTLinkFlagsLinux(
@@ -1673,6 +1825,7 @@ static void addSanitizerRTLinkFlagsLinux(
CmdArgs.push_back("-lpthread");
CmdArgs.push_back("-lrt");
CmdArgs.push_back("-ldl");
+ CmdArgs.push_back("-lm");
// If possible, use a dynamic symbols file to export the symbols from the
// runtime library. If we can't do so, use -export-dynamic instead to export
@@ -1690,16 +1843,15 @@ static void addSanitizerRTLinkFlagsLinux(
/// This needs to be called before we add the C run-time (malloc, etc).
static void addAsanRTLinux(const ToolChain &TC, const ArgList &Args,
ArgStringList &CmdArgs) {
- if(TC.getTriple().getEnvironment() == llvm::Triple::Android) {
+ if (TC.getTriple().getEnvironment() == llvm::Triple::Android) {
SmallString<128> LibAsan(TC.getDriver().ResourceDir);
llvm::sys::path::append(LibAsan, "lib", "linux",
(Twine("libclang_rt.asan-") +
TC.getArchName() + "-android.so"));
CmdArgs.insert(CmdArgs.begin(), Args.MakeArgString(LibAsan));
} else {
- if (!Args.hasArg(options::OPT_shared)) {
+ if (!Args.hasArg(options::OPT_shared))
addSanitizerRTLinkFlagsLinux(TC, Args, CmdArgs, "asan", true);
- }
}
}
@@ -1707,18 +1859,24 @@ static void addAsanRTLinux(const ToolChain &TC, const ArgList &Args,
/// This needs to be called before we add the C run-time (malloc, etc).
static void addTsanRTLinux(const ToolChain &TC, const ArgList &Args,
ArgStringList &CmdArgs) {
- if (!Args.hasArg(options::OPT_shared)) {
+ if (!Args.hasArg(options::OPT_shared))
addSanitizerRTLinkFlagsLinux(TC, Args, CmdArgs, "tsan", true);
- }
}
/// If MemorySanitizer is enabled, add appropriate linker flags (Linux).
/// This needs to be called before we add the C run-time (malloc, etc).
static void addMsanRTLinux(const ToolChain &TC, const ArgList &Args,
ArgStringList &CmdArgs) {
- if (!Args.hasArg(options::OPT_shared)) {
+ if (!Args.hasArg(options::OPT_shared))
addSanitizerRTLinkFlagsLinux(TC, Args, CmdArgs, "msan", true);
- }
+}
+
+/// If LeakSanitizer is enabled, add appropriate linker flags (Linux).
+/// This needs to be called before we add the C run-time (malloc, etc).
+static void addLsanRTLinux(const ToolChain &TC, const ArgList &Args,
+ ArgStringList &CmdArgs) {
+ if (!Args.hasArg(options::OPT_shared))
+ addSanitizerRTLinkFlagsLinux(TC, Args, CmdArgs, "lsan", true);
}
/// If UndefinedBehaviorSanitizer is enabled, add appropriate linker flags
@@ -1726,9 +1884,6 @@ static void addMsanRTLinux(const ToolChain &TC, const ArgList &Args,
static void addUbsanRTLinux(const ToolChain &TC, const ArgList &Args,
ArgStringList &CmdArgs, bool IsCXX,
bool HasOtherSanitizerRt) {
- if (Args.hasArg(options::OPT_shared))
- return;
-
// Need a copy of sanitizer_common. This could come from another sanitizer
// runtime; if we're not including one, include our own copy.
if (!HasOtherSanitizerRt)
@@ -1742,22 +1897,42 @@ static void addUbsanRTLinux(const ToolChain &TC, const ArgList &Args,
addSanitizerRTLinkFlagsLinux(TC, Args, CmdArgs, "ubsan_cxx", false);
}
+static void addDfsanRTLinux(const ToolChain &TC, const ArgList &Args,
+ ArgStringList &CmdArgs) {
+ if (!Args.hasArg(options::OPT_shared))
+ addSanitizerRTLinkFlagsLinux(TC, Args, CmdArgs, "dfsan", true);
+}
+
+static bool shouldUseFramePointerForTarget(const ArgList &Args,
+ const llvm::Triple &Triple) {
+ switch (Triple.getArch()) {
+ // Don't use a frame pointer on linux if optimizing for certain targets.
+ case llvm::Triple::mips64:
+ case llvm::Triple::mips64el:
+ case llvm::Triple::mips:
+ case llvm::Triple::mipsel:
+ case llvm::Triple::systemz:
+ case llvm::Triple::x86:
+ case llvm::Triple::x86_64:
+ if (Triple.isOSLinux())
+ if (Arg *A = Args.getLastArg(options::OPT_O_Group))
+ if (!A->getOption().matches(options::OPT_O0))
+ return false;
+ return true;
+ case llvm::Triple::xcore:
+ return false;
+ default:
+ return true;
+ }
+}
+
static bool shouldUseFramePointer(const ArgList &Args,
const llvm::Triple &Triple) {
if (Arg *A = Args.getLastArg(options::OPT_fno_omit_frame_pointer,
options::OPT_fomit_frame_pointer))
return A->getOption().matches(options::OPT_fno_omit_frame_pointer);
- // Don't use a frame pointer on linux x86 and x86_64 if optimizing.
- if ((Triple.getArch() == llvm::Triple::x86_64 ||
- Triple.getArch() == llvm::Triple::x86) &&
- Triple.getOS() == llvm::Triple::Linux) {
- if (Arg *A = Args.getLastArg(options::OPT_O_Group))
- if (!A->getOption().matches(options::OPT_O0))
- return false;
- }
-
- return true;
+ return shouldUseFramePointerForTarget(Args, Triple);
}
static bool shouldUseLeafFramePointer(const ArgList &Args,
@@ -1766,38 +1941,11 @@ static bool shouldUseLeafFramePointer(const ArgList &Args,
options::OPT_momit_leaf_frame_pointer))
return A->getOption().matches(options::OPT_mno_omit_leaf_frame_pointer);
- // Don't use a leaf frame pointer on linux x86 and x86_64 if optimizing.
- if ((Triple.getArch() == llvm::Triple::x86_64 ||
- Triple.getArch() == llvm::Triple::x86) &&
- Triple.getOS() == llvm::Triple::Linux) {
- if (Arg *A = Args.getLastArg(options::OPT_O_Group))
- if (!A->getOption().matches(options::OPT_O0))
- return false;
- }
-
- return true;
+ return shouldUseFramePointerForTarget(Args, Triple);
}
-/// If the PWD environment variable is set, add a CC1 option to specify the
-/// debug compilation directory.
+/// Add a CC1 option to specify the debug compilation directory.
static void addDebugCompDirArg(const ArgList &Args, ArgStringList &CmdArgs) {
- struct stat StatPWDBuf, StatDotBuf;
-
- const char *pwd = ::getenv("PWD");
- if (!pwd)
- return;
-
- if (llvm::sys::path::is_absolute(pwd) &&
- stat(pwd, &StatPWDBuf) == 0 &&
- stat(".", &StatDotBuf) == 0 &&
- StatPWDBuf.st_ino == StatDotBuf.st_ino &&
- StatPWDBuf.st_dev == StatDotBuf.st_dev) {
- CmdArgs.push_back("-fdebug-compilation-dir");
- CmdArgs.push_back(Args.MakeArgString(pwd));
- return;
- }
-
- // Fall back to using getcwd.
SmallString<128> cwd;
if (!llvm::sys::fs::current_path(cwd)) {
CmdArgs.push_back("-fdebug-compilation-dir");
@@ -1854,6 +2002,37 @@ static bool isOptimizationLevelFast(const ArgList &Args) {
return false;
}
+/// \brief Vectorize at all optimization levels greater than 1 except for -Oz.
+static bool shouldEnableVectorizerAtOLevel(const ArgList &Args) {
+ if (Arg *A = Args.getLastArg(options::OPT_O_Group)) {
+ if (A->getOption().matches(options::OPT_O4) ||
+ A->getOption().matches(options::OPT_Ofast))
+ return true;
+
+ if (A->getOption().matches(options::OPT_O0))
+ return false;
+
+ assert(A->getOption().matches(options::OPT_O) && "Must have a -O flag");
+
+ // Vectorize -Os.
+ StringRef S(A->getValue());
+ if (S == "s")
+ return true;
+
+ // Don't vectorize -Oz.
+ if (S == "z")
+ return false;
+
+ unsigned OptLevel = 0;
+ if (S.getAsInteger(10, OptLevel))
+ return false;
+
+ return OptLevel > 1;
+ }
+
+ return false;
+}
+
void Clang::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
@@ -1896,35 +2075,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
} else if (isa<AssembleJobAction>(JA)) {
CmdArgs.push_back("-emit-obj");
- if (UseRelaxAll(C, Args))
- CmdArgs.push_back("-mrelax-all");
-
- // When using an integrated assembler, translate -Wa, and -Xassembler
- // options.
- for (arg_iterator it = Args.filtered_begin(options::OPT_Wa_COMMA,
- options::OPT_Xassembler),
- ie = Args.filtered_end(); it != ie; ++it) {
- const Arg *A = *it;
- A->claim();
-
- for (unsigned i = 0, e = A->getNumValues(); i != e; ++i) {
- StringRef Value = A->getValue(i);
-
- if (Value == "-force_cpusubtype_ALL") {
- // Do nothing, this is the default and we don't support anything else.
- } else if (Value == "-L") {
- CmdArgs.push_back("-msave-temp-labels");
- } else if (Value == "--fatal-warnings") {
- CmdArgs.push_back("-mllvm");
- CmdArgs.push_back("-fatal-assembler-warnings");
- } else if (Value == "--noexecstack") {
- CmdArgs.push_back("-mnoexecstack");
- } else {
- D.Diag(diag::err_drv_unsupported_option_argument)
- << A->getOption().getName() << Value;
- }
- }
- }
+ CollectArgsForIntegratedAssembler(C, Args, CmdArgs, D);
// Also ignore explicit -force_cpusubtype_ALL option.
(void) Args.hasArg(options::OPT_force__cpusubtype__ALL);
@@ -2071,7 +2222,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
}
}
- // Inroduce a Darwin-specific hack. If the default is PIC but the flags
+ // Introduce a Darwin-specific hack. If the default is PIC but the flags
// specified while enabling PIC enabled level 1 PIC, just force it back to
// level 2 PIC instead. This matches the behavior of Darwin GCC (based on my
// informal testing).
@@ -2082,8 +2233,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// PIC or PIE options above, if these show up, PIC is disabled.
llvm::Triple Triple(TripleStr);
if (KernelOrKext &&
- (Triple.getOS() != llvm::Triple::IOS ||
- Triple.isOSVersionLT(6)))
+ (!Triple.isiOS() || Triple.isOSVersionLT(6)))
PIC = PIE = false;
if (Args.hasArg(options::OPT_static))
PIC = PIE = false;
@@ -2134,6 +2284,19 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(A->getValue());
}
+ if (Arg *A = Args.getLastArg(options::OPT_fpcc_struct_return,
+ options::OPT_freg_struct_return)) {
+ if (getToolChain().getArch() != llvm::Triple::x86) {
+ D.Diag(diag::err_drv_unsupported_opt_for_target)
+ << A->getSpelling() << getToolChain().getTriple().str();
+ } else if (A->getOption().matches(options::OPT_fpcc_struct_return)) {
+ CmdArgs.push_back("-fpcc-struct-return");
+ } else {
+ assert(A->getOption().matches(options::OPT_freg_struct_return));
+ CmdArgs.push_back("-freg-struct-return");
+ }
+ }
+
if (Args.hasFlag(options::OPT_mrtd, options::OPT_mno_rtd, false))
CmdArgs.push_back("-mrtd");
@@ -2149,11 +2312,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
OptSpecifier StrictAliasingAliasOption = OFastEnabled ? options::OPT_Ofast :
options::OPT_fstrict_aliasing;
if (!Args.hasFlag(options::OPT_fstrict_aliasing, StrictAliasingAliasOption,
- options::OPT_fno_strict_aliasing,
- getToolChain().IsStrictAliasingDefault()))
+ options::OPT_fno_strict_aliasing, true))
CmdArgs.push_back("-relaxed-aliasing");
- if (Args.hasArg(options::OPT_fstruct_path_tbaa))
- CmdArgs.push_back("-struct-path-tbaa");
+ if (!Args.hasFlag(options::OPT_fstruct_path_tbaa,
+ options::OPT_fno_struct_path_tbaa))
+ CmdArgs.push_back("-no-struct-path-tbaa");
if (Args.hasFlag(options::OPT_fstrict_enums, options::OPT_fno_strict_enums,
false))
CmdArgs.push_back("-fstrict-enums");
@@ -2201,8 +2364,17 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (Arg *A = Args.getLastArg(options::OPT_ffast_math, FastMathAliasOption,
options::OPT_fno_fast_math,
options::OPT_fmath_errno,
- options::OPT_fno_math_errno))
- MathErrno = A->getOption().getID() == options::OPT_fmath_errno;
+ options::OPT_fno_math_errno)) {
+ // Turning on -ffast_math (with either flag) removes the need for MathErrno.
+ // However, turning *off* -ffast_math merely restores the toolchain default
+ // (which may be false).
+ if (A->getOption().getID() == options::OPT_fno_math_errno ||
+ A->getOption().getID() == options::OPT_ffast_math ||
+ A->getOption().getID() == options::OPT_Ofast)
+ MathErrno = false;
+ else if (A->getOption().getID() == options::OPT_fmath_errno)
+ MathErrno = true;
+ }
if (MathErrno)
CmdArgs.push_back("-fmath-errno");
@@ -2349,8 +2521,25 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(A->getValue());
}
- // Add target specific cpu and features flags.
- switch(getToolChain().getTriple().getArch()) {
+ // Add the target cpu
+ std::string ETripleStr = getToolChain().ComputeEffectiveClangTriple(Args);
+ llvm::Triple ETriple(ETripleStr);
+ std::string CPU = getCPUName(Args, ETriple);
+ if (!CPU.empty()) {
+ CmdArgs.push_back("-target-cpu");
+ CmdArgs.push_back(Args.MakeArgString(CPU));
+ }
+
+ if (const Arg *A = Args.getLastArg(options::OPT_mfpmath_EQ)) {
+ CmdArgs.push_back("-mfpmath");
+ CmdArgs.push_back(A->getValue());
+ }
+
+ // Add the target features
+ getTargetFeatures(D, ETriple, Args, CmdArgs);
+
+ // Add target specific flags.
+ switch(getToolChain().getArch()) {
default:
break;
@@ -2366,15 +2555,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
AddMIPSTargetArgs(Args, CmdArgs);
break;
- case llvm::Triple::ppc:
- case llvm::Triple::ppc64:
- AddPPCTargetArgs(Args, CmdArgs);
- break;
-
- case llvm::Triple::r600:
- AddR600TargetArgs(Args, CmdArgs);
- break;
-
case llvm::Triple::sparc:
AddSparcTargetArgs(Args, CmdArgs);
break;
@@ -2389,7 +2569,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
break;
}
-
+ // Add clang-cl arguments.
+ if (getToolChain().getDriver().IsCLMode())
+ AddClangCLArgs(Args, CmdArgs);
// Pass the linker version in use.
if (Arg *A = Args.getLastArg(options::OPT_mlinker_version_EQ)) {
@@ -2407,7 +2589,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Arg *Unsupported;
if (types::isCXX(InputType) &&
getToolChain().getTriple().isOSDarwin() &&
- getToolChain().getTriple().getArch() == llvm::Triple::x86) {
+ getToolChain().getArch() == llvm::Triple::x86) {
if ((Unsupported = Args.getLastArg(options::OPT_fapple_kext)) ||
(Unsupported = Args.getLastArg(options::OPT_mkernel)))
D.Diag(diag::err_drv_clang_unsupported_opt_cxx_darwin_i386)
@@ -2437,9 +2619,20 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (Arg *A = Args.getLastArg(options::OPT_g_Group)) {
if (A->getOption().matches(options::OPT_gline_tables_only))
CmdArgs.push_back("-gline-tables-only");
+ else if (A->getOption().matches(options::OPT_gdwarf_2))
+ CmdArgs.push_back("-gdwarf-2");
+ else if (A->getOption().matches(options::OPT_gdwarf_3))
+ CmdArgs.push_back("-gdwarf-3");
+ else if (A->getOption().matches(options::OPT_gdwarf_4))
+ CmdArgs.push_back("-gdwarf-4");
else if (!A->getOption().matches(options::OPT_g0) &&
- !A->getOption().matches(options::OPT_ggdb0))
- CmdArgs.push_back("-g");
+ !A->getOption().matches(options::OPT_ggdb0)) {
+ // Default is dwarf-2 for darwin.
+ if (getToolChain().getTriple().isOSDarwin())
+ CmdArgs.push_back("-gdwarf-2");
+ else
+ CmdArgs.push_back("-g");
+ }
}
// We ignore flags -gstrict-dwarf and -grecord-gcc-switches for now.
@@ -2447,16 +2640,25 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (Args.hasArg(options::OPT_gcolumn_info))
CmdArgs.push_back("-dwarf-column-info");
+ // FIXME: Move backend command line options to the module.
// -gsplit-dwarf should turn on -g and enable the backend dwarf
// splitting and extraction.
// FIXME: Currently only works on Linux.
- if (getToolChain().getTriple().getOS() == llvm::Triple::Linux &&
+ if (getToolChain().getTriple().isOSLinux() &&
Args.hasArg(options::OPT_gsplit_dwarf)) {
CmdArgs.push_back("-g");
CmdArgs.push_back("-backend-option");
CmdArgs.push_back("-split-dwarf=Enable");
}
+ // -ggnu-pubnames turns on gnu style pubnames in the backend.
+ if (Args.hasArg(options::OPT_ggnu_pubnames)) {
+ CmdArgs.push_back("-backend-option");
+ CmdArgs.push_back("-generate-gnu-dwarf-pub-sections");
+ }
+
+ Args.AddAllArgs(CmdArgs, options::OPT_fdebug_types_section);
+
Args.AddAllArgs(CmdArgs, options::OPT_ffunction_sections);
Args.AddAllArgs(CmdArgs, options::OPT_fdata_sections);
@@ -2475,12 +2677,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-coverage-file");
SmallString<128> CoverageFilename(Output.getFilename());
if (llvm::sys::path::is_relative(CoverageFilename.str())) {
- if (const char *pwd = ::getenv("PWD")) {
- if (llvm::sys::path::is_absolute(pwd)) {
- SmallString<128> Pwd(pwd);
- llvm::sys::path::append(Pwd, CoverageFilename.str());
- CoverageFilename.swap(Pwd);
- }
+ SmallString<128> Pwd;
+ if (!llvm::sys::fs::current_path(Pwd)) {
+ llvm::sys::path::append(Pwd, CoverageFilename.str());
+ CoverageFilename.swap(Pwd);
}
}
CmdArgs.push_back(Args.MakeArgString(CoverageFilename));
@@ -2505,7 +2705,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddLastArg(CmdArgs, options::OPT_working_directory);
bool ARCMTEnabled = false;
- if (!Args.hasArg(options::OPT_fno_objc_arc)) {
+ if (!Args.hasArg(options::OPT_fno_objc_arc, options::OPT_fobjc_arc)) {
if (const Arg *A = Args.getLastArg(options::OPT_ccc_arcmt_check,
options::OPT_ccc_arcmt_modify,
options::OPT_ccc_arcmt_migrate)) {
@@ -2529,6 +2729,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
break;
}
}
+ } else {
+ Args.ClaimAllArgs(options::OPT_ccc_arcmt_check);
+ Args.ClaimAllArgs(options::OPT_ccc_arcmt_modify);
+ Args.ClaimAllArgs(options::OPT_ccc_arcmt_migrate);
}
if (const Arg *A = Args.getLastArg(options::OPT_ccc_objcmt_migrate)) {
@@ -2540,14 +2744,32 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(A->getValue());
if (!Args.hasArg(options::OPT_objcmt_migrate_literals,
- options::OPT_objcmt_migrate_subscripting)) {
+ options::OPT_objcmt_migrate_subscripting,
+ options::OPT_objcmt_migrate_property)) {
// None specified, means enable them all.
CmdArgs.push_back("-objcmt-migrate-literals");
CmdArgs.push_back("-objcmt-migrate-subscripting");
+ CmdArgs.push_back("-objcmt-migrate-property");
} else {
Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_literals);
Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_subscripting);
+ Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_property);
}
+ } else {
+ Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_literals);
+ Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_subscripting);
+ Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_property);
+ Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_all);
+ Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_readonly_property);
+ Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_readwrite_property);
+ Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_annotation);
+ Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_instancetype);
+ Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_nsmacros);
+ Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_protocol_conformance);
+ Args.AddLastArg(CmdArgs, options::OPT_objcmt_atomic_property);
+ Args.AddLastArg(CmdArgs, options::OPT_objcmt_returns_innerpointer_property);
+ Args.AddLastArg(CmdArgs, options::OPT_objcmt_ns_nonatomic_iosonly);
+ Args.AddLastArg(CmdArgs, options::OPT_objcmt_white_list_dir_path);
}
// Add preprocessing options like -I, -D, etc. if we are using the
@@ -2563,16 +2785,14 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// preprocessed inputs and configure concludes that -fPIC is not supported.
Args.ClaimAllArgs(options::OPT_D);
- // Manually translate -O to -O2 and -O4 to -O3; let clang reject
- // others.
+ // Manually translate -O4 to -O3; let clang reject others.
if (Arg *A = Args.getLastArg(options::OPT_O_Group)) {
- if (A->getOption().matches(options::OPT_O4))
+ if (A->getOption().matches(options::OPT_O4)) {
CmdArgs.push_back("-O3");
- else if (A->getOption().matches(options::OPT_O) &&
- A->getValue()[0] == '\0')
- CmdArgs.push_back("-O2");
- else
+ D.Diag(diag::warn_O4_is_O3);
+ } else {
A->render(Args, CmdArgs);
+ }
}
// Don't warn about unused -flto. This can happen when we're preprocessing or
@@ -2586,7 +2806,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddLastArg(CmdArgs, options::OPT_w);
// Handle -{std, ansi, trigraphs} -- take the last of -{std, ansi}
- // (-ansi is equivalent to -std=c89).
+ // (-ansi is equivalent to -std=c89 or -std=c++98).
//
// If a std is supplied, only add -trigraphs if it follows the
// option.
@@ -2619,13 +2839,20 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddLastArg(CmdArgs, options::OPT_trigraphs);
}
- // Map the bizarre '-Wwrite-strings' flag to a more sensible
- // '-fconst-strings'; this better indicates its actual behavior.
- if (Args.hasFlag(options::OPT_Wwrite_strings, options::OPT_Wno_write_strings,
- false)) {
- // For perfect compatibility with GCC, we do this even in the presence of
- // '-w'. This flag names something other than a warning for GCC.
- CmdArgs.push_back("-fconst-strings");
+ // GCC's behavior for -Wwrite-strings is a bit strange:
+ // * In C, this "warning flag" changes the types of string literals from
+ // 'char[N]' to 'const char[N]', and thus triggers an unrelated warning
+ // for the discarded qualifier.
+ // * In C++, this is just a normal warning flag.
+ //
+ // Implementing this warning correctly in C is hard, so we follow GCC's
+ // behavior for now. FIXME: Directly diagnose uses of a string literal as
+ // a non-const char* in C, rather than using this crude hack.
+ if (!types::isCXX(InputType)) {
+ DiagnosticsEngine::Level DiagLevel = D.getDiags().getDiagnosticLevel(
+ diag::warn_deprecated_string_literal_conversion_c, SourceLocation());
+ if (DiagLevel > DiagnosticsEngine::Ignored)
+ CmdArgs.push_back("-fconst-strings");
}
// GCC provides a macro definition '__DEPRECATED' when -Wdeprecated is active
@@ -2663,11 +2890,21 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(A->getValue());
}
+ if (Arg *A = Args.getLastArg(options::OPT_foperator_arrow_depth_EQ)) {
+ CmdArgs.push_back("-foperator-arrow-depth");
+ CmdArgs.push_back(A->getValue());
+ }
+
if (Arg *A = Args.getLastArg(options::OPT_fconstexpr_depth_EQ)) {
CmdArgs.push_back("-fconstexpr-depth");
CmdArgs.push_back(A->getValue());
}
+ if (Arg *A = Args.getLastArg(options::OPT_fconstexpr_steps_EQ)) {
+ CmdArgs.push_back("-fconstexpr-steps");
+ CmdArgs.push_back(A->getValue());
+ }
+
if (Arg *A = Args.getLastArg(options::OPT_fbracket_depth_EQ)) {
CmdArgs.push_back("-fbracket-depth");
CmdArgs.push_back(A->getValue());
@@ -2759,11 +2996,14 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddLastArg(CmdArgs, options::OPT_flimit_debug_info);
Args.AddLastArg(CmdArgs, options::OPT_fno_limit_debug_info);
Args.AddLastArg(CmdArgs, options::OPT_fno_operator_names);
- Args.AddLastArg(CmdArgs, options::OPT_faltivec);
+ // AltiVec language extensions aren't relevant for assembling.
+ if (!isa<PreprocessJobAction>(JA) ||
+ Output.getType() != types::TY_PP_Asm)
+ Args.AddLastArg(CmdArgs, options::OPT_faltivec);
Args.AddLastArg(CmdArgs, options::OPT_fdiagnostics_show_template_tree);
Args.AddLastArg(CmdArgs, options::OPT_fno_elide_type);
- SanitizerArgs Sanitize(getToolChain(), Args);
+ const SanitizerArgs &Sanitize = getToolChain().getSanitizerArgs();
Sanitize.addArgs(Args, CmdArgs);
if (!Args.hasFlag(options::OPT_fsanitize_recover,
@@ -2778,10 +3018,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// Report an error for -faltivec on anything other than PowerPC.
if (const Arg *A = Args.getLastArg(options::OPT_faltivec))
- if (!(getToolChain().getTriple().getArch() == llvm::Triple::ppc ||
- getToolChain().getTriple().getArch() == llvm::Triple::ppc64))
+ if (!(getToolChain().getArch() == llvm::Triple::ppc ||
+ getToolChain().getArch() == llvm::Triple::ppc64 ||
+ getToolChain().getArch() == llvm::Triple::ppc64le))
D.Diag(diag::err_drv_argument_only_allowed_with)
- << A->getAsString(Args) << "ppc/ppc64";
+ << A->getAsString(Args) << "ppc/ppc64/ppc64le";
if (getToolChain().SupportsProfiling())
Args.AddLastArg(CmdArgs, options::OPT_pg);
@@ -2822,8 +3063,15 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (A->getOption().matches(options::OPT_fno_strict_overflow))
CmdArgs.push_back("-fwrapv");
}
+
+ if (Arg *A = Args.getLastArg(options::OPT_freroll_loops,
+ options::OPT_fno_reroll_loops))
+ if (A->getOption().matches(options::OPT_freroll_loops))
+ CmdArgs.push_back("-freroll-loops");
+
Args.AddLastArg(CmdArgs, options::OPT_fwritable_strings);
- Args.AddLastArg(CmdArgs, options::OPT_funroll_loops);
+ Args.AddLastArg(CmdArgs, options::OPT_funroll_loops,
+ options::OPT_fno_unroll_loops);
Args.AddLastArg(CmdArgs, options::OPT_pthread);
@@ -2876,13 +3124,39 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(Args.MakeArgString("-mstack-alignment=" + alignment));
}
// -mkernel implies -mstrict-align; don't add the redundant option.
- if (Args.hasArg(options::OPT_mstrict_align) && !KernelOrKext) {
- CmdArgs.push_back("-backend-option");
- CmdArgs.push_back("-arm-strict-align");
+ if (!KernelOrKext) {
+ if (Arg *A = Args.getLastArg(options::OPT_mno_unaligned_access,
+ options::OPT_munaligned_access)) {
+ if (A->getOption().matches(options::OPT_mno_unaligned_access)) {
+ CmdArgs.push_back("-backend-option");
+ CmdArgs.push_back("-arm-strict-align");
+ } else {
+ CmdArgs.push_back("-backend-option");
+ CmdArgs.push_back("-arm-no-strict-align");
+ }
+ }
+ }
+
+ if (Arg *A = Args.getLastArg(options::OPT_mrestrict_it,
+ options::OPT_mno_restrict_it)) {
+ if (A->getOption().matches(options::OPT_mrestrict_it)) {
+ CmdArgs.push_back("-backend-option");
+ CmdArgs.push_back("-arm-restrict-it");
+ } else {
+ CmdArgs.push_back("-backend-option");
+ CmdArgs.push_back("-arm-no-restrict-it");
+ }
}
// Forward -f options with positive and negative forms; we translate
// these by hand.
+ if (Arg *A = Args.getLastArg(options::OPT_fprofile_sample_use_EQ)) {
+ StringRef fname = A->getValue();
+ if (!llvm::sys::fs::exists(fname))
+ D.Diag(diag::err_drv_no_such_file) << fname;
+ else
+ A->render(Args, CmdArgs);
+ }
if (Args.hasArg(options::OPT_mkernel)) {
if (!Args.hasArg(options::OPT_fapple_kext) && types::isCXX(InputType))
@@ -2926,6 +3200,35 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
}
}
+ // -fmodule-maps enables module map processing (off by default) for header
+ // checking. It is implied by -fmodules.
+ if (Args.hasFlag(options::OPT_fmodule_maps, options::OPT_fno_module_maps,
+ false)) {
+ CmdArgs.push_back("-fmodule-maps");
+ }
+
+ // -fmodules-decluse checks that modules used are declared so (off by
+ // default).
+ if (Args.hasFlag(options::OPT_fmodules_decluse,
+ options::OPT_fno_modules_decluse,
+ false)) {
+ CmdArgs.push_back("-fmodules-decluse");
+ }
+
+ // -fmodule-name specifies the module that is currently being built (or
+ // used for header checking by -fmodule-maps).
+ if (Arg *A = Args.getLastArg(options::OPT_fmodule_name)) {
+ A->claim();
+ A->render(Args, CmdArgs);
+ }
+
+ // -fmodule-map-file can be used to specify a file containing module
+ // definitions.
+ if (Arg *A = Args.getLastArg(options::OPT_fmodule_map_file)) {
+ A->claim();
+ A->render(Args, CmdArgs);
+ }
+
// If a module path was provided, pass it along. Otherwise, use a temporary
// directory.
if (Arg *A = Args.getLastArg(options::OPT_fmodules_cache_path)) {
@@ -2981,7 +3284,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// -fshort-enums=0 is default for all architectures except Hexagon.
if (Args.hasFlag(options::OPT_fshort_enums,
options::OPT_fno_short_enums,
- getToolChain().getTriple().getArch() ==
+ getToolChain().getArch() ==
llvm::Triple::hexagon))
CmdArgs.push_back("-fshort-enums");
@@ -2996,11 +3299,12 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-fno-threadsafe-statics");
// -fuse-cxa-atexit is default.
- if (!Args.hasFlag(options::OPT_fuse_cxa_atexit,
- options::OPT_fno_use_cxa_atexit,
- getToolChain().getTriple().getOS() != llvm::Triple::Cygwin &&
- getToolChain().getTriple().getOS() != llvm::Triple::MinGW32 &&
- getToolChain().getTriple().getArch() != llvm::Triple::hexagon) ||
+ if (!Args.hasFlag(
+ options::OPT_fuse_cxa_atexit, options::OPT_fno_use_cxa_atexit,
+ getToolChain().getTriple().getOS() != llvm::Triple::Cygwin &&
+ getToolChain().getTriple().getOS() != llvm::Triple::MinGW32 &&
+ getToolChain().getArch() != llvm::Triple::hexagon &&
+ getToolChain().getArch() != llvm::Triple::xcore) ||
KernelOrKext)
CmdArgs.push_back("-fno-use-cxa-atexit");
@@ -3018,13 +3322,13 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
true))))
CmdArgs.push_back("-fms-compatibility");
- // -fmsc-version=1300 is default.
+ // -fmsc-version=1700 is default.
if (Args.hasFlag(options::OPT_fms_extensions, options::OPT_fno_ms_extensions,
getToolChain().getTriple().getOS() == llvm::Triple::Win32) ||
Args.hasArg(options::OPT_fmsc_version)) {
StringRef msc_ver = Args.getLastArgValue(options::OPT_fmsc_version);
if (msc_ver.empty())
- CmdArgs.push_back("-fmsc-version=1300");
+ CmdArgs.push_back("-fmsc-version=1700");
else
CmdArgs.push_back(Args.MakeArgString("-fmsc-version=" + msc_ver));
}
@@ -3062,12 +3366,13 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
ObjCRuntime objcRuntime = AddObjCRuntimeArgs(Args, CmdArgs, rewriteKind);
// -fobjc-dispatch-method is only relevant with the nonfragile-abi, and
- // legacy is the default.
- if (objcRuntime.isNonFragile()) {
+ // legacy is the default. Next runtime is always legacy dispatch and
+ // -fno-objc-legacy-dispatch gets ignored silently.
+ if (objcRuntime.isNonFragile() && !objcRuntime.isNeXTFamily()) {
if (!Args.hasFlag(options::OPT_fobjc_legacy_dispatch,
options::OPT_fno_objc_legacy_dispatch,
objcRuntime.isLegacyDispatchDefaultForArch(
- getToolChain().getTriple().getArch()))) {
+ getToolChain().getArch()))) {
if (getToolChain().UseObjCMixedDispatch())
CmdArgs.push_back("-fobjc-dispatch-method=mixed");
else
@@ -3075,12 +3380,16 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
}
}
- // -fobjc-default-synthesize-properties=1 is default. This only has an effect
- // if the nonfragile objc abi is used.
- if (getToolChain().IsObjCDefaultSynthPropertiesDefault()) {
- CmdArgs.push_back("-fobjc-default-synthesize-properties");
- }
-
+ // When ObjectiveC legacy runtime is in effect on MacOSX,
+ // turn on the option to do Array/Dictionary subscripting
+ // by default.
+ if (getToolChain().getTriple().getArch() == llvm::Triple::x86 &&
+ getToolChain().getTriple().isMacOSX() &&
+ !getToolChain().getTriple().isMacOSXVersionLT(10, 7) &&
+ objcRuntime.getKind() == ObjCRuntime::FragileMacOSX &&
+ objcRuntime.isNeXTFamily())
+ CmdArgs.push_back("-fobjc-subscripting-legacy-runtime");
+
// -fencode-extended-block-signature=1 is default.
if (getToolChain().IsEncodeExtendedBlockSignatureDefault()) {
CmdArgs.push_back("-fencode-extended-block-signature");
@@ -3160,16 +3469,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (Arg *A = Args.getLastArg(options::OPT_fshort_wchar))
A->render(Args, CmdArgs);
- // -fno-pascal-strings is default, only pass non-default. If the tool chain
- // happened to translate to -mpascal-strings, we want to back translate here.
- //
- // FIXME: This is gross; that translation should be pulled from the
- // tool chain.
+ // -fno-pascal-strings is default, only pass non-default.
if (Args.hasFlag(options::OPT_fpascal_strings,
options::OPT_fno_pascal_strings,
- false) ||
- Args.hasFlag(options::OPT_mpascal_strings,
- options::OPT_mno_pascal_strings,
false))
CmdArgs.push_back("-fpascal-strings");
@@ -3184,7 +3486,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-fpack-struct=1");
}
- if (KernelOrKext) {
+ if (KernelOrKext || isNoCommonDefault(getToolChain().getTriple())) {
if (!Args.hasArg(options::OPT_fcommon))
CmdArgs.push_back("-fno-common");
Args.ClaimAllArgs(options::OPT_fno_common);
@@ -3284,6 +3586,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
(ShowColors == Colors_Auto && llvm::sys::Process::StandardErrHasColors()))
CmdArgs.push_back("-fcolor-diagnostics");
+ if (Args.hasArg(options::OPT_fansi_escape_codes))
+ CmdArgs.push_back("-fansi-escape-codes");
+
if (!Args.hasFlag(options::OPT_fshow_source_location,
options::OPT_fno_show_source_location))
CmdArgs.push_back("-fno-show-source-location");
@@ -3303,31 +3608,25 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
false))
CmdArgs.push_back("-fasm-blocks");
- // If -Ofast is the optimization level, then -fvectorize should be enabled.
- // This alias option is being used to simplify the hasFlag logic.
- OptSpecifier VectorizeAliasOption = OFastEnabled ? options::OPT_Ofast :
+ // Enable vectorization per default according to the optimization level
+ // selected. For optimization levels that want vectorization we use the alias
+ // option to simplify the hasFlag logic.
+ bool EnableVec = shouldEnableVectorizerAtOLevel(Args);
+ OptSpecifier VectorizeAliasOption = EnableVec ? options::OPT_O_Group :
options::OPT_fvectorize;
-
- // -fvectorize is default.
if (Args.hasFlag(options::OPT_fvectorize, VectorizeAliasOption,
- options::OPT_fno_vectorize, true)) {
- CmdArgs.push_back("-backend-option");
+ options::OPT_fno_vectorize, EnableVec))
CmdArgs.push_back("-vectorize-loops");
- }
- // -fno-slp-vectorize is default.
+ // -fslp-vectorize is default.
if (Args.hasFlag(options::OPT_fslp_vectorize,
- options::OPT_fno_slp_vectorize, false)) {
- CmdArgs.push_back("-backend-option");
+ options::OPT_fno_slp_vectorize, true))
CmdArgs.push_back("-vectorize-slp");
- }
// -fno-slp-vectorize-aggressive is default.
if (Args.hasFlag(options::OPT_fslp_vectorize_aggressive,
- options::OPT_fno_slp_vectorize_aggressive, false)) {
- CmdArgs.push_back("-backend-option");
+ options::OPT_fno_slp_vectorize_aggressive, false))
CmdArgs.push_back("-vectorize-slp-aggressive");
- }
if (Arg *A = Args.getLastArg(options::OPT_fshow_overloads_EQ))
A->render(Args, CmdArgs);
@@ -3354,13 +3653,20 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
options::OPT_fno_apple_pragma_pack, false))
CmdArgs.push_back("-fapple-pragma-pack");
+ // le32-specific flags:
+ // -fno-math-builtin: clang should not convert math builtins to intrinsics
+ // by default.
+ if (getToolChain().getArch() == llvm::Triple::le32) {
+ CmdArgs.push_back("-fno-math-builtin");
+ }
+
// Default to -fno-builtin-str{cat,cpy} on Darwin for ARM.
//
// FIXME: This is disabled until clang -cc1 supports -fno-builtin-foo. PR4941.
#if 0
if (getToolChain().getTriple().isOSDarwin() &&
- (getToolChain().getTriple().getArch() == llvm::Triple::arm ||
- getToolChain().getTriple().getArch() == llvm::Triple::thumb)) {
+ (getToolChain().getArch() == llvm::Triple::arm ||
+ getToolChain().getArch() == llvm::Triple::thumb)) {
if (!Args.hasArg(options::OPT_fbuiltin_strcat))
CmdArgs.push_back("-fno-builtin-strcat");
if (!Args.hasArg(options::OPT_fbuiltin_strcpy))
@@ -3457,7 +3763,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// Add the split debug info name to the command lines here so we
// can propagate it to the backend.
bool SplitDwarf = Args.hasArg(options::OPT_gsplit_dwarf) &&
- (getToolChain().getTriple().getOS() == llvm::Triple::Linux) &&
+ getToolChain().getTriple().isOSLinux() &&
(isa<AssembleJobAction>(JA) || isa<CompileJobAction>(JA));
const char *SplitDwarfOut;
if (SplitDwarf) {
@@ -3467,7 +3773,15 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
}
// Finally add the compile command to the compilation.
- C.addCommand(new Command(JA, *this, Exec, CmdArgs));
+ if (Args.hasArg(options::OPT__SLASH_fallback)) {
+ tools::visualstudio::Compile CL(getToolChain());
+ Command *CLCommand = CL.GetCommand(C, JA, Output, Inputs, Args,
+ LinkingOutput);
+ C.addCommand(new FallbackCommand(JA, *this, Exec, CmdArgs, CLCommand));
+ } else {
+ C.addCommand(new Command(JA, *this, Exec, CmdArgs));
+ }
+
// Handle the debug info splitting at object creation time if we're
// creating an object.
@@ -3492,38 +3806,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Args.ClaimAllArgs(options::OPT_clang_ignored_f_Group);
Args.ClaimAllArgs(options::OPT_clang_ignored_m_Group);
- // Disable warnings for clang -E -use-gold-plugin -emit-llvm foo.c
- Args.ClaimAllArgs(options::OPT_use_gold_plugin);
+ // Disable warnings for clang -E -emit-llvm foo.c
Args.ClaimAllArgs(options::OPT_emit_llvm);
}
-void ClangAs::AddARMTargetArgs(const ArgList &Args,
- ArgStringList &CmdArgs) const {
- const Driver &D = getToolChain().getDriver();
- llvm::Triple Triple = getToolChain().getTriple();
-
- // Set the CPU based on -march= and -mcpu=.
- CmdArgs.push_back("-target-cpu");
- CmdArgs.push_back(Args.MakeArgString(getARMTargetCPU(Args, Triple)));
-
- // Honor -mfpu=.
- if (const Arg *A = Args.getLastArg(options::OPT_mfpu_EQ))
- addFPUArgs(D, A, Args, CmdArgs);
-
- // Honor -mfpmath=.
- if (const Arg *A = Args.getLastArg(options::OPT_mfpmath_EQ))
- addFPMathArgs(D, A, Args, CmdArgs, getARMTargetCPU(Args, Triple));
-}
-
-void ClangAs::AddX86TargetArgs(const ArgList &Args,
- ArgStringList &CmdArgs) const {
- // Set the CPU based on -march=.
- if (const char *CPUName = getX86TargetCPU(Args, getToolChain().getTriple())) {
- CmdArgs.push_back("-target-cpu");
- CmdArgs.push_back(CPUName);
- }
-}
-
/// Add options related to the Objective-C runtime/ABI.
///
/// Returns true if the runtime is non-fragile.
@@ -3649,6 +3935,67 @@ ObjCRuntime Clang::AddObjCRuntimeArgs(const ArgList &args,
return runtime;
}
+void Clang::AddClangCLArgs(const ArgList &Args, ArgStringList &CmdArgs) const {
+ unsigned RTOptionID = options::OPT__SLASH_MT;
+
+ if (Args.hasArg(options::OPT__SLASH_LDd))
+ // The /LDd option implies /MTd. The dependent lib part can be overridden,
+ // but defining _DEBUG is sticky.
+ RTOptionID = options::OPT__SLASH_MTd;
+
+ if (Arg *A = Args.getLastArg(options::OPT__SLASH_M_Group))
+ RTOptionID = A->getOption().getID();
+
+ switch(RTOptionID) {
+ case options::OPT__SLASH_MD:
+ if (Args.hasArg(options::OPT__SLASH_LDd))
+ CmdArgs.push_back("-D_DEBUG");
+ CmdArgs.push_back("-D_MT");
+ CmdArgs.push_back("-D_DLL");
+ CmdArgs.push_back("--dependent-lib=msvcrt");
+ break;
+ case options::OPT__SLASH_MDd:
+ CmdArgs.push_back("-D_DEBUG");
+ CmdArgs.push_back("-D_MT");
+ CmdArgs.push_back("-D_DLL");
+ CmdArgs.push_back("--dependent-lib=msvcrtd");
+ break;
+ case options::OPT__SLASH_MT:
+ if (Args.hasArg(options::OPT__SLASH_LDd))
+ CmdArgs.push_back("-D_DEBUG");
+ CmdArgs.push_back("-D_MT");
+ CmdArgs.push_back("--dependent-lib=libcmt");
+ break;
+ case options::OPT__SLASH_MTd:
+ CmdArgs.push_back("-D_DEBUG");
+ CmdArgs.push_back("-D_MT");
+ CmdArgs.push_back("--dependent-lib=libcmtd");
+ break;
+ default:
+ llvm_unreachable("Unexpected option ID.");
+ }
+
+ // This provides POSIX compatibility (maps 'open' to '_open'), which most
+ // users want. The /Za flag to cl.exe turns this off, but it's not
+ // implemented in clang.
+ CmdArgs.push_back("--dependent-lib=oldnames");
+
+ // FIXME: Make this default for the win32 triple.
+ CmdArgs.push_back("-cxx-abi");
+ CmdArgs.push_back("microsoft");
+
+ if (Arg *A = Args.getLastArg(options::OPT_show_includes))
+ A->render(Args, CmdArgs);
+
+ if (!Args.hasArg(options::OPT_fdiagnostics_format_EQ)) {
+ CmdArgs.push_back("-fdiagnostics-format");
+ if (Args.hasArg(options::OPT__SLASH_fallback))
+ CmdArgs.push_back("msvc-fallback");
+ else
+ CmdArgs.push_back("msvc");
+ }
+}
+
void ClangAs::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
@@ -3663,8 +4010,6 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA,
Args.ClaimAllArgs(options::OPT_w);
// and "clang -emit-llvm -c foo.s"
Args.ClaimAllArgs(options::OPT_emit_llvm);
- // and "clang -use-gold-plugin -c foo.s"
- Args.ClaimAllArgs(options::OPT_use_gold_plugin);
// Invoke ourselves in -cc1as mode.
//
@@ -3687,25 +4032,18 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-main-file-name");
CmdArgs.push_back(Clang::getBaseInputName(Args, Inputs));
- if (UseRelaxAll(C, Args))
- CmdArgs.push_back("-relax-all");
-
- // Add target specific cpu and features flags.
- switch(getToolChain().getTriple().getArch()) {
- default:
- break;
-
- case llvm::Triple::arm:
- case llvm::Triple::thumb:
- AddARMTargetArgs(Args, CmdArgs);
- break;
-
- case llvm::Triple::x86:
- case llvm::Triple::x86_64:
- AddX86TargetArgs(Args, CmdArgs);
- break;
+ // Add the target cpu
+ const llvm::Triple &Triple = getToolChain().getTriple();
+ std::string CPU = getCPUName(Args, Triple);
+ if (!CPU.empty()) {
+ CmdArgs.push_back("-target-cpu");
+ CmdArgs.push_back(Args.MakeArgString(CPU));
}
+ // Add the target features
+ const Driver &D = getToolChain().getDriver();
+ getTargetFeatures(D, Triple, Args, CmdArgs);
+
// Ignore explicit -force_cpusubtype_ALL option.
(void) Args.hasArg(options::OPT_force__cpusubtype__ALL);
@@ -3755,8 +4093,9 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA,
// FIXME: Add -static support, once we have it.
- Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,
- options::OPT_Xassembler);
+ CollectArgsForIntegratedAssembler(C, Args, CmdArgs,
+ getToolChain().getDriver());
+
Args.AddAllArgs(CmdArgs, options::OPT_mllvm);
assert(Output.isFilename() && "Unexpected lipo output.");
@@ -3773,7 +4112,7 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA,
// creating an object.
// TODO: Currently only works on linux with newer objcopy.
if (Args.hasArg(options::OPT_gsplit_dwarf) &&
- (getToolChain().getTriple().getOS() == llvm::Triple::Linux))
+ getToolChain().getTriple().isOSLinux())
SplitDebugInfo(getToolChain(), C, *this, JA, Args, Output,
SplitDebugName(Args, Inputs));
}
@@ -3795,6 +4134,11 @@ void gcc::Common::ConstructJob(Compilation &C, const JobAction &JA,
A->getOption().matches(options::OPT_g_Group))
continue;
+ // Don't forward any -W arguments to assembly and link steps.
+ if ((isa<AssembleJobAction>(JA) || isa<LinkJobAction>(JA)) &&
+ A->getOption().matches(options::OPT_W_Group))
+ continue;
+
// It is unfortunate that we have to claim here, as this means
// we will basically never report anything interesting for
// platforms using a generic gcc, even if we are just using gcc
@@ -3816,6 +4160,8 @@ void gcc::Common::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("ppc");
else if (Arch == llvm::Triple::ppc64)
CmdArgs.push_back("ppc64");
+ else if (Arch == llvm::Triple::ppc64le)
+ CmdArgs.push_back("ppc64le");
else
CmdArgs.push_back(Args.MakeArgString(getToolChain().getArchName()));
}
@@ -3827,7 +4173,8 @@ void gcc::Common::ConstructJob(Compilation &C, const JobAction &JA,
// here.
if (Arch == llvm::Triple::x86 || Arch == llvm::Triple::ppc)
CmdArgs.push_back("-m32");
- else if (Arch == llvm::Triple::x86_64 || Arch == llvm::Triple::ppc64)
+ else if (Arch == llvm::Triple::x86_64 || Arch == llvm::Triple::ppc64 ||
+ Arch == llvm::Triple::ppc64le)
CmdArgs.push_back("-m64");
if (Output.isFilename()) {
@@ -3890,7 +4237,7 @@ void gcc::Common::ConstructJob(Compilation &C, const JobAction &JA,
const char *GCCName;
if (!customGCCName.empty())
GCCName = customGCCName.c_str();
- else if (D.CCCIsCXX) {
+ else if (D.CCCIsCXX()) {
GCCName = "g++";
} else
GCCName = "gcc";
@@ -4152,7 +4499,7 @@ void hexagon::Link::ConstructJob(Compilation &C, const JobAction &JA,
// Libraries
//----------------------------------------------------------------------------
if (incStdLib && incDefLibs) {
- if (D.CCCIsCXX) {
+ if (D.CCCIsCXX()) {
ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
CmdArgs.push_back("-lm");
}
@@ -4179,10 +4526,7 @@ void hexagon::Link::ConstructJob(Compilation &C, const JobAction &JA,
}
std::string Linker = ToolChain.GetProgramPath("hexagon-ld");
- C.addCommand(
- new Command(
- JA, *this,
- Args.MakeArgString(Linker), CmdArgs));
+ C.addCommand(new Command(JA, *this, Args.MakeArgString(Linker), CmdArgs));
}
// Hexagon tools end.
@@ -4206,7 +4550,7 @@ llvm::Triple::ArchType darwin::getArchTypeForDarwinArchName(StringRef Str) {
.Cases("i386", "i486", "i486SX", "i586", "i686", llvm::Triple::x86)
.Cases("pentium", "pentpro", "pentIIm3", "pentIIm5", "pentium4",
llvm::Triple::x86)
- .Case("x86_64", llvm::Triple::x86_64)
+ .Cases("x86_64", "x86_64h", llvm::Triple::x86_64)
// This is derived from the driver driver.
.Cases("arm", "armv4t", "armv5", "armv6", "armv6m", llvm::Triple::arm)
.Cases("armv7", "armv7em", "armv7f", "armv7k", "armv7m", llvm::Triple::arm)
@@ -4266,6 +4610,11 @@ void darwin::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
SourceAction = SourceAction->getInputs()[0];
}
+ // If -no_integrated_as is used add -Q to the darwin assember driver to make
+ // sure it runs its system assembler not clang's integrated assembler.
+ if (Args.hasArg(options::OPT_no_integrated_as))
+ CmdArgs.push_back("-Q");
+
// Forward -g, assuming we are dealing with an actual assembly file.
if (SourceAction->getType() == types::TY_Asm ||
SourceAction->getType() == types::TY_PP_Asm) {
@@ -4279,12 +4628,12 @@ void darwin::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
AddDarwinArch(Args, CmdArgs);
// Use -force_cpusubtype_ALL on x86 by default.
- if (getToolChain().getTriple().getArch() == llvm::Triple::x86 ||
- getToolChain().getTriple().getArch() == llvm::Triple::x86_64 ||
+ if (getToolChain().getArch() == llvm::Triple::x86 ||
+ getToolChain().getArch() == llvm::Triple::x86_64 ||
Args.hasArg(options::OPT_force__cpusubtype__ALL))
CmdArgs.push_back("-force_cpusubtype_ALL");
- if (getToolChain().getTriple().getArch() != llvm::Triple::x86_64 &&
+ if (getToolChain().getArch() != llvm::Triple::x86_64 &&
(((Args.hasArg(options::OPT_mkernel) ||
Args.hasArg(options::OPT_fapple_kext)) &&
(!getDarwinToolChain().isTargetIPhoneOS() ||
@@ -4375,6 +4724,9 @@ void darwin::Link::AddLinkArgs(Compilation &C,
CmdArgs.push_back("-demangle");
}
+ if (Args.hasArg(options::OPT_rdynamic) && Version[0] >= 137)
+ CmdArgs.push_back("-export_dynamic");
+
// If we are using LTO, then automatically create a temporary file path for
// the linker to use, so that it's lifetime will extend past a possible
// dsymutil step.
@@ -4573,7 +4925,6 @@ void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddAllArgs(CmdArgs, options::OPT_Z_Flag);
Args.AddAllArgs(CmdArgs, options::OPT_u_Group);
Args.AddLastArg(CmdArgs, options::OPT_e);
- Args.AddAllArgs(CmdArgs, options::OPT_m_Separate);
Args.AddAllArgs(CmdArgs, options::OPT_r);
// Forward -ObjC when either -ObjC or -ObjC++ is used, to force loading
@@ -4582,9 +4933,6 @@ void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA,
if (Args.hasArg(options::OPT_ObjC) || Args.hasArg(options::OPT_ObjCXX))
CmdArgs.push_back("-ObjC");
- if (Args.hasArg(options::OPT_rdynamic))
- CmdArgs.push_back("-export_dynamic");
-
CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename());
@@ -4681,19 +5029,6 @@ void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddAllArgs(CmdArgs, options::OPT_L);
- SanitizerArgs Sanitize(getToolChain(), Args);
- // If we're building a dynamic lib with -fsanitize=address,
- // unresolved symbols may appear. Mark all
- // of them as dynamic_lookup. Linking executables is handled in
- // lib/Driver/ToolChains.cpp.
- if (Sanitize.needsAsanRt()) {
- if (Args.hasArg(options::OPT_dynamiclib) ||
- Args.hasArg(options::OPT_bundle)) {
- CmdArgs.push_back("-undefined");
- CmdArgs.push_back("dynamic_lookup");
- }
- }
-
if (Args.hasArg(options::OPT_fopenmp))
// This is more complicated in gcc...
CmdArgs.push_back("-lgomp");
@@ -4733,7 +5068,7 @@ void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA,
if (!Args.hasArg(options::OPT_nostdlib) &&
!Args.hasArg(options::OPT_nodefaultlibs)) {
- if (getToolChain().getDriver().CCCIsCXX)
+ if (getToolChain().getDriver().CCCIsCXX())
getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
// link_ssp spec is empty.
@@ -4858,18 +5193,17 @@ void solaris::Link::ConstructJob(Compilation &C, const JobAction &JA,
std::string LibPath = "/usr/lib/";
llvm::Triple::ArchType Arch = T.getArch();
switch (Arch) {
- case llvm::Triple::x86:
- GCCLibPath += ("i386-" + T.getVendorName() + "-" +
- T.getOSName()).str() + "/4.5.2/";
- break;
- case llvm::Triple::x86_64:
- GCCLibPath += ("i386-" + T.getVendorName() + "-" +
- T.getOSName()).str();
- GCCLibPath += "/4.5.2/amd64/";
- LibPath += "amd64/";
- break;
- default:
- assert(0 && "Unsupported architecture");
+ case llvm::Triple::x86:
+ GCCLibPath +=
+ ("i386-" + T.getVendorName() + "-" + T.getOSName()).str() + "/4.5.2/";
+ break;
+ case llvm::Triple::x86_64:
+ GCCLibPath += ("i386-" + T.getVendorName() + "-" + T.getOSName()).str();
+ GCCLibPath += "/4.5.2/amd64/";
+ LibPath += "amd64/";
+ break;
+ default:
+ llvm_unreachable("Unsupported architecture");
}
ArgStringList CmdArgs;
@@ -4915,7 +5249,7 @@ void solaris::Link::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(Args.MakeArgString(LibPath + "values-Xa.o"));
CmdArgs.push_back(Args.MakeArgString(GCCLibPath + "crtbegin.o"));
}
- if (getToolChain().getDriver().CCCIsCXX)
+ if (getToolChain().getDriver().CCCIsCXX())
CmdArgs.push_back(Args.MakeArgString(LibPath + "cxa_finalize.o"));
}
@@ -4930,7 +5264,7 @@ void solaris::Link::ConstructJob(Compilation &C, const JobAction &JA,
if (!Args.hasArg(options::OPT_nostdlib) &&
!Args.hasArg(options::OPT_nodefaultlibs)) {
- if (getToolChain().getDriver().CCCIsCXX)
+ if (getToolChain().getDriver().CCCIsCXX())
getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
CmdArgs.push_back("-lgcc_s");
if (!Args.hasArg(options::OPT_shared)) {
@@ -5072,6 +5406,40 @@ void openbsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
const char *LinkingOutput) const {
ArgStringList CmdArgs;
+ // When building 32-bit code on OpenBSD/amd64, we have to explicitly
+ // instruct as in the base system to assemble 32-bit code.
+ if (getToolChain().getArch() == llvm::Triple::x86)
+ CmdArgs.push_back("--32");
+ else if (getToolChain().getArch() == llvm::Triple::ppc) {
+ CmdArgs.push_back("-mppc");
+ CmdArgs.push_back("-many");
+ } else if (getToolChain().getArch() == llvm::Triple::mips64 ||
+ getToolChain().getArch() == llvm::Triple::mips64el) {
+ StringRef CPUName;
+ StringRef ABIName;
+ getMipsCPUAndABI(Args, getToolChain().getTriple(), CPUName, ABIName);
+
+ CmdArgs.push_back("-mabi");
+ CmdArgs.push_back(getGnuCompatibleMipsABIName(ABIName).data());
+
+ if (getToolChain().getArch() == llvm::Triple::mips64)
+ CmdArgs.push_back("-EB");
+ else
+ CmdArgs.push_back("-EL");
+
+ Arg *LastPICArg = Args.getLastArg(options::OPT_fPIC, options::OPT_fno_PIC,
+ options::OPT_fpic, options::OPT_fno_pic,
+ options::OPT_fPIE, options::OPT_fno_PIE,
+ options::OPT_fpie, options::OPT_fno_pie);
+ if (LastPICArg &&
+ (LastPICArg->getOption().matches(options::OPT_fPIC) ||
+ LastPICArg->getOption().matches(options::OPT_fpic) ||
+ LastPICArg->getOption().matches(options::OPT_fPIE) ||
+ LastPICArg->getOption().matches(options::OPT_fpie))) {
+ CmdArgs.push_back("-KPIC");
+ }
+ }
+
Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,
options::OPT_Xassembler);
@@ -5105,6 +5473,11 @@ void openbsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
// handled somewhere else.
Args.ClaimAllArgs(options::OPT_w);
+ if (getToolChain().getArch() == llvm::Triple::mips64)
+ CmdArgs.push_back("-EB");
+ else if (getToolChain().getArch() == llvm::Triple::mips64el)
+ CmdArgs.push_back("-EL");
+
if ((!Args.hasArg(options::OPT_nostdlib)) &&
(!Args.hasArg(options::OPT_shared))) {
CmdArgs.push_back("-e");
@@ -5126,6 +5499,9 @@ void openbsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
}
}
+ if (Args.hasArg(options::OPT_nopie))
+ CmdArgs.push_back("-nopie");
+
if (Output.isFilename()) {
CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename());
@@ -5168,7 +5544,7 @@ void openbsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
if (!Args.hasArg(options::OPT_nostdlib) &&
!Args.hasArg(options::OPT_nodefaultlibs)) {
- if (D.CCCIsCXX) {
+ if (D.CCCIsCXX()) {
getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
if (Args.hasArg(options::OPT_pg))
CmdArgs.push_back("-lm_p");
@@ -5298,7 +5674,7 @@ void bitrig::Link::ConstructJob(Compilation &C, const JobAction &JA,
if (!Args.hasArg(options::OPT_nostdlib) &&
!Args.hasArg(options::OPT_nodefaultlibs)) {
- if (D.CCCIsCXX) {
+ if (D.CCCIsCXX()) {
getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
if (Args.hasArg(options::OPT_pg))
CmdArgs.push_back("-lm_p");
@@ -5321,23 +5697,21 @@ void bitrig::Link::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-lc");
}
- std::string myarch = "-lclang_rt.";
- const llvm::Triple &T = getToolChain().getTriple();
- llvm::Triple::ArchType Arch = T.getArch();
- switch (Arch) {
- case llvm::Triple::arm:
- myarch += ("arm");
- break;
- case llvm::Triple::x86:
- myarch += ("i386");
- break;
- case llvm::Triple::x86_64:
- myarch += ("amd64");
- break;
- default:
- assert(0 && "Unsupported architecture");
- }
- CmdArgs.push_back(Args.MakeArgString(myarch));
+ StringRef MyArch;
+ switch (getToolChain().getTriple().getArch()) {
+ case llvm::Triple::arm:
+ MyArch = "arm";
+ break;
+ case llvm::Triple::x86:
+ MyArch = "i386";
+ break;
+ case llvm::Triple::x86_64:
+ MyArch = "amd64";
+ break;
+ default:
+ llvm_unreachable("Unsupported architecture");
+ }
+ CmdArgs.push_back(Args.MakeArgString("-lclang_rt." + MyArch));
}
if (!Args.hasArg(options::OPT_nostdlib) &&
@@ -5374,7 +5748,7 @@ void freebsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
getToolChain().getArch() == llvm::Triple::mips64el) {
StringRef CPUName;
StringRef ABIName;
- getMipsCPUAndABI(Args, getToolChain(), CPUName, ABIName);
+ getMipsCPUAndABI(Args, getToolChain().getTriple(), CPUName, ABIName);
CmdArgs.push_back("-march");
CmdArgs.push_back(CPUName.data());
@@ -5534,11 +5908,31 @@ void freebsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddAllArgs(CmdArgs, options::OPT_Z_Flag);
Args.AddAllArgs(CmdArgs, options::OPT_r);
+ // Tell the linker to load the plugin. This has to come before AddLinkerInputs
+ // as gold requires -plugin to come before any -plugin-opt that -Wl might
+ // forward.
+ if (D.IsUsingLTO(Args)) {
+ CmdArgs.push_back("-plugin");
+ std::string Plugin = ToolChain.getDriver().Dir + "/../lib/LLVMgold.so";
+ CmdArgs.push_back(Args.MakeArgString(Plugin));
+
+ // Try to pass driver level flags relevant to LTO code generation down to
+ // the plugin.
+
+ // Handle flags for selecting CPU variants.
+ std::string CPU = getCPUName(Args, ToolChain.getTriple());
+ if (!CPU.empty()) {
+ CmdArgs.push_back(
+ Args.MakeArgString(Twine("-plugin-opt=mcpu=") +
+ CPU));
+ }
+ }
+
AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs);
if (!Args.hasArg(options::OPT_nostdlib) &&
!Args.hasArg(options::OPT_nodefaultlibs)) {
- if (D.CCCIsCXX) {
+ if (D.CCCIsCXX()) {
ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
if (Args.hasArg(options::OPT_pg))
CmdArgs.push_back("-lm_p");
@@ -5618,11 +6012,45 @@ void netbsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
if (getToolChain().getArch() == llvm::Triple::x86)
CmdArgs.push_back("--32");
- // Set byte order explicitly
- if (getToolChain().getArch() == llvm::Triple::mips)
- CmdArgs.push_back("-EB");
- else if (getToolChain().getArch() == llvm::Triple::mipsel)
- CmdArgs.push_back("-EL");
+ // Pass the target CPU to GNU as for ARM, since the source code might
+ // not have the correct .cpu annotation.
+ if (getToolChain().getArch() == llvm::Triple::arm) {
+ std::string MArch(getARMTargetCPU(Args, getToolChain().getTriple()));
+ CmdArgs.push_back(Args.MakeArgString("-mcpu=" + MArch));
+ }
+
+ if (getToolChain().getArch() == llvm::Triple::mips ||
+ getToolChain().getArch() == llvm::Triple::mipsel ||
+ getToolChain().getArch() == llvm::Triple::mips64 ||
+ getToolChain().getArch() == llvm::Triple::mips64el) {
+ StringRef CPUName;
+ StringRef ABIName;
+ getMipsCPUAndABI(Args, getToolChain().getTriple(), CPUName, ABIName);
+
+ CmdArgs.push_back("-march");
+ CmdArgs.push_back(CPUName.data());
+
+ CmdArgs.push_back("-mabi");
+ CmdArgs.push_back(getGnuCompatibleMipsABIName(ABIName).data());
+
+ if (getToolChain().getArch() == llvm::Triple::mips ||
+ getToolChain().getArch() == llvm::Triple::mips64)
+ CmdArgs.push_back("-EB");
+ else
+ CmdArgs.push_back("-EL");
+
+ Arg *LastPICArg = Args.getLastArg(options::OPT_fPIC, options::OPT_fno_PIC,
+ options::OPT_fpic, options::OPT_fno_pic,
+ options::OPT_fPIE, options::OPT_fno_PIE,
+ options::OPT_fpie, options::OPT_fno_pie);
+ if (LastPICArg &&
+ (LastPICArg->getOption().matches(options::OPT_fPIC) ||
+ LastPICArg->getOption().matches(options::OPT_fpic) ||
+ LastPICArg->getOption().matches(options::OPT_fPIE) ||
+ LastPICArg->getOption().matches(options::OPT_fpie))) {
+ CmdArgs.push_back("-KPIC");
+ }
+ }
Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,
options::OPT_Xassembler);
@@ -5706,34 +6134,39 @@ void netbsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);
+ unsigned Major, Minor, Micro;
+ getToolChain().getTriple().getOSVersion(Major, Minor, Micro);
+ bool useLibgcc = true;
+ if (Major >= 7 || (Major == 6 && Minor == 99 && Micro >= 23) || Major == 0) {
+ if (getToolChain().getArch() == llvm::Triple::x86 ||
+ getToolChain().getArch() == llvm::Triple::x86_64)
+ useLibgcc = false;
+ }
+
if (!Args.hasArg(options::OPT_nostdlib) &&
!Args.hasArg(options::OPT_nodefaultlibs)) {
- if (D.CCCIsCXX) {
+ if (D.CCCIsCXX()) {
getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
CmdArgs.push_back("-lm");
}
- // FIXME: For some reason GCC passes -lgcc and -lgcc_s before adding
- // the default system libraries. Just mimic this for now.
- if (Args.hasArg(options::OPT_static)) {
- CmdArgs.push_back("-lgcc_eh");
- } else {
- CmdArgs.push_back("--as-needed");
- CmdArgs.push_back("-lgcc_s");
- CmdArgs.push_back("--no-as-needed");
- }
- CmdArgs.push_back("-lgcc");
-
if (Args.hasArg(options::OPT_pthread))
CmdArgs.push_back("-lpthread");
CmdArgs.push_back("-lc");
- CmdArgs.push_back("-lgcc");
- if (Args.hasArg(options::OPT_static)) {
- CmdArgs.push_back("-lgcc_eh");
- } else {
- CmdArgs.push_back("--as-needed");
- CmdArgs.push_back("-lgcc_s");
- CmdArgs.push_back("--no-as-needed");
+ if (useLibgcc) {
+ if (Args.hasArg(options::OPT_static)) {
+ // libgcc_eh depends on libc, so resolve as much as possible,
+ // pull in any new requirements from libc and then get the rest
+ // of libgcc.
+ CmdArgs.push_back("-lgcc_eh");
+ CmdArgs.push_back("-lc");
+ CmdArgs.push_back("-lgcc");
+ } else {
+ CmdArgs.push_back("-lgcc");
+ CmdArgs.push_back("--as-needed");
+ CmdArgs.push_back("-lgcc_s");
+ CmdArgs.push_back("--no-as-needed");
+ }
}
}
@@ -5776,10 +6209,16 @@ void gnutools::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-a64");
CmdArgs.push_back("-mppc64");
CmdArgs.push_back("-many");
+ } else if (getToolChain().getArch() == llvm::Triple::ppc64le) {
+ CmdArgs.push_back("-a64");
+ CmdArgs.push_back("-mppc64le");
+ CmdArgs.push_back("-many");
} else if (getToolChain().getArch() == llvm::Triple::arm) {
StringRef MArch = getToolChain().getArchName();
if (MArch == "armv7" || MArch == "armv7a" || MArch == "armv7-a")
CmdArgs.push_back("-mfpu=neon");
+ if (MArch == "armv8" || MArch == "armv8a" || MArch == "armv8-a")
+ CmdArgs.push_back("-mfpu=crypto-neon-fp-armv8");
StringRef ARMFloatABI = getARMFloatABI(getToolChain().getDriver(), Args,
getToolChain().getTriple());
@@ -5794,7 +6233,7 @@ void gnutools::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
getToolChain().getArch() == llvm::Triple::mips64el) {
StringRef CPUName;
StringRef ABIName;
- getMipsCPUAndABI(Args, getToolChain(), CPUName, ABIName);
+ getMipsCPUAndABI(Args, getToolChain().getTriple(), CPUName, ABIName);
CmdArgs.push_back("-march");
CmdArgs.push_back(CPUName.data());
@@ -5808,12 +6247,31 @@ void gnutools::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
else
CmdArgs.push_back("-EL");
+ if (Arg *A = Args.getLastArg(options::OPT_mnan_EQ)) {
+ if (StringRef(A->getValue()) == "2008")
+ CmdArgs.push_back(Args.MakeArgString("-mnan=2008"));
+ }
+
+ if (Arg *A = Args.getLastArg(options::OPT_mfp32, options::OPT_mfp64)) {
+ if (A->getOption().matches(options::OPT_mfp32))
+ CmdArgs.push_back(Args.MakeArgString("-mfp32"));
+ else
+ CmdArgs.push_back(Args.MakeArgString("-mfp64"));
+ }
+
Args.AddLastArg(CmdArgs, options::OPT_mips16, options::OPT_mno_mips16);
Args.AddLastArg(CmdArgs, options::OPT_mmicromips,
options::OPT_mno_micromips);
Args.AddLastArg(CmdArgs, options::OPT_mdsp, options::OPT_mno_dsp);
Args.AddLastArg(CmdArgs, options::OPT_mdspr2, options::OPT_mno_dspr2);
+ if (Arg *A = Args.getLastArg(options::OPT_mmsa, options::OPT_mno_msa)) {
+ // Do not use AddLastArg because not all versions of MIPS assembler
+ // support -mmsa / -mno-msa options.
+ if (A->getOption().matches(options::OPT_mmsa))
+ CmdArgs.push_back(Args.MakeArgString("-mmsa"));
+ }
+
Arg *LastPICArg = Args.getLastArg(options::OPT_fPIC, options::OPT_fno_PIC,
options::OPT_fpic, options::OPT_fno_pic,
options::OPT_fPIE, options::OPT_fno_PIE,
@@ -5826,8 +6284,10 @@ void gnutools::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-KPIC");
}
} else if (getToolChain().getArch() == llvm::Triple::systemz) {
- // At the moment we always produce z10 code.
- CmdArgs.push_back("-march=z10");
+ // Always pass an -march option, since our default of z10 is later
+ // than the GNU assembler's default.
+ StringRef CPUName = getSystemZTargetCPU(Args);
+ CmdArgs.push_back(Args.MakeArgString("-march=" + CPUName));
}
Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,
@@ -5845,6 +6305,14 @@ void gnutools::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
const char *Exec =
Args.MakeArgString(getToolChain().GetProgramPath("as"));
C.addCommand(new Command(JA, *this, Exec, CmdArgs));
+
+ // Handle the debug info splitting at object creation time if we're
+ // creating an object.
+ // TODO: Currently only works on linux with newer objcopy.
+ if (Args.hasArg(options::OPT_gsplit_dwarf) &&
+ getToolChain().getTriple().isOSLinux())
+ SplitDebugInfo(getToolChain(), C, *this, JA, Args, Output,
+ SplitDebugName(Args, Inputs));
}
static void AddLibgcc(llvm::Triple Triple, const Driver &D,
@@ -5852,23 +6320,23 @@ static void AddLibgcc(llvm::Triple Triple, const Driver &D,
bool isAndroid = Triple.getEnvironment() == llvm::Triple::Android;
bool StaticLibgcc = Args.hasArg(options::OPT_static_libgcc) ||
Args.hasArg(options::OPT_static);
- if (!D.CCCIsCXX)
+ if (!D.CCCIsCXX())
CmdArgs.push_back("-lgcc");
if (StaticLibgcc || isAndroid) {
- if (D.CCCIsCXX)
+ if (D.CCCIsCXX())
CmdArgs.push_back("-lgcc");
} else {
- if (!D.CCCIsCXX)
+ if (!D.CCCIsCXX())
CmdArgs.push_back("--as-needed");
CmdArgs.push_back("-lgcc_s");
- if (!D.CCCIsCXX)
+ if (!D.CCCIsCXX())
CmdArgs.push_back("--no-as-needed");
}
if (StaticLibgcc && !isAndroid)
CmdArgs.push_back("-lgcc_eh");
- else if (!Args.hasArg(options::OPT_shared) && D.CCCIsCXX)
+ else if (!Args.hasArg(options::OPT_shared) && D.CCCIsCXX())
CmdArgs.push_back("-lgcc");
// According to Android ABI, we have to link with libdl if we are
@@ -5885,6 +6353,39 @@ static bool hasMipsN32ABIArg(const ArgList &Args) {
return A && (A->getValue() == StringRef("n32"));
}
+static StringRef getLinuxDynamicLinker(const ArgList &Args,
+ const toolchains::Linux &ToolChain) {
+ if (ToolChain.getTriple().getEnvironment() == llvm::Triple::Android)
+ return "/system/bin/linker";
+ else if (ToolChain.getArch() == llvm::Triple::x86)
+ return "/lib/ld-linux.so.2";
+ else if (ToolChain.getArch() == llvm::Triple::aarch64)
+ return "/lib/ld-linux-aarch64.so.1";
+ else if (ToolChain.getArch() == llvm::Triple::arm ||
+ ToolChain.getArch() == llvm::Triple::thumb) {
+ if (ToolChain.getTriple().getEnvironment() == llvm::Triple::GNUEABIHF)
+ return "/lib/ld-linux-armhf.so.3";
+ else
+ return "/lib/ld-linux.so.3";
+ } else if (ToolChain.getArch() == llvm::Triple::mips ||
+ ToolChain.getArch() == llvm::Triple::mipsel)
+ return "/lib/ld.so.1";
+ else if (ToolChain.getArch() == llvm::Triple::mips64 ||
+ ToolChain.getArch() == llvm::Triple::mips64el) {
+ if (hasMipsN32ABIArg(Args))
+ return "/lib32/ld.so.1";
+ else
+ return "/lib64/ld.so.1";
+ } else if (ToolChain.getArch() == llvm::Triple::ppc)
+ return "/lib/ld.so.1";
+ else if (ToolChain.getArch() == llvm::Triple::ppc64 ||
+ ToolChain.getArch() == llvm::Triple::ppc64le ||
+ ToolChain.getArch() == llvm::Triple::systemz)
+ return "/lib64/ld64.so.1";
+ else
+ return "/lib64/ld-linux-x86-64.so.2";
+}
+
void gnutools::Link::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
@@ -5895,7 +6396,7 @@ void gnutools::Link::ConstructJob(Compilation &C, const JobAction &JA,
const Driver &D = ToolChain.getDriver();
const bool isAndroid =
ToolChain.getTriple().getEnvironment() == llvm::Triple::Android;
- SanitizerArgs Sanitize(getToolChain(), Args);
+ const SanitizerArgs &Sanitize = ToolChain.getSanitizerArgs();
const bool IsPIE =
!Args.hasArg(options::OPT_shared) &&
(Args.hasArg(options::OPT_pie) || Sanitize.hasZeroBaseShadow());
@@ -5982,36 +6483,8 @@ void gnutools::Link::ConstructJob(Compilation &C, const JobAction &JA,
(!Args.hasArg(options::OPT_static) &&
!Args.hasArg(options::OPT_shared))) {
CmdArgs.push_back("-dynamic-linker");
- if (isAndroid)
- CmdArgs.push_back("/system/bin/linker");
- else if (ToolChain.getArch() == llvm::Triple::x86)
- CmdArgs.push_back("/lib/ld-linux.so.2");
- else if (ToolChain.getArch() == llvm::Triple::aarch64)
- CmdArgs.push_back("/lib/ld-linux-aarch64.so.1");
- else if (ToolChain.getArch() == llvm::Triple::arm ||
- ToolChain.getArch() == llvm::Triple::thumb) {
- if (ToolChain.getTriple().getEnvironment() == llvm::Triple::GNUEABIHF)
- CmdArgs.push_back("/lib/ld-linux-armhf.so.3");
- else
- CmdArgs.push_back("/lib/ld-linux.so.3");
- }
- else if (ToolChain.getArch() == llvm::Triple::mips ||
- ToolChain.getArch() == llvm::Triple::mipsel)
- CmdArgs.push_back("/lib/ld.so.1");
- else if (ToolChain.getArch() == llvm::Triple::mips64 ||
- ToolChain.getArch() == llvm::Triple::mips64el) {
- if (hasMipsN32ABIArg(Args))
- CmdArgs.push_back("/lib32/ld.so.1");
- else
- CmdArgs.push_back("/lib64/ld.so.1");
- }
- else if (ToolChain.getArch() == llvm::Triple::ppc)
- CmdArgs.push_back("/lib/ld.so.1");
- else if (ToolChain.getArch() == llvm::Triple::ppc64 ||
- ToolChain.getArch() == llvm::Triple::systemz)
- CmdArgs.push_back("/lib64/ld64.so.1");
- else
- CmdArgs.push_back("/lib64/ld-linux-x86-64.so.2");
+ CmdArgs.push_back(Args.MakeArgString(
+ D.DyldPrefix + getLinuxDynamicLinker(Args, ToolChain)));
}
CmdArgs.push_back("-o");
@@ -6022,7 +6495,9 @@ void gnutools::Link::ConstructJob(Compilation &C, const JobAction &JA,
if (!isAndroid) {
const char *crt1 = NULL;
if (!Args.hasArg(options::OPT_shared)){
- if (IsPIE)
+ if (Args.hasArg(options::OPT_pg))
+ crt1 = "gcrt1.o";
+ else if (IsPIE)
crt1 = "Scrt1.o";
else
crt1 = "crt1.o";
@@ -6059,7 +6534,7 @@ void gnutools::Link::ConstructJob(Compilation &C, const JobAction &JA,
// Tell the linker to load the plugin. This has to come before AddLinkerInputs
// as gold requires -plugin to come before any -plugin-opt that -Wl might
// forward.
- if (D.IsUsingLTO(Args) || Args.hasArg(options::OPT_use_gold_plugin)) {
+ if (D.IsUsingLTO(Args)) {
CmdArgs.push_back("-plugin");
std::string Plugin = ToolChain.getDriver().Dir + "/../lib/LLVMgold.so";
CmdArgs.push_back(Args.MakeArgString(Plugin));
@@ -6067,20 +6542,13 @@ void gnutools::Link::ConstructJob(Compilation &C, const JobAction &JA,
// Try to pass driver level flags relevant to LTO code generation down to
// the plugin.
- // Handle architecture-specific flags for selecting CPU variants.
- if (ToolChain.getArch() == llvm::Triple::x86 ||
- ToolChain.getArch() == llvm::Triple::x86_64)
+ // Handle flags for selecting CPU variants.
+ std::string CPU = getCPUName(Args, ToolChain.getTriple());
+ if (!CPU.empty()) {
CmdArgs.push_back(
- Args.MakeArgString(Twine("-plugin-opt=mcpu=") +
- getX86TargetCPU(Args, ToolChain.getTriple())));
- else if (ToolChain.getArch() == llvm::Triple::arm ||
- ToolChain.getArch() == llvm::Triple::thumb)
- CmdArgs.push_back(
- Args.MakeArgString(Twine("-plugin-opt=mcpu=") +
- getARMTargetCPU(Args, ToolChain.getTriple())));
-
- // FIXME: Factor out logic for MIPS, PPC, and other targets to support this
- // as well.
+ Args.MakeArgString(Twine("-plugin-opt=mcpu=") +
+ CPU));
+ }
}
@@ -6091,17 +6559,24 @@ void gnutools::Link::ConstructJob(Compilation &C, const JobAction &JA,
// Call these before we add the C++ ABI library.
if (Sanitize.needsUbsanRt())
- addUbsanRTLinux(getToolChain(), Args, CmdArgs, D.CCCIsCXX,
+ addUbsanRTLinux(getToolChain(), Args, CmdArgs, D.CCCIsCXX(),
Sanitize.needsAsanRt() || Sanitize.needsTsanRt() ||
- Sanitize.needsMsanRt());
+ Sanitize.needsMsanRt() || Sanitize.needsLsanRt());
if (Sanitize.needsAsanRt())
addAsanRTLinux(getToolChain(), Args, CmdArgs);
if (Sanitize.needsTsanRt())
addTsanRTLinux(getToolChain(), Args, CmdArgs);
if (Sanitize.needsMsanRt())
addMsanRTLinux(getToolChain(), Args, CmdArgs);
+ if (Sanitize.needsLsanRt())
+ addLsanRTLinux(getToolChain(), Args, CmdArgs);
+ if (Sanitize.needsDfsanRt())
+ addDfsanRTLinux(getToolChain(), Args, CmdArgs);
- if (D.CCCIsCXX &&
+ // The profile runtime also needs access to system libraries.
+ addProfileRTLinux(getToolChain(), Args, CmdArgs);
+
+ if (D.CCCIsCXX() &&
!Args.hasArg(options::OPT_nostdlib) &&
!Args.hasArg(options::OPT_nodefaultlibs)) {
bool OnlyLibstdcxxStatic = Args.hasArg(options::OPT_static_libstdcxx) &&
@@ -6157,8 +6632,6 @@ void gnutools::Link::ConstructJob(Compilation &C, const JobAction &JA,
}
}
- addProfileRT(getToolChain(), Args, CmdArgs, getToolChain().getTriple());
-
C.addCommand(new Command(JA, *this, ToolChain.Linker.c_str(), CmdArgs));
}
@@ -6219,7 +6692,7 @@ void minix::Link::ConstructJob(Compilation &C, const JobAction &JA,
if (!Args.hasArg(options::OPT_nostdlib) &&
!Args.hasArg(options::OPT_nodefaultlibs)) {
- if (D.CCCIsCXX) {
+ if (D.CCCIsCXX()) {
getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
CmdArgs.push_back("-lm");
}
@@ -6367,7 +6840,7 @@ void dragonfly::Link::ConstructJob(Compilation &C, const JobAction &JA,
}
}
- if (D.CCCIsCXX) {
+ if (D.CCCIsCXX()) {
getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
CmdArgs.push_back("-lm");
}
@@ -6439,22 +6912,223 @@ void visualstudio::Link::ConstructJob(Compilation &C, const JobAction &JA,
}
if (!Args.hasArg(options::OPT_nostdlib) &&
- !Args.hasArg(options::OPT_nostartfiles)) {
+ !Args.hasArg(options::OPT_nostartfiles) &&
+ !C.getDriver().IsCLMode()) {
CmdArgs.push_back("-defaultlib:libcmt");
}
CmdArgs.push_back("-nologo");
+ bool DLL = Args.hasArg(options::OPT__SLASH_LD, options::OPT__SLASH_LDd);
+
+ if (DLL) {
+ CmdArgs.push_back(Args.MakeArgString("-dll"));
+
+ SmallString<128> ImplibName(Output.getFilename());
+ llvm::sys::path::replace_extension(ImplibName, "lib");
+ CmdArgs.push_back(Args.MakeArgString(std::string("-implib:") +
+ ImplibName.str()));
+ }
+
+ if (getToolChain().getSanitizerArgs().needsAsanRt()) {
+ CmdArgs.push_back(Args.MakeArgString("-debug"));
+ CmdArgs.push_back(Args.MakeArgString("-incremental:no"));
+ SmallString<128> LibSanitizer(getToolChain().getDriver().ResourceDir);
+ llvm::sys::path::append(LibSanitizer, "lib", "windows");
+ if (DLL) {
+ llvm::sys::path::append(LibSanitizer, "clang_rt.asan_dll_thunk-i386.lib");
+ } else {
+ llvm::sys::path::append(LibSanitizer, "clang_rt.asan-i386.lib");
+ }
+ // FIXME: Handle 64-bit.
+ CmdArgs.push_back(Args.MakeArgString(LibSanitizer));
+ }
+
Args.AddAllArgValues(CmdArgs, options::OPT_l);
+ Args.AddAllArgValues(CmdArgs, options::OPT__SLASH_link);
// Add filenames immediately.
for (InputInfoList::const_iterator
it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
if (it->isFilename())
CmdArgs.push_back(it->getFilename());
+ else
+ it->getInputArg().renderAsInput(Args, CmdArgs);
}
const char *Exec =
Args.MakeArgString(getToolChain().GetProgramPath("link.exe"));
C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}
+
+void visualstudio::Compile::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ C.addCommand(GetCommand(C, JA, Output, Inputs, Args, LinkingOutput));
+}
+
+// Try to find FallbackName on PATH that is not identical to ClangProgramPath.
+// If one cannot be found, return FallbackName.
+// We do this special search to prevent clang-cl from falling back onto itself
+// if it's available as cl.exe on the path.
+static std::string FindFallback(const char *FallbackName,
+ const char *ClangProgramPath) {
+ llvm::Optional<std::string> OptPath = llvm::sys::Process::GetEnv("PATH");
+ if (!OptPath.hasValue())
+ return FallbackName;
+
+#ifdef LLVM_ON_WIN32
+ const StringRef PathSeparators = ";";
+#else
+ const StringRef PathSeparators = ":";
+#endif
+
+ SmallVector<StringRef, 8> PathSegments;
+ llvm::SplitString(OptPath.getValue(), PathSegments, PathSeparators);
+
+ for (size_t i = 0, e = PathSegments.size(); i != e; ++i) {
+ const StringRef &PathSegment = PathSegments[i];
+ if (PathSegment.empty())
+ continue;
+
+ SmallString<128> FilePath(PathSegment);
+ llvm::sys::path::append(FilePath, FallbackName);
+ if (llvm::sys::fs::can_execute(Twine(FilePath)) &&
+ !llvm::sys::fs::equivalent(Twine(FilePath), ClangProgramPath))
+ return FilePath.str();
+ }
+
+ return FallbackName;
+}
+
+Command *visualstudio::Compile::GetCommand(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ ArgStringList CmdArgs;
+ CmdArgs.push_back("/nologo");
+ CmdArgs.push_back("/c"); // Compile only.
+ CmdArgs.push_back("/W0"); // No warnings.
+
+ // The goal is to be able to invoke this tool correctly based on
+ // any flag accepted by clang-cl.
+
+ // These are spelled the same way in clang and cl.exe,.
+ Args.AddAllArgs(CmdArgs, options::OPT_D, options::OPT_U);
+ Args.AddAllArgs(CmdArgs, options::OPT_I);
+
+ // Optimization level.
+ if (Arg *A = Args.getLastArg(options::OPT_O, options::OPT_O0)) {
+ if (A->getOption().getID() == options::OPT_O0) {
+ CmdArgs.push_back("/Od");
+ } else {
+ StringRef OptLevel = A->getValue();
+ if (OptLevel == "1" || OptLevel == "2" || OptLevel == "s")
+ A->render(Args, CmdArgs);
+ else if (OptLevel == "3")
+ CmdArgs.push_back("/Ox");
+ }
+ }
+
+ // Flags for which clang-cl have an alias.
+ // FIXME: How can we ensure this stays in sync with relevant clang-cl options?
+
+ if (Arg *A = Args.getLastArg(options::OPT_frtti, options::OPT_fno_rtti))
+ CmdArgs.push_back(A->getOption().getID() == options::OPT_frtti ? "/GR"
+ : "/GR-");
+ if (Args.hasArg(options::OPT_fsyntax_only))
+ CmdArgs.push_back("/Zs");
+
+ std::vector<std::string> Includes = Args.getAllArgValues(options::OPT_include);
+ for (size_t I = 0, E = Includes.size(); I != E; ++I)
+ CmdArgs.push_back(Args.MakeArgString(std::string("/FI") + Includes[I]));
+
+ // Flags that can simply be passed through.
+ Args.AddAllArgs(CmdArgs, options::OPT__SLASH_LD);
+ Args.AddAllArgs(CmdArgs, options::OPT__SLASH_LDd);
+
+ // The order of these flags is relevant, so pick the last one.
+ if (Arg *A = Args.getLastArg(options::OPT__SLASH_MD, options::OPT__SLASH_MDd,
+ options::OPT__SLASH_MT, options::OPT__SLASH_MTd))
+ A->render(Args, CmdArgs);
+
+
+ // Input filename.
+ assert(Inputs.size() == 1);
+ const InputInfo &II = Inputs[0];
+ assert(II.getType() == types::TY_C || II.getType() == types::TY_CXX);
+ CmdArgs.push_back(II.getType() == types::TY_C ? "/Tc" : "/Tp");
+ if (II.isFilename())
+ CmdArgs.push_back(II.getFilename());
+ else
+ II.getInputArg().renderAsInput(Args, CmdArgs);
+
+ // Output filename.
+ assert(Output.getType() == types::TY_Object);
+ const char *Fo = Args.MakeArgString(std::string("/Fo") +
+ Output.getFilename());
+ CmdArgs.push_back(Fo);
+
+ const Driver &D = getToolChain().getDriver();
+ std::string Exec = FindFallback("cl.exe", D.getClangProgramPath());
+
+ return new Command(JA, *this, Args.MakeArgString(Exec), CmdArgs);
+}
+
+
+/// XCore Tools
+// We pass assemble and link construction to the xcc tool.
+
+void XCore::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ ArgStringList CmdArgs;
+
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back(Output.getFilename());
+
+ CmdArgs.push_back("-c");
+
+ if (Args.hasArg(options::OPT_g_Group)) {
+ CmdArgs.push_back("-g");
+ }
+
+ Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,
+ options::OPT_Xassembler);
+
+ for (InputInfoList::const_iterator
+ it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
+ const InputInfo &II = *it;
+ CmdArgs.push_back(II.getFilename());
+ }
+
+ const char *Exec =
+ Args.MakeArgString(getToolChain().GetProgramPath("xcc"));
+ C.addCommand(new Command(JA, *this, Exec, CmdArgs));
+}
+
+void XCore::Link::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ ArgStringList CmdArgs;
+
+ if (Output.isFilename()) {
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back(Output.getFilename());
+ } else {
+ assert(Output.isNothing() && "Invalid output.");
+ }
+
+ AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);
+
+ const char *Exec =
+ Args.MakeArgString(getToolChain().GetProgramPath("xcc"));
+ C.addCommand(new Command(JA, *this, Exec, CmdArgs));
+}
OpenPOWER on IntegriCloud