aboutsummaryrefslogtreecommitdiff
path: root/lib/Driver/Tools.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Driver/Tools.cpp')
-rw-r--r--lib/Driver/Tools.cpp2884
1 files changed, 1882 insertions, 1002 deletions
diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp
index b013eb510c4e..198e82e15369 100644
--- a/lib/Driver/Tools.cpp
+++ b/lib/Driver/Tools.cpp
@@ -10,6 +10,7 @@
#include "Tools.h"
#include "InputInfo.h"
#include "ToolChains.h"
+#include "clang/Basic/LangOptions.h"
#include "clang/Basic/ObjCRuntime.h"
#include "clang/Basic/Version.h"
#include "clang/Driver/Action.h"
@@ -21,7 +22,6 @@
#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"
@@ -29,28 +29,47 @@
#include "llvm/Option/Arg.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Option/Option.h"
+#include "llvm/Support/Compression.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/Program.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;
+static void addAssemblerKPIC(const ArgList &Args, ArgStringList &CmdArgs) {
+ 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)
+ return;
+ if (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");
+ }
+}
+
/// 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 (Arg *A = Args.getLastArg(options::OPT_C, options::OPT_CC)) {
+ if (!Args.hasArg(options::OPT_E) && !Args.hasArg(options::OPT__SLASH_P) &&
+ !Args.hasArg(options::OPT__SLASH_EP) && !D.CCCIsCPP()) {
D.Diag(diag::err_drv_argument_only_allowed_with)
- << A->getAsString(Args) << "-E";
+ << A->getBaseArg().getAsString(Args)
+ << (D.IsCLMode() ? "/E, /P or /EP" : "-E");
+ }
+ }
}
/// CheckCodeGenerationOptions - Perform some validation of code generation
@@ -157,10 +176,7 @@ static void AddLinkerInputs(const ToolChain &TC,
// (constructed via -Xarch_).
Args.AddAllArgValues(CmdArgs, options::OPT_Zlinker_input);
- for (InputInfoList::const_iterator
- it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
- const InputInfo &II = *it;
-
+ for (const auto &II : Inputs) {
if (!TC.HasNativeLLVMSupport()) {
// Don't try to pass LLVM inputs unless we have native support.
if (II.getType() == types::TY_LLVM_IR ||
@@ -181,16 +197,23 @@ static void AddLinkerInputs(const ToolChain &TC,
const Arg &A = II.getInputArg();
// Handle reserved library options.
- if (A.getOption().matches(options::OPT_Z_reserved_lib_stdcxx)) {
+ if (A.getOption().matches(options::OPT_Z_reserved_lib_stdcxx))
TC.AddCXXStdlibLibArgs(Args, CmdArgs);
- } else if (A.getOption().matches(options::OPT_Z_reserved_lib_cckext)) {
+ else if (A.getOption().matches(options::OPT_Z_reserved_lib_cckext))
TC.AddCCKextLibArgs(Args, CmdArgs);
- } else
- A.renderAsInput(Args, CmdArgs);
+ else if (A.getOption().matches(options::OPT_z)) {
+ // Pass -z prefix for gcc linker compatibility.
+ A.claim();
+ A.render(Args, CmdArgs);
+ } else {
+ A.renderAsInput(Args, CmdArgs);
+ }
}
// LIBRARY_PATH - included following the user specified library paths.
- addDirectoryList(Args, CmdArgs, "-L", "LIBRARY_PATH");
+ // and only supported on native toolchains.
+ if (!TC.isCrossCompiling())
+ addDirectoryList(Args, CmdArgs, "-L", "LIBRARY_PATH");
}
/// \brief Determine whether Objective-C automated reference counting is
@@ -208,25 +231,6 @@ static bool isObjCRuntimeLinked(const ArgList &Args) {
return Args.hasArg(options::OPT_fobjc_link_runtime);
}
-static void addProfileRT(const ToolChain &TC, const ArgList &Args,
- ArgStringList &CmdArgs,
- llvm::Triple Triple) {
- 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;
-
- // GCC links libgcov.a by adding -L<inst>/gcc/lib/gcc/<triple>/<ver> -lgcov to
- // the link line. We cannot do the same thing because unlike gcov there is a
- // libprofile_rt.so. We used to use the -l:libprofile_rt.a syntax, but that is
- // not supported by old linkers.
- std::string ProfileRT =
- std::string(TC.getDriver().Dir) + "/../lib/libprofile_rt.a";
-
- CmdArgs.push_back(Args.MakeArgString(ProfileRT));
-}
-
static bool forwardToGCC(const Option &O) {
// Don't forward inputs from the original command line. They are added from
// InputInfoList.
@@ -297,6 +301,9 @@ void Clang::AddPreprocessingOptions(Compilation &C,
if (A->getOption().matches(options::OPT_M) ||
A->getOption().matches(options::OPT_MD))
CmdArgs.push_back("-sys-header-deps");
+
+ if (isa<PrecompileJobAction>(JA))
+ CmdArgs.push_back("-module-file-deps");
}
if (Args.hasArg(options::OPT_MG)) {
@@ -442,129 +449,6 @@ void Clang::AddPreprocessingOptions(Compilation &C,
getToolChain().AddClangSystemIncludeArgs(Args, CmdArgs);
}
-/// getLLVMArchSuffixForARM - Get the LLVM arch name to use for a particular
-/// CPU.
-//
-// FIXME: This is redundant with -mcpu, why does LLVM use this.
-// 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")
- .Cases("arm940t", "ep9312","v4t")
- .Cases("arm10tdmi", "arm1020t", "v5")
- .Cases("arm9e", "arm926ej-s", "arm946e-s", "v5e")
- .Cases("arm966e-s", "arm968e-s", "arm10e", "v5e")
- .Cases("arm1020e", "arm1022e", "xscale", "iwmmxt", "v5e")
- .Cases("arm1136j-s", "arm1136jf-s", "arm1176jz-s", "v6")
- .Cases("arm1176jzf-s", "mpcorenovfp", "mpcore", "v6")
- .Cases("arm1156t2-s", "arm1156t2f-s", "v6t2")
- .Cases("cortex-a5", "cortex-a7", "cortex-a8", "v7")
- .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("");
-}
-
-/// getARMTargetCPU - Get the (LLVM) name of the ARM cpu we are targeting.
-//
-// FIXME: tblgen this.
-static std::string getARMTargetCPU(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;
- }
-
- StringRef MArch;
- if (Arg *A = Args.getLastArg(options::OPT_march_EQ)) {
- // Otherwise, if we have -march= choose the base CPU for that arch.
- MArch = A->getValue();
- } else {
- // Otherwise, use the Arch from the triple.
- MArch = Triple.getArchName();
- }
-
- if (Triple.getOS() == llvm::Triple::NetBSD) {
- if (MArch == "armv6")
- return "arm1176jzf-s";
- }
-
- // Handle -march=native.
- std::string NativeMArch;
- if (MArch == "native") {
- std::string CPU = llvm::sys::getHostCPUName();
- if (CPU != "generic") {
- // Translate the native cpu into the architecture. The switch below will
- // then chose the minimum cpu for that arch.
- NativeMArch = std::string("arm") + getLLVMArchSuffixForARM(CPU);
- MArch = NativeMArch;
- }
- }
-
- return llvm::StringSwitch<const char *>(MArch)
- .Cases("armv2", "armv2a","arm2")
- .Case("armv3", "arm6")
- .Case("armv3m", "arm7m")
- .Case("armv4", "strongarm")
- .Case("armv4t", "arm7tdmi")
- .Cases("armv5", "armv5t", "arm10tdmi")
- .Cases("armv5e", "armv5te", "arm1022e")
- .Case("armv5tej", "arm926ej-s")
- .Cases("armv6", "armv6k", "arm1136jf-s")
- .Case("armv6j", "arm1136j-s")
- .Cases("armv6z", "armv6zk", "arm1176jzf-s")
- .Case("armv6t2", "arm1156t2-s")
- .Cases("armv6m", "armv6-m", "cortex-m0")
- .Cases("armv7", "armv7a", "armv7-a", "cortex-a8")
- .Cases("armv7em", "armv7e-m", "cortex-m4")
- .Cases("armv7f", "armv7-f", "cortex-a9-mp")
- .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 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()) {
@@ -572,7 +456,15 @@ static bool isSignedCharDefault(const llvm::Triple &Triple) {
return true;
case llvm::Triple::aarch64:
+ case llvm::Triple::aarch64_be:
+ case llvm::Triple::arm64:
+ case llvm::Triple::arm64_be:
case llvm::Triple::arm:
+ case llvm::Triple::armeb:
+ if (Triple.isOSDarwin() || Triple.isOSWindows())
+ return true;
+ return false;
+
case llvm::Triple::ppc:
case llvm::Triple::ppc64:
if (Triple.isOSDarwin())
@@ -596,33 +488,6 @@ static bool isNoCommonDefault(const llvm::Triple &Triple) {
}
}
-// 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,
@@ -659,16 +524,28 @@ static void getARMFPUFeatures(const Driver &D, const Arg *A,
Features.push_back("-vfp2");
Features.push_back("-vfp3");
Features.push_back("-neon");
+ } else if (FPU == "vfp") {
+ Features.push_back("+vfp2");
+ Features.push_back("-neon");
} else if (FPU == "vfp3-d16" || FPU == "vfpv3-d16") {
Features.push_back("+vfp3");
Features.push_back("+d16");
Features.push_back("-neon");
- } else if (FPU == "vfp") {
- Features.push_back("+vfp2");
- Features.push_back("-neon");
} else if (FPU == "vfp3" || FPU == "vfpv3") {
Features.push_back("+vfp3");
Features.push_back("-neon");
+ } else if (FPU == "vfp4-d16" || FPU == "vfpv4-d16") {
+ Features.push_back("+vfp4");
+ Features.push_back("+d16");
+ Features.push_back("-neon");
+ } else if (FPU == "vfp4" || FPU == "vfpv4") {
+ Features.push_back("+vfp4");
+ Features.push_back("-neon");
+ } else if (FPU == "fp4-sp-d16" || FPU == "fpv4-sp-d16") {
+ Features.push_back("+vfp4");
+ Features.push_back("+d16");
+ Features.push_back("+fp-only-sp");
+ Features.push_back("-neon");
} else if (FPU == "fp-armv8") {
Features.push_back("+fp-armv8");
Features.push_back("-neon");
@@ -696,9 +573,8 @@ static void getARMFPUFeatures(const Driver &D, const Arg *A,
// Select the float ABI as determined by -msoft-float, -mhard-float, and
// -mfloat-abi=.
-static StringRef getARMFloatABI(const Driver &D,
- const ArgList &Args,
- const llvm::Triple &Triple) {
+StringRef tools::arm::getARMFloatABI(const Driver &D, const ArgList &Args,
+ const llvm::Triple &Triple) {
StringRef FloatABI;
if (Arg *A = Args.getLastArg(options::OPT_msoft_float,
options::OPT_mhard_float,
@@ -727,7 +603,7 @@ static StringRef getARMFloatABI(const Driver &D,
//
// FIXME: Factor out an ARM class so we can cache the arch somewhere.
std::string ArchName =
- getLLVMArchSuffixForARM(getARMTargetCPU(Args, Triple));
+ arm::getLLVMArchSuffixForARM(arm::getARMTargetCPU(Args, Triple));
if (StringRef(ArchName).startswith("v6") ||
StringRef(ArchName).startswith("v7"))
FloatABI = "softfp";
@@ -736,9 +612,21 @@ static StringRef getARMFloatABI(const Driver &D,
break;
}
+ // FIXME: this is invalid for WindowsCE
+ case llvm::Triple::Win32:
+ FloatABI = "hard";
+ break;
+
case llvm::Triple::FreeBSD:
- // FreeBSD defaults to soft float
- FloatABI = "soft";
+ switch(Triple.getEnvironment()) {
+ case llvm::Triple::GNUEABIHF:
+ FloatABI = "hard";
+ break;
+ default:
+ // FreeBSD defaults to soft float
+ FloatABI = "soft";
+ break;
+ }
break;
default:
@@ -749,13 +637,16 @@ static StringRef getARMFloatABI(const Driver &D,
case llvm::Triple::GNUEABI:
FloatABI = "softfp";
break;
+ case llvm::Triple::EABIHF:
+ FloatABI = "hard";
+ break;
case llvm::Triple::EABI:
// EABI is always AAPCS, and if it was not marked 'hard', it's softfp
FloatABI = "softfp";
break;
case llvm::Triple::Android: {
std::string ArchName =
- getLLVMArchSuffixForARM(getARMTargetCPU(Args, Triple));
+ arm::getLLVMArchSuffixForARM(arm::getARMTargetCPU(Args, Triple));
if (StringRef(ArchName).startswith("v7"))
FloatABI = "softfp";
else
@@ -765,7 +656,9 @@ static StringRef getARMFloatABI(const Driver &D,
default:
// Assume "soft", but warn the user we are guessing.
FloatABI = "soft";
- D.Diag(diag::warn_drv_assuming_mfloat_abi_is) << "soft";
+ if (Triple.getOS() != llvm::Triple::UnknownOS ||
+ !Triple.isOSBinFormatMachO())
+ D.Diag(diag::warn_drv_assuming_mfloat_abi_is) << "soft";
break;
}
}
@@ -776,18 +669,30 @@ static StringRef getARMFloatABI(const Driver &D,
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");
+ std::vector<const char *> &Features,
+ bool ForAS) {
+ StringRef FloatABI = tools::arm::getARMFloatABI(D, Args, Triple);
+ if (!ForAS) {
+ // 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. We should probably pass this a new
+ // -target-option, which is handled by the -cc1/-cc1as invocation.
+ //
+ // FIXME2: For consistency, it would be ideal if we set up the target
+ // machine state the same when using the frontend or the assembler. We don't
+ // currently do that for the assembler, we pass the options directly to the
+ // backend and never even instantiate the frontend TargetInfo. If we did,
+ // and used its handleTargetFeatures hook, then we could ensure the
+ // assembler and the frontend behave the same.
- // Use software floating point argument passing?
- if (FloatABI != "hard")
- Features.push_back("+soft-float-abi");
+ // 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))
@@ -797,8 +702,11 @@ static void getARMTargetFeatures(const Driver &D, const llvm::Triple &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")
+ if (FloatABI == "soft") {
Features.push_back("-neon");
+ // Also need to explicitly disable features which imply NEON.
+ Features.push_back("-crypto");
+ }
// En/disable crc
if (Arg *A = Args.getLastArg(options::OPT_mcrc,
@@ -817,23 +725,28 @@ void Clang::AddARMTargetArgs(const ArgList &Args,
// Get the effective triple, which takes into account the deployment target.
std::string TripleStr = getToolChain().ComputeEffectiveClangTriple(Args);
llvm::Triple Triple(TripleStr);
- std::string CPUName = getARMTargetCPU(Args, Triple);
+ std::string CPUName = arm::getARMTargetCPU(Args, Triple);
// Select the ABI to use.
//
// FIXME: Support -meabi.
- const char *ABIName = 0;
+ const char *ABIName = nullptr;
if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) {
ABIName = A->getValue();
- } else if (Triple.isOSDarwin()) {
+ } else if (Triple.isOSBinFormatMachO()) {
// The backend is hardwired to assume AAPCS for M-class processors, ensure
// the frontend matches that.
if (Triple.getEnvironment() == llvm::Triple::EABI ||
+ (Triple.getOS() == llvm::Triple::UnknownOS &&
+ Triple.getObjectFormat() == llvm::Triple::MachO) ||
StringRef(CPUName).startswith("cortex-m")) {
ABIName = "aapcs";
} else {
ABIName = "apcs-gnu";
}
+ } else if (Triple.isOSWindows()) {
+ // FIXME: this is invalid for WindowsCE
+ ABIName = "aapcs";
} else {
// Select the default based on the platform.
switch(Triple.getEnvironment()) {
@@ -842,6 +755,7 @@ void Clang::AddARMTargetArgs(const ArgList &Args,
case llvm::Triple::GNUEABIHF:
ABIName = "aapcs-linux";
break;
+ case llvm::Triple::EABIHF:
case llvm::Triple::EABI:
ABIName = "aapcs";
break;
@@ -853,7 +767,7 @@ void Clang::AddARMTargetArgs(const ArgList &Args,
CmdArgs.push_back(ABIName);
// Determine floating point ABI from the options & target defaults.
- StringRef FloatABI = getARMFloatABI(D, Args, Triple);
+ StringRef FloatABI = tools::arm::getARMFloatABI(D, Args, Triple);
if (FloatABI == "soft") {
// Floating point operations and argument passing are soft.
//
@@ -900,23 +814,97 @@ void Clang::AddARMTargetArgs(const ArgList &Args,
true))
CmdArgs.push_back("-no-implicit-float");
- // 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");
- }
+ // 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");
+ }
+}
+
+/// getAArch64TargetCPU - Get the (LLVM) name of the AArch64 cpu we are
+/// targeting.
+static std::string getAArch64TargetCPU(const ArgList &Args) {
+ Arg *A;
+ std::string CPU;
+ // If we have -mtune or -mcpu, use that.
+ if ((A = Args.getLastArg(options::OPT_mtune_EQ))) {
+ CPU = A->getValue();
+ } else if ((A = Args.getLastArg(options::OPT_mcpu_EQ))) {
+ StringRef Mcpu = A->getValue();
+ CPU = Mcpu.split("+").first;
+ }
+
+ // Handle CPU name is 'native'.
+ if (CPU == "native")
+ return llvm::sys::getHostCPUName();
+ else if (CPU.size())
+ return CPU;
+
+ // Make sure we pick "cyclone" if -arch is used.
+ // FIXME: Should this be picked by checking the target triple instead?
+ if (Args.getLastArg(options::OPT_arch))
+ return "cyclone";
+
+ return "generic";
+}
+
+void Clang::AddAArch64TargetArgs(const ArgList &Args,
+ ArgStringList &CmdArgs) const {
+ std::string TripleStr = getToolChain().ComputeEffectiveClangTriple(Args);
+ llvm::Triple Triple(TripleStr);
+
+ if (!Args.hasFlag(options::OPT_mred_zone, options::OPT_mno_red_zone, true) ||
+ Args.hasArg(options::OPT_mkernel) ||
+ Args.hasArg(options::OPT_fapple_kext))
+ CmdArgs.push_back("-disable-red-zone");
+
+ if (!Args.hasFlag(options::OPT_mimplicit_float,
+ options::OPT_mno_implicit_float, true))
+ CmdArgs.push_back("-no-implicit-float");
+
+ const char *ABIName = nullptr;
+ if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ))
+ ABIName = A->getValue();
+ else if (Triple.isOSDarwin())
+ ABIName = "darwinpcs";
+ else
+ ABIName = "aapcs";
+
+ CmdArgs.push_back("-target-abi");
+ CmdArgs.push_back(ABIName);
+
+ if (Args.hasArg(options::OPT_mstrict_align)) {
+ CmdArgs.push_back("-backend-option");
+ CmdArgs.push_back("-aarch64-strict-align");
+ }
+
+ // Setting -mno-global-merge disables the codegen global merge pass. Setting
+ // -mglobal-merge has no effect as the pass is enabled by default.
+ if (Arg *A = Args.getLastArg(options::OPT_mglobal_merge,
+ options::OPT_mno_global_merge)) {
+ if (A->getOption().matches(options::OPT_mno_global_merge))
+ CmdArgs.push_back("-mno-global-merge");
+ }
}
// Get CPU and ABI names. They are not independent
// so we have to calculate them together.
-static void getMipsCPUAndABI(const ArgList &Args,
- const llvm::Triple &Triple,
- StringRef &CPUName,
- StringRef &ABIName) {
- const char *DefMips32CPU = "mips32";
- const char *DefMips64CPU = "mips64";
+void mips::getMipsCPUAndABI(const ArgList &Args,
+ const llvm::Triple &Triple,
+ StringRef &CPUName,
+ StringRef &ABIName) {
+ const char *DefMips32CPU = "mips32r2";
+ const char *DefMips64CPU = "mips64r2";
+
+ // MIPS32r6 is the default for mips(el)?-img-linux-gnu and MIPS64r6 is the
+ // default for mips64(el)?-img-linux-gnu.
+ if (Triple.getVendor() == llvm::Triple::ImaginationTechnologies &&
+ Triple.getEnvironment() == llvm::Triple::GNU) {
+ DefMips32CPU = "mips32r6";
+ DefMips64CPU = "mips64r6";
+ }
if (Arg *A = Args.getLastArg(options::OPT_march_EQ,
options::OPT_mcpu_EQ))
@@ -948,22 +936,22 @@ static void getMipsCPUAndABI(const ArgList &Args,
}
}
- if (!ABIName.empty()) {
+ if (ABIName.empty()) {
+ // Deduce ABI name from the target triple.
+ if (Triple.getArch() == llvm::Triple::mips ||
+ Triple.getArch() == llvm::Triple::mipsel)
+ ABIName = "o32";
+ else
+ ABIName = "n64";
+ }
+
+ if (CPUName.empty()) {
// Deduce CPU name from ABI name.
CPUName = llvm::StringSwitch<const char *>(ABIName)
- .Cases("32", "o32", "eabi", DefMips32CPU)
- .Cases("n32", "n64", "64", DefMips64CPU)
+ .Cases("o32", "eabi", DefMips32CPU)
+ .Cases("n32", "n64", DefMips64CPU)
.Default("");
}
- else if (!CPUName.empty()) {
- // Deduce ABI name from CPU name.
- ABIName = llvm::StringSwitch<const char *>(CPUName)
- .Cases("mips32", "mips32r2", "o32")
- .Cases("mips64", "mips64r2", "n64")
- .Default("");
- }
-
- // FIXME: Warn on inconsistent cpu and abi usage.
}
// Convert ABI name to the GNU tools acceptable variant.
@@ -1017,11 +1005,27 @@ static void AddTargetFeature(const ArgList &Args,
}
}
-static void getMIPSTargetFeatures(const Driver &D, const ArgList &Args,
+static void getMIPSTargetFeatures(const Driver &D, const llvm::Triple &Triple,
+ const ArgList &Args,
std::vector<const char *> &Features) {
+ StringRef CPUName;
+ StringRef ABIName;
+ mips::getMipsCPUAndABI(Args, Triple, CPUName, ABIName);
+ ABIName = getGnuCompatibleMipsABIName(ABIName);
+
+ // Always override the backend's default ABI.
+ std::string ABIFeature = llvm::StringSwitch<StringRef>(ABIName)
+ .Case("32", "+o32")
+ .Case("n32", "+n32")
+ .Case("64", "+n64")
+ .Case("eabi", "+eabi")
+ .Default(("+" + ABIName).str());
+ Features.push_back("-o32");
+ Features.push_back("-n64");
+ Features.push_back(Args.MakeArgString(ABIFeature));
+
StringRef FloatABI = getMipsFloatABI(D, Args);
- bool IsMips16 = Args.getLastArg(options::OPT_mips16) != NULL;
- if (FloatABI == "soft" || (FloatABI == "hard" && IsMips16)) {
+ if (FloatABI == "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.
@@ -1029,8 +1033,14 @@ static void getMIPSTargetFeatures(const Driver &D, const ArgList &Args,
}
if (Arg *A = Args.getLastArg(options::OPT_mnan_EQ)) {
- if (StringRef(A->getValue()) == "2008")
+ StringRef Val = StringRef(A->getValue());
+ if (Val == "2008")
Features.push_back("+nan2008");
+ else if (Val == "legacy")
+ Features.push_back("-nan2008");
+ else
+ D.Diag(diag::err_drv_unsupported_option_argument)
+ << A->getOption().getName() << Val;
}
AddTargetFeature(Args, Features, options::OPT_msingle_float,
@@ -1045,8 +1055,25 @@ static void getMIPSTargetFeatures(const Driver &D, const ArgList &Args,
"dspr2");
AddTargetFeature(Args, Features, options::OPT_mmsa, options::OPT_mno_msa,
"msa");
- AddTargetFeature(Args, Features, options::OPT_mfp64, options::OPT_mfp32,
- "fp64");
+
+ // Add the last -mfp32/-mfpxx/-mfp64 or if none are given and the ABI is O32
+ // pass -mfpxx
+ if (Arg *A = Args.getLastArg(options::OPT_mfp32, options::OPT_mfpxx,
+ options::OPT_mfp64)) {
+ if (A->getOption().matches(options::OPT_mfp32))
+ Features.push_back(Args.MakeArgString("-fp64"));
+ else if (A->getOption().matches(options::OPT_mfpxx)) {
+ Features.push_back(Args.MakeArgString("+fpxx"));
+ Features.push_back(Args.MakeArgString("+nooddspreg"));
+ } else
+ Features.push_back(Args.MakeArgString("+fp64"));
+ } else if (mips::isFPXXDefault(Triple, CPUName, ABIName)) {
+ Features.push_back(Args.MakeArgString("+fpxx"));
+ Features.push_back(Args.MakeArgString("+nooddspreg"));
+ }
+
+ AddTargetFeature(Args, Features, options::OPT_mno_odd_spreg,
+ options::OPT_modd_spreg, "nooddspreg");
}
void Clang::AddMIPSTargetArgs(const ArgList &Args,
@@ -1055,25 +1082,18 @@ void Clang::AddMIPSTargetArgs(const ArgList &Args,
StringRef CPUName;
StringRef ABIName;
const llvm::Triple &Triple = getToolChain().getTriple();
- getMipsCPUAndABI(Args, Triple, CPUName, ABIName);
+ mips::getMipsCPUAndABI(Args, Triple, CPUName, ABIName);
CmdArgs.push_back("-target-abi");
CmdArgs.push_back(ABIName.data());
StringRef FloatABI = getMipsFloatABI(D, Args);
- bool IsMips16 = Args.getLastArg(options::OPT_mips16) != NULL;
-
- if (FloatABI == "soft" || (FloatABI == "hard" && IsMips16)) {
+ if (FloatABI == "soft") {
// Floating point operations and argument passing are soft.
CmdArgs.push_back("-msoft-float");
CmdArgs.push_back("-mfloat-abi");
CmdArgs.push_back("soft");
-
- if (FloatABI == "hard" && IsMips16) {
- CmdArgs.push_back("-mllvm");
- CmdArgs.push_back("-mips16-hard-float");
- }
}
else {
// Floating point operations and argument passing are hard.
@@ -1159,6 +1179,7 @@ static std::string getPPCTargetCPU(const ArgList &Args) {
.Case("power6", "pwr6")
.Case("power6x", "pwr6x")
.Case("power7", "pwr7")
+ .Case("power8", "pwr8")
.Case("pwr3", "pwr3")
.Case("pwr4", "pwr4")
.Case("pwr5", "pwr5")
@@ -1166,6 +1187,7 @@ static std::string getPPCTargetCPU(const ArgList &Args) {
.Case("pwr6", "pwr6")
.Case("pwr6x", "pwr6x")
.Case("pwr7", "pwr7")
+ .Case("pwr8", "pwr8")
.Case("powerpc", "ppc")
.Case("powerpc64", "ppc64")
.Case("powerpc64le", "ppc64le")
@@ -1239,7 +1261,7 @@ void Clang::AddSparcTargetArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
const Driver &D = getToolChain().getDriver();
- // Select the float ABI as determined by -msoft-float, -mhard-float, and
+ // Select the float ABI as determined by -msoft-float and -mhard-float.
StringRef FloatABI;
if (Arg *A = Args.getLastArg(options::OPT_msoft_float,
options::OPT_mhard_float)) {
@@ -1297,7 +1319,7 @@ static const char *getX86TargetCPU(const ArgList &Args,
if (Triple.getArch() != llvm::Triple::x86_64 &&
Triple.getArch() != llvm::Triple::x86)
- return 0; // This routine is only handling x86 targets.
+ return nullptr; // This routine is only handling x86 targets.
bool Is64Bit = Triple.getArch() == llvm::Triple::x86_64;
@@ -1308,10 +1330,9 @@ static const char *getX86TargetCPU(const ArgList &Args,
return Is64Bit ? "core2" : "yonah";
}
- // All x86 devices running Android have core2 as their common
- // denominator. This makes a better choice than pentium4.
+ // On Android use targets compatible with gcc
if (Triple.getEnvironment() == llvm::Triple::Android)
- return "core2";
+ return Is64Bit ? "x86-64" : "i686";
// Everything else goes to x86-64 in 64-bit mode.
if (Is64Bit)
@@ -1338,11 +1359,16 @@ static std::string getCPUName(const ArgList &Args, const llvm::Triple &T) {
return "";
case llvm::Triple::aarch64:
- return getAArch64TargetCPU(Args, T);
+ case llvm::Triple::aarch64_be:
+ case llvm::Triple::arm64:
+ case llvm::Triple::arm64_be:
+ return getAArch64TargetCPU(Args);
case llvm::Triple::arm:
+ case llvm::Triple::armeb:
case llvm::Triple::thumb:
- return getARMTargetCPU(Args, T);
+ case llvm::Triple::thumbeb:
+ return arm::getARMTargetCPU(Args, T);
case llvm::Triple::mips:
case llvm::Triple::mipsel:
@@ -1350,7 +1376,7 @@ static std::string getCPUName(const ArgList &Args, const llvm::Triple &T) {
case llvm::Triple::mips64el: {
StringRef CPUName;
StringRef ABIName;
- getMipsCPUAndABI(Args, T, CPUName, ABIName);
+ mips::getMipsCPUAndABI(Args, T, CPUName, ABIName);
return CPUName;
}
@@ -1373,7 +1399,8 @@ static std::string getCPUName(const ArgList &Args, const llvm::Triple &T) {
}
case llvm::Triple::sparc:
- if (const Arg *A = Args.getLastArg(options::OPT_march_EQ))
+ case llvm::Triple::sparcv9:
+ if (const Arg *A = Args.getLastArg(options::OPT_mcpu_EQ))
return A->getValue();
return "";
@@ -1392,7 +1419,26 @@ static std::string getCPUName(const ArgList &Args, const llvm::Triple &T) {
}
}
-static void getX86TargetFeatures(const llvm::Triple &Triple,
+static void AddGoldPlugin(const ToolChain &ToolChain, const ArgList &Args,
+ ArgStringList &CmdArgs) {
+ // 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.
+ 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));
+}
+
+static void getX86TargetFeatures(const Driver & D,
+ const llvm::Triple &Triple,
const ArgList &Args,
std::vector<const char *> &Features) {
if (Triple.getArchName() == "x86_64h") {
@@ -1406,6 +1452,40 @@ static void getX86TargetFeatures(const llvm::Triple &Triple,
Features.push_back("-fsgsbase");
}
+ // Add features to comply with gcc on Android
+ if (Triple.getEnvironment() == llvm::Triple::Android) {
+ if (Triple.getArch() == llvm::Triple::x86_64) {
+ Features.push_back("+sse4.2");
+ Features.push_back("+popcnt");
+ } else
+ Features.push_back("+ssse3");
+ }
+
+ // Set features according to the -arch flag on MSVC
+ if (Arg *A = Args.getLastArg(options::OPT__SLASH_arch)) {
+ StringRef Arch = A->getValue();
+ bool ArchUsed = false;
+ // First, look for flags that are shared in x86 and x86-64.
+ if (Triple.getArch() == llvm::Triple::x86_64 ||
+ Triple.getArch() == llvm::Triple::x86) {
+ if (Arch == "AVX" || Arch == "AVX2") {
+ ArchUsed = true;
+ Features.push_back(Args.MakeArgString("+" + Arch.lower()));
+ }
+ }
+ // Then, look for x86-specific flags.
+ if (Triple.getArch() == llvm::Triple::x86) {
+ if (Arch == "IA32") {
+ ArchUsed = true;
+ } else if (Arch == "SSE" || Arch == "SSE2") {
+ ArchUsed = true;
+ Features.push_back(Args.MakeArgString("+" + Arch.lower()));
+ }
+ }
+ if (!ArchUsed)
+ D.Diag(clang::diag::warn_drv_unused_argument) << A->getAsString(Args);
+ }
+
// 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),
@@ -1449,6 +1529,17 @@ void Clang::AddX86TargetArgs(const ArgList &Args,
}
if (NoImplicitFloat)
CmdArgs.push_back("-no-implicit-float");
+
+ if (Arg *A = Args.getLastArg(options::OPT_masm_EQ)) {
+ StringRef Value = A->getValue();
+ if (Value == "intel" || Value == "att") {
+ CmdArgs.push_back("-mllvm");
+ CmdArgs.push_back(Args.MakeArgString("-x86-asm-syntax=" + Value));
+ } else {
+ getToolChain().getDriver().Diag(diag::err_drv_unsupported_option_argument)
+ << A->getOption().getName() << Value;
+ }
+ }
}
static inline bool HasPICArg(const ArgList &Args) {
@@ -1496,15 +1587,146 @@ void Clang::AddHexagonTargetArgs(const ArgList &Args,
CmdArgs.push_back ("-machine-sink-split=0");
}
+// Decode AArch64 features from string like +[no]featureA+[no]featureB+...
+static bool DecodeAArch64Features(const Driver &D, const StringRef &text,
+ std::vector<const char *> &Features) {
+ SmallVector<StringRef, 8> Split;
+ text.split(Split, StringRef("+"), -1, false);
+
+ for (unsigned I = 0, E = Split.size(); I != E; ++I) {
+ const char *result = llvm::StringSwitch<const char *>(Split[I])
+ .Case("fp", "+fp-armv8")
+ .Case("simd", "+neon")
+ .Case("crc", "+crc")
+ .Case("crypto", "+crypto")
+ .Case("nofp", "-fp-armv8")
+ .Case("nosimd", "-neon")
+ .Case("nocrc", "-crc")
+ .Case("nocrypto", "-crypto")
+ .Default(nullptr);
+ if (result)
+ Features.push_back(result);
+ else if (Split[I] == "neon" || Split[I] == "noneon")
+ D.Diag(diag::err_drv_no_neon_modifier);
+ else
+ return false;
+ }
+ return true;
+}
+
+// Check if the CPU name and feature modifiers in -mcpu are legal. If yes,
+// decode CPU and feature.
+static bool DecodeAArch64Mcpu(const Driver &D, StringRef Mcpu, StringRef &CPU,
+ std::vector<const char *> &Features) {
+ std::pair<StringRef, StringRef> Split = Mcpu.split("+");
+ CPU = Split.first;
+ if (CPU == "cyclone" || CPU == "cortex-a53" || CPU == "cortex-a57") {
+ Features.push_back("+neon");
+ Features.push_back("+crc");
+ Features.push_back("+crypto");
+ } else if (CPU == "generic") {
+ Features.push_back("+neon");
+ } else {
+ return false;
+ }
+
+ if (Split.second.size() && !DecodeAArch64Features(D, Split.second, Features))
+ return false;
+
+ return true;
+}
+
+static bool
+getAArch64ArchFeaturesFromMarch(const Driver &D, StringRef March,
+ const ArgList &Args,
+ std::vector<const char *> &Features) {
+ std::pair<StringRef, StringRef> Split = March.split("+");
+ if (Split.first != "armv8-a")
+ return false;
+
+ if (Split.second.size() && !DecodeAArch64Features(D, Split.second, Features))
+ return false;
+
+ return true;
+}
+
+static bool
+getAArch64ArchFeaturesFromMcpu(const Driver &D, StringRef Mcpu,
+ const ArgList &Args,
+ std::vector<const char *> &Features) {
+ StringRef CPU;
+ if (!DecodeAArch64Mcpu(D, Mcpu, CPU, Features))
+ return false;
+
+ return true;
+}
+
+static bool
+getAArch64MicroArchFeaturesFromMtune(const Driver &D, StringRef Mtune,
+ const ArgList &Args,
+ std::vector<const char *> &Features) {
+ // Handle CPU name is 'native'.
+ if (Mtune == "native")
+ Mtune = llvm::sys::getHostCPUName();
+ if (Mtune == "cyclone") {
+ Features.push_back("+zcm");
+ Features.push_back("+zcz");
+ }
+ return true;
+}
+
+static bool
+getAArch64MicroArchFeaturesFromMcpu(const Driver &D, StringRef Mcpu,
+ const ArgList &Args,
+ std::vector<const char *> &Features) {
+ StringRef CPU;
+ std::vector<const char *> DecodedFeature;
+ if (!DecodeAArch64Mcpu(D, Mcpu, CPU, DecodedFeature))
+ return false;
+
+ return getAArch64MicroArchFeaturesFromMtune(D, CPU, Args, Features);
+}
+
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);
+ Arg *A;
+ bool success = true;
+ // Enable NEON by default.
+ Features.push_back("+neon");
+ if ((A = Args.getLastArg(options::OPT_march_EQ)))
+ success = getAArch64ArchFeaturesFromMarch(D, A->getValue(), Args, Features);
+ else if ((A = Args.getLastArg(options::OPT_mcpu_EQ)))
+ success = getAArch64ArchFeaturesFromMcpu(D, A->getValue(), Args, Features);
+
+ if (success && (A = Args.getLastArg(options::OPT_mtune_EQ)))
+ success =
+ getAArch64MicroArchFeaturesFromMtune(D, A->getValue(), Args, Features);
+ else if (success && (A = Args.getLastArg(options::OPT_mcpu_EQ)))
+ success =
+ getAArch64MicroArchFeaturesFromMcpu(D, A->getValue(), Args, Features);
+
+ if (!success)
+ D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args);
+
+ if (Args.getLastArg(options::OPT_mgeneral_regs_only)) {
+ Features.push_back("-fp-armv8");
+ Features.push_back("-crypto");
+ 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");
+ }
}
static void getTargetFeatures(const Driver &D, const llvm::Triple &Triple,
- const ArgList &Args, ArgStringList &CmdArgs) {
+ const ArgList &Args, ArgStringList &CmdArgs,
+ bool ForAS) {
std::vector<const char *> Features;
switch (Triple.getArch()) {
default:
@@ -1513,12 +1735,14 @@ static void getTargetFeatures(const Driver &D, const llvm::Triple &Triple,
case llvm::Triple::mipsel:
case llvm::Triple::mips64:
case llvm::Triple::mips64el:
- getMIPSTargetFeatures(D, Args, Features);
+ getMIPSTargetFeatures(D, Triple, Args, Features);
break;
case llvm::Triple::arm:
+ case llvm::Triple::armeb:
case llvm::Triple::thumb:
- getARMTargetFeatures(D, Triple, Args, Features);
+ case llvm::Triple::thumbeb:
+ getARMTargetFeatures(D, Triple, Args, Features, ForAS);
break;
case llvm::Triple::ppc:
@@ -1530,11 +1754,14 @@ static void getTargetFeatures(const Driver &D, const llvm::Triple &Triple,
getSparcTargetFeatures(Args, Features);
break;
case llvm::Triple::aarch64:
+ case llvm::Triple::aarch64_be:
+ case llvm::Triple::arm64:
+ case llvm::Triple::arm64_be:
getAArch64TargetFeatures(D, Args, Features);
break;
case llvm::Triple::x86:
case llvm::Triple::x86_64:
- getX86TargetFeatures(Triple, Args, Features);
+ getX86TargetFeatures(D, Triple, Args, Features);
break;
}
@@ -1569,7 +1796,7 @@ shouldUseExceptionTablesForObjCExceptions(const ObjCRuntime &runtime,
if (runtime.isNonFragile())
return true;
- if (!Triple.isOSDarwin())
+ if (!Triple.isMacOSX())
return false;
return (!Triple.isMacOSXVersionLT(10,5) &&
@@ -1577,6 +1804,45 @@ shouldUseExceptionTablesForObjCExceptions(const ObjCRuntime &runtime,
Triple.getArch() == llvm::Triple::arm));
}
+namespace {
+ struct ExceptionSettings {
+ bool ExceptionsEnabled;
+ bool ShouldUseExceptionTables;
+ ExceptionSettings() : ExceptionsEnabled(false),
+ ShouldUseExceptionTables(false) {}
+ };
+} // end anonymous namespace.
+
+// exceptionSettings() exists to share the logic between -cc1 and linker
+// invocations.
+static ExceptionSettings exceptionSettings(const ArgList &Args,
+ const llvm::Triple &Triple) {
+ ExceptionSettings ES;
+
+ // Are exceptions enabled by default?
+ ES.ExceptionsEnabled = (Triple.getArch() != llvm::Triple::xcore);
+
+ // This keeps track of whether exceptions were explicitly turned on or off.
+ bool DidHaveExplicitExceptionFlag = false;
+
+ if (Arg *A = Args.getLastArg(options::OPT_fexceptions,
+ options::OPT_fno_exceptions)) {
+ if (A->getOption().matches(options::OPT_fexceptions))
+ ES.ExceptionsEnabled = true;
+ else
+ ES.ExceptionsEnabled = false;
+
+ DidHaveExplicitExceptionFlag = true;
+ }
+
+ // Exception tables and cleanups can be enabled with -fexceptions even if the
+ // language itself doesn't support exceptions.
+ if (ES.ExceptionsEnabled && DidHaveExplicitExceptionFlag)
+ ES.ShouldUseExceptionTables = true;
+
+ return ES;
+}
+
/// addExceptionArgs - Adds exception related arguments to the driver command
/// arguments. There's a master flag, -fexceptions and also language specific
/// flags to enable/disable C++ and Objective-C exceptions.
@@ -1599,28 +1865,8 @@ static void addExceptionArgs(const ArgList &Args, types::ID InputType,
return;
}
- // Exceptions are enabled by default.
- bool ExceptionsEnabled = true;
-
- // This keeps track of whether exceptions were explicitly turned on or off.
- bool DidHaveExplicitExceptionFlag = false;
-
- if (Arg *A = Args.getLastArg(options::OPT_fexceptions,
- options::OPT_fno_exceptions)) {
- if (A->getOption().matches(options::OPT_fexceptions))
- ExceptionsEnabled = true;
- else
- ExceptionsEnabled = false;
-
- DidHaveExplicitExceptionFlag = true;
- }
-
- bool ShouldUseExceptionTables = false;
-
- // Exception tables and cleanups can be enabled with -fexceptions even if the
- // language itself doesn't support exceptions.
- if (ExceptionsEnabled && DidHaveExplicitExceptionFlag)
- ShouldUseExceptionTables = true;
+ // Gather the exception settings from the command line arguments.
+ ExceptionSettings ES = exceptionSettings(Args, Triple);
// Obj-C exceptions are enabled by default, regardless of -fexceptions. This
// is not necessarily sensible, but follows GCC.
@@ -1630,12 +1876,12 @@ static void addExceptionArgs(const ArgList &Args, types::ID InputType,
true)) {
CmdArgs.push_back("-fobjc-exceptions");
- ShouldUseExceptionTables |=
+ ES.ShouldUseExceptionTables |=
shouldUseExceptionTablesForObjCExceptions(objcRuntime, Triple);
}
if (types::isCXX(InputType)) {
- bool CXXExceptionsEnabled = ExceptionsEnabled;
+ bool CXXExceptionsEnabled = ES.ExceptionsEnabled;
if (Arg *A = Args.getLastArg(options::OPT_fcxx_exceptions,
options::OPT_fno_cxx_exceptions,
@@ -1650,11 +1896,11 @@ static void addExceptionArgs(const ArgList &Args, types::ID InputType,
if (CXXExceptionsEnabled) {
CmdArgs.push_back("-fcxx-exceptions");
- ShouldUseExceptionTables = true;
+ ES.ShouldUseExceptionTables = true;
}
}
- if (ShouldUseExceptionTables)
+ if (ES.ShouldUseExceptionTables)
CmdArgs.push_back("-fexceptions");
}
@@ -1670,19 +1916,6 @@ static bool ShouldDisableAutolink(const ArgList &Args,
Default);
}
-static bool ShouldDisableCFI(const ArgList &Args,
- const ToolChain &TC) {
- bool Default = true;
- if (TC.getTriple().isOSDarwin()) {
- // The native darwin assembler doesn't support cfi directives, so
- // we disable them if we think the .s file will be passed to it.
- Default = TC.useIntegratedAs();
- }
- return !Args.hasFlag(options::OPT_fdwarf2_cfi_asm,
- options::OPT_fno_dwarf2_cfi_asm,
- Default);
-}
-
static bool ShouldDisableDwarfDirectory(const ArgList &Args,
const ToolChain &TC) {
bool UseDwarfDirectory = Args.hasFlag(options::OPT_fdwarf_directory_asm,
@@ -1696,8 +1929,8 @@ static bool ContainsCompileAction(const Action *A) {
if (isa<CompileJobAction>(A))
return true;
- for (Action::const_iterator it = A->begin(), ie = A->end(); it != ie; ++it)
- if (ContainsCompileAction(*it))
+ for (const auto &Act : *A)
+ if (ContainsCompileAction(Act))
return true;
return false;
@@ -1713,9 +1946,8 @@ static bool UseRelaxAll(Compilation &C, const ArgList &Args) {
if (RelaxDefault) {
RelaxDefault = false;
- for (ActionList::const_iterator it = C.getActions().begin(),
- ie = C.getActions().end(); it != ie; ++it) {
- if (ContainsCompileAction(*it)) {
+ for (const auto &Act : C.getActions()) {
+ if (ContainsCompileAction(Act)) {
RelaxDefault = true;
break;
}
@@ -1742,6 +1974,7 @@ static void CollectArgsForIntegratedAssembler(Compilation &C,
// When using an integrated assembler, translate -Wa, and -Xassembler
// options.
+ bool CompressDebugSections = false;
for (arg_iterator it = Args.filtered_begin(options::OPT_Wa_COMMA,
options::OPT_Xassembler),
ie = Args.filtered_end(); it != ie; ++it) {
@@ -1765,48 +1998,116 @@ static void CollectArgsForIntegratedAssembler(Compilation &C,
CmdArgs.push_back("-fatal-assembler-warnings");
} else if (Value == "--noexecstack") {
CmdArgs.push_back("-mnoexecstack");
+ } else if (Value == "-compress-debug-sections" ||
+ Value == "--compress-debug-sections") {
+ CompressDebugSections = true;
+ } else if (Value == "-nocompress-debug-sections" ||
+ Value == "--nocompress-debug-sections") {
+ CompressDebugSections = false;
} 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 if (Value.startswith("-gdwarf-")) {
+ CmdArgs.push_back(Value.data());
} else {
D.Diag(diag::err_drv_unsupported_option_argument)
<< A->getOption().getName() << Value;
}
}
}
+ if (CompressDebugSections) {
+ if (llvm::zlib::isAvailable())
+ CmdArgs.push_back("-compress-debug-sections");
+ else
+ D.Diag(diag::warn_debug_compression_unavailable);
+ }
}
-static void addProfileRTLinux(
+// Until ARM libraries are build separately, we have them all in one library
+static StringRef getArchNameForCompilerRTLib(const ToolChain &TC) {
+ if (TC.getArch() == llvm::Triple::arm ||
+ TC.getArch() == llvm::Triple::armeb)
+ return "arm";
+ else
+ return TC.getArchName();
+}
+
+static SmallString<128> getCompilerRTLibDir(const ToolChain &TC) {
+ // The runtimes are located in the OS-specific resource directory.
+ SmallString<128> Res(TC.getDriver().ResourceDir);
+ const llvm::Triple &Triple = TC.getTriple();
+ // TC.getOS() yield "freebsd10.0" whereas "freebsd" is expected.
+ StringRef OSLibName = (Triple.getOS() == llvm::Triple::FreeBSD) ?
+ "freebsd" : TC.getOS();
+ llvm::sys::path::append(Res, "lib", OSLibName);
+ return Res;
+}
+
+// This adds the static libclang_rt.builtins-arch.a directly to the command line
+// FIXME: Make sure we can also emit shared objects if they're requested
+// and available, check for possible errors, etc.
+static void addClangRTLinux(
+ const ToolChain &TC, const ArgList &Args, ArgStringList &CmdArgs) {
+ SmallString<128> LibClangRT = getCompilerRTLibDir(TC);
+ llvm::sys::path::append(LibClangRT, Twine("libclang_rt.builtins-") +
+ getArchNameForCompilerRTLib(TC) +
+ ".a");
+
+ CmdArgs.push_back(Args.MakeArgString(LibClangRT));
+ CmdArgs.push_back("-lgcc_s");
+ if (TC.getDriver().CCCIsCXX())
+ CmdArgs.push_back("-lgcc_eh");
+}
+
+static void addProfileRT(
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_fprofile_instr_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");
+ // -fprofile-instr-generate requires position-independent code to build with
+ // shared objects. Link against the right archive.
+ const char *Lib = "libclang_rt.profile-";
+ if (Args.hasArg(options::OPT_fprofile_instr_generate) &&
+ Args.hasArg(options::OPT_shared))
+ Lib = "libclang_rt.profile-pic-";
+
+ SmallString<128> LibProfile = getCompilerRTLibDir(TC);
+ llvm::sys::path::append(LibProfile,
+ Twine(Lib) + getArchNameForCompilerRTLib(TC) + ".a");
CmdArgs.push_back(Args.MakeArgString(LibProfile));
}
-static void addSanitizerRTLinkFlagsLinux(
- const ToolChain &TC, const ArgList &Args, ArgStringList &CmdArgs,
- const StringRef Sanitizer, bool BeforeLibStdCXX,
- bool ExportSymbols = true) {
- // Sanitizer runtime is located in the Linux library directory and
- // has name "libclang_rt.<Sanitizer>-<ArchName>.a".
- SmallString<128> LibSanitizer(TC.getDriver().ResourceDir);
- llvm::sys::path::append(
- LibSanitizer, "lib", "linux",
- (Twine("libclang_rt.") + Sanitizer + "-" + TC.getArchName() + ".a"));
+static SmallString<128> getSanitizerRTLibName(const ToolChain &TC,
+ const StringRef Sanitizer,
+ bool Shared) {
+ // Sanitizer runtime has name "libclang_rt.<Sanitizer>-<ArchName>.{a,so}"
+ // (or "libclang_rt.<Sanitizer>-<ArchName>-android.so for Android)
+ const char *EnvSuffix =
+ TC.getTriple().getEnvironment() == llvm::Triple::Android ? "-android" : "";
+ SmallString<128> LibSanitizer = getCompilerRTLibDir(TC);
+ llvm::sys::path::append(LibSanitizer,
+ Twine("libclang_rt.") + Sanitizer + "-" +
+ getArchNameForCompilerRTLib(TC) + EnvSuffix +
+ (Shared ? ".so" : ".a"));
+ return LibSanitizer;
+}
+
+static void addSanitizerRTLinkFlags(const ToolChain &TC, const ArgList &Args,
+ ArgStringList &CmdArgs,
+ const StringRef Sanitizer,
+ bool BeforeLibStdCXX,
+ bool ExportSymbols = true,
+ bool LinkDeps = true) {
+ SmallString<128> LibSanitizer =
+ getSanitizerRTLibName(TC, Sanitizer, /*Shared*/ false);
// Sanitizer runtime may need to come before -lstdc++ (or -lc++, libstdc++.a,
// etc.) so that the linker picks custom versions of the global 'operator
@@ -1822,10 +2123,15 @@ static void addSanitizerRTLinkFlagsLinux(
CmdArgs.insert(BeforeLibStdCXX ? CmdArgs.begin() : CmdArgs.end(),
LibSanitizerArgs.begin(), LibSanitizerArgs.end());
- CmdArgs.push_back("-lpthread");
- CmdArgs.push_back("-lrt");
- CmdArgs.push_back("-ldl");
- CmdArgs.push_back("-lm");
+ if (LinkDeps) {
+ // Link sanitizer dependencies explicitly
+ CmdArgs.push_back("-lpthread");
+ CmdArgs.push_back("-lrt");
+ CmdArgs.push_back("-lm");
+ // There's no libdl on FreeBSD.
+ if (TC.getTriple().getOS() != llvm::Triple::FreeBSD)
+ CmdArgs.push_back("-ldl");
+ }
// 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
@@ -1841,66 +2147,102 @@ static void addSanitizerRTLinkFlagsLinux(
/// If AddressSanitizer is enabled, add appropriate linker flags (Linux).
/// 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) {
- 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));
+static void addAsanRT(const ToolChain &TC, const ArgList &Args,
+ ArgStringList &CmdArgs, bool Shared, bool IsCXX) {
+ if (Shared) {
+ // Link dynamic runtime if necessary.
+ SmallString<128> LibSanitizer =
+ getSanitizerRTLibName(TC, "asan", Shared);
+ CmdArgs.insert(CmdArgs.begin(), Args.MakeArgString(LibSanitizer));
+ }
+
+ // Do not link static runtime to DSOs or if compiling for Android.
+ if (Args.hasArg(options::OPT_shared) ||
+ (TC.getTriple().getEnvironment() == llvm::Triple::Android))
+ return;
+
+ if (Shared) {
+ addSanitizerRTLinkFlags(TC, Args, CmdArgs, "asan-preinit",
+ /*BeforeLibStdCXX*/ true, /*ExportSymbols*/ false,
+ /*LinkDeps*/ false);
} else {
- if (!Args.hasArg(options::OPT_shared))
- addSanitizerRTLinkFlagsLinux(TC, Args, CmdArgs, "asan", true);
+ addSanitizerRTLinkFlags(TC, Args, CmdArgs, "asan", true);
+ if (IsCXX)
+ addSanitizerRTLinkFlags(TC, Args, CmdArgs, "asan_cxx", true);
}
}
/// If ThreadSanitizer is enabled, add appropriate linker flags (Linux).
/// 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) {
+static void addTsanRT(const ToolChain &TC, const ArgList &Args,
+ ArgStringList &CmdArgs) {
if (!Args.hasArg(options::OPT_shared))
- addSanitizerRTLinkFlagsLinux(TC, Args, CmdArgs, "tsan", true);
+ addSanitizerRTLinkFlags(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) {
+static void addMsanRT(const ToolChain &TC, const ArgList &Args,
+ ArgStringList &CmdArgs) {
if (!Args.hasArg(options::OPT_shared))
- addSanitizerRTLinkFlagsLinux(TC, Args, CmdArgs, "msan", true);
+ addSanitizerRTLinkFlags(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) {
+static void addLsanRT(const ToolChain &TC, const ArgList &Args,
+ ArgStringList &CmdArgs) {
if (!Args.hasArg(options::OPT_shared))
- addSanitizerRTLinkFlagsLinux(TC, Args, CmdArgs, "lsan", true);
+ addSanitizerRTLinkFlags(TC, Args, CmdArgs, "lsan", true);
}
/// If UndefinedBehaviorSanitizer is enabled, add appropriate linker flags
/// (Linux).
-static void addUbsanRTLinux(const ToolChain &TC, const ArgList &Args,
- ArgStringList &CmdArgs, bool IsCXX,
- bool HasOtherSanitizerRt) {
+static void addUbsanRT(const ToolChain &TC, const ArgList &Args,
+ ArgStringList &CmdArgs, bool IsCXX,
+ bool HasOtherSanitizerRt) {
+ // Do not link runtime into shared libraries.
+ 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)
- addSanitizerRTLinkFlagsLinux(TC, Args, CmdArgs, "san", true, false);
+ addSanitizerRTLinkFlags(TC, Args, CmdArgs, "san", true, false);
- addSanitizerRTLinkFlagsLinux(TC, Args, CmdArgs, "ubsan", false);
+ addSanitizerRTLinkFlags(TC, Args, CmdArgs, "ubsan", false, true);
// Only include the bits of the runtime which need a C++ ABI library if
// we're linking in C++ mode.
if (IsCXX)
- addSanitizerRTLinkFlagsLinux(TC, Args, CmdArgs, "ubsan_cxx", false);
+ addSanitizerRTLinkFlags(TC, Args, CmdArgs, "ubsan_cxx", false, true);
}
-static void addDfsanRTLinux(const ToolChain &TC, const ArgList &Args,
- ArgStringList &CmdArgs) {
+static void addDfsanRT(const ToolChain &TC, const ArgList &Args,
+ ArgStringList &CmdArgs) {
if (!Args.hasArg(options::OPT_shared))
- addSanitizerRTLinkFlagsLinux(TC, Args, CmdArgs, "dfsan", true);
+ addSanitizerRTLinkFlags(TC, Args, CmdArgs, "dfsan", true);
+}
+
+// Should be called before we add C++ ABI library.
+static void addSanitizerRuntimes(const ToolChain &TC, const ArgList &Args,
+ ArgStringList &CmdArgs) {
+ const SanitizerArgs &Sanitize = TC.getSanitizerArgs();
+ const Driver &D = TC.getDriver();
+ if (Sanitize.needsUbsanRt())
+ addUbsanRT(TC, Args, CmdArgs, D.CCCIsCXX(),
+ Sanitize.needsAsanRt() || Sanitize.needsTsanRt() ||
+ Sanitize.needsMsanRt() || Sanitize.needsLsanRt());
+ if (Sanitize.needsAsanRt())
+ addAsanRT(TC, Args, CmdArgs, Sanitize.needsSharedAsanRt(), D.CCCIsCXX());
+ if (Sanitize.needsTsanRt())
+ addTsanRT(TC, Args, CmdArgs);
+ if (Sanitize.needsMsanRt())
+ addMsanRT(TC, Args, CmdArgs);
+ if (Sanitize.needsLsanRt())
+ addLsanRT(TC, Args, CmdArgs);
+ if (Sanitize.needsDfsanRt())
+ addDfsanRT(TC, Args, CmdArgs);
}
static bool shouldUseFramePointerForTarget(const ArgList &Args,
@@ -1962,7 +2304,8 @@ static const char *SplitDebugName(const ArgList &Args,
return Args.MakeArgString(T);
} else {
// Use the compilation dir.
- SmallString<128> T(Args.getLastArgValue(options::OPT_fdebug_compilation_dir));
+ SmallString<128> T(
+ Args.getLastArgValue(options::OPT_fdebug_compilation_dir));
SmallString<128> F(llvm::sys::path::stem(Inputs[0].getBaseInput()));
llvm::sys::path::replace_extension(F, "dwo");
T += F;
@@ -1996,7 +2339,8 @@ static void SplitDebugInfo(const ToolChain &TC, Compilation &C,
}
/// \brief Vectorize at all optimization levels greater than 1 except for -Oz.
-static bool shouldEnableVectorizerAtOLevel(const ArgList &Args) {
+/// For -Oz the loop vectorizer is disable, while the slp vectorizer is enabled.
+static bool shouldEnableVectorizerAtOLevel(const ArgList &Args, bool isSlpVec) {
if (Arg *A = Args.getLastArg(options::OPT_O_Group)) {
if (A->getOption().matches(options::OPT_O4) ||
A->getOption().matches(options::OPT_Ofast))
@@ -2012,9 +2356,9 @@ static bool shouldEnableVectorizerAtOLevel(const ArgList &Args) {
if (S == "s")
return true;
- // Don't vectorize -Oz.
+ // Don't vectorize -Oz, unless it's the slp vectorizer.
if (S == "z")
- return false;
+ return isSlpVec;
unsigned OptLevel = 0;
if (S.getAsInteger(10, OptLevel))
@@ -2026,6 +2370,41 @@ static bool shouldEnableVectorizerAtOLevel(const ArgList &Args) {
return false;
}
+/// Add -x lang to \p CmdArgs for \p Input.
+static void addDashXForInput(const ArgList &Args, const InputInfo &Input,
+ ArgStringList &CmdArgs) {
+ // When using -verify-pch, we don't want to provide the type
+ // 'precompiled-header' if it was inferred from the file extension
+ if (Args.hasArg(options::OPT_verify_pch) && Input.getType() == types::TY_PCH)
+ return;
+
+ CmdArgs.push_back("-x");
+ if (Args.hasArg(options::OPT_rewrite_objc))
+ CmdArgs.push_back(types::getTypeName(types::TY_PP_ObjCXX));
+ else
+ CmdArgs.push_back(types::getTypeName(Input.getType()));
+}
+
+static std::string getMSCompatibilityVersion(const char *VersionStr) {
+ unsigned Version;
+ if (StringRef(VersionStr).getAsInteger(10, Version))
+ return "0";
+
+ if (Version < 100)
+ return llvm::utostr_32(Version) + ".0";
+
+ if (Version < 10000)
+ return llvm::utostr_32(Version / 100) + "." +
+ llvm::utostr_32(Version % 100);
+
+ unsigned Build = 0, Factor = 1;
+ for ( ; Version > 10000; Version = Version / 10, Factor = Factor * 10)
+ Build = Build + (Version % 10) * Factor;
+ return llvm::utostr_32(Version / 100) + "." +
+ llvm::utostr_32(Version % 100) + "." +
+ llvm::utostr_32(Build);
+}
+
void Clang::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
@@ -2036,6 +2415,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
const Driver &D = getToolChain().getDriver();
ArgStringList CmdArgs;
+ bool IsWindowsGNU = getToolChain().getTriple().isWindowsGNUEnvironment();
+ bool IsWindowsCygnus =
+ getToolChain().getTriple().isWindowsCygwinEnvironment();
+ bool IsWindowsMSVC = getToolChain().getTriple().isWindowsMSVCEnvironment();
+
assert(Inputs.size() == 1 && "Unable to handle multiple inputs.");
// Invoke ourselves in -cc1 mode.
@@ -2048,6 +2432,22 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
std::string TripleStr = getToolChain().ComputeEffectiveClangTriple(Args);
CmdArgs.push_back(Args.MakeArgString(TripleStr));
+ const llvm::Triple TT(TripleStr);
+ if (TT.isOSWindows() && (TT.getArch() == llvm::Triple::arm ||
+ TT.getArch() == llvm::Triple::thumb)) {
+ unsigned Offset = TT.getArch() == llvm::Triple::arm ? 4 : 6;
+ unsigned Version;
+ TT.getArchName().substr(Offset).getAsInteger(10, Version);
+ if (Version < 7)
+ D.Diag(diag::err_target_unsupported_arch) << TT.getArchName()
+ << TripleStr;
+ }
+
+ // Push all default warning arguments that are specific to
+ // the given target. These come before user provided warning options
+ // are provided.
+ getToolChain().addClangWarningOptions(CmdArgs);
+
// Select the appropriate action.
RewriteKind rewriteKind = RK_None;
@@ -2082,6 +2482,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-emit-pch");
else
CmdArgs.push_back("-emit-pth");
+ } else if (isa<VerifyPCHJobAction>(JA)) {
+ CmdArgs.push_back("-verify-pch");
} else {
assert(isa<CompileJobAction>(JA) && "Invalid action for clang tool.");
@@ -2111,8 +2513,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
}
}
- // The make clang go fast button.
- CmdArgs.push_back("-disable-free");
+ // We normally speed up the clang process a bit by skipping destructors at
+ // exit, but when we're generating diagnostics we can rely on some of the
+ // cleanup.
+ if (!C.isForDiagnostics())
+ CmdArgs.push_back("-disable-free");
// Disable the verification pass in -asserts builds.
#ifdef NDEBUG
@@ -2142,7 +2547,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (!Args.hasArg(options::OPT__analyzer_no_default_checks)) {
CmdArgs.push_back("-analyzer-checker=core");
- if (getToolChain().getTriple().getOS() != llvm::Triple::Win32)
+ if (!IsWindowsMSVC)
CmdArgs.push_back("-analyzer-checker=unix");
if (getToolChain().getTriple().getVendor() == llvm::Triple::Apple)
@@ -2153,8 +2558,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (types::isCXX(Inputs[0].getType()))
CmdArgs.push_back("-analyzer-checker=cplusplus");
- // Enable the following experimental checkers for testing.
- CmdArgs.push_back("-analyzer-checker=security.insecureAPI.UncheckedReturn");
+ // Enable the following experimental checkers for testing.
+ CmdArgs.push_back(
+ "-analyzer-checker=security.insecureAPI.UncheckedReturn");
CmdArgs.push_back("-analyzer-checker=security.insecureAPI.getpw");
CmdArgs.push_back("-analyzer-checker=security.insecureAPI.gets");
CmdArgs.push_back("-analyzer-checker=security.insecureAPI.mktemp");
@@ -2185,6 +2591,54 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
bool PIC = PIE || getToolChain().isPICDefault();
bool IsPICLevelTwo = PIC;
+ // Android-specific defaults for PIC/PIE
+ if (getToolChain().getTriple().getEnvironment() == llvm::Triple::Android) {
+ switch (getToolChain().getTriple().getArch()) {
+ case llvm::Triple::arm:
+ case llvm::Triple::armeb:
+ case llvm::Triple::thumb:
+ case llvm::Triple::thumbeb:
+ case llvm::Triple::aarch64:
+ case llvm::Triple::arm64:
+ case llvm::Triple::mips:
+ case llvm::Triple::mipsel:
+ case llvm::Triple::mips64:
+ case llvm::Triple::mips64el:
+ PIC = true; // "-fpic"
+ break;
+
+ case llvm::Triple::x86:
+ case llvm::Triple::x86_64:
+ PIC = true; // "-fPIC"
+ IsPICLevelTwo = true;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ // OpenBSD-specific defaults for PIE
+ if (getToolChain().getTriple().getOS() == llvm::Triple::OpenBSD) {
+ switch (getToolChain().getTriple().getArch()) {
+ case llvm::Triple::mips64:
+ case llvm::Triple::mips64el:
+ case llvm::Triple::sparc:
+ case llvm::Triple::x86:
+ case llvm::Triple::x86_64:
+ IsPICLevelTwo = false; // "-fpie"
+ break;
+
+ case llvm::Triple::ppc:
+ case llvm::Triple::sparcv9:
+ IsPICLevelTwo = true; // "-fPIE"
+ break;
+
+ default:
+ break;
+ }
+ }
+
// For the PIC and PIE flag options, this logic is different from the
// legacy logic in very old versions of GCC, as that logic was just
// a bug no one had ever fixed. This logic is both more rational and
@@ -2225,8 +2679,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// Note that these flags are trump-cards. Regardless of the order w.r.t. the
// PIC or PIE options above, if these show up, PIC is disabled.
llvm::Triple Triple(TripleStr);
- if (KernelOrKext &&
- (!Triple.isiOS() || Triple.isOSVersionLT(6)))
+ if (KernelOrKext && (!Triple.isiOS() || Triple.isOSVersionLT(6) ||
+ Triple.getArch() == llvm::Triple::arm64 ||
+ Triple.getArch() == llvm::Triple::aarch64))
PIC = PIE = false;
if (Args.hasArg(options::OPT_static))
PIC = PIE = false;
@@ -2272,6 +2727,13 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// LLVM Code Generator Options.
+ if (Arg *A = Args.getLastArg(options::OPT_Wframe_larger_than_EQ)) {
+ StringRef v = A->getValue();
+ CmdArgs.push_back("-mllvm");
+ CmdArgs.push_back(Args.MakeArgString("-warn-stack-size=" + v));
+ A->claim();
+ }
+
if (Arg *A = Args.getLastArg(options::OPT_mregparm_EQ)) {
CmdArgs.push_back("-mregparm");
CmdArgs.push_back(A->getValue());
@@ -2304,8 +2766,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// enabled. This alias option is being used to simplify the hasFlag logic.
OptSpecifier StrictAliasingAliasOption = OFastEnabled ? options::OPT_Ofast :
options::OPT_fstrict_aliasing;
+ // We turn strict aliasing off by default if we're in CL mode, since MSVC
+ // doesn't do any TBAA.
+ bool TBAAOnByDefault = !getToolChain().getDriver().IsCLMode();
if (!Args.hasFlag(options::OPT_fstrict_aliasing, StrictAliasingAliasOption,
- options::OPT_fno_strict_aliasing, true))
+ options::OPT_fno_strict_aliasing, TBAAOnByDefault))
CmdArgs.push_back("-relaxed-aliasing");
if (!Args.hasFlag(options::OPT_fstruct_path_tbaa,
options::OPT_fno_struct_path_tbaa))
@@ -2452,18 +2917,24 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
options::OPT_fno_fast_math))
if (!A->getOption().matches(options::OPT_fno_fast_math))
CmdArgs.push_back("-ffast-math");
- if (Arg *A = Args.getLastArg(options::OPT_ffinite_math_only, options::OPT_fno_fast_math))
+ if (Arg *A = Args.getLastArg(options::OPT_ffinite_math_only,
+ options::OPT_fno_fast_math))
if (A->getOption().matches(options::OPT_ffinite_math_only))
CmdArgs.push_back("-ffinite-math-only");
// Decide whether to use verbose asm. Verbose assembly is the default on
// toolchains which have the integrated assembler on by default.
- bool IsVerboseAsmDefault = getToolChain().IsIntegratedAssemblerDefault();
+ bool IsIntegratedAssemblerDefault =
+ getToolChain().IsIntegratedAssemblerDefault();
if (Args.hasFlag(options::OPT_fverbose_asm, options::OPT_fno_verbose_asm,
- IsVerboseAsmDefault) ||
+ IsIntegratedAssemblerDefault) ||
Args.hasArg(options::OPT_dA))
CmdArgs.push_back("-masm-verbose");
+ if (!Args.hasFlag(options::OPT_fintegrated_as, options::OPT_fno_integrated_as,
+ IsIntegratedAssemblerDefault))
+ CmdArgs.push_back("-no-integrated-as");
+
if (Args.hasArg(options::OPT_fdebug_pass_structure)) {
CmdArgs.push_back("-mdebug-pass");
CmdArgs.push_back("Structure");
@@ -2491,10 +2962,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// -fasynchronous-unwind-tables and -fnon-call-exceptions interact in more
// complicated ways.
bool AsynchronousUnwindTables =
- Args.hasFlag(options::OPT_fasynchronous_unwind_tables,
- options::OPT_fno_asynchronous_unwind_tables,
- getToolChain().IsUnwindTablesDefault() &&
- !KernelOrKext);
+ Args.hasFlag(options::OPT_fasynchronous_unwind_tables,
+ options::OPT_fno_asynchronous_unwind_tables,
+ (getToolChain().IsUnwindTablesDefault() ||
+ getToolChain().getSanitizerArgs().needsUnwindTables()) &&
+ !KernelOrKext);
if (Args.hasFlag(options::OPT_funwind_tables, options::OPT_fno_unwind_tables,
AsynchronousUnwindTables))
CmdArgs.push_back("-munwind-tables");
@@ -2529,7 +3001,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
}
// Add the target features
- getTargetFeatures(D, ETriple, Args, CmdArgs);
+ getTargetFeatures(D, ETriple, Args, CmdArgs, false);
// Add target specific flags.
switch(getToolChain().getArch()) {
@@ -2537,10 +3009,19 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
break;
case llvm::Triple::arm:
+ case llvm::Triple::armeb:
case llvm::Triple::thumb:
+ case llvm::Triple::thumbeb:
AddARMTargetArgs(Args, CmdArgs, KernelOrKext);
break;
+ case llvm::Triple::aarch64:
+ case llvm::Triple::aarch64_be:
+ case llvm::Triple::arm64:
+ case llvm::Triple::arm64_be:
+ AddAArch64TargetArgs(Args, CmdArgs);
+ break;
+
case llvm::Triple::mips:
case llvm::Triple::mipsel:
case llvm::Triple::mips64:
@@ -2549,6 +3030,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
break;
case llvm::Triple::sparc:
+ case llvm::Triple::sparcv9:
AddSparcTargetArgs(Args, CmdArgs);
break;
@@ -2606,13 +3088,20 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
D.CCLogDiagnosticsFilename : "-");
}
- // Use the last option from "-g" group. "-gline-tables-only"
- // is preserved, all other debug options are substituted with "-g".
+ // Use the last option from "-g" group. "-gline-tables-only" and "-gdwarf-x"
+ // are preserved, all other debug options are substituted with "-g".
Args.ClaimAllArgs(options::OPT_g_Group);
if (Arg *A = Args.getLastArg(options::OPT_g_Group)) {
- if (A->getOption().matches(options::OPT_gline_tables_only))
+ if (A->getOption().matches(options::OPT_gline_tables_only)) {
+ // FIXME: we should support specifying dwarf version with
+ // -gline-tables-only.
CmdArgs.push_back("-gline-tables-only");
- else if (A->getOption().matches(options::OPT_gdwarf_2))
+ // Default is dwarf-2 for Darwin, OpenBSD and FreeBSD.
+ const llvm::Triple &Triple = getToolChain().getTriple();
+ if (Triple.isOSDarwin() || Triple.getOS() == llvm::Triple::OpenBSD ||
+ Triple.getOS() == llvm::Triple::FreeBSD)
+ CmdArgs.push_back("-gdwarf-2");
+ } 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");
@@ -2620,8 +3109,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-gdwarf-4");
else if (!A->getOption().matches(options::OPT_g0) &&
!A->getOption().matches(options::OPT_ggdb0)) {
- // Default is dwarf-2 for darwin.
- if (getToolChain().getTriple().isOSDarwin())
+ // Default is dwarf-2 for Darwin, OpenBSD and FreeBSD.
+ const llvm::Triple &Triple = getToolChain().getTriple();
+ if (Triple.isOSDarwin() || Triple.getOS() == llvm::Triple::OpenBSD ||
+ Triple.getOS() == llvm::Triple::FreeBSD)
CmdArgs.push_back("-gdwarf-2");
else
CmdArgs.push_back("-g");
@@ -2630,7 +3121,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// We ignore flags -gstrict-dwarf and -grecord-gcc-switches for now.
Args.ClaimAllArgs(options::OPT_g_flags_Group);
- if (Args.hasArg(options::OPT_gcolumn_info))
+ if (Args.hasFlag(options::OPT_gcolumn_info, options::OPT_gno_column_info,
+ /*Default*/ true))
CmdArgs.push_back("-dwarf-column-info");
// FIXME: Move backend command line options to the module.
@@ -2650,13 +3142,44 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-generate-gnu-dwarf-pub-sections");
}
- Args.AddAllArgs(CmdArgs, options::OPT_fdebug_types_section);
+ // -gdwarf-aranges turns on the emission of the aranges section in the
+ // backend.
+ if (Args.hasArg(options::OPT_gdwarf_aranges)) {
+ CmdArgs.push_back("-backend-option");
+ CmdArgs.push_back("-generate-arange-section");
+ }
+
+ if (Args.hasFlag(options::OPT_fdebug_types_section,
+ options::OPT_fno_debug_types_section, false)) {
+ CmdArgs.push_back("-backend-option");
+ CmdArgs.push_back("-generate-type-units");
+ }
+
+ if (Args.hasFlag(options::OPT_ffunction_sections,
+ options::OPT_fno_function_sections, false)) {
+ CmdArgs.push_back("-ffunction-sections");
+ }
- Args.AddAllArgs(CmdArgs, options::OPT_ffunction_sections);
- Args.AddAllArgs(CmdArgs, options::OPT_fdata_sections);
+ if (Args.hasFlag(options::OPT_fdata_sections,
+ options::OPT_fno_data_sections, false)) {
+ CmdArgs.push_back("-fdata-sections");
+ }
Args.AddAllArgs(CmdArgs, options::OPT_finstrument_functions);
+ if (Args.hasArg(options::OPT_fprofile_instr_generate) &&
+ (Args.hasArg(options::OPT_fprofile_instr_use) ||
+ Args.hasArg(options::OPT_fprofile_instr_use_EQ)))
+ D.Diag(diag::err_drv_argument_not_allowed_with)
+ << "-fprofile-instr-generate" << "-fprofile-instr-use";
+
+ Args.AddAllArgs(CmdArgs, options::OPT_fprofile_instr_generate);
+
+ if (Arg *A = Args.getLastArg(options::OPT_fprofile_instr_use_EQ))
+ A->render(Args, CmdArgs);
+ else if (Args.hasArg(options::OPT_fprofile_instr_use))
+ CmdArgs.push_back("-fprofile-instr-use=pgo-data");
+
if (Args.hasArg(options::OPT_ftest_coverage) ||
Args.hasArg(options::OPT_coverage))
CmdArgs.push_back("-femit-coverage-notes");
@@ -2762,7 +3285,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
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);
+ Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_designated_init);
+ Args.AddLastArg(CmdArgs, options::OPT_objcmt_whitelist_dir_path);
}
// Add preprocessing options like -I, -D, etc. if we are using the
@@ -2788,10 +3312,18 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
}
}
+ // Warn about ignored options to clang.
+ for (arg_iterator it = Args.filtered_begin(
+ options::OPT_clang_ignored_gcc_optimization_f_Group),
+ ie = Args.filtered_end(); it != ie; ++it) {
+ D.Diag(diag::warn_ignored_gcc_optimization) << (*it)->getAsString(Args);
+ }
+
// Don't warn about unused -flto. This can happen when we're preprocessing or
// precompiling.
Args.ClaimAllArgs(options::OPT_flto);
+ Args.AddAllArgs(CmdArgs, options::OPT_R_Group);
Args.AddAllArgs(CmdArgs, options::OPT_W_Group);
if (Args.hasFlag(options::OPT_pedantic, options::OPT_no_pedantic, false))
CmdArgs.push_back("-pedantic");
@@ -2826,7 +3358,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (!types::isCXX(InputType))
Args.AddAllArgsTranslated(CmdArgs, options::OPT_std_default_EQ,
"-std=", /*Joined=*/true);
- else if (getToolChain().getTriple().getOS() == llvm::Triple::Win32)
+ else if (IsWindowsMSVC)
CmdArgs.push_back("-std=c++11");
Args.AddLastArg(CmdArgs, options::OPT_trigraphs);
@@ -2842,9 +3374,13 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// 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)
+ // FIXME: This should behave just like a warning flag, and thus should also
+ // respect -Weverything, -Wno-everything, -Werror=write-strings, and so on.
+ Arg *WriteStrings =
+ Args.getLastArg(options::OPT_Wwrite_strings,
+ options::OPT_Wno_write_strings, options::OPT_w);
+ if (WriteStrings &&
+ WriteStrings->getOption().matches(options::OPT_Wwrite_strings))
CmdArgs.push_back("-fconst-strings");
}
@@ -2865,9 +3401,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-fno-gnu-keywords");
}
- if (ShouldDisableCFI(Args, getToolChain()))
- CmdArgs.push_back("-fno-dwarf2-cfi-asm");
-
if (ShouldDisableDwarfDirectory(Args, getToolChain()))
CmdArgs.push_back("-fno-dwarf-directory-asm");
@@ -2985,8 +3518,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// Forward -f (flag) options which we can pass directly.
Args.AddLastArg(CmdArgs, options::OPT_femit_all_decls);
Args.AddLastArg(CmdArgs, options::OPT_fheinous_gnu_extensions);
- Args.AddLastArg(CmdArgs, options::OPT_flimit_debug_info);
- Args.AddLastArg(CmdArgs, options::OPT_fno_limit_debug_info);
+ Args.AddLastArg(CmdArgs, options::OPT_fstandalone_debug);
+ Args.AddLastArg(CmdArgs, options::OPT_fno_standalone_debug);
Args.AddLastArg(CmdArgs, options::OPT_fno_operator_names);
// AltiVec language extensions aren't relevant for assembling.
if (!isa<PreprocessJobAction>(JA) ||
@@ -3003,8 +3536,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
true))
CmdArgs.push_back("-fno-sanitize-recover");
- if (Args.hasArg(options::OPT_fcatch_undefined_behavior) ||
- Args.hasFlag(options::OPT_fsanitize_undefined_trap_on_error,
+ if (Args.hasFlag(options::OPT_fsanitize_undefined_trap_on_error,
options::OPT_fno_sanitize_undefined_trap_on_error, false))
CmdArgs.push_back("-fsanitize-undefined-trap-on-error");
@@ -3027,10 +3559,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (Args.getLastArg(options::OPT_fapple_kext))
CmdArgs.push_back("-fapple-kext");
- if (Args.hasFlag(options::OPT_frewrite_includes,
- options::OPT_fno_rewrite_includes, false))
- CmdArgs.push_back("-frewrite-includes");
-
Args.AddLastArg(CmdArgs, options::OPT_fobjc_sender_dependent_dispatch);
Args.AddLastArg(CmdArgs, options::OPT_fdiagnostics_print_source_range_info);
Args.AddLastArg(CmdArgs, options::OPT_fdiagnostics_parseable_fixits);
@@ -3072,11 +3600,15 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
unsigned StackProtectorLevel = 0;
if (Arg *A = Args.getLastArg(options::OPT_fno_stack_protector,
options::OPT_fstack_protector_all,
+ options::OPT_fstack_protector_strong,
options::OPT_fstack_protector)) {
- if (A->getOption().matches(options::OPT_fstack_protector))
- StackProtectorLevel = 1;
+ if (A->getOption().matches(options::OPT_fstack_protector)) {
+ StackProtectorLevel = std::max<unsigned>(LangOptions::SSPOn,
+ getToolChain().GetDefaultStackProtectorLevel(KernelOrKext));
+ } else if (A->getOption().matches(options::OPT_fstack_protector_strong))
+ StackProtectorLevel = LangOptions::SSPStrong;
else if (A->getOption().matches(options::OPT_fstack_protector_all))
- StackProtectorLevel = 2;
+ StackProtectorLevel = LangOptions::SSPReq;
} else {
StackProtectorLevel =
getToolChain().GetDefaultStackProtectorLevel(KernelOrKext);
@@ -3121,10 +3653,22 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
options::OPT_munaligned_access)) {
if (A->getOption().matches(options::OPT_mno_unaligned_access)) {
CmdArgs.push_back("-backend-option");
- CmdArgs.push_back("-arm-strict-align");
+ if (getToolChain().getTriple().getArch() == llvm::Triple::aarch64 ||
+ getToolChain().getTriple().getArch() == llvm::Triple::aarch64_be ||
+ getToolChain().getTriple().getArch() == llvm::Triple::arm64 ||
+ getToolChain().getTriple().getArch() == llvm::Triple::arm64_be)
+ CmdArgs.push_back("-aarch64-strict-align");
+ else
+ CmdArgs.push_back("-arm-strict-align");
} else {
CmdArgs.push_back("-backend-option");
- CmdArgs.push_back("-arm-no-strict-align");
+ if (getToolChain().getTriple().getArch() == llvm::Triple::aarch64 ||
+ getToolChain().getTriple().getArch() == llvm::Triple::aarch64_be ||
+ getToolChain().getTriple().getArch() == llvm::Triple::arm64 ||
+ getToolChain().getTriple().getArch() == llvm::Triple::arm64_be)
+ CmdArgs.push_back("-aarch64-no-strict-align");
+ else
+ CmdArgs.push_back("-arm-no-strict-align");
}
}
}
@@ -3138,6 +3682,22 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-backend-option");
CmdArgs.push_back("-arm-no-restrict-it");
}
+ } else if (TT.isOSWindows() && (TT.getArch() == llvm::Triple::arm ||
+ TT.getArch() == llvm::Triple::thumb)) {
+ // Windows on ARM expects restricted IT blocks
+ CmdArgs.push_back("-backend-option");
+ CmdArgs.push_back("-arm-restrict-it");
+ }
+
+ if (TT.getArch() == llvm::Triple::arm ||
+ TT.getArch() == llvm::Triple::thumb) {
+ if (Arg *A = Args.getLastArg(options::OPT_mlong_calls,
+ options::OPT_mno_long_calls)) {
+ if (A->getOption().matches(options::OPT_mlong_calls)) {
+ CmdArgs.push_back("-backend-option");
+ CmdArgs.push_back("-arm-long-calls");
+ }
+ }
}
// Forward -f options with positive and negative forms; we translate
@@ -3207,44 +3767,78 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-fmodules-decluse");
}
+ // -fmodules-strict-decluse is like -fmodule-decluse, but also checks that
+ // all #included headers are part of modules.
+ if (Args.hasFlag(options::OPT_fmodules_strict_decluse,
+ options::OPT_fno_modules_strict_decluse,
+ false)) {
+ CmdArgs.push_back("-fmodules-strict-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();
+ if (Arg *A = Args.getLastArg(options::OPT_fmodule_name))
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();
+ if (Arg *A = Args.getLastArg(options::OPT_fmodule_map_file))
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)) {
- A->claim();
- if (HaveModules) {
- A->render(Args, CmdArgs);
+ // -fmodule-cache-path specifies where our module files should be written.
+ SmallString<128> ModuleCachePath;
+ if (Arg *A = Args.getLastArg(options::OPT_fmodules_cache_path))
+ ModuleCachePath = A->getValue();
+ if (HaveModules) {
+ if (C.isForDiagnostics()) {
+ // When generating crash reports, we want to emit the modules along with
+ // the reproduction sources, so we ignore any provided module path.
+ ModuleCachePath = Output.getFilename();
+ llvm::sys::path::replace_extension(ModuleCachePath, ".cache");
+ llvm::sys::path::append(ModuleCachePath, "modules");
+ } else if (ModuleCachePath.empty()) {
+ // No module path was provided: use the default.
+ llvm::sys::path::system_temp_directory(/*erasedOnReboot=*/false,
+ ModuleCachePath);
+ llvm::sys::path::append(ModuleCachePath, "org.llvm.clang");
+ llvm::sys::path::append(ModuleCachePath, "ModuleCache");
}
- } else if (HaveModules) {
- SmallString<128> DefaultModuleCache;
- llvm::sys::path::system_temp_directory(/*erasedOnReboot=*/false,
- DefaultModuleCache);
- llvm::sys::path::append(DefaultModuleCache, "org.llvm.clang");
- llvm::sys::path::append(DefaultModuleCache, "ModuleCache");
const char Arg[] = "-fmodules-cache-path=";
- DefaultModuleCache.insert(DefaultModuleCache.begin(),
- Arg, Arg + strlen(Arg));
- CmdArgs.push_back(Args.MakeArgString(DefaultModuleCache));
+ ModuleCachePath.insert(ModuleCachePath.begin(), Arg, Arg + strlen(Arg));
+ CmdArgs.push_back(Args.MakeArgString(ModuleCachePath));
}
+ // When building modules and generating crashdumps, we need to dump a module
+ // dependency VFS alongside the output.
+ if (HaveModules && C.isForDiagnostics()) {
+ SmallString<128> VFSDir(Output.getFilename());
+ llvm::sys::path::replace_extension(VFSDir, ".cache");
+ llvm::sys::path::append(VFSDir, "vfs");
+ CmdArgs.push_back("-module-dependency-dir");
+ CmdArgs.push_back(Args.MakeArgString(VFSDir));
+ }
+
+ if (Arg *A = Args.getLastArg(options::OPT_fmodules_user_build_path))
+ if (HaveModules)
+ A->render(Args, CmdArgs);
+
// Pass through all -fmodules-ignore-macro arguments.
Args.AddAllArgs(CmdArgs, options::OPT_fmodules_ignore_macro);
Args.AddLastArg(CmdArgs, options::OPT_fmodules_prune_interval);
Args.AddLastArg(CmdArgs, options::OPT_fmodules_prune_after);
+ Args.AddLastArg(CmdArgs, options::OPT_fbuild_session_timestamp);
+
+ if (Args.getLastArg(options::OPT_fmodules_validate_once_per_build_session)) {
+ if (!Args.getLastArg(options::OPT_fbuild_session_timestamp))
+ D.Diag(diag::err_drv_modules_validate_once_requires_timestamp);
+
+ Args.AddLastArg(CmdArgs,
+ options::OPT_fmodules_validate_once_per_build_session);
+ }
+
+ Args.AddLastArg(CmdArgs, options::OPT_fmodules_validate_system_headers);
+
// -faccess-control is default.
if (Args.hasFlag(options::OPT_fno_access_control,
options::OPT_faccess_control,
@@ -3291,41 +3885,52 @@ 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().getArch() != llvm::Triple::hexagon &&
- getToolChain().getArch() != llvm::Triple::xcore) ||
+ if (!Args.hasFlag(options::OPT_fuse_cxa_atexit,
+ options::OPT_fno_use_cxa_atexit,
+ !IsWindowsCygnus && !IsWindowsGNU &&
+ getToolChain().getArch() != llvm::Triple::hexagon &&
+ getToolChain().getArch() != llvm::Triple::xcore) ||
KernelOrKext)
CmdArgs.push_back("-fno-use-cxa-atexit");
// -fms-extensions=0 is default.
if (Args.hasFlag(options::OPT_fms_extensions, options::OPT_fno_ms_extensions,
- getToolChain().getTriple().getOS() == llvm::Triple::Win32))
+ IsWindowsMSVC))
CmdArgs.push_back("-fms-extensions");
// -fms-compatibility=0 is default.
if (Args.hasFlag(options::OPT_fms_compatibility,
options::OPT_fno_ms_compatibility,
- (getToolChain().getTriple().getOS() == llvm::Triple::Win32 &&
- Args.hasFlag(options::OPT_fms_extensions,
- options::OPT_fno_ms_extensions,
- true))))
+ (IsWindowsMSVC && Args.hasFlag(options::OPT_fms_extensions,
+ options::OPT_fno_ms_extensions,
+ true))))
CmdArgs.push_back("-fms-compatibility");
- // -fmsc-version=1700 is default.
+ // -fms-compatibility-version=17.00 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=1700");
+ IsWindowsMSVC) || Args.hasArg(options::OPT_fmsc_version) ||
+ Args.hasArg(options::OPT_fms_compatibility_version)) {
+ const Arg *MSCVersion = Args.getLastArg(options::OPT_fmsc_version);
+ const Arg *MSCompatibilityVersion =
+ Args.getLastArg(options::OPT_fms_compatibility_version);
+
+ if (MSCVersion && MSCompatibilityVersion)
+ D.Diag(diag::err_drv_argument_not_allowed_with)
+ << MSCVersion->getAsString(Args)
+ << MSCompatibilityVersion->getAsString(Args);
+
+ std::string Ver;
+ if (MSCompatibilityVersion)
+ Ver = Args.getLastArgValue(options::OPT_fms_compatibility_version);
+ else if (MSCVersion)
+ Ver = getMSCompatibilityVersion(MSCVersion->getValue());
+
+ if (Ver.empty())
+ CmdArgs.push_back("-fms-compatibility-version=17.00");
else
- CmdArgs.push_back(Args.MakeArgString("-fmsc-version=" + msc_ver));
+ CmdArgs.push_back(Args.MakeArgString("-fms-compatibility-version=" + Ver));
}
-
// -fno-borland-extensions is default.
if (Args.hasFlag(options::OPT_fborland_extensions,
options::OPT_fno_borland_extensions, false))
@@ -3334,8 +3939,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// -fno-delayed-template-parsing is default, except for Windows where MSVC STL
// needs it.
if (Args.hasFlag(options::OPT_fdelayed_template_parsing,
- options::OPT_fno_delayed_template_parsing,
- getToolChain().getTriple().getOS() == llvm::Triple::Win32))
+ options::OPT_fno_delayed_template_parsing, IsWindowsMSVC))
CmdArgs.push_back("-fdelayed-template-parsing");
// -fgnu-keywords default varies depending on language; only pass if
@@ -3358,9 +3962,10 @@ 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. Next runtime is always legacy dispatch and
- // -fno-objc-legacy-dispatch gets ignored silently.
- if (objcRuntime.isNonFragile() && !objcRuntime.isNeXTFamily()) {
+ // legacy is the default. Except for deployment taget of 10.5,
+ // next runtime is always legacy dispatch and -fno-objc-legacy-dispatch
+ // gets ignored silently.
+ if (objcRuntime.isNonFragile()) {
if (!Args.hasFlag(options::OPT_fobjc_legacy_dispatch,
options::OPT_fno_objc_legacy_dispatch,
objcRuntime.isLegacyDispatchDefaultForArch(
@@ -3436,9 +4041,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
}
}
- // Add exception args.
- addExceptionArgs(Args, InputType, getToolChain().getTriple(),
- KernelOrKext, objcRuntime, CmdArgs);
+ // Handle GCC-style exception args.
+ if (!C.getDriver().IsCLMode())
+ addExceptionArgs(Args, InputType, getToolChain().getTriple(), KernelOrKext,
+ objcRuntime, CmdArgs);
if (getToolChain().UseSjLjExceptions())
CmdArgs.push_back("-fsjlj-exceptions");
@@ -3458,7 +4064,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// -fshort-wchar default varies depending on platform; only
// pass if specified.
- if (Arg *A = Args.getLastArg(options::OPT_fshort_wchar))
+ if (Arg *A = Args.getLastArg(options::OPT_fshort_wchar,
+ options::OPT_fno_short_wchar))
A->render(Args, CmdArgs);
// -fno-pascal-strings is default, only pass non-default.
@@ -3501,6 +4108,14 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
D.Diag(diag::err_drv_clang_unsupported)
<< Args.getLastArg(options::OPT_fno_for_scope)->getAsString(Args);
+ // -finput_charset=UTF-8 is default. Reject others
+ if (Arg *inputCharset = Args.getLastArg(
+ options::OPT_finput_charset_EQ)) {
+ StringRef value = inputCharset->getValue();
+ if (value != "UTF-8")
+ D.Diag(diag::err_drv_invalid_value) << inputCharset->getAsString(Args) << value;
+ }
+
// -fcaret-diagnostics is default.
if (!Args.hasFlag(options::OPT_fcaret_diagnostics,
options::OPT_fno_caret_diagnostics, true))
@@ -3543,9 +4158,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// Support both clang's -f[no-]color-diagnostics and gcc's
// -f[no-]diagnostics-colors[=never|always|auto].
enum { Colors_On, Colors_Off, Colors_Auto } ShowColors = Colors_Auto;
- for (ArgList::const_iterator it = Args.begin(), ie = Args.end();
- it != ie; ++it) {
- const Option &O = (*it)->getOption();
+ for (const auto &Arg : Args) {
+ const Option &O = Arg->getOption();
if (!O.matches(options::OPT_fcolor_diagnostics) &&
!O.matches(options::OPT_fdiagnostics_color) &&
!O.matches(options::OPT_fno_color_diagnostics) &&
@@ -3553,7 +4167,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
!O.matches(options::OPT_fdiagnostics_color_EQ))
continue;
- (*it)->claim();
+ Arg->claim();
if (O.matches(options::OPT_fcolor_diagnostics) ||
O.matches(options::OPT_fdiagnostics_color)) {
ShowColors = Colors_On;
@@ -3562,7 +4176,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
ShowColors = Colors_Off;
} else {
assert(O.matches(options::OPT_fdiagnostics_color_EQ));
- StringRef value((*it)->getValue());
+ StringRef value(Arg->getValue());
if (value == "always")
ShowColors = Colors_On;
else if (value == "never")
@@ -3603,16 +4217,19 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// 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);
+ bool EnableVec = shouldEnableVectorizerAtOLevel(Args, false);
OptSpecifier VectorizeAliasOption = EnableVec ? options::OPT_O_Group :
options::OPT_fvectorize;
if (Args.hasFlag(options::OPT_fvectorize, VectorizeAliasOption,
options::OPT_fno_vectorize, EnableVec))
CmdArgs.push_back("-vectorize-loops");
- // -fslp-vectorize is default.
- if (Args.hasFlag(options::OPT_fslp_vectorize,
- options::OPT_fno_slp_vectorize, true))
+ // -fslp-vectorize is enabled based on the optimization level selected.
+ bool EnableSLPVec = shouldEnableVectorizerAtOLevel(Args, true);
+ OptSpecifier SLPVectAliasOption = EnableSLPVec ? options::OPT_O_Group :
+ options::OPT_fslp_vectorize;
+ if (Args.hasFlag(options::OPT_fslp_vectorize, SLPVectAliasOption,
+ options::OPT_fno_slp_vectorize, EnableSLPVec))
CmdArgs.push_back("-vectorize-slp");
// -fno-slp-vectorize-aggressive is default.
@@ -3666,6 +4283,15 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
}
#endif
+ // Enable rewrite includes if the user's asked for it or if we're generating
+ // diagnostics.
+ // TODO: Once -module-dependency-dir works with -frewrite-includes it'd be
+ // nice to enable this when doing a crashdump for modules as well.
+ if (Args.hasFlag(options::OPT_frewrite_includes,
+ options::OPT_fno_rewrite_includes, false) ||
+ (C.isForDiagnostics() && !HaveModules))
+ CmdArgs.push_back("-frewrite-includes");
+
// Only allow -traditional or -traditional-cpp outside in preprocessing modes.
if (Arg *A = Args.getLastArg(options::OPT_traditional,
options::OPT_traditional_cpp)) {
@@ -3716,14 +4342,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
assert(Output.isNothing() && "Invalid output.");
}
- for (InputInfoList::const_iterator
- it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
- const InputInfo &II = *it;
- CmdArgs.push_back("-x");
- if (Args.hasArg(options::OPT_rewrite_objc))
- CmdArgs.push_back(types::getTypeName(types::TY_PP_ObjCXX));
- else
- CmdArgs.push_back(types::getTypeName(II.getType()));
+ for (const auto &II : Inputs) {
+ addDashXForInput(Args, II, CmdArgs);
+
if (II.isFilename())
CmdArgs.push_back(II.getFilename());
else
@@ -3738,9 +4359,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// analysis.
if (getToolChain().UseDwarfDebugFlags()) {
ArgStringList OriginalArgs;
- for (ArgList::const_iterator it = Args.begin(),
- ie = Args.end(); it != ie; ++it)
- (*it)->render(Args, OriginalArgs);
+ for (const auto &Arg : Args)
+ Arg->render(Args, OriginalArgs);
SmallString<256> Flags;
Flags += Exec;
@@ -3765,10 +4385,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
}
// Finally add the compile command to the compilation.
- if (Args.hasArg(options::OPT__SLASH_fallback)) {
- tools::visualstudio::Compile CL(getToolChain());
- Command *CLCommand = CL.GetCommand(C, JA, Output, Inputs, Args,
- LinkingOutput);
+ if (Args.hasArg(options::OPT__SLASH_fallback) &&
+ Output.getType() == types::TY_Object &&
+ (InputType == types::TY_C || InputType == types::TY_CXX)) {
+ Command *CLCommand = getCLFallback()->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));
@@ -3927,6 +4548,45 @@ ObjCRuntime Clang::AddObjCRuntimeArgs(const ArgList &args,
return runtime;
}
+static bool maybeConsumeDash(const std::string &EH, size_t &I) {
+ bool HaveDash = (I + 1 < EH.size() && EH[I + 1] == '-');
+ I += HaveDash;
+ return !HaveDash;
+}
+
+struct EHFlags {
+ EHFlags() : Synch(false), Asynch(false), NoExceptC(false) {}
+ bool Synch;
+ bool Asynch;
+ bool NoExceptC;
+};
+
+/// /EH controls whether to run destructor cleanups when exceptions are
+/// thrown. There are three modifiers:
+/// - s: Cleanup after "synchronous" exceptions, aka C++ exceptions.
+/// - a: Cleanup after "asynchronous" exceptions, aka structured exceptions.
+/// The 'a' modifier is unimplemented and fundamentally hard in LLVM IR.
+/// - c: Assume that extern "C" functions are implicitly noexcept. This
+/// modifier is an optimization, so we ignore it for now.
+/// The default is /EHs-c-, meaning cleanups are disabled.
+static EHFlags parseClangCLEHFlags(const Driver &D, const ArgList &Args) {
+ EHFlags EH;
+ std::vector<std::string> EHArgs = Args.getAllArgValues(options::OPT__SLASH_EH);
+ for (auto EHVal : EHArgs) {
+ for (size_t I = 0, E = EHVal.size(); I != E; ++I) {
+ switch (EHVal[I]) {
+ case 'a': EH.Asynch = maybeConsumeDash(EHVal, I); continue;
+ case 'c': EH.NoExceptC = maybeConsumeDash(EHVal, I); continue;
+ case 's': EH.Synch = maybeConsumeDash(EHVal, I); continue;
+ default: break;
+ }
+ D.Diag(clang::diag::err_drv_invalid_value) << "/EH" << EHVal;
+ break;
+ }
+ }
+ return EH;
+}
+
void Clang::AddClangCLArgs(const ArgList &Args, ArgStringList &CmdArgs) const {
unsigned RTOptionID = options::OPT__SLASH_MT;
@@ -3972,11 +4632,58 @@ void Clang::AddClangCLArgs(const ArgList &Args, ArgStringList &CmdArgs) const {
// 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");
+ // Both /showIncludes and /E (and /EP) write to stdout. Allowing both
+ // would produce interleaved output, so ignore /showIncludes in such cases.
+ if (!Args.hasArg(options::OPT_E) && !Args.hasArg(options::OPT__SLASH_EP))
+ if (Arg *A = Args.getLastArg(options::OPT_show_includes))
+ A->render(Args, CmdArgs);
+
+ // This controls whether or not we emit RTTI data for polymorphic types.
+ if (Args.hasFlag(options::OPT__SLASH_GR_, options::OPT__SLASH_GR,
+ /*default=*/false))
+ CmdArgs.push_back("-fno-rtti-data");
+
+ const Driver &D = getToolChain().getDriver();
+ EHFlags EH = parseClangCLEHFlags(D, Args);
+ // FIXME: Do something with NoExceptC.
+ if (EH.Synch || EH.Asynch) {
+ CmdArgs.push_back("-fexceptions");
+ CmdArgs.push_back("-fcxx-exceptions");
+ }
+
+ // /EP should expand to -E -P.
+ if (Args.hasArg(options::OPT__SLASH_EP)) {
+ CmdArgs.push_back("-E");
+ CmdArgs.push_back("-P");
+ }
+
+ Arg *MostGeneralArg = Args.getLastArg(options::OPT__SLASH_vmg);
+ Arg *BestCaseArg = Args.getLastArg(options::OPT__SLASH_vmb);
+ if (MostGeneralArg && BestCaseArg)
+ D.Diag(clang::diag::err_drv_argument_not_allowed_with)
+ << MostGeneralArg->getAsString(Args) << BestCaseArg->getAsString(Args);
- if (Arg *A = Args.getLastArg(options::OPT_show_includes))
+ if (MostGeneralArg) {
+ Arg *SingleArg = Args.getLastArg(options::OPT__SLASH_vms);
+ Arg *MultipleArg = Args.getLastArg(options::OPT__SLASH_vmm);
+ Arg *VirtualArg = Args.getLastArg(options::OPT__SLASH_vmv);
+
+ Arg *FirstConflict = SingleArg ? SingleArg : MultipleArg;
+ Arg *SecondConflict = VirtualArg ? VirtualArg : MultipleArg;
+ if (FirstConflict && SecondConflict && FirstConflict != SecondConflict)
+ D.Diag(clang::diag::err_drv_argument_not_allowed_with)
+ << FirstConflict->getAsString(Args)
+ << SecondConflict->getAsString(Args);
+
+ if (SingleArg)
+ CmdArgs.push_back("-fms-memptr-rep=single");
+ else if (MultipleArg)
+ CmdArgs.push_back("-fms-memptr-rep=multiple");
+ else
+ CmdArgs.push_back("-fms-memptr-rep=virtual");
+ }
+
+ if (Arg *A = Args.getLastArg(options::OPT_vtordisp_mode_EQ))
A->render(Args, CmdArgs);
if (!Args.hasArg(options::OPT_fdiagnostics_format_EQ)) {
@@ -3988,6 +4695,12 @@ void Clang::AddClangCLArgs(const ArgList &Args, ArgStringList &CmdArgs) const {
}
}
+visualstudio::Compile *Clang::getCLFallback() const {
+ if (!CLFallback)
+ CLFallback.reset(new visualstudio::Compile(getToolChain()));
+ return CLFallback.get();
+}
+
void ClangAs::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
@@ -4034,7 +4747,7 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA,
// Add the target features
const Driver &D = getToolChain().getDriver();
- getTargetFeatures(D, Triple, Args, CmdArgs);
+ getTargetFeatures(D, Triple, Args, CmdArgs, true);
// Ignore explicit -force_cpusubtype_ALL option.
(void) Args.hasArg(options::OPT_force__cpusubtype__ALL);
@@ -4055,6 +4768,13 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA,
if (!A->getOption().matches(options::OPT_g0))
CmdArgs.push_back("-g");
+ if (Args.hasArg(options::OPT_gdwarf_2))
+ CmdArgs.push_back("-gdwarf-2");
+ if (Args.hasArg(options::OPT_gdwarf_3))
+ CmdArgs.push_back("-gdwarf-3");
+ if (Args.hasArg(options::OPT_gdwarf_4))
+ CmdArgs.push_back("-gdwarf-4");
+
// Add the -fdebug-compilation-dir flag if needed.
addDebugCompDirArg(Args, CmdArgs);
@@ -4068,9 +4788,8 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA,
// analysis.
if (getToolChain().UseDwarfDebugFlags()) {
ArgStringList OriginalArgs;
- for (ArgList::const_iterator it = Args.begin(),
- ie = Args.end(); it != ie; ++it)
- (*it)->render(Args, OriginalArgs);
+ for (const auto &Arg : Args)
+ Arg->render(Args, OriginalArgs);
SmallString<256> Flags;
const char *Exec = getToolChain().getDriver().getClangProgramPath();
@@ -4085,6 +4804,16 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA,
// FIXME: Add -static support, once we have it.
+ // Consume all the warning flags. Usually this would be handled more
+ // gracefully by -cc1 (warning about unknown warning flags, etc) but -cc1as
+ // doesn't handle that so rather than warning about unused flags that are
+ // actually used, we'll lie by omission instead.
+ // FIXME: Stop lying and consume only the appropriate driver flags
+ for (arg_iterator it = Args.filtered_begin(options::OPT_W_Group),
+ ie = Args.filtered_end();
+ it != ie; ++it)
+ (*it)->claim();
+
CollectArgsForIntegratedAssembler(C, Args, CmdArgs,
getToolChain().getDriver());
@@ -4117,9 +4846,7 @@ void gcc::Common::ConstructJob(Compilation &C, const JobAction &JA,
const Driver &D = getToolChain().getDriver();
ArgStringList CmdArgs;
- for (ArgList::const_iterator
- it = Args.begin(), ie = Args.end(); it != ie; ++it) {
- Arg *A = *it;
+ for (const auto &A : Args) {
if (forwardToGCC(A->getOption())) {
// Don't forward any -g arguments to assembly steps.
if (isa<AssembleJobAction>(JA) &&
@@ -4188,10 +4915,7 @@ void gcc::Common::ConstructJob(Compilation &C, const JobAction &JA,
//
// FIXME: For the linker case specifically, can we safely convert
// inputs into '-Wl,' options?
- for (InputInfoList::const_iterator
- it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
- const InputInfo &II = *it;
-
+ for (const auto &II : Inputs) {
// Don't try to pass LLVM or AST inputs to a generic gcc.
if (II.getType() == types::TY_LLVM_IR || II.getType() == types::TY_LTO_IR ||
II.getType() == types::TY_LLVM_BC || II.getType() == types::TY_LTO_BC)
@@ -4244,11 +4968,6 @@ void gcc::Preprocess::RenderExtraToolArgs(const JobAction &JA,
CmdArgs.push_back("-E");
}
-void gcc::Precompile::RenderExtraToolArgs(const JobAction &JA,
- ArgStringList &CmdArgs) const {
- // The type is good enough.
-}
-
void gcc::Compile::RenderExtraToolArgs(const JobAction &JA,
ArgStringList &CmdArgs) const {
const Driver &D = getToolChain().getDriver();
@@ -4266,11 +4985,6 @@ void gcc::Compile::RenderExtraToolArgs(const JobAction &JA,
}
}
-void gcc::Assemble::RenderExtraToolArgs(const JobAction &JA,
- ArgStringList &CmdArgs) const {
- CmdArgs.push_back("-c");
-}
-
void gcc::Link::RenderExtraToolArgs(const JobAction &JA,
ArgStringList &CmdArgs) const {
// The types are (hopefully) good enough.
@@ -4320,10 +5034,7 @@ void hexagon::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
//
// FIXME: For the linker case specifically, can we safely convert
// inputs into '-Wl,' options?
- for (InputInfoList::const_iterator
- it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
- const InputInfo &II = *it;
-
+ for (const auto &II : Inputs) {
// Don't try to pass LLVM or AST inputs to a generic gcc.
if (II.getType() == types::TY_LLVM_IR || II.getType() == types::TY_LTO_IR ||
II.getType() == types::TY_LLVM_BC || II.getType() == types::TY_LTO_BC)
@@ -4344,11 +5055,10 @@ void hexagon::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
}
const char *GCCName = "hexagon-as";
- const char *Exec =
- Args.MakeArgString(getToolChain().GetProgramPath(GCCName));
+ const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath(GCCName));
C.addCommand(new Command(JA, *this, Exec, CmdArgs));
-
}
+
void hexagon::Link::RenderExtraToolArgs(const JobAction &JA,
ArgStringList &CmdArgs) const {
// The types are (hopefully) good enough.
@@ -4390,10 +5100,8 @@ void hexagon::Link::ConstructJob(Compilation &C, const JobAction &JA,
//----------------------------------------------------------------------------
//
//----------------------------------------------------------------------------
- for (std::vector<std::string>::const_iterator i = ToolChain.ExtraOpts.begin(),
- e = ToolChain.ExtraOpts.end();
- i != e; ++i)
- CmdArgs.push_back(i->c_str());
+ for (const auto &Opt : ToolChain.ExtraOpts)
+ CmdArgs.push_back(Opt.c_str());
std::string MarchString = toolchains::Hexagon_TC::GetTargetCPU(Args);
CmdArgs.push_back(Args.MakeArgString("-m" + MarchString));
@@ -4469,12 +5177,8 @@ void hexagon::Link::ConstructJob(Compilation &C, const JobAction &JA,
// Library Search Paths
//----------------------------------------------------------------------------
const ToolChain::path_list &LibPaths = ToolChain.getFilePaths();
- for (ToolChain::path_list::const_iterator
- i = LibPaths.begin(),
- e = LibPaths.end();
- i != e;
- ++i)
- CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + *i));
+ for (const auto &LibPath : LibPaths)
+ CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + LibPath));
//----------------------------------------------------------------------------
//
@@ -4522,7 +5226,116 @@ void hexagon::Link::ConstructJob(Compilation &C, const JobAction &JA,
}
// Hexagon tools end.
-llvm::Triple::ArchType darwin::getArchTypeForDarwinArchName(StringRef Str) {
+/// Get the (LLVM) name of the minimum ARM CPU for the arch we are targeting.
+const char *arm::getARMCPUForMArch(const ArgList &Args,
+ const llvm::Triple &Triple) {
+ StringRef MArch;
+ if (Arg *A = Args.getLastArg(options::OPT_march_EQ)) {
+ // Otherwise, if we have -march= choose the base CPU for that arch.
+ MArch = A->getValue();
+ } else {
+ // Otherwise, use the Arch from the triple.
+ MArch = Triple.getArchName();
+ }
+
+ // Handle -march=native.
+ if (MArch == "native") {
+ std::string CPU = llvm::sys::getHostCPUName();
+ if (CPU != "generic") {
+ // Translate the native cpu into the architecture. The switch below will
+ // then chose the minimum cpu for that arch.
+ MArch = std::string("arm") + arm::getLLVMArchSuffixForARM(CPU);
+ }
+ }
+
+ return Triple.getARMCPUForArch(MArch);
+}
+
+/// getARMTargetCPU - Get the (LLVM) name of the ARM cpu we are targeting.
+StringRef arm::getARMTargetCPU(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 getARMCPUForMArch(Args, Triple);
+}
+
+/// getLLVMArchSuffixForARM - Get the LLVM arch name to use for a particular
+/// CPU.
+//
+// FIXME: This is redundant with -mcpu, why does LLVM use this.
+// FIXME: tblgen this, or kill it!
+const char *arm::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")
+ .Cases("arm940t", "ep9312","v4t")
+ .Cases("arm10tdmi", "arm1020t", "v5")
+ .Cases("arm9e", "arm926ej-s", "arm946e-s", "v5e")
+ .Cases("arm966e-s", "arm968e-s", "arm10e", "v5e")
+ .Cases("arm1020e", "arm1022e", "xscale", "iwmmxt", "v5e")
+ .Cases("arm1136j-s", "arm1136jf-s", "arm1176jz-s", "v6")
+ .Cases("arm1176jzf-s", "mpcorenovfp", "mpcore", "v6")
+ .Cases("arm1156t2-s", "arm1156t2f-s", "v6t2")
+ .Cases("cortex-a5", "cortex-a7", "cortex-a8", "cortex-a9-mp", "v7")
+ .Cases("cortex-a9", "cortex-a12", "cortex-a15", "krait", "v7")
+ .Cases("cortex-r4", "cortex-r5", "v7r")
+ .Case("cortex-m0", "v6m")
+ .Case("cortex-m3", "v7m")
+ .Case("cortex-m4", "v7em")
+ .Case("swift", "v7s")
+ .Case("cyclone", "v8")
+ .Cases("cortex-a53", "cortex-a57", "v8")
+ .Default("");
+}
+
+bool mips::hasMipsAbiArg(const ArgList &Args, const char *Value) {
+ Arg *A = Args.getLastArg(options::OPT_mabi_EQ);
+ return A && (A->getValue() == StringRef(Value));
+}
+
+bool mips::isNaN2008(const ArgList &Args, const llvm::Triple &Triple) {
+ if (Arg *NaNArg = Args.getLastArg(options::OPT_mnan_EQ))
+ return llvm::StringSwitch<bool>(NaNArg->getValue())
+ .Case("2008", true)
+ .Case("legacy", false)
+ .Default(false);
+
+ // NaN2008 is the default for MIPS32r6/MIPS64r6.
+ return llvm::StringSwitch<bool>(getCPUName(Args, Triple))
+ .Cases("mips32r6", "mips64r6", true)
+ .Default(false);
+
+ return false;
+}
+
+bool mips::isFPXXDefault(const llvm::Triple &Triple, StringRef CPUName,
+ StringRef ABIName) {
+ if (Triple.getVendor() != llvm::Triple::ImaginationTechnologies &&
+ Triple.getVendor() != llvm::Triple::MipsTechnologies)
+ return false;
+
+ if (ABIName != "32")
+ return false;
+
+ return llvm::StringSwitch<bool>(CPUName)
+ .Cases("mips2", "mips3", "mips4", "mips5", true)
+ .Cases("mips32", "mips32r2", true)
+ .Cases("mips64", "mips64r2", true)
+ .Default(false);
+}
+
+llvm::Triple::ArchType darwin::getArchTypeForMachOArchName(StringRef Str) {
// See arch(3) and llvm-gcc's driver-driver.c. We don't implement support for
// archs which Darwin doesn't use.
@@ -4545,8 +5358,9 @@ llvm::Triple::ArchType darwin::getArchTypeForDarwinArchName(StringRef Str) {
.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)
+ .Cases("armv7", "armv7em", "armv7k", "armv7m", llvm::Triple::arm)
.Cases("armv7s", "xscale", llvm::Triple::arm)
+ .Case("arm64", llvm::Triple::arm64)
.Case("r600", llvm::Triple::r600)
.Case("nvptx", llvm::Triple::nvptx)
.Case("nvptx64", llvm::Triple::nvptx64)
@@ -4555,6 +5369,18 @@ llvm::Triple::ArchType darwin::getArchTypeForDarwinArchName(StringRef Str) {
.Default(llvm::Triple::UnknownArch);
}
+void darwin::setTripleTypeForMachOArchName(llvm::Triple &T, StringRef Str) {
+ llvm::Triple::ArchType Arch = getArchTypeForMachOArchName(Str);
+ T.setArch(Arch);
+
+ if (Str == "x86_64h")
+ T.setArchName(Str);
+ else if (Str == "armv6m" || Str == "armv7m" || Str == "armv7em") {
+ T.setOS(llvm::Triple::UnknownOS);
+ T.setObjectFormat(llvm::Triple::MachO);
+ }
+}
+
const char *Clang::getBaseInputName(const ArgList &Args,
const InputInfoList &Inputs) {
return Args.MakeArgString(
@@ -4602,14 +5428,14 @@ 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
+ // If -fno_integrated_as is used add -Q to the darwin assember driver to make
// sure it runs its system assembler not clang's integrated assembler.
// Applicable to darwin11+ and Xcode 4+. darwin<10 lacked integrated-as.
// FIXME: at run-time detect assembler capabilities or rely on version
// information forwarded by -target-assembler-version (future)
- if (Args.hasArg(options::OPT_no_integrated_as)) {
- const llvm::Triple& t(getToolChain().getTriple());
- if (!(t.isMacOSX() && t.isMacOSXVersionLT(10, 7)))
+ if (Args.hasArg(options::OPT_fno_integrated_as)) {
+ const llvm::Triple &T(getToolChain().getTriple());
+ if (!(T.isMacOSX() && T.isMacOSXVersionLT(10, 7)))
CmdArgs.push_back("-Q");
}
@@ -4623,7 +5449,7 @@ void darwin::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
}
// Derived from asm spec.
- AddDarwinArch(Args, CmdArgs);
+ AddMachOArch(Args, CmdArgs);
// Use -force_cpusubtype_ALL on x86 by default.
if (getToolChain().getArch() == llvm::Triple::x86 ||
@@ -4634,8 +5460,7 @@ void darwin::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
if (getToolChain().getArch() != llvm::Triple::x86_64 &&
(((Args.hasArg(options::OPT_mkernel) ||
Args.hasArg(options::OPT_fapple_kext)) &&
- (!getDarwinToolChain().isTargetIPhoneOS() ||
- getDarwinToolChain().isIPhoneOSVersionLT(6, 0))) ||
+ getMachOToolChain().isKernelStatic()) ||
Args.hasArg(options::OPT_static)))
CmdArgs.push_back("-static");
@@ -4656,11 +5481,11 @@ void darwin::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}
-void darwin::DarwinTool::anchor() {}
+void darwin::MachOTool::anchor() {}
-void darwin::DarwinTool::AddDarwinArch(const ArgList &Args,
- ArgStringList &CmdArgs) const {
- StringRef ArchName = getDarwinToolChain().getDarwinArchName(Args);
+void darwin::MachOTool::AddMachOArch(const ArgList &Args,
+ ArgStringList &CmdArgs) const {
+ StringRef ArchName = getMachOToolChain().getMachOArchName(Args);
// Derived from darwin_arch spec.
CmdArgs.push_back("-arch");
@@ -4675,9 +5500,8 @@ bool darwin::Link::NeedsTempPath(const InputInfoList &Inputs) const {
// We only need to generate a temp path for LTO if we aren't compiling object
// files. When compiling source files, we run 'dsymutil' after linking. We
// don't run 'dsymutil' when compiling object files.
- for (InputInfoList::const_iterator
- it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it)
- if (it->getType() != types::TY_Object)
+ for (const auto &Input : Inputs)
+ if (Input.getType() != types::TY_Object)
return true;
return false;
@@ -4688,7 +5512,7 @@ void darwin::Link::AddLinkArgs(Compilation &C,
ArgStringList &CmdArgs,
const InputInfoList &Inputs) const {
const Driver &D = getToolChain().getDriver();
- const toolchains::Darwin &DarwinTC = getDarwinToolChain();
+ const toolchains::MachO &MachOTC = getMachOToolChain();
unsigned Version[3] = { 0, 0, 0 };
if (Arg *A = Args.getLastArg(options::OPT_mlinker_version_EQ)) {
@@ -4700,27 +5524,10 @@ void darwin::Link::AddLinkArgs(Compilation &C,
<< A->getAsString(Args);
}
- // Newer linkers support -demangle, pass it if supported and not disabled by
+ // Newer linkers support -demangle. Pass it if supported and not disabled by
// the user.
- if (Version[0] >= 100 && !Args.hasArg(options::OPT_Z_Xlinker__no_demangle)) {
- // Don't pass -demangle to ld_classic.
- //
- // FIXME: This is a temporary workaround, ld should be handling this.
- bool UsesLdClassic = (getToolChain().getArch() == llvm::Triple::x86 &&
- Args.hasArg(options::OPT_static));
- if (getToolChain().getArch() == llvm::Triple::x86) {
- for (arg_iterator it = Args.filtered_begin(options::OPT_Xlinker,
- options::OPT_Wl_COMMA),
- ie = Args.filtered_end(); it != ie; ++it) {
- const Arg *A = *it;
- for (unsigned i = 0, e = A->getNumValues(); i != e; ++i)
- if (StringRef(A->getValue(i)) == "-kext")
- UsesLdClassic = true;
- }
- }
- if (!UsesLdClassic)
- CmdArgs.push_back("-demangle");
- }
+ if (Version[0] >= 100 && !Args.hasArg(options::OPT_Z_Xlinker__no_demangle))
+ CmdArgs.push_back("-demangle");
if (Args.hasArg(options::OPT_rdynamic) && Version[0] >= 137)
CmdArgs.push_back("-export_dynamic");
@@ -4746,7 +5553,7 @@ void darwin::Link::AddLinkArgs(Compilation &C,
}
if (!Args.hasArg(options::OPT_dynamiclib)) {
- AddDarwinArch(Args, CmdArgs);
+ AddMachOArch(Args, CmdArgs);
// FIXME: Why do this only on this path?
Args.AddLastArg(CmdArgs, options::OPT_force__cpusubtype__ALL);
@@ -4782,7 +5589,7 @@ void darwin::Link::AddLinkArgs(Compilation &C,
Args.AddAllArgsTranslated(CmdArgs, options::OPT_current__version,
"-dylib_current_version");
- AddDarwinArch(Args, CmdArgs);
+ AddMachOArch(Args, CmdArgs);
Args.AddAllArgsTranslated(CmdArgs, options::OPT_install__name,
"-dylib_install_name");
@@ -4791,7 +5598,7 @@ void darwin::Link::AddLinkArgs(Compilation &C,
Args.AddLastArg(CmdArgs, options::OPT_all__load);
Args.AddAllArgs(CmdArgs, options::OPT_allowable__client);
Args.AddLastArg(CmdArgs, options::OPT_bind__at__load);
- if (DarwinTC.isTargetIPhoneOS())
+ if (MachOTC.isTargetIOSBased())
Args.AddLastArg(CmdArgs, options::OPT_arch__errors__fatal);
Args.AddLastArg(CmdArgs, options::OPT_dead__strip);
Args.AddLastArg(CmdArgs, options::OPT_no__dead__strip__inits__and__terms);
@@ -4805,22 +5612,7 @@ void darwin::Link::AddLinkArgs(Compilation &C,
Args.AddAllArgs(CmdArgs, options::OPT_init);
// Add the deployment target.
- VersionTuple TargetVersion = DarwinTC.getTargetVersion();
-
- // If we had an explicit -mios-simulator-version-min argument, honor that,
- // otherwise use the traditional deployment targets. We can't just check the
- // is-sim attribute because existing code follows this path, and the linker
- // may not handle the argument.
- //
- // FIXME: We may be able to remove this, once we can verify no one depends on
- // it.
- if (Args.hasArg(options::OPT_mios_simulator_version_min_EQ))
- CmdArgs.push_back("-ios_simulator_version_min");
- else if (DarwinTC.isTargetIPhoneOS())
- CmdArgs.push_back("-iphoneos_version_min");
- else
- CmdArgs.push_back("-macosx_version_min");
- CmdArgs.push_back(Args.MakeArgString(TargetVersion.getAsString()));
+ MachOTC.addMinVersionArgs(Args, CmdArgs);
Args.AddLastArg(CmdArgs, options::OPT_nomultidefs);
Args.AddLastArg(CmdArgs, options::OPT_multi__module);
@@ -4889,6 +5681,12 @@ void darwin::Link::AddLinkArgs(Compilation &C,
Args.AddLastArg(CmdArgs, options::OPT_Mach);
}
+enum LibOpenMP {
+ LibUnknown,
+ LibGOMP,
+ LibIOMP5
+};
+
void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
@@ -4904,8 +5702,8 @@ void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA,
/// Hack(tm) to ignore linking errors when we are doing ARC migration.
if (Args.hasArg(options::OPT_ccc_arcmt_check,
options::OPT_ccc_arcmt_migrate)) {
- for (ArgList::const_iterator I = Args.begin(), E = Args.end(); I != E; ++I)
- (*I)->claim();
+ for (const auto &Arg : Args)
+ Arg->claim();
const char *Exec =
Args.MakeArgString(getToolChain().GetProgramPath("touch"));
CmdArgs.push_back(Output.getFilename());
@@ -4935,120 +5733,42 @@ void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(Output.getFilename());
if (!Args.hasArg(options::OPT_nostdlib) &&
- !Args.hasArg(options::OPT_nostartfiles)) {
- // Derived from startfile spec.
- if (Args.hasArg(options::OPT_dynamiclib)) {
- // Derived from darwin_dylib1 spec.
- if (getDarwinToolChain().isTargetIOSSimulator()) {
- // The simulator doesn't have a versioned crt1 file.
- CmdArgs.push_back("-ldylib1.o");
- } else if (getDarwinToolChain().isTargetIPhoneOS()) {
- if (getDarwinToolChain().isIPhoneOSVersionLT(3, 1))
- CmdArgs.push_back("-ldylib1.o");
- } else {
- if (getDarwinToolChain().isMacosxVersionLT(10, 5))
- CmdArgs.push_back("-ldylib1.o");
- else if (getDarwinToolChain().isMacosxVersionLT(10, 6))
- CmdArgs.push_back("-ldylib1.10.5.o");
- }
- } else {
- if (Args.hasArg(options::OPT_bundle)) {
- if (!Args.hasArg(options::OPT_static)) {
- // Derived from darwin_bundle1 spec.
- if (getDarwinToolChain().isTargetIOSSimulator()) {
- // The simulator doesn't have a versioned crt1 file.
- CmdArgs.push_back("-lbundle1.o");
- } else if (getDarwinToolChain().isTargetIPhoneOS()) {
- if (getDarwinToolChain().isIPhoneOSVersionLT(3, 1))
- CmdArgs.push_back("-lbundle1.o");
- } else {
- if (getDarwinToolChain().isMacosxVersionLT(10, 6))
- CmdArgs.push_back("-lbundle1.o");
- }
- }
- } else {
- if (Args.hasArg(options::OPT_pg) &&
- getToolChain().SupportsProfiling()) {
- if (Args.hasArg(options::OPT_static) ||
- Args.hasArg(options::OPT_object) ||
- Args.hasArg(options::OPT_preload)) {
- CmdArgs.push_back("-lgcrt0.o");
- } else {
- CmdArgs.push_back("-lgcrt1.o");
-
- // darwin_crt2 spec is empty.
- }
- // By default on OS X 10.8 and later, we don't link with a crt1.o
- // file and the linker knows to use _main as the entry point. But,
- // when compiling with -pg, we need to link with the gcrt1.o file,
- // so pass the -no_new_main option to tell the linker to use the
- // "start" symbol as the entry point.
- if (getDarwinToolChain().isTargetMacOS() &&
- !getDarwinToolChain().isMacosxVersionLT(10, 8))
- CmdArgs.push_back("-no_new_main");
- } else {
- if (Args.hasArg(options::OPT_static) ||
- Args.hasArg(options::OPT_object) ||
- Args.hasArg(options::OPT_preload)) {
- CmdArgs.push_back("-lcrt0.o");
- } else {
- // Derived from darwin_crt1 spec.
- if (getDarwinToolChain().isTargetIOSSimulator()) {
- // The simulator doesn't have a versioned crt1 file.
- CmdArgs.push_back("-lcrt1.o");
- } else if (getDarwinToolChain().isTargetIPhoneOS()) {
- if (getDarwinToolChain().isIPhoneOSVersionLT(3, 1))
- CmdArgs.push_back("-lcrt1.o");
- else if (getDarwinToolChain().isIPhoneOSVersionLT(6, 0))
- CmdArgs.push_back("-lcrt1.3.1.o");
- } else {
- if (getDarwinToolChain().isMacosxVersionLT(10, 5))
- CmdArgs.push_back("-lcrt1.o");
- else if (getDarwinToolChain().isMacosxVersionLT(10, 6))
- CmdArgs.push_back("-lcrt1.10.5.o");
- else if (getDarwinToolChain().isMacosxVersionLT(10, 8))
- CmdArgs.push_back("-lcrt1.10.6.o");
-
- // darwin_crt2 spec is empty.
- }
- }
- }
- }
- }
-
- if (!getDarwinToolChain().isTargetIPhoneOS() &&
- Args.hasArg(options::OPT_shared_libgcc) &&
- getDarwinToolChain().isMacosxVersionLT(10, 5)) {
- const char *Str =
- Args.MakeArgString(getToolChain().GetFilePath("crt3.o"));
- CmdArgs.push_back(Str);
- }
- }
+ !Args.hasArg(options::OPT_nostartfiles))
+ getMachOToolChain().addStartObjectFileArgs(Args, CmdArgs);
Args.AddAllArgs(CmdArgs, options::OPT_L);
- if (Args.hasArg(options::OPT_fopenmp))
- // This is more complicated in gcc...
+ LibOpenMP UsedOpenMPLib = LibUnknown;
+ if (Args.hasArg(options::OPT_fopenmp)) {
+ UsedOpenMPLib = LibGOMP;
+ } else if (const Arg *A = Args.getLastArg(options::OPT_fopenmp_EQ)) {
+ UsedOpenMPLib = llvm::StringSwitch<LibOpenMP>(A->getValue())
+ .Case("libgomp", LibGOMP)
+ .Case("libiomp5", LibIOMP5)
+ .Default(LibUnknown);
+ if (UsedOpenMPLib == LibUnknown)
+ getToolChain().getDriver().Diag(diag::err_drv_unsupported_option_argument)
+ << A->getOption().getName() << A->getValue();
+ }
+ switch (UsedOpenMPLib) {
+ case LibGOMP:
CmdArgs.push_back("-lgomp");
+ break;
+ case LibIOMP5:
+ CmdArgs.push_back("-liomp5");
+ break;
+ case LibUnknown:
+ break;
+ }
AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);
if (isObjCRuntimeLinked(Args) &&
!Args.hasArg(options::OPT_nostdlib) &&
!Args.hasArg(options::OPT_nodefaultlibs)) {
- // Avoid linking compatibility stubs on i386 mac.
- if (!getDarwinToolChain().isTargetMacOS() ||
- getDarwinToolChain().getArch() != llvm::Triple::x86) {
- // If we don't have ARC or subscripting runtime support, link in the
- // runtime stubs. We have to do this *before* adding any of the normal
- // linker inputs so that its initializer gets run first.
- ObjCRuntime runtime =
- getDarwinToolChain().getDefaultObjCRuntime(/*nonfragile*/ true);
- // We use arclite library for both ARC and subscripting support.
- if ((!runtime.hasNativeARC() && isObjCAutoRefCount(Args)) ||
- !runtime.hasSubscripting())
- getDarwinToolChain().AddLinkARCArgs(Args, CmdArgs);
- }
+ // We use arclite library for both ARC and subscripting support.
+ getMachOToolChain().AddLinkARCArgs(Args, CmdArgs);
+
CmdArgs.push_back("-framework");
CmdArgs.push_back("Foundation");
// Link libobj.
@@ -5072,7 +5792,7 @@ void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA,
// link_ssp spec is empty.
// Let the tool chain choose which runtime library to link.
- getDarwinToolChain().AddLinkRuntimeLibArgs(Args, CmdArgs);
+ getMachOToolChain().AddLinkRuntimeLibArgs(Args, CmdArgs);
}
if (!Args.hasArg(options::OPT_nostdlib) &&
@@ -5084,7 +5804,7 @@ void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddAllArgs(CmdArgs, options::OPT_F);
const char *Exec =
- Args.MakeArgString(getToolChain().GetProgramPath("ld"));
+ Args.MakeArgString(getToolChain().GetLinkerPath());
C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}
@@ -5101,14 +5821,12 @@ void darwin::Lipo::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-output");
CmdArgs.push_back(Output.getFilename());
- for (InputInfoList::const_iterator
- it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
- const InputInfo &II = *it;
+ for (const auto &II : Inputs) {
assert(II.isFilename() && "Unexpected lipo input.");
CmdArgs.push_back(II.getFilename());
}
- const char *Exec =
- Args.MakeArgString(getToolChain().GetProgramPath("lipo"));
+
+ const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("lipo"));
C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}
@@ -5168,18 +5886,13 @@ void solaris::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename());
- for (InputInfoList::const_iterator
- it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
- const InputInfo &II = *it;
+ for (const auto &II : Inputs)
CmdArgs.push_back(II.getFilename());
- }
- const char *Exec =
- Args.MakeArgString(getToolChain().GetProgramPath("as"));
+ const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as"));
C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}
-
void solaris::Link::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
@@ -5278,10 +5991,10 @@ void solaris::Link::ConstructJob(Compilation &C, const JobAction &JA,
}
CmdArgs.push_back(Args.MakeArgString(LibPath + "crtn.o"));
- addProfileRT(getToolChain(), Args, CmdArgs, getToolChain().getTriple());
+ addProfileRT(getToolChain(), Args, CmdArgs);
const char *Exec =
- Args.MakeArgString(getToolChain().GetProgramPath("ld"));
+ Args.MakeArgString(getToolChain().GetLinkerPath());
C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}
@@ -5298,14 +6011,10 @@ void auroraux::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename());
- for (InputInfoList::const_iterator
- it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
- const InputInfo &II = *it;
+ for (const auto &II : Inputs)
CmdArgs.push_back(II.getFilename());
- }
- const char *Exec =
- Args.MakeArgString(getToolChain().GetProgramPath("gas"));
+ const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("gas"));
C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}
@@ -5390,10 +6099,10 @@ void auroraux::Link::ConstructJob(Compilation &C, const JobAction &JA,
getToolChain().GetFilePath("crtend.o")));
}
- addProfileRT(getToolChain(), Args, CmdArgs, getToolChain().getTriple());
+ addProfileRT(getToolChain(), Args, CmdArgs);
const char *Exec =
- Args.MakeArgString(getToolChain().GetProgramPath("ld"));
+ Args.MakeArgString(getToolChain().GetLinkerPath());
C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}
@@ -5403,19 +6112,36 @@ void openbsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
const ArgList &Args,
const char *LinkingOutput) const {
ArgStringList CmdArgs;
+ bool NeedsKPIC = false;
- // 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)
+ switch (getToolChain().getArch()) {
+ case llvm::Triple::x86:
+ // When building 32-bit code on OpenBSD/amd64, we have to explicitly
+ // instruct as in the base system to assemble 32-bit code.
CmdArgs.push_back("--32");
- else if (getToolChain().getArch() == llvm::Triple::ppc) {
+ break;
+
+ case llvm::Triple::ppc:
CmdArgs.push_back("-mppc");
CmdArgs.push_back("-many");
- } else if (getToolChain().getArch() == llvm::Triple::mips64 ||
- getToolChain().getArch() == llvm::Triple::mips64el) {
+ break;
+
+ case llvm::Triple::sparc:
+ CmdArgs.push_back("-32");
+ NeedsKPIC = true;
+ break;
+
+ case llvm::Triple::sparcv9:
+ CmdArgs.push_back("-64");
+ CmdArgs.push_back("-Av9a");
+ NeedsKPIC = true;
+ break;
+
+ case llvm::Triple::mips64:
+ case llvm::Triple::mips64el: {
StringRef CPUName;
StringRef ABIName;
- getMipsCPUAndABI(Args, getToolChain().getTriple(), CPUName, ABIName);
+ mips::getMipsCPUAndABI(Args, getToolChain().getTriple(), CPUName, ABIName);
CmdArgs.push_back("-mabi");
CmdArgs.push_back(getGnuCompatibleMipsABIName(ABIName).data());
@@ -5425,30 +6151,25 @@ void openbsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
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");
- }
+ NeedsKPIC = true;
+ break;
}
+ default:
+ break;
+ }
+
+ if (NeedsKPIC)
+ addAssemblerKPIC(Args, CmdArgs);
+
Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,
options::OPT_Xassembler);
CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename());
- for (InputInfoList::const_iterator
- it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
- const InputInfo &II = *it;
+ for (const auto &II : Inputs)
CmdArgs.push_back(II.getFilename());
- }
const char *Exec =
Args.MakeArgString(getToolChain().GetProgramPath("as"));
@@ -5583,7 +6304,7 @@ void openbsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
}
const char *Exec =
- Args.MakeArgString(getToolChain().GetProgramPath("ld"));
+ Args.MakeArgString(getToolChain().GetLinkerPath());
C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}
@@ -5600,14 +6321,10 @@ void bitrig::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename());
- for (InputInfoList::const_iterator
- it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
- const InputInfo &II = *it;
+ for (const auto &II : Inputs)
CmdArgs.push_back(II.getFilename());
- }
- const char *Exec =
- Args.MakeArgString(getToolChain().GetProgramPath("as"));
+ const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as"));
C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}
@@ -5723,7 +6440,7 @@ void bitrig::Link::ConstructJob(Compilation &C, const JobAction &JA,
}
const char *Exec =
- Args.MakeArgString(getToolChain().GetProgramPath("ld"));
+ Args.MakeArgString(getToolChain().GetLinkerPath());
C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}
@@ -5746,7 +6463,7 @@ void freebsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
getToolChain().getArch() == llvm::Triple::mips64el) {
StringRef CPUName;
StringRef ABIName;
- getMipsCPUAndABI(Args, getToolChain().getTriple(), CPUName, ABIName);
+ mips::getMipsCPUAndABI(Args, getToolChain().getTriple(), CPUName, ABIName);
CmdArgs.push_back("-march");
CmdArgs.push_back(CPUName.data());
@@ -5760,21 +6477,23 @@ void freebsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
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");
- }
+ addAssemblerKPIC(Args, CmdArgs);
} else if (getToolChain().getArch() == llvm::Triple::arm ||
- getToolChain().getArch() == llvm::Triple::thumb) {
- CmdArgs.push_back("-mfpu=softvfp");
+ getToolChain().getArch() == llvm::Triple::armeb ||
+ getToolChain().getArch() == llvm::Triple::thumb ||
+ getToolChain().getArch() == llvm::Triple::thumbeb) {
+ const Driver &D = getToolChain().getDriver();
+ const llvm::Triple &Triple = getToolChain().getTriple();
+ StringRef FloatABI = arm::getARMFloatABI(D, Args, Triple);
+
+ if (FloatABI == "hard") {
+ CmdArgs.push_back("-mfpu=vfp");
+ } else {
+ CmdArgs.push_back("-mfpu=softvfp");
+ }
+
switch(getToolChain().getTriple().getEnvironment()) {
+ case llvm::Triple::GNUEABIHF:
case llvm::Triple::GNUEABI:
case llvm::Triple::EABI:
CmdArgs.push_back("-meabi=5");
@@ -5783,6 +6502,14 @@ void freebsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
default:
CmdArgs.push_back("-matpcs");
}
+ } else if (getToolChain().getArch() == llvm::Triple::sparc ||
+ getToolChain().getArch() == llvm::Triple::sparcv9) {
+ if (getToolChain().getArch() == llvm::Triple::sparc)
+ CmdArgs.push_back("-Av8plusa");
+ else
+ CmdArgs.push_back("-Av9a");
+
+ addAssemblerKPIC(Args, CmdArgs);
}
Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,
@@ -5791,14 +6518,10 @@ void freebsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename());
- for (InputInfoList::const_iterator
- it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
- const InputInfo &II = *it;
+ for (const auto &II : Inputs)
CmdArgs.push_back(II.getFilename());
- }
- const char *Exec =
- Args.MakeArgString(getToolChain().GetProgramPath("as"));
+ const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as"));
C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}
@@ -5810,6 +6533,9 @@ void freebsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
const toolchains::FreeBSD& ToolChain =
static_cast<const toolchains::FreeBSD&>(getToolChain());
const Driver &D = ToolChain.getDriver();
+ const bool IsPIE =
+ !Args.hasArg(options::OPT_shared) &&
+ (Args.hasArg(options::OPT_pie) || ToolChain.isPIEDefault());
ArgStringList CmdArgs;
// Silence warning for "clang -g foo.o -o foo"
@@ -5823,7 +6549,7 @@ void freebsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
if (!D.SysRoot.empty())
CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));
- if (Args.hasArg(options::OPT_pie))
+ if (IsPIE)
CmdArgs.push_back("-pie");
if (Args.hasArg(options::OPT_static)) {
@@ -5869,11 +6595,11 @@ void freebsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
if (!Args.hasArg(options::OPT_nostdlib) &&
!Args.hasArg(options::OPT_nostartfiles)) {
- const char *crt1 = NULL;
+ const char *crt1 = nullptr;
if (!Args.hasArg(options::OPT_shared)) {
if (Args.hasArg(options::OPT_pg))
crt1 = "gcrt1.o";
- else if (Args.hasArg(options::OPT_pie))
+ else if (IsPIE)
crt1 = "Scrt1.o";
else
crt1 = "crt1.o";
@@ -5883,10 +6609,10 @@ void freebsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crti.o")));
- const char *crtbegin = NULL;
+ const char *crtbegin = nullptr;
if (Args.hasArg(options::OPT_static))
crtbegin = "crtbeginT.o";
- else if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_pie))
+ else if (Args.hasArg(options::OPT_shared) || IsPIE)
crtbegin = "crtbeginS.o";
else
crtbegin = "crtbegin.o";
@@ -5896,9 +6622,8 @@ void freebsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddAllArgs(CmdArgs, options::OPT_L);
const ToolChain::path_list Paths = ToolChain.getFilePaths();
- for (ToolChain::path_list::const_iterator i = Paths.begin(), e = Paths.end();
- i != e; ++i)
- CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + *i));
+ for (const auto &Path : Paths)
+ CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + Path));
Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
Args.AddAllArgs(CmdArgs, options::OPT_e);
Args.AddAllArgs(CmdArgs, options::OPT_s);
@@ -5906,25 +6631,8 @@ 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));
- }
- }
+ if (D.IsUsingLTO(Args))
+ AddGoldPlugin(ToolChain, Args, CmdArgs);
AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs);
@@ -5984,17 +6692,19 @@ void freebsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
if (!Args.hasArg(options::OPT_nostdlib) &&
!Args.hasArg(options::OPT_nostartfiles)) {
- if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_pie))
+ if (Args.hasArg(options::OPT_shared) || IsPIE)
CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtendS.o")));
else
CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtend.o")));
CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtn.o")));
}
- addProfileRT(ToolChain, Args, CmdArgs, ToolChain.getTriple());
+ addSanitizerRuntimes(getToolChain(), Args, CmdArgs);
+
+ addProfileRT(ToolChain, Args, CmdArgs);
const char *Exec =
- Args.MakeArgString(ToolChain.GetProgramPath("ld"));
+ Args.MakeArgString(getToolChain().GetLinkerPath());
C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}
@@ -6005,25 +6715,28 @@ void netbsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
const char *LinkingOutput) const {
ArgStringList CmdArgs;
- // When building 32-bit code on NetBSD/amd64, we have to explicitly
- // instruct as in the base system to assemble 32-bit code.
- if (getToolChain().getArch() == llvm::Triple::x86)
+ // GNU as needs different flags for creating the correct output format
+ // on architectures with different ABIs or optional feature sets.
+ switch (getToolChain().getArch()) {
+ case llvm::Triple::x86:
CmdArgs.push_back("--32");
-
- // 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()));
+ break;
+ case llvm::Triple::arm:
+ case llvm::Triple::armeb:
+ case llvm::Triple::thumb:
+ case llvm::Triple::thumbeb: {
+ std::string MArch(arm::getARMTargetCPU(Args, getToolChain().getTriple()));
CmdArgs.push_back(Args.MakeArgString("-mcpu=" + MArch));
+ break;
}
- if (getToolChain().getArch() == llvm::Triple::mips ||
- getToolChain().getArch() == llvm::Triple::mipsel ||
- getToolChain().getArch() == llvm::Triple::mips64 ||
- getToolChain().getArch() == llvm::Triple::mips64el) {
+ case llvm::Triple::mips:
+ case llvm::Triple::mipsel:
+ case llvm::Triple::mips64:
+ case llvm::Triple::mips64el: {
StringRef CPUName;
StringRef ABIName;
- getMipsCPUAndABI(Args, getToolChain().getTriple(), CPUName, ABIName);
+ mips::getMipsCPUAndABI(Args, getToolChain().getTriple(), CPUName, ABIName);
CmdArgs.push_back("-march");
CmdArgs.push_back(CPUName.data());
@@ -6037,17 +6750,23 @@ void netbsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
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");
- }
+ addAssemblerKPIC(Args, CmdArgs);
+ break;
+ }
+
+ case llvm::Triple::sparc:
+ CmdArgs.push_back("-32");
+ addAssemblerKPIC(Args, CmdArgs);
+ break;
+
+ case llvm::Triple::sparcv9:
+ CmdArgs.push_back("-64");
+ CmdArgs.push_back("-Av9");
+ addAssemblerKPIC(Args, CmdArgs);
+ break;
+
+ default:
+ break;
}
Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,
@@ -6056,11 +6775,8 @@ void netbsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename());
- for (InputInfoList::const_iterator
- it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
- const InputInfo &II = *it;
+ for (const auto &II : Inputs)
CmdArgs.push_back(II.getFilename());
- }
const char *Exec = Args.MakeArgString((getToolChain().GetProgramPath("as")));
C.addCommand(new Command(JA, *this, Exec, CmdArgs));
@@ -6077,12 +6793,12 @@ void netbsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
if (!D.SysRoot.empty())
CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));
+ CmdArgs.push_back("--eh-frame-hdr");
if (Args.hasArg(options::OPT_static)) {
CmdArgs.push_back("-Bstatic");
} else {
if (Args.hasArg(options::OPT_rdynamic))
CmdArgs.push_back("-export-dynamic");
- CmdArgs.push_back("--eh-frame-hdr");
if (Args.hasArg(options::OPT_shared)) {
CmdArgs.push_back("-Bshareable");
} else {
@@ -6091,11 +6807,61 @@ void netbsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
}
}
- // When building 32-bit code on NetBSD/amd64, we have to explicitly
- // instruct ld in the base system to link 32-bit code.
- if (getToolChain().getArch() == llvm::Triple::x86) {
+ // Many NetBSD architectures support more than one ABI.
+ // Determine the correct emulation for ld.
+ switch (getToolChain().getArch()) {
+ case llvm::Triple::x86:
CmdArgs.push_back("-m");
CmdArgs.push_back("elf_i386");
+ break;
+ case llvm::Triple::arm:
+ case llvm::Triple::armeb:
+ case llvm::Triple::thumb:
+ case llvm::Triple::thumbeb:
+ CmdArgs.push_back("-m");
+ switch (getToolChain().getTriple().getEnvironment()) {
+ case llvm::Triple::EABI:
+ case llvm::Triple::GNUEABI:
+ CmdArgs.push_back("armelf_nbsd_eabi");
+ break;
+ case llvm::Triple::EABIHF:
+ case llvm::Triple::GNUEABIHF:
+ CmdArgs.push_back("armelf_nbsd_eabihf");
+ break;
+ default:
+ CmdArgs.push_back("armelf_nbsd");
+ break;
+ }
+ break;
+ case llvm::Triple::mips64:
+ case llvm::Triple::mips64el:
+ if (mips::hasMipsAbiArg(Args, "32")) {
+ CmdArgs.push_back("-m");
+ if (getToolChain().getArch() == llvm::Triple::mips64)
+ CmdArgs.push_back("elf32btsmip");
+ else
+ CmdArgs.push_back("elf32ltsmip");
+ } else if (mips::hasMipsAbiArg(Args, "64")) {
+ CmdArgs.push_back("-m");
+ if (getToolChain().getArch() == llvm::Triple::mips64)
+ CmdArgs.push_back("elf64btsmip");
+ else
+ CmdArgs.push_back("elf64ltsmip");
+ }
+ break;
+
+ case llvm::Triple::sparc:
+ CmdArgs.push_back("-m");
+ CmdArgs.push_back("elf32_sparc");
+ break;
+
+ case llvm::Triple::sparcv9:
+ CmdArgs.push_back("-m");
+ CmdArgs.push_back("elf64_sparc");
+ break;
+
+ default:
+ break;
}
if (Output.isFilename()) {
@@ -6135,10 +6901,19 @@ void netbsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
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)
+ if (Major >= 7 || (Major == 6 && Minor == 99 && Micro >= 40) || Major == 0) {
+ switch(getToolChain().getArch()) {
+ case llvm::Triple::arm:
+ case llvm::Triple::armeb:
+ case llvm::Triple::thumb:
+ case llvm::Triple::thumbeb:
+ case llvm::Triple::x86:
+ case llvm::Triple::x86_64:
useLibgcc = false;
+ break;
+ default:
+ break;
+ }
}
if (!Args.hasArg(options::OPT_nostdlib) &&
@@ -6180,9 +6955,9 @@ void netbsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
"crtn.o")));
}
- addProfileRT(getToolChain(), Args, CmdArgs, getToolChain().getTriple());
+ addProfileRT(getToolChain(), Args, CmdArgs);
- const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("ld"));
+ const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath());
C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}
@@ -6192,13 +6967,17 @@ void gnutools::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
const ArgList &Args,
const char *LinkingOutput) const {
ArgStringList CmdArgs;
+ bool NeedsKPIC = false;
// Add --32/--64 to make sure we get the format we want.
// This is incomplete
if (getToolChain().getArch() == llvm::Triple::x86) {
CmdArgs.push_back("--32");
} else if (getToolChain().getArch() == llvm::Triple::x86_64) {
- CmdArgs.push_back("--64");
+ if (getToolChain().getTriple().getEnvironment() == llvm::Triple::GNUX32)
+ CmdArgs.push_back("--x32");
+ else
+ CmdArgs.push_back("--64");
} else if (getToolChain().getArch() == llvm::Triple::ppc) {
CmdArgs.push_back("-a32");
CmdArgs.push_back("-mppc");
@@ -6209,21 +6988,41 @@ void gnutools::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-many");
} else if (getToolChain().getArch() == llvm::Triple::ppc64le) {
CmdArgs.push_back("-a64");
- CmdArgs.push_back("-mppc64le");
+ CmdArgs.push_back("-mppc64");
CmdArgs.push_back("-many");
- } else if (getToolChain().getArch() == llvm::Triple::arm) {
+ CmdArgs.push_back("-mlittle-endian");
+ } else if (getToolChain().getArch() == llvm::Triple::sparc) {
+ CmdArgs.push_back("-32");
+ CmdArgs.push_back("-Av8plusa");
+ NeedsKPIC = true;
+ } else if (getToolChain().getArch() == llvm::Triple::sparcv9) {
+ CmdArgs.push_back("-64");
+ CmdArgs.push_back("-Av9a");
+ NeedsKPIC = true;
+ } else if (getToolChain().getArch() == llvm::Triple::arm ||
+ getToolChain().getArch() == llvm::Triple::armeb) {
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")
+ if (MArch == "armv8" || MArch == "armv8a" || MArch == "armv8-a" ||
+ MArch == "armebv8" || MArch == "armebv8a" || MArch == "armebv8-a")
CmdArgs.push_back("-mfpu=crypto-neon-fp-armv8");
- StringRef ARMFloatABI = getARMFloatABI(getToolChain().getDriver(), Args,
- getToolChain().getTriple());
+ StringRef ARMFloatABI = tools::arm::getARMFloatABI(
+ getToolChain().getDriver(), Args, getToolChain().getTriple());
CmdArgs.push_back(Args.MakeArgString("-mfloat-abi=" + ARMFloatABI));
Args.AddLastArg(CmdArgs, options::OPT_march_EQ);
- Args.AddLastArg(CmdArgs, options::OPT_mcpu_EQ);
+
+ // FIXME: remove krait check when GNU tools support krait cpu
+ // for now replace it with -march=armv7-a to avoid a lower
+ // march from being picked in the absence of a cpu flag.
+ Arg *A;
+ if ((A = Args.getLastArg(options::OPT_mcpu_EQ)) &&
+ StringRef(A->getValue()) == "krait")
+ CmdArgs.push_back("-march=armv7-a");
+ else
+ Args.AddLastArg(CmdArgs, options::OPT_mcpu_EQ);
Args.AddLastArg(CmdArgs, options::OPT_mfpu_EQ);
} else if (getToolChain().getArch() == llvm::Triple::mips ||
getToolChain().getArch() == llvm::Triple::mipsel ||
@@ -6231,13 +7030,34 @@ void gnutools::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
getToolChain().getArch() == llvm::Triple::mips64el) {
StringRef CPUName;
StringRef ABIName;
- getMipsCPUAndABI(Args, getToolChain().getTriple(), CPUName, ABIName);
+ mips::getMipsCPUAndABI(Args, getToolChain().getTriple(), CPUName, ABIName);
+ ABIName = getGnuCompatibleMipsABIName(ABIName);
CmdArgs.push_back("-march");
CmdArgs.push_back(CPUName.data());
CmdArgs.push_back("-mabi");
- CmdArgs.push_back(getGnuCompatibleMipsABIName(ABIName).data());
+ CmdArgs.push_back(ABIName.data());
+
+ // -mno-shared should be emitted unless -fpic, -fpie, -fPIC, -fPIE,
+ // or -mshared (not implemented) is in effect.
+ bool IsPicOrPie = false;
+ if (Arg *A = 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 (A->getOption().matches(options::OPT_fPIC) ||
+ A->getOption().matches(options::OPT_fpic) ||
+ A->getOption().matches(options::OPT_fPIE) ||
+ A->getOption().matches(options::OPT_fpie))
+ IsPicOrPie = true;
+ }
+ if (!IsPicOrPie)
+ CmdArgs.push_back("-mno-shared");
+
+ // LLVM doesn't support -mplt yet and acts as if it is always given.
+ // However, -mplt has no effect with the N64 ABI.
+ CmdArgs.push_back(ABIName == "64" ? "-KPIC" : "-call_nonpic");
if (getToolChain().getArch() == llvm::Triple::mips ||
getToolChain().getArch() == llvm::Triple::mips64)
@@ -6250,14 +7070,28 @@ void gnutools::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
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"));
+ // Add the last -mfp32/-mfpxx/-mfp64 or -mfpxx if it is enabled by default.
+ if (Arg *A = Args.getLastArg(options::OPT_mfp32, options::OPT_mfpxx,
+ options::OPT_mfp64)) {
+ A->claim();
+ A->render(Args, CmdArgs);
+ } else if (mips::isFPXXDefault(getToolChain().getTriple(), CPUName,
+ ABIName))
+ CmdArgs.push_back("-mfpxx");
+
+ // Pass on -mmips16 or -mno-mips16. However, the assembler equivalent of
+ // -mno-mips16 is actually -no-mips16.
+ if (Arg *A = Args.getLastArg(options::OPT_mips16,
+ options::OPT_mno_mips16)) {
+ if (A->getOption().matches(options::OPT_mips16)) {
+ A->claim();
+ A->render(Args, CmdArgs);
+ } else {
+ A->claim();
+ CmdArgs.push_back("-no-mips16");
+ }
}
- 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);
@@ -6270,17 +7104,13 @@ void gnutools::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
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,
- 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.AddLastArg(CmdArgs, options::OPT_mhard_float,
+ options::OPT_msoft_float);
+
+ Args.AddLastArg(CmdArgs, options::OPT_modd_spreg,
+ options::OPT_mno_odd_spreg);
+
+ NeedsKPIC = true;
} else if (getToolChain().getArch() == llvm::Triple::systemz) {
// Always pass an -march option, since our default of z10 is later
// than the GNU assembler's default.
@@ -6288,20 +7118,19 @@ void gnutools::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(Args.MakeArgString("-march=" + CPUName));
}
+ if (NeedsKPIC)
+ addAssemblerKPIC(Args, CmdArgs);
+
Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,
options::OPT_Xassembler);
CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename());
- for (InputInfoList::const_iterator
- it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
- const InputInfo &II = *it;
+ for (const auto &II : Inputs)
CmdArgs.push_back(II.getFilename());
- }
- const char *Exec =
- Args.MakeArgString(getToolChain().GetProgramPath("as"));
+ 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
@@ -6313,7 +7142,7 @@ void gnutools::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
SplitDebugName(Args, Inputs));
}
-static void AddLibgcc(llvm::Triple Triple, const Driver &D,
+static void AddLibgcc(const llvm::Triple &Triple, const Driver &D,
ArgStringList &CmdArgs, const ArgList &Args) {
bool isAndroid = Triple.getEnvironment() == llvm::Triple::Android;
bool StaticLibgcc = Args.hasArg(options::OPT_static_libgcc) ||
@@ -6346,44 +7175,77 @@ static void AddLibgcc(llvm::Triple Triple, const Driver &D,
CmdArgs.push_back("-ldl");
}
-static bool hasMipsN32ABIArg(const ArgList &Args) {
- Arg *A = Args.getLastArg(options::OPT_mabi_EQ);
- 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)
+ if (ToolChain.getTriple().getEnvironment() == llvm::Triple::Android) {
+ if (ToolChain.getTriple().isArch64Bit())
+ return "/system/bin/linker64";
+ else
+ return "/system/bin/linker";
+ } else if (ToolChain.getArch() == llvm::Triple::x86 ||
+ ToolChain.getArch() == llvm::Triple::sparc)
return "/lib/ld-linux.so.2";
- else if (ToolChain.getArch() == llvm::Triple::aarch64)
+ else if (ToolChain.getArch() == llvm::Triple::aarch64 ||
+ ToolChain.getArch() == llvm::Triple::arm64)
return "/lib/ld-linux-aarch64.so.1";
+ else if (ToolChain.getArch() == llvm::Triple::aarch64_be ||
+ ToolChain.getArch() == llvm::Triple::arm64_be)
+ return "/lib/ld-linux-aarch64_be.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::armeb ||
+ ToolChain.getArch() == llvm::Triple::thumbeb) {
+ if (ToolChain.getTriple().getEnvironment() == llvm::Triple::GNUEABIHF)
+ return "/lib/ld-linux-armhf.so.3"; /* TODO: check which dynamic linker name. */
+ else
+ return "/lib/ld-linux.so.3"; /* TODO: check which dynamic linker name. */
} else if (ToolChain.getArch() == llvm::Triple::mips ||
- ToolChain.getArch() == llvm::Triple::mipsel)
+ ToolChain.getArch() == llvm::Triple::mipsel) {
+ if (mips::isNaN2008(Args, ToolChain.getTriple()))
+ return "/lib/ld-linux-mipsn8.so.1";
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::mips64 ||
+ ToolChain.getArch() == llvm::Triple::mips64el) {
+ if (mips::hasMipsAbiArg(Args, "n32"))
+ return mips::isNaN2008(Args, ToolChain.getTriple())
+ ? "/lib32/ld-linux-mipsn8.so.1" : "/lib32/ld.so.1";
+ return mips::isNaN2008(Args, ToolChain.getTriple())
+ ? "/lib64/ld-linux-mipsn8.so.1" : "/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 if (ToolChain.getArch() == llvm::Triple::ppc64le)
+ return "/lib64/ld64.so.2";
+ else if (ToolChain.getArch() == llvm::Triple::sparcv9)
+ return "/lib64/ld-linux.so.2";
+ else if (ToolChain.getArch() == llvm::Triple::x86_64 &&
+ ToolChain.getTriple().getEnvironment() == llvm::Triple::GNUX32)
+ return "/libx32/ld-linux-x32.so.2";
else
return "/lib64/ld-linux-x86-64.so.2";
}
+static void AddRunTimeLibs(const ToolChain &TC, const Driver &D,
+ ArgStringList &CmdArgs, const ArgList &Args) {
+ // Make use of compiler-rt if --rtlib option is used
+ ToolChain::RuntimeLibType RLT = TC.GetRuntimeLibType(Args);
+
+ switch(RLT) {
+ case ToolChain::RLT_CompilerRT:
+ addClangRTLinux(TC, Args, CmdArgs);
+ break;
+ case ToolChain::RLT_Libgcc:
+ AddLibgcc(TC.getTriple(), D, CmdArgs, Args);
+ break;
+ }
+}
+
void gnutools::Link::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
@@ -6394,10 +7256,14 @@ void gnutools::Link::ConstructJob(Compilation &C, const JobAction &JA,
const Driver &D = ToolChain.getDriver();
const bool isAndroid =
ToolChain.getTriple().getEnvironment() == llvm::Triple::Android;
- const SanitizerArgs &Sanitize = ToolChain.getSanitizerArgs();
const bool IsPIE =
!Args.hasArg(options::OPT_shared) &&
- (Args.hasArg(options::OPT_pie) || Sanitize.hasZeroBaseShadow());
+ !Args.hasArg(options::OPT_static) &&
+ (Args.hasArg(options::OPT_pie) || ToolChain.isPIEDefault() ||
+ // On Android every code is PIC so every executable is PIE
+ // Cannot use isPIEDefault here since otherwise
+ // PIE only logic will be enabled during compilation
+ isAndroid);
ArgStringList CmdArgs;
@@ -6421,10 +7287,8 @@ void gnutools::Link::ConstructJob(Compilation &C, const JobAction &JA,
if (Args.hasArg(options::OPT_s))
CmdArgs.push_back("-s");
- for (std::vector<std::string>::const_iterator i = ToolChain.ExtraOpts.begin(),
- e = ToolChain.ExtraOpts.end();
- i != e; ++i)
- CmdArgs.push_back(i->c_str());
+ for (const auto &Opt : ToolChain.ExtraOpts)
+ CmdArgs.push_back(Opt.c_str());
if (!Args.hasArg(options::OPT_static)) {
CmdArgs.push_back("--eh-frame-hdr");
@@ -6433,51 +7297,68 @@ void gnutools::Link::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-m");
if (ToolChain.getArch() == llvm::Triple::x86)
CmdArgs.push_back("elf_i386");
- else if (ToolChain.getArch() == llvm::Triple::aarch64)
+ else if (ToolChain.getArch() == llvm::Triple::aarch64 ||
+ ToolChain.getArch() == llvm::Triple::arm64)
CmdArgs.push_back("aarch64linux");
+ else if (ToolChain.getArch() == llvm::Triple::aarch64_be ||
+ ToolChain.getArch() == llvm::Triple::arm64_be)
+ CmdArgs.push_back("aarch64_be_linux");
else if (ToolChain.getArch() == llvm::Triple::arm
|| ToolChain.getArch() == llvm::Triple::thumb)
CmdArgs.push_back("armelf_linux_eabi");
+ else if (ToolChain.getArch() == llvm::Triple::armeb
+ || ToolChain.getArch() == llvm::Triple::thumbeb)
+ CmdArgs.push_back("armebelf_linux_eabi"); /* TODO: check which NAME. */
else if (ToolChain.getArch() == llvm::Triple::ppc)
CmdArgs.push_back("elf32ppclinux");
else if (ToolChain.getArch() == llvm::Triple::ppc64)
CmdArgs.push_back("elf64ppc");
+ else if (ToolChain.getArch() == llvm::Triple::ppc64le)
+ CmdArgs.push_back("elf64lppc");
+ else if (ToolChain.getArch() == llvm::Triple::sparc)
+ CmdArgs.push_back("elf32_sparc");
+ else if (ToolChain.getArch() == llvm::Triple::sparcv9)
+ CmdArgs.push_back("elf64_sparc");
else if (ToolChain.getArch() == llvm::Triple::mips)
CmdArgs.push_back("elf32btsmip");
else if (ToolChain.getArch() == llvm::Triple::mipsel)
CmdArgs.push_back("elf32ltsmip");
else if (ToolChain.getArch() == llvm::Triple::mips64) {
- if (hasMipsN32ABIArg(Args))
+ if (mips::hasMipsAbiArg(Args, "n32"))
CmdArgs.push_back("elf32btsmipn32");
else
CmdArgs.push_back("elf64btsmip");
}
else if (ToolChain.getArch() == llvm::Triple::mips64el) {
- if (hasMipsN32ABIArg(Args))
+ if (mips::hasMipsAbiArg(Args, "n32"))
CmdArgs.push_back("elf32ltsmipn32");
else
CmdArgs.push_back("elf64ltsmip");
}
else if (ToolChain.getArch() == llvm::Triple::systemz)
CmdArgs.push_back("elf64_s390");
+ else if (ToolChain.getArch() == llvm::Triple::x86_64 &&
+ ToolChain.getTriple().getEnvironment() == llvm::Triple::GNUX32)
+ CmdArgs.push_back("elf32_x86_64");
else
CmdArgs.push_back("elf_x86_64");
if (Args.hasArg(options::OPT_static)) {
- if (ToolChain.getArch() == llvm::Triple::arm
- || ToolChain.getArch() == llvm::Triple::thumb)
+ if (ToolChain.getArch() == llvm::Triple::arm ||
+ ToolChain.getArch() == llvm::Triple::armeb ||
+ ToolChain.getArch() == llvm::Triple::thumb ||
+ ToolChain.getArch() == llvm::Triple::thumbeb)
CmdArgs.push_back("-Bstatic");
else
CmdArgs.push_back("-static");
} else if (Args.hasArg(options::OPT_shared)) {
CmdArgs.push_back("-shared");
- if (isAndroid) {
- CmdArgs.push_back("-Bsymbolic");
- }
}
if (ToolChain.getArch() == llvm::Triple::arm ||
+ ToolChain.getArch() == llvm::Triple::armeb ||
ToolChain.getArch() == llvm::Triple::thumb ||
+ ToolChain.getArch() == llvm::Triple::thumbeb ||
(!Args.hasArg(options::OPT_static) &&
!Args.hasArg(options::OPT_shared))) {
CmdArgs.push_back("-dynamic-linker");
@@ -6491,7 +7372,7 @@ void gnutools::Link::ConstructJob(Compilation &C, const JobAction &JA,
if (!Args.hasArg(options::OPT_nostdlib) &&
!Args.hasArg(options::OPT_nostartfiles)) {
if (!isAndroid) {
- const char *crt1 = NULL;
+ const char *crt1 = nullptr;
if (!Args.hasArg(options::OPT_shared)){
if (Args.hasArg(options::OPT_pg))
crt1 = "gcrt1.o";
@@ -6522,57 +7403,24 @@ void gnutools::Link::ConstructJob(Compilation &C, const JobAction &JA,
}
Args.AddAllArgs(CmdArgs, options::OPT_L);
+ Args.AddAllArgs(CmdArgs, options::OPT_u);
const ToolChain::path_list Paths = ToolChain.getFilePaths();
- for (ToolChain::path_list::const_iterator i = Paths.begin(), e = Paths.end();
- i != e; ++i)
- CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + *i));
-
- // 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));
- }
- }
+ for (const auto &Path : Paths)
+ CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + Path));
+ if (D.IsUsingLTO(Args))
+ AddGoldPlugin(ToolChain, Args, CmdArgs);
if (Args.hasArg(options::OPT_Z_Xlinker__no_demangle))
CmdArgs.push_back("--no-demangle");
AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs);
- // Call these before we add the C++ ABI library.
- if (Sanitize.needsUbsanRt())
- addUbsanRTLinux(getToolChain(), Args, CmdArgs, D.CCCIsCXX(),
- Sanitize.needsAsanRt() || Sanitize.needsTsanRt() ||
- 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);
-
+ addSanitizerRuntimes(getToolChain(), Args, CmdArgs);
// The profile runtime also needs access to system libraries.
- addProfileRTLinux(getToolChain(), Args, CmdArgs);
+ addProfileRT(getToolChain(), Args, CmdArgs);
if (D.CCCIsCXX() &&
!Args.hasArg(options::OPT_nostdlib) &&
@@ -6592,19 +7440,37 @@ void gnutools::Link::ConstructJob(Compilation &C, const JobAction &JA,
if (Args.hasArg(options::OPT_static))
CmdArgs.push_back("--start-group");
- bool OpenMP = Args.hasArg(options::OPT_fopenmp);
- if (OpenMP) {
+ LibOpenMP UsedOpenMPLib = LibUnknown;
+ if (Args.hasArg(options::OPT_fopenmp)) {
+ UsedOpenMPLib = LibGOMP;
+ } else if (const Arg *A = Args.getLastArg(options::OPT_fopenmp_EQ)) {
+ UsedOpenMPLib = llvm::StringSwitch<LibOpenMP>(A->getValue())
+ .Case("libgomp", LibGOMP)
+ .Case("libiomp5", LibIOMP5)
+ .Default(LibUnknown);
+ if (UsedOpenMPLib == LibUnknown)
+ D.Diag(diag::err_drv_unsupported_option_argument)
+ << A->getOption().getName() << A->getValue();
+ }
+ switch (UsedOpenMPLib) {
+ case LibGOMP:
CmdArgs.push_back("-lgomp");
- // FIXME: Exclude this for platforms whith libgomp that doesn't require
- // librt. Most modern Linux platfroms require it, but some may not.
+ // FIXME: Exclude this for platforms with libgomp that don't require
+ // librt. Most modern Linux platforms require it, but some may not.
CmdArgs.push_back("-lrt");
+ break;
+ case LibIOMP5:
+ CmdArgs.push_back("-liomp5");
+ break;
+ case LibUnknown:
+ break;
}
+ AddRunTimeLibs(ToolChain, D, CmdArgs, Args);
- AddLibgcc(ToolChain.getTriple(), D, CmdArgs, Args);
-
- if (Args.hasArg(options::OPT_pthread) ||
- Args.hasArg(options::OPT_pthreads) || OpenMP)
+ if ((Args.hasArg(options::OPT_pthread) ||
+ Args.hasArg(options::OPT_pthreads) || UsedOpenMPLib != LibUnknown) &&
+ !isAndroid)
CmdArgs.push_back("-lpthread");
CmdArgs.push_back("-lc");
@@ -6612,7 +7478,7 @@ void gnutools::Link::ConstructJob(Compilation &C, const JobAction &JA,
if (Args.hasArg(options::OPT_static))
CmdArgs.push_back("--end-group");
else
- AddLibgcc(ToolChain.getTriple(), D, CmdArgs, Args);
+ AddRunTimeLibs(ToolChain, D, CmdArgs, Args);
}
if (!Args.hasArg(options::OPT_nostartfiles)) {
@@ -6640,20 +7506,15 @@ void minix::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
const char *LinkingOutput) const {
ArgStringList CmdArgs;
- Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,
- options::OPT_Xassembler);
+ Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename());
- for (InputInfoList::const_iterator
- it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
- const InputInfo &II = *it;
+ for (const auto &II : Inputs)
CmdArgs.push_back(II.getFilename());
- }
- const char *Exec =
- Args.MakeArgString(getToolChain().GetProgramPath("as"));
+ const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as"));
C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}
@@ -6686,7 +7547,7 @@ void minix::Link::ConstructJob(Compilation &C, const JobAction &JA,
AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);
- addProfileRT(getToolChain(), Args, CmdArgs, getToolChain().getTriple());
+ addProfileRT(getToolChain(), Args, CmdArgs);
if (!Args.hasArg(options::OPT_nostdlib) &&
!Args.hasArg(options::OPT_nodefaultlibs)) {
@@ -6707,7 +7568,7 @@ void minix::Link::ConstructJob(Compilation &C, const JobAction &JA,
Args.MakeArgString(getToolChain().GetFilePath("crtend.o")));
}
- const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("ld"));
+ const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath());
C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}
@@ -6727,20 +7588,15 @@ void dragonfly::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
if (getToolChain().getArch() == llvm::Triple::x86)
CmdArgs.push_back("--32");
- Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,
- options::OPT_Xassembler);
+ Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename());
- for (InputInfoList::const_iterator
- it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
- const InputInfo &II = *it;
+ for (const auto &II : Inputs)
CmdArgs.push_back(II.getFilename());
- }
- const char *Exec =
- Args.MakeArgString(getToolChain().GetProgramPath("as"));
+ const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as"));
C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}
@@ -6888,13 +7744,21 @@ void dragonfly::Link::ConstructJob(Compilation &C, const JobAction &JA,
getToolChain().GetFilePath("crtn.o")));
}
- addProfileRT(getToolChain(), Args, CmdArgs, getToolChain().getTriple());
+ addProfileRT(getToolChain(), Args, CmdArgs);
- const char *Exec =
- Args.MakeArgString(getToolChain().GetProgramPath("ld"));
+ const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath());
C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}
+static void addSanitizerRTWindows(const ToolChain &TC, const ArgList &Args,
+ ArgStringList &CmdArgs,
+ const StringRef RTName) {
+ SmallString<128> LibSanitizer(getCompilerRTLibDir(TC));
+ llvm::sys::path::append(LibSanitizer,
+ Twine("clang_rt.") + RTName + ".lib");
+ CmdArgs.push_back(Args.MakeArgString(LibSanitizer));
+}
+
void visualstudio::Link::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
@@ -6917,6 +7781,10 @@ void visualstudio::Link::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-nologo");
+ if (Args.hasArg(options::OPT_g_Group)) {
+ CmdArgs.push_back("-debug");
+ }
+
bool DLL = Args.hasArg(options::OPT__SLASH_LD, options::OPT__SLASH_LDd);
if (DLL) {
@@ -6931,28 +7799,25 @@ void visualstudio::Link::ConstructJob(Compilation &C, const JobAction &JA,
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");
+ // FIXME: Handle 64-bit.
if (DLL) {
- llvm::sys::path::append(LibSanitizer, "clang_rt.asan_dll_thunk-i386.lib");
+ addSanitizerRTWindows(getToolChain(), Args, CmdArgs,
+ "asan_dll_thunk-i386");
} else {
- llvm::sys::path::append(LibSanitizer, "clang_rt.asan-i386.lib");
+ addSanitizerRTWindows(getToolChain(), Args, CmdArgs, "asan-i386");
+ addSanitizerRTWindows(getToolChain(), Args, CmdArgs, "asan_cxx-i386");
}
- // 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());
+ for (const auto &Input : Inputs)
+ if (Input.isFilename())
+ CmdArgs.push_back(Input.getFilename());
else
- it->getInputArg().renderAsInput(Args, CmdArgs);
- }
+ Input.getInputArg().renderAsInput(Args, CmdArgs);
const char *Exec =
Args.MakeArgString(getToolChain().GetProgramPath("link.exe"));
@@ -6977,14 +7842,9 @@ static std::string FindFallback(const char *FallbackName,
if (!OptPath.hasValue())
return FallbackName;
-#ifdef LLVM_ON_WIN32
- const StringRef PathSeparators = ";";
-#else
- const StringRef PathSeparators = ":";
-#endif
-
+ const char EnvPathSeparatorStr[] = {llvm::sys::EnvPathSeparator, '\0'};
SmallVector<StringRef, 8> PathSegments;
- llvm::SplitString(OptPath.getValue(), PathSegments, PathSeparators);
+ llvm::SplitString(OptPath.getValue(), PathSegments, EnvPathSeparatorStr);
for (size_t i = 0, e = PathSegments.size(); i != e; ++i) {
const StringRef &PathSegment = PathSegments[i];
@@ -7034,19 +7894,31 @@ Command *visualstudio::Compile::GetCommand(Compilation &C, const JobAction &JA,
// 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.hasFlag(options::OPT__SLASH_GR_, options::OPT__SLASH_GR,
+ /*default=*/false))
+ CmdArgs.push_back("/GR-");
+ if (Arg *A = Args.getLastArg(options::OPT_ffunction_sections,
+ options::OPT_fno_function_sections))
+ CmdArgs.push_back(A->getOption().getID() == options::OPT_ffunction_sections
+ ? "/Gy"
+ : "/Gy-");
+ if (Arg *A = Args.getLastArg(options::OPT_fdata_sections,
+ options::OPT_fno_data_sections))
+ CmdArgs.push_back(
+ A->getOption().getID() == options::OPT_fdata_sections ? "/Gw" : "/Gw-");
if (Args.hasArg(options::OPT_fsyntax_only))
CmdArgs.push_back("/Zs");
+ if (Args.hasArg(options::OPT_g_Flag, options::OPT_gline_tables_only))
+ CmdArgs.push_back("/Z7");
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]));
+ for (const auto &Include : Includes)
+ CmdArgs.push_back(Args.MakeArgString(std::string("/FI") + Include));
// Flags that can simply be passed through.
Args.AddAllArgs(CmdArgs, options::OPT__SLASH_LD);
Args.AddAllArgs(CmdArgs, options::OPT__SLASH_LDd);
+ Args.AddAllArgs(CmdArgs, options::OPT__SLASH_EH);
// 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,
@@ -7072,7 +7944,6 @@ Command *visualstudio::Compile::GetCommand(Compilation &C, const JobAction &JA,
const Driver &D = getToolChain().getDriver();
std::string Exec = FindFallback("cl.exe", D.getClangProgramPath());
-
return new Command(JA, *this, Args.MakeArgString(Exec), CmdArgs);
}
@@ -7092,21 +7963,24 @@ void XCore::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-c");
- if (Args.hasArg(options::OPT_g_Group)) {
- CmdArgs.push_back("-g");
- }
+ if (Args.hasArg(options::OPT_v))
+ CmdArgs.push_back("-v");
+
+ if (Arg *A = Args.getLastArg(options::OPT_g_Group))
+ if (!A->getOption().matches(options::OPT_g0))
+ CmdArgs.push_back("-g");
+
+ if (Args.hasFlag(options::OPT_fverbose_asm, options::OPT_fno_verbose_asm,
+ false))
+ CmdArgs.push_back("-fverbose-asm");
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;
+ for (const auto &II : Inputs)
CmdArgs.push_back(II.getFilename());
- }
- const char *Exec =
- Args.MakeArgString(getToolChain().GetProgramPath("xcc"));
+ const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("xcc"));
C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}
@@ -7124,9 +7998,15 @@ void XCore::Link::ConstructJob(Compilation &C, const JobAction &JA,
assert(Output.isNothing() && "Invalid output.");
}
+ if (Args.hasArg(options::OPT_v))
+ CmdArgs.push_back("-v");
+
+ ExceptionSettings EH = exceptionSettings(Args, getToolChain().getTriple());
+ if (EH.ShouldUseExceptionTables)
+ CmdArgs.push_back("-fexceptions");
+
AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);
- const char *Exec =
- Args.MakeArgString(getToolChain().GetProgramPath("xcc"));
+ const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("xcc"));
C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}