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.cpp629
1 files changed, 430 insertions, 199 deletions
diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp
index ef759ff6d3..aba1fe4d2d 100644
--- a/lib/Driver/Tools.cpp
+++ b/lib/Driver/Tools.cpp
@@ -7,6 +7,7 @@
//
//===----------------------------------------------------------------------===//
+#include <sys/stat.h>
#include "Tools.h"
#include "InputInfo.h"
#include "SanitizerArgs.h"
@@ -544,6 +545,9 @@ static bool isSignedCharDefault(const llvm::Triple &Triple) {
if (Triple.isOSDarwin())
return true;
return false;
+
+ case llvm::Triple::systemz:
+ return false;
}
}
@@ -815,7 +819,9 @@ void Clang::AddARMTargetArgs(const ArgList &Args,
CmdArgs.push_back("-mno-global-merge");
}
- if (Args.hasArg(options::OPT_mno_implicit_float))
+ if (!Args.hasFlag(options::OPT_mimplicit_float,
+ options::OPT_mno_implicit_float,
+ true))
CmdArgs.push_back("-no-implicit-float");
}
@@ -851,8 +857,15 @@ static void getMipsCPUAndABI(const ArgList &Args,
CPUName = A->getValue();
}
- if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ))
+ if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) {
ABIName = A->getValue();
+ // Convert a GNU style Mips ABI name to the name
+ // accepted by LLVM Mips backend.
+ ABIName = llvm::StringSwitch<llvm::StringRef>(ABIName)
+ .Case("32", "o32")
+ .Case("64", "n64")
+ .Default(ABIName);
+ }
// Setup default CPU and ABI names.
if (CPUName.empty() && ABIName.empty()) {
@@ -899,8 +912,6 @@ static StringRef getGnuCompatibleMipsABIName(StringRef ABI) {
// Select the MIPS float ABI as determined by -msoft-float, -mhard-float,
// and -mfloat-abi=.
static StringRef getMipsFloatABI(const Driver &D, const ArgList &Args) {
- // Select the float ABI as determined by -msoft-float, -mhard-float,
- // and -mfloat-abi=.
StringRef FloatABI;
if (Arg *A = Args.getLastArg(options::OPT_msoft_float,
options::OPT_mhard_float,
@@ -911,7 +922,7 @@ static StringRef getMipsFloatABI(const Driver &D, const ArgList &Args) {
FloatABI = "hard";
else {
FloatABI = A->getValue();
- if (FloatABI != "soft" && FloatABI != "single" && FloatABI != "hard") {
+ if (FloatABI != "soft" && FloatABI != "hard") {
D.Diag(diag::err_drv_invalid_mfloat_abi) << A->getAsString(Args);
FloatABI = "hard";
}
@@ -944,7 +955,7 @@ static void AddTargetFeature(const ArgList &Args,
}
void Clang::AddMIPSTargetArgs(const ArgList &Args,
- ArgStringList &CmdArgs) const {
+ ArgStringList &CmdArgs) const {
const Driver &D = getToolChain().getDriver();
StringRef CPUName;
StringRef ABIName;
@@ -977,12 +988,6 @@ void Clang::AddMIPSTargetArgs(const ArgList &Args,
CmdArgs.push_back("-mips16-hard-float");
}
}
- else if (FloatABI == "single") {
- // Restrict the use of hardware floating-point
- // instructions to 32-bit operations.
- CmdArgs.push_back("-target-feature");
- CmdArgs.push_back("+single-float");
- }
else {
// Floating point operations and argument passing are hard.
assert(FloatABI == "hard" && "Invalid float abi!");
@@ -991,9 +996,15 @@ void Clang::AddMIPSTargetArgs(const ArgList &Args,
}
AddTargetFeature(Args, CmdArgs,
+ options::OPT_msingle_float, options::OPT_mdouble_float,
+ "single-float");
+ AddTargetFeature(Args, CmdArgs,
options::OPT_mips16, options::OPT_mno_mips16,
"mips16");
AddTargetFeature(Args, CmdArgs,
+ options::OPT_mmicromips, options::OPT_mno_micromips,
+ "micromips");
+ AddTargetFeature(Args, CmdArgs,
options::OPT_mdsp, options::OPT_mno_dsp,
"dsp");
AddTargetFeature(Args, CmdArgs,
@@ -1097,17 +1108,55 @@ void Clang::AddPPCTargetArgs(const ArgList &Args,
}
// Allow override of the Altivec feature.
- if (Args.hasFlag(options::OPT_fno_altivec, options::OPT_faltivec, false)) {
- CmdArgs.push_back("-target-feature");
- CmdArgs.push_back("-altivec");
- }
+ AddTargetFeature(Args, CmdArgs,
+ options::OPT_faltivec, options::OPT_fno_altivec,
+ "altivec");
+
+ AddTargetFeature(Args, CmdArgs,
+ options::OPT_mfprnd, options::OPT_mno_fprnd,
+ "fprnd");
+
+ // Note that gcc calls this mfcrf and LLVM calls this mfocrf.
+ AddTargetFeature(Args, CmdArgs,
+ options::OPT_mmfcrf, options::OPT_mno_mfcrf,
+ "mfocrf");
+
+ AddTargetFeature(Args, CmdArgs,
+ options::OPT_mpopcntd, options::OPT_mno_popcntd,
+ "popcntd");
+ // It is really only possible to turn qpx off because turning qpx on is tied
+ // to using the a2q CPU.
if (Args.hasFlag(options::OPT_mno_qpx, options::OPT_mqpx, false)) {
CmdArgs.push_back("-target-feature");
CmdArgs.push_back("-qpx");
}
}
+/// Get the (LLVM) name of the R600 gpu we are targeting.
+static std::string getR600TargetGPU(const ArgList &Args) {
+ if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) {
+ std::string GPUName = A->getValue();
+ return llvm::StringSwitch<const char *>(GPUName)
+ .Cases("rv630", "rv635", "r600")
+ .Cases("rv610", "rv620", "rs780", "rs880")
+ .Case("rv740", "rv770")
+ .Case("palm", "cedar")
+ .Cases("sumo", "sumo2", "sumo")
+ .Case("hemlock", "cypress")
+ .Case("aruba", "cayman")
+ .Default(GPUName.c_str());
+ }
+ return "";
+}
+
+void Clang::AddR600TargetArgs(const ArgList &Args,
+ ArgStringList &CmdArgs) const {
+ std::string TargetGPUName = getR600TargetGPU(Args);
+ CmdArgs.push_back("-target-cpu");
+ CmdArgs.push_back(Args.MakeArgString(TargetGPUName.c_str()));
+}
+
void Clang::AddSparcTargetArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
const Driver &D = getToolChain().getDriver();
@@ -1217,6 +1266,7 @@ void Clang::AddX86TargetArgs(const ArgList &Args,
Args.hasArg(options::OPT_fapple_kext));
if (Arg *A = Args.getLastArg(options::OPT_msoft_float,
options::OPT_mno_soft_float,
+ options::OPT_mimplicit_float,
options::OPT_mno_implicit_float)) {
const Option &O = A->getOption();
NoImplicitFloat = (O.matches(options::OPT_mno_implicit_float) ||
@@ -1414,36 +1464,36 @@ static void addExceptionArgs(const ArgList &Args, types::ID InputType,
CmdArgs.push_back("-fexceptions");
}
+static bool ShouldDisableAutolink(const ArgList &Args,
+ const ToolChain &TC) {
+ bool Default = true;
+ if (TC.getTriple().isOSDarwin()) {
+ // The native darwin assembler doesn't support the linker_option directives,
+ // so we disable them if we think the .s file will be passed to it.
+ Default = TC.useIntegratedAs();
+ }
+ return !Args.hasFlag(options::OPT_fautolink, options::OPT_fno_autolink,
+ 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 = Args.hasFlag(options::OPT_integrated_as,
- options::OPT_no_integrated_as,
- TC.IsIntegratedAssemblerDefault());
+ Default = TC.useIntegratedAs();
}
return !Args.hasFlag(options::OPT_fdwarf2_cfi_asm,
options::OPT_fno_dwarf2_cfi_asm,
Default);
}
-static bool ShouldUseIntegratedAssembler(const ArgList &Args,
- const ToolChain &TC) {
- bool IsIADefault = TC.IsIntegratedAssemblerDefault();
- bool UseIntegratedAs = Args.hasFlag(options::OPT_integrated_as,
- options::OPT_no_integrated_as,
- IsIADefault);
- return UseIntegratedAs;
-}
-
static bool ShouldDisableDwarfDirectory(const ArgList &Args,
const ToolChain &TC) {
- bool UseIntegratedAs = ShouldUseIntegratedAssembler(Args, TC);
bool UseDwarfDirectory = Args.hasFlag(options::OPT_fdwarf_directory_asm,
options::OPT_fno_dwarf_directory_asm,
- UseIntegratedAs);
+ TC.useIntegratedAs());
return !UseDwarfDirectory;
}
@@ -1482,11 +1532,12 @@ static bool UseRelaxAll(Compilation &C, const ArgList &Args) {
RelaxDefault);
}
-SanitizerArgs::SanitizerArgs(const Driver &D, const ArgList &Args)
+SanitizerArgs::SanitizerArgs(const ToolChain &TC, const ArgList &Args)
: Kind(0), BlacklistFile(""), MsanTrackOrigins(false),
AsanZeroBaseShadow(false) {
unsigned AllKinds = 0; // All kinds of sanitizers that were turned on
// at least once (possibly, disabled further).
+ const Driver &D = TC.getDriver();
for (ArgList::const_iterator I = Args.begin(), E = Args.end(); I != E; ++I) {
unsigned Add, Remove;
if (!parse(D, Args, *I, Add, Remove, true))
@@ -1578,40 +1629,61 @@ SanitizerArgs::SanitizerArgs(const Driver &D, const ArgList &Args)
/* Default */false);
// Parse -f(no-)sanitize-address-zero-base-shadow options.
- if (NeedsAsan)
+ if (NeedsAsan) {
+ bool IsAndroid = (TC.getTriple().getEnvironment() == llvm::Triple::Android);
+ bool ZeroBaseShadowDefault = IsAndroid;
AsanZeroBaseShadow =
- Args.hasFlag(options::OPT_fsanitize_address_zero_base_shadow,
- options::OPT_fno_sanitize_address_zero_base_shadow,
- /* Default */false);
+ Args.hasFlag(options::OPT_fsanitize_address_zero_base_shadow,
+ options::OPT_fno_sanitize_address_zero_base_shadow,
+ ZeroBaseShadowDefault);
+ // Zero-base shadow is a requirement on Android.
+ if (IsAndroid && !AsanZeroBaseShadow) {
+ D.Diag(diag::err_drv_argument_not_allowed_with)
+ << "-fno-sanitize-address-zero-base-shadow"
+ << lastArgumentForKind(D, Args, Address);
+ }
+ }
}
static void addSanitizerRTLinkFlagsLinux(
const ToolChain &TC, const ArgList &Args, ArgStringList &CmdArgs,
- const StringRef Sanitizer, bool BeforeLibStdCXX) {
+ 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"));
+
// Sanitizer runtime may need to come before -lstdc++ (or -lc++, libstdc++.a,
// etc.) so that the linker picks custom versions of the global 'operator
// new' and 'operator delete' symbols. We take the extreme (but simple)
// strategy of inserting it at the front of the link command. It also
// needs to be forced to end up in the executable, so wrap it in
// whole-archive.
- if (BeforeLibStdCXX) {
- SmallVector<const char *, 3> PrefixArgs;
- PrefixArgs.push_back("-whole-archive");
- PrefixArgs.push_back(Args.MakeArgString(LibSanitizer));
- PrefixArgs.push_back("-no-whole-archive");
- CmdArgs.insert(CmdArgs.begin(), PrefixArgs.begin(), PrefixArgs.end());
- } else {
- CmdArgs.push_back(Args.MakeArgString(LibSanitizer));
- }
+ SmallVector<const char *, 3> LibSanitizerArgs;
+ LibSanitizerArgs.push_back("-whole-archive");
+ LibSanitizerArgs.push_back(Args.MakeArgString(LibSanitizer));
+ LibSanitizerArgs.push_back("-no-whole-archive");
+
+ 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("-export-dynamic");
+
+ // 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
+ // all symbols from the binary.
+ if (ExportSymbols) {
+ if (llvm::sys::fs::exists(LibSanitizer + ".syms"))
+ CmdArgs.push_back(
+ Args.MakeArgString("--dynamic-list=" + LibSanitizer + ".syms"));
+ else
+ CmdArgs.push_back("-export-dynamic");
+ }
}
/// If AddressSanitizer is enabled, add appropriate linker flags (Linux).
@@ -1619,11 +1691,6 @@ static void addSanitizerRTLinkFlagsLinux(
static void addAsanRTLinux(const ToolChain &TC, const ArgList &Args,
ArgStringList &CmdArgs) {
if(TC.getTriple().getEnvironment() == llvm::Triple::Android) {
- if (!Args.hasArg(options::OPT_shared)) {
- if (!Args.hasArg(options::OPT_pie))
- TC.getDriver().Diag(diag::err_drv_asan_android_requires_pie);
- }
-
SmallString<128> LibAsan(TC.getDriver().ResourceDir);
llvm::sys::path::append(LibAsan, "lib", "linux",
(Twine("libclang_rt.asan-") +
@@ -1631,13 +1698,6 @@ static void addAsanRTLinux(const ToolChain &TC, const ArgList &Args,
CmdArgs.insert(CmdArgs.begin(), Args.MakeArgString(LibAsan));
} else {
if (!Args.hasArg(options::OPT_shared)) {
- bool ZeroBaseShadow = Args.hasFlag(
- options::OPT_fsanitize_address_zero_base_shadow,
- options::OPT_fno_sanitize_address_zero_base_shadow, false);
- if (ZeroBaseShadow && !Args.hasArg(options::OPT_pie)) {
- TC.getDriver().Diag(diag::err_drv_argument_only_allowed_with) <<
- "-fsanitize-address-zero-base-shadow" << "-pie";
- }
addSanitizerRTLinkFlagsLinux(TC, Args, CmdArgs, "asan", true);
}
}
@@ -1648,9 +1708,6 @@ static void addAsanRTLinux(const ToolChain &TC, const ArgList &Args,
static void addTsanRTLinux(const ToolChain &TC, const ArgList &Args,
ArgStringList &CmdArgs) {
if (!Args.hasArg(options::OPT_shared)) {
- if (!Args.hasArg(options::OPT_pie))
- TC.getDriver().Diag(diag::err_drv_argument_only_allowed_with) <<
- "-fsanitize=thread" << "-pie";
addSanitizerRTLinkFlagsLinux(TC, Args, CmdArgs, "tsan", true);
}
}
@@ -1660,9 +1717,6 @@ static void addTsanRTLinux(const ToolChain &TC, const ArgList &Args,
static void addMsanRTLinux(const ToolChain &TC, const ArgList &Args,
ArgStringList &CmdArgs) {
if (!Args.hasArg(options::OPT_shared)) {
- if (!Args.hasArg(options::OPT_pie))
- TC.getDriver().Diag(diag::err_drv_argument_only_allowed_with) <<
- "-fsanitize=memory" << "-pie";
addSanitizerRTLinkFlagsLinux(TC, Args, CmdArgs, "msan", true);
}
}
@@ -1670,8 +1724,22 @@ static void addMsanRTLinux(const ToolChain &TC, const ArgList &Args,
/// If UndefinedBehaviorSanitizer is enabled, add appropriate linker flags
/// (Linux).
static void addUbsanRTLinux(const ToolChain &TC, const ArgList &Args,
- ArgStringList &CmdArgs) {
+ ArgStringList &CmdArgs, bool IsCXX,
+ bool HasOtherSanitizerRt) {
+ if (Args.hasArg(options::OPT_shared))
+ return;
+
+ // Need a copy of sanitizer_common. This could come from another sanitizer
+ // runtime; if we're not including one, include our own copy.
+ if (!HasOtherSanitizerRt)
+ addSanitizerRTLinkFlagsLinux(TC, Args, CmdArgs, "san", true, false);
+
addSanitizerRTLinkFlagsLinux(TC, Args, CmdArgs, "ubsan", false);
+
+ // 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);
}
static bool shouldUseFramePointer(const ArgList &Args,
@@ -1692,17 +1760,48 @@ static bool shouldUseFramePointer(const ArgList &Args,
return true;
}
+static bool shouldUseLeafFramePointer(const ArgList &Args,
+ const llvm::Triple &Triple) {
+ if (Arg *A = Args.getLastArg(options::OPT_mno_omit_leaf_frame_pointer,
+ options::OPT_momit_leaf_frame_pointer))
+ return A->getOption().matches(options::OPT_mno_omit_leaf_frame_pointer);
+
+ // Don't use a leaf frame pointer on linux x86 and x86_64 if optimizing.
+ if ((Triple.getArch() == llvm::Triple::x86_64 ||
+ Triple.getArch() == llvm::Triple::x86) &&
+ Triple.getOS() == llvm::Triple::Linux) {
+ if (Arg *A = Args.getLastArg(options::OPT_O_Group))
+ if (!A->getOption().matches(options::OPT_O0))
+ return false;
+ }
+
+ return true;
+}
+
/// If the PWD environment variable is set, add a CC1 option to specify the
/// debug compilation directory.
static void addDebugCompDirArg(const ArgList &Args, ArgStringList &CmdArgs) {
- if (const char *pwd = ::getenv("PWD")) {
- // GCC also verifies that stat(pwd) and stat(".") have the same inode
- // number. Not doing those because stats are slow, but we could.
- if (llvm::sys::path::is_absolute(pwd)) {
- std::string CompDir = pwd;
- CmdArgs.push_back("-fdebug-compilation-dir");
- CmdArgs.push_back(Args.MakeArgString(CompDir));
- }
+ struct stat StatPWDBuf, StatDotBuf;
+
+ const char *pwd = ::getenv("PWD");
+ if (!pwd)
+ return;
+
+ if (llvm::sys::path::is_absolute(pwd) &&
+ stat(pwd, &StatPWDBuf) == 0 &&
+ stat(".", &StatDotBuf) == 0 &&
+ StatPWDBuf.st_ino == StatDotBuf.st_ino &&
+ StatPWDBuf.st_dev == StatDotBuf.st_dev) {
+ CmdArgs.push_back("-fdebug-compilation-dir");
+ CmdArgs.push_back(Args.MakeArgString(pwd));
+ return;
+ }
+
+ // Fall back to using getcwd.
+ SmallString<128> cwd;
+ if (!llvm::sys::fs::current_path(cwd)) {
+ CmdArgs.push_back("-fdebug-compilation-dir");
+ CmdArgs.push_back(Args.MakeArgString(cwd));
}
}
@@ -1748,6 +1847,13 @@ static void SplitDebugInfo(const ToolChain &TC, Compilation &C,
C.addCommand(new Command(JA, T, Exec, StripArgs));
}
+static bool isOptimizationLevelFast(const ArgList &Args) {
+ if (Arg *A = Args.getLastArg(options::OPT_O_Group))
+ if (A->getOption().matches(options::OPT_Ofast))
+ return true;
+ return false;
+}
+
void Clang::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
@@ -1781,8 +1887,12 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
} else if (isa<PreprocessJobAction>(JA)) {
if (Output.getType() == types::TY_Dependencies)
CmdArgs.push_back("-Eonly");
- else
+ else {
CmdArgs.push_back("-E");
+ if (Args.hasArg(options::OPT_rewrite_objc) &&
+ !Args.hasArg(options::OPT_g_Group))
+ CmdArgs.push_back("-P");
+ }
} else if (isa<AssembleJobAction>(JA)) {
CmdArgs.push_back("-emit-obj");
@@ -1843,6 +1953,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-S");
} else if (JA.getType() == types::TY_AST) {
CmdArgs.push_back("-emit-pch");
+ } else if (JA.getType() == types::TY_ModuleFile) {
+ CmdArgs.push_back("-module-file-info");
} else if (JA.getType() == types::TY_RewrittenObjC) {
CmdArgs.push_back("-rewrite-objc");
rewriteKind = RK_NonFragile;
@@ -1894,6 +2006,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-analyzer-checker=deadcode");
+ 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");
CmdArgs.push_back("-analyzer-checker=security.insecureAPI.getpw");
@@ -1922,37 +2037,38 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CheckCodeGenerationOptions(D, Args);
- // 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 consistent with GCC's new
- // logic now that the bugs are fixed. The last argument relating to either
- // PIC or PIE wins, and no other argument is used. If the last argument is
- // any flavor of the '-fno-...' arguments, both PIC and PIE are disabled. Any
- // PIE option implicitly enables PIC at the same level.
- bool PIE = false;
- bool PIC = getToolChain().isPICDefault();
+ bool PIE = getToolChain().isPIEDefault();
+ bool PIC = PIE || getToolChain().isPICDefault();
bool IsPICLevelTwo = PIC;
- 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)) {
- Option O = A->getOption();
- if (O.matches(options::OPT_fPIC) || O.matches(options::OPT_fpic) ||
- O.matches(options::OPT_fPIE) || O.matches(options::OPT_fpie)) {
- PIE = O.matches(options::OPT_fPIE) || O.matches(options::OPT_fpie);
- PIC = PIE || O.matches(options::OPT_fPIC) || O.matches(options::OPT_fpic);
- IsPICLevelTwo = O.matches(options::OPT_fPIE) ||
- O.matches(options::OPT_fPIC);
- } else {
- PIE = PIC = false;
- }
- }
+
+ // 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
+ // consistent with GCC's new logic now that the bugs are fixed. The last
+ // argument relating to either PIC or PIE wins, and no other argument is
+ // used. If the last argument is any flavor of the '-fno-...' arguments,
+ // both PIC and PIE are disabled. Any PIE option implicitly enables PIC
+ // at the same level.
+ 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);
// Check whether the tool chain trumps the PIC-ness decision. If the PIC-ness
// is forced, then neither PIC nor PIE flags will have no effect.
- if (getToolChain().isPICDefaultForced()) {
- PIE = false;
- PIC = getToolChain().isPICDefault();
- IsPICLevelTwo = PIC;
+ if (!getToolChain().isPICDefaultForced()) {
+ if (LastPICArg) {
+ Option O = LastPICArg->getOption();
+ if (O.matches(options::OPT_fPIC) || O.matches(options::OPT_fpic) ||
+ O.matches(options::OPT_fPIE) || O.matches(options::OPT_fpie)) {
+ PIE = O.matches(options::OPT_fPIE) || O.matches(options::OPT_fpie);
+ PIC = PIE || O.matches(options::OPT_fPIC) ||
+ O.matches(options::OPT_fpic);
+ IsPICLevelTwo = O.matches(options::OPT_fPIE) ||
+ O.matches(options::OPT_fPIC);
+ } else {
+ PIE = PIC = false;
+ }
+ }
}
// Inroduce a Darwin-specific hack. If the default is PIC but the flags
@@ -2026,10 +2142,18 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (!Args.hasFlag(options::OPT_fzero_initialized_in_bss,
options::OPT_fno_zero_initialized_in_bss))
CmdArgs.push_back("-mno-zero-initialized-in-bss");
- if (!Args.hasFlag(options::OPT_fstrict_aliasing,
+
+ bool OFastEnabled = isOptimizationLevelFast(Args);
+ // If -Ofast is the optimization level, then -fstrict-aliasing should be
+ // enabled. This alias option is being used to simplify the hasFlag logic.
+ OptSpecifier StrictAliasingAliasOption = OFastEnabled ? options::OPT_Ofast :
+ options::OPT_fstrict_aliasing;
+ if (!Args.hasFlag(options::OPT_fstrict_aliasing, StrictAliasingAliasOption,
options::OPT_fno_strict_aliasing,
getToolChain().IsStrictAliasingDefault()))
CmdArgs.push_back("-relaxed-aliasing");
+ if (Args.hasArg(options::OPT_fstruct_path_tbaa))
+ CmdArgs.push_back("-struct-path-tbaa");
if (Args.hasFlag(options::OPT_fstrict_enums, options::OPT_fno_strict_enums,
false))
CmdArgs.push_back("-fstrict-enums");
@@ -2037,12 +2161,21 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
options::OPT_fno_optimize_sibling_calls))
CmdArgs.push_back("-mdisable-tail-calls");
+ // Handle segmented stacks.
+ if (Args.hasArg(options::OPT_fsplit_stack))
+ CmdArgs.push_back("-split-stacks");
+
+ // If -Ofast is the optimization level, then -ffast-math should be enabled.
+ // This alias option is being used to simplify the getLastArg logic.
+ OptSpecifier FastMathAliasOption = OFastEnabled ? options::OPT_Ofast :
+ options::OPT_ffast_math;
+
// Handle various floating point optimization flags, mapping them to the
// appropriate LLVM code generation flags. The pattern for all of these is to
// default off the codegen optimizations, and if any flag enables them and no
// flag disables them after the flag enabling them, enable the codegen
// optimization. This is complicated by several "umbrella" flags.
- if (Arg *A = Args.getLastArg(options::OPT_ffast_math,
+ if (Arg *A = Args.getLastArg(options::OPT_ffast_math, FastMathAliasOption,
options::OPT_fno_fast_math,
options::OPT_ffinite_math_only,
options::OPT_fno_finite_math_only,
@@ -2052,7 +2185,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
A->getOption().getID() != options::OPT_fno_finite_math_only &&
A->getOption().getID() != options::OPT_fhonor_infinities)
CmdArgs.push_back("-menable-no-infs");
- if (Arg *A = Args.getLastArg(options::OPT_ffast_math,
+ if (Arg *A = Args.getLastArg(options::OPT_ffast_math, FastMathAliasOption,
options::OPT_fno_fast_math,
options::OPT_ffinite_math_only,
options::OPT_fno_finite_math_only,
@@ -2065,7 +2198,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// -fmath-errno is the default on some platforms, e.g. BSD-derived OSes.
bool MathErrno = getToolChain().IsMathErrnoDefault();
- if (Arg *A = Args.getLastArg(options::OPT_ffast_math,
+ if (Arg *A = Args.getLastArg(options::OPT_ffast_math, FastMathAliasOption,
options::OPT_fno_fast_math,
options::OPT_fmath_errno,
options::OPT_fno_math_errno))
@@ -2078,7 +2211,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// entire set of LLVM optimizations, so collect them through all the flag
// madness.
bool AssociativeMath = false;
- if (Arg *A = Args.getLastArg(options::OPT_ffast_math,
+ if (Arg *A = Args.getLastArg(options::OPT_ffast_math, FastMathAliasOption,
options::OPT_fno_fast_math,
options::OPT_funsafe_math_optimizations,
options::OPT_fno_unsafe_math_optimizations,
@@ -2089,7 +2222,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
A->getOption().getID() != options::OPT_fno_associative_math)
AssociativeMath = true;
bool ReciprocalMath = false;
- if (Arg *A = Args.getLastArg(options::OPT_ffast_math,
+ if (Arg *A = Args.getLastArg(options::OPT_ffast_math, FastMathAliasOption,
options::OPT_fno_fast_math,
options::OPT_funsafe_math_optimizations,
options::OPT_fno_unsafe_math_optimizations,
@@ -2100,7 +2233,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
A->getOption().getID() != options::OPT_fno_reciprocal_math)
ReciprocalMath = true;
bool SignedZeros = true;
- if (Arg *A = Args.getLastArg(options::OPT_ffast_math,
+ if (Arg *A = Args.getLastArg(options::OPT_ffast_math, FastMathAliasOption,
options::OPT_fno_fast_math,
options::OPT_funsafe_math_optimizations,
options::OPT_fno_unsafe_math_optimizations,
@@ -2111,7 +2244,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
A->getOption().getID() != options::OPT_fsigned_zeros)
SignedZeros = false;
bool TrappingMath = true;
- if (Arg *A = Args.getLastArg(options::OPT_ffast_math,
+ if (Arg *A = Args.getLastArg(options::OPT_ffast_math, FastMathAliasOption,
options::OPT_fno_fast_math,
options::OPT_funsafe_math_optimizations,
options::OPT_fno_unsafe_math_optimizations,
@@ -2127,7 +2260,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// Validate and pass through -fp-contract option.
- if (Arg *A = Args.getLastArg(options::OPT_ffast_math,
+ if (Arg *A = Args.getLastArg(options::OPT_ffast_math, FastMathAliasOption,
options::OPT_fno_fast_math,
options::OPT_ffp_contract)) {
if (A->getOption().getID() == options::OPT_ffp_contract) {
@@ -2138,7 +2271,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
D.Diag(diag::err_drv_unsupported_option_argument)
<< A->getOption().getName() << Val;
}
- } else if (A->getOption().getID() == options::OPT_ffast_math) {
+ } else if (A->getOption().matches(options::OPT_ffast_math) ||
+ (OFastEnabled && A->getOption().matches(options::OPT_Ofast))) {
// If fast-math is set then set the fp-contract mode to fast.
CmdArgs.push_back(Args.MakeArgString("-ffp-contract=fast"));
}
@@ -2149,9 +2283,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// preprocessor macros. This is distinct from enabling any optimizations as
// these options induce language changes which must survive serialization
// and deserialization, etc.
- if (Arg *A = Args.getLastArg(options::OPT_ffast_math, options::OPT_fno_fast_math))
- if (A->getOption().matches(options::OPT_ffast_math))
- CmdArgs.push_back("-ffast-math");
+ if (Arg *A = Args.getLastArg(options::OPT_ffast_math, FastMathAliasOption,
+ 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 (A->getOption().matches(options::OPT_ffinite_math_only))
CmdArgs.push_back("-ffinite-math-only");
@@ -2236,6 +2371,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
AddPPCTargetArgs(Args, CmdArgs);
break;
+ case llvm::Triple::r600:
+ AddR600TargetArgs(Args, CmdArgs);
+ break;
+
case llvm::Triple::sparc:
AddSparcTargetArgs(Args, CmdArgs);
break;
@@ -2258,10 +2397,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(A->getValue());
}
- // -mno-omit-leaf-frame-pointer is the default on Darwin.
- if (Args.hasFlag(options::OPT_momit_leaf_frame_pointer,
- options::OPT_mno_omit_leaf_frame_pointer,
- !getToolChain().getTriple().isOSDarwin()))
+ if (!shouldUseLeafFramePointer(Args, getToolChain().getTriple()))
CmdArgs.push_back("-momit-leaf-frame-pointer");
// Explicitly error on some things we know we don't support and can't just
@@ -2515,6 +2651,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (ShouldDisableDwarfDirectory(Args, getToolChain()))
CmdArgs.push_back("-fno-dwarf-directory-asm");
+ if (ShouldDisableAutolink(Args, getToolChain()))
+ CmdArgs.push_back("-fno-autolink");
+
// Add in -fdebug-compilation-dir if necessary.
addDebugCompDirArg(Args, CmdArgs);
@@ -2623,7 +2762,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddLastArg(CmdArgs, options::OPT_fdiagnostics_show_template_tree);
Args.AddLastArg(CmdArgs, options::OPT_fno_elide_type);
- SanitizerArgs Sanitize(D, Args);
+ SanitizerArgs Sanitize(getToolChain(), Args);
Sanitize.addArgs(Args, CmdArgs);
if (!Args.hasFlag(options::OPT_fsanitize_recover,
@@ -2784,12 +2923,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-fmodules");
HaveModules = true;
}
-
- if (HaveModules && !ShouldUseIntegratedAssembler(Args, getToolChain())) {
- D.Diag(diag::err_drv_modules_integrated_as);
- D.Diag(diag::note_drv_modules_integrated_as);
- return;
- }
}
// If a module path was provided, pass it along. Otherwise, use a temporary
@@ -2803,7 +2936,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
SmallString<128> DefaultModuleCache;
llvm::sys::path::system_temp_directory(/*erasedOnReboot=*/false,
DefaultModuleCache);
- llvm::sys::path::append(DefaultModuleCache, "clang-module-cache");
+ 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));
@@ -2812,15 +2946,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// Pass through all -fmodules-ignore-macro arguments.
Args.AddAllArgs(CmdArgs, options::OPT_fmodules_ignore_macro);
-
- // -fmodules-autolink (on by default when modules is enabled) automatically
- // links against libraries for imported modules.
- if (HaveModules &&
- Args.hasFlag(options::OPT_fmodules_autolink,
- options::OPT_fno_modules_autolink,
- true)) {
- CmdArgs.push_back("-fmodules-autolink");
- }
+ Args.AddLastArg(CmdArgs, options::OPT_fmodules_prune_interval);
+ Args.AddLastArg(CmdArgs, options::OPT_fmodules_prune_after);
// -faccess-control is default.
if (Args.hasFlag(options::OPT_fno_access_control,
@@ -3118,9 +3245,42 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// Color diagnostics are the default, unless the terminal doesn't support
// them.
- if (Args.hasFlag(options::OPT_fcolor_diagnostics,
- options::OPT_fno_color_diagnostics,
- llvm::sys::Process::StandardErrHasColors()))
+ // 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();
+ if (!O.matches(options::OPT_fcolor_diagnostics) &&
+ !O.matches(options::OPT_fdiagnostics_color) &&
+ !O.matches(options::OPT_fno_color_diagnostics) &&
+ !O.matches(options::OPT_fno_diagnostics_color) &&
+ !O.matches(options::OPT_fdiagnostics_color_EQ))
+ continue;
+
+ (*it)->claim();
+ if (O.matches(options::OPT_fcolor_diagnostics) ||
+ O.matches(options::OPT_fdiagnostics_color)) {
+ ShowColors = Colors_On;
+ } else if (O.matches(options::OPT_fno_color_diagnostics) ||
+ O.matches(options::OPT_fno_diagnostics_color)) {
+ ShowColors = Colors_Off;
+ } else {
+ assert(O.matches(options::OPT_fdiagnostics_color_EQ));
+ StringRef value((*it)->getValue());
+ if (value == "always")
+ ShowColors = Colors_On;
+ else if (value == "never")
+ ShowColors = Colors_Off;
+ else if (value == "auto")
+ ShowColors = Colors_Auto;
+ else
+ getToolChain().getDriver().Diag(diag::err_drv_clang_unsupported)
+ << ("-fdiagnostics-color=" + value).str();
+ }
+ }
+ if (ShowColors == Colors_On ||
+ (ShowColors == Colors_Auto && llvm::sys::Process::StandardErrHasColors()))
CmdArgs.push_back("-fcolor-diagnostics");
if (!Args.hasFlag(options::OPT_fshow_source_location,
@@ -3142,8 +3302,13 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
false))
CmdArgs.push_back("-fasm-blocks");
+ // If -Ofast is the optimization level, then -fvectorize should be enabled.
+ // This alias option is being used to simplify the hasFlag logic.
+ OptSpecifier VectorizeAliasOption = OFastEnabled ? options::OPT_Ofast :
+ options::OPT_fvectorize;
+
// -fvectorize is default.
- if (Args.hasFlag(options::OPT_fvectorize,
+ if (Args.hasFlag(options::OPT_fvectorize, VectorizeAliasOption,
options::OPT_fno_vectorize, true)) {
CmdArgs.push_back("-backend-option");
CmdArgs.push_back("-vectorize-loops");
@@ -3153,7 +3318,14 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (Args.hasFlag(options::OPT_fslp_vectorize,
options::OPT_fno_slp_vectorize, false)) {
CmdArgs.push_back("-backend-option");
- CmdArgs.push_back("-vectorize");
+ CmdArgs.push_back("-vectorize-slp");
+ }
+
+ // -fno-slp-vectorize-aggressive is default.
+ if (Args.hasFlag(options::OPT_fslp_vectorize_aggressive,
+ options::OPT_fno_slp_vectorize_aggressive, false)) {
+ CmdArgs.push_back("-backend-option");
+ CmdArgs.push_back("-vectorize-slp-aggressive");
}
if (Arg *A = Args.getLastArg(options::OPT_fshow_overloads_EQ))
@@ -3218,6 +3390,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// Forward -fcomment-block-commands to -cc1.
Args.AddAllArgs(CmdArgs, options::OPT_fcomment_block_commands);
+ // Forward -fparse-all-comments to -cc1.
+ Args.AddAllArgs(CmdArgs, options::OPT_fparse_all_comments);
// Forward -Xclang arguments to -cc1, and -mllvm arguments to the LLVM option
// parser.
@@ -3593,6 +3767,14 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA,
const char *Exec = getToolChain().getDriver().getClangProgramPath();
C.addCommand(new Command(JA, *this, Exec, CmdArgs));
+
+ // Handle the debug info splitting at object creation time if we're
+ // creating an object.
+ // TODO: Currently only works on linux with newer objcopy.
+ if (Args.hasArg(options::OPT_gsplit_dwarf) &&
+ (getToolChain().getTriple().getOS() == llvm::Triple::Linux))
+ SplitDebugInfo(getToolChain(), C, *this, JA, Args, Output,
+ SplitDebugName(Args, Inputs));
}
void gcc::Common::ConstructJob(Compilation &C, const JobAction &JA,
@@ -3644,7 +3826,7 @@ void gcc::Common::ConstructJob(Compilation &C, const JobAction &JA,
// here.
if (Arch == llvm::Triple::x86 || Arch == llvm::Triple::ppc)
CmdArgs.push_back("-m32");
- else if (Arch == llvm::Triple::x86_64 || Arch == llvm::Triple::x86_64)
+ else if (Arch == llvm::Triple::x86_64 || Arch == llvm::Triple::ppc64)
CmdArgs.push_back("-m64");
if (Output.isFilename()) {
@@ -3678,6 +3860,9 @@ void gcc::Common::ConstructJob(Compilation &C, const Jo