summaryrefslogtreecommitdiffstats
path: root/lib/Driver/Tools.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Driver/Tools.cpp')
-rw-r--r--lib/Driver/Tools.cpp989
1 files changed, 725 insertions, 264 deletions
diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp
index 47b5294..b4234cf 100644
--- a/lib/Driver/Tools.cpp
+++ b/lib/Driver/Tools.cpp
@@ -16,11 +16,11 @@
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Job.h"
-#include "clang/Driver/ObjCRuntime.h"
#include "clang/Driver/Option.h"
#include "clang/Driver/Options.h"
#include "clang/Driver/ToolChain.h"
#include "clang/Driver/Util.h"
+#include "clang/Basic/ObjCRuntime.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringSwitch.h"
@@ -174,8 +174,10 @@ static bool isObjCAutoRefCount(const ArgList &Args) {
/// \brief Determine whether we are linking the ObjC runtime.
static bool isObjCRuntimeLinked(const ArgList &Args) {
- if (isObjCAutoRefCount(Args))
+ if (isObjCAutoRefCount(Args)) {
+ Args.ClaimAllArgs(options::OPT_fobjc_link_runtime);
return true;
+ }
return Args.hasArg(options::OPT_fobjc_link_runtime);
}
@@ -422,16 +424,47 @@ 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)
+ .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-a8", "cortex-a9", "v7")
+ .Case("cortex-m3", "v7m")
+ .Case("cortex-m4", "v7m")
+ .Case("cortex-m0", "v6m")
+ .Default("");
+}
+
/// getARMTargetCPU - Get the (LLVM) name of the ARM cpu we are targeting.
//
// FIXME: tblgen this.
-static const char *getARMTargetCPU(const ArgList &Args,
+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))
- return A->getValue(Args);
+ if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) {
+ StringRef MCPU = A->getValue(Args);
+ // Handle -mcpu=native.
+ if (MCPU == "native")
+ return llvm::sys::getHostCPUName();
+ else
+ return MCPU;
+ }
StringRef MArch;
if (Arg *A = Args.getLastArg(options::OPT_march_EQ)) {
@@ -442,13 +475,25 @@ static const char *getARMTargetCPU(const ArgList &Args,
MArch = Triple.getArchName();
}
+ // 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")
.Cases("armv4", "armv4t", "arm7tdmi")
.Cases("armv5", "armv5t", "arm10tdmi")
- .Cases("armv5e", "armv5te", "arm1026ejs")
+ .Cases("armv5e", "armv5te", "arm1022e")
.Case("armv5tej", "arm926ej-s")
.Cases("armv6", "armv6k", "arm1136jf-s")
.Case("armv6j", "arm1136j-s")
@@ -465,31 +510,6 @@ static const char *getARMTargetCPU(const ArgList &Args,
.Default("arm7tdmi");
}
-/// 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)
- .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-a8", "cortex-a9", "v7")
- .Case("cortex-m3", "v7m")
- .Case("cortex-m4", "v7m")
- .Case("cortex-m0", "v6m")
- .Default("");
-}
-
// FIXME: Move to target hook.
static bool isSignedCharDefault(const llvm::Triple &Triple) {
switch (Triple.getArch()) {
@@ -601,25 +621,21 @@ static StringRef getARMFloatABI(const Driver &D,
// Darwin defaults to "softfp" for v6 and v7.
//
// FIXME: Factor out an ARM class so we can cache the arch somewhere.
- StringRef ArchName =
+ std::string ArchName =
getLLVMArchSuffixForARM(getARMTargetCPU(Args, Triple));
- if (ArchName.startswith("v6") || ArchName.startswith("v7"))
+ if (StringRef(ArchName).startswith("v6") ||
+ StringRef(ArchName).startswith("v7"))
FloatABI = "softfp";
else
FloatABI = "soft";
break;
}
- case llvm::Triple::Linux: {
- if (Triple.getEnvironment() == llvm::Triple::GNUEABI) {
- FloatABI = "softfp";
- break;
- }
- }
- // fall through
-
default:
switch(Triple.getEnvironment()) {
+ case llvm::Triple::GNUEABIHF:
+ FloatABI = "hard";
+ break;
case llvm::Triple::GNUEABI:
FloatABI = "softfp";
break;
@@ -628,9 +644,9 @@ static StringRef getARMFloatABI(const Driver &D,
FloatABI = "softfp";
break;
case llvm::Triple::ANDROIDEABI: {
- StringRef ArchName =
+ std::string ArchName =
getLLVMArchSuffixForARM(getARMTargetCPU(Args, Triple));
- if (ArchName.startswith("v7"))
+ if (StringRef(ArchName).startswith("v7"))
FloatABI = "softfp";
else
FloatABI = "soft";
@@ -666,6 +682,7 @@ void Clang::AddARMTargetArgs(const ArgList &Args,
switch(Triple.getEnvironment()) {
case llvm::Triple::ANDROIDEABI:
case llvm::Triple::GNUEABI:
+ case llvm::Triple::GNUEABIHF:
ABIName = "aapcs-linux";
break;
case llvm::Triple::EABI:
@@ -680,7 +697,7 @@ void Clang::AddARMTargetArgs(const ArgList &Args,
// Set the CPU based on -march= and -mcpu=.
CmdArgs.push_back("-target-cpu");
- CmdArgs.push_back(getARMTargetCPU(Args, Triple));
+ CmdArgs.push_back(Args.MakeArgString(getARMTargetCPU(Args, Triple)));
// Determine floating point ABI from the options & target defaults.
StringRef FloatABI = getARMFloatABI(D, Args, Triple);
@@ -755,6 +772,9 @@ void Clang::AddARMTargetArgs(const ArgList &Args,
if (A->getOption().matches(options::OPT_mno_global_merge))
CmdArgs.push_back("-mno-global-merge");
}
+
+ if (Args.hasArg(options::OPT_mno_implicit_float))
+ CmdArgs.push_back("-no-implicit-float");
}
// Get default architecture.
@@ -825,19 +845,9 @@ static void getMipsCPUAndABI(const ArgList &Args,
ABIName = getMipsABIFromArch(ArchName);
}
-void Clang::AddMIPSTargetArgs(const ArgList &Args,
- ArgStringList &CmdArgs) const {
- const Driver &D = getToolChain().getDriver();
- StringRef CPUName;
- StringRef ABIName;
- getMipsCPUAndABI(Args, getToolChain(), CPUName, ABIName);
-
- CmdArgs.push_back("-target-cpu");
- CmdArgs.push_back(CPUName.data());
-
- CmdArgs.push_back("-target-abi");
- CmdArgs.push_back(ABIName.data());
-
+// 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;
@@ -851,8 +861,7 @@ void Clang::AddMIPSTargetArgs(const ArgList &Args,
else {
FloatABI = A->getValue(Args);
if (FloatABI != "soft" && FloatABI != "single" && FloatABI != "hard") {
- D.Diag(diag::err_drv_invalid_mfloat_abi)
- << A->getAsString(Args);
+ D.Diag(diag::err_drv_invalid_mfloat_abi) << A->getAsString(Args);
FloatABI = "hard";
}
}
@@ -866,6 +875,38 @@ void Clang::AddMIPSTargetArgs(const ArgList &Args,
FloatABI = "hard";
}
+ return FloatABI;
+}
+
+static void AddTargetFeature(const ArgList &Args,
+ ArgStringList &CmdArgs,
+ OptSpecifier OnOpt,
+ OptSpecifier OffOpt,
+ StringRef FeatureName) {
+ if (Arg *A = Args.getLastArg(OnOpt, OffOpt)) {
+ CmdArgs.push_back("-target-feature");
+ if (A->getOption().matches(OnOpt))
+ CmdArgs.push_back(Args.MakeArgString("+" + FeatureName));
+ else
+ CmdArgs.push_back(Args.MakeArgString("-" + FeatureName));
+ }
+}
+
+void Clang::AddMIPSTargetArgs(const ArgList &Args,
+ ArgStringList &CmdArgs) const {
+ const Driver &D = getToolChain().getDriver();
+ StringRef CPUName;
+ StringRef ABIName;
+ getMipsCPUAndABI(Args, getToolChain(), CPUName, ABIName);
+
+ CmdArgs.push_back("-target-cpu");
+ CmdArgs.push_back(CPUName.data());
+
+ CmdArgs.push_back("-target-abi");
+ CmdArgs.push_back(ABIName.data());
+
+ StringRef FloatABI = getMipsFloatABI(D, Args);
+
if (FloatABI == "soft") {
// Floating point operations and argument passing are soft.
CmdArgs.push_back("-msoft-float");
@@ -890,6 +931,82 @@ void Clang::AddMIPSTargetArgs(const ArgList &Args,
CmdArgs.push_back("-mfloat-abi");
CmdArgs.push_back("hard");
}
+
+ AddTargetFeature(Args, CmdArgs,
+ options::OPT_mips16, options::OPT_mno_mips16,
+ "mips16");
+ AddTargetFeature(Args, CmdArgs,
+ options::OPT_mdsp, options::OPT_mno_dsp,
+ "dsp");
+ AddTargetFeature(Args, CmdArgs,
+ options::OPT_mdspr2, options::OPT_mno_dspr2,
+ "dspr2");
+}
+
+/// getPPCTargetCPU - Get the (LLVM) name of the PowerPC cpu we are targeting.
+static std::string getPPCTargetCPU(const ArgList &Args) {
+ if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) {
+ StringRef CPUName = A->getValue(Args);
+
+ if (CPUName == "native") {
+ std::string CPU = llvm::sys::getHostCPUName();
+ if (!CPU.empty() && CPU != "generic")
+ return CPU;
+ else
+ return "";
+ }
+
+ return llvm::StringSwitch<const char *>(CPUName)
+ .Case("common", "generic")
+ .Case("440", "440")
+ .Case("440fp", "440")
+ .Case("450", "450")
+ .Case("601", "601")
+ .Case("602", "602")
+ .Case("603", "603")
+ .Case("603e", "603e")
+ .Case("603ev", "603ev")
+ .Case("604", "604")
+ .Case("604e", "604e")
+ .Case("620", "620")
+ .Case("G3", "g3")
+ .Case("7400", "7400")
+ .Case("G4", "g4")
+ .Case("7450", "7450")
+ .Case("G4+", "g4+")
+ .Case("750", "750")
+ .Case("970", "970")
+ .Case("G5", "g5")
+ .Case("a2", "a2")
+ .Case("power6", "pwr6")
+ .Case("power7", "pwr7")
+ .Case("powerpc", "ppc")
+ .Case("powerpc64", "ppc64")
+ .Default("");
+ }
+
+ return "";
+}
+
+void Clang::AddPPCTargetArgs(const ArgList &Args,
+ ArgStringList &CmdArgs) const {
+ std::string TargetCPUName = getPPCTargetCPU(Args);
+
+ // LLVM may default to generating code for the native CPU,
+ // but, like gcc, we default to a more generic option for
+ // each architecture. (except on Darwin)
+ llvm::Triple Triple = getToolChain().getTriple();
+ if (TargetCPUName.empty() && !Triple.isOSDarwin()) {
+ if (Triple.getArch() == llvm::Triple::ppc64)
+ TargetCPUName = "ppc64";
+ else
+ TargetCPUName = "ppc";
+ }
+
+ if (!TargetCPUName.empty()) {
+ CmdArgs.push_back("-target-cpu");
+ CmdArgs.push_back(Args.MakeArgString(TargetCPUName.c_str()));
+ }
}
void Clang::AddSparcTargetArgs(const ArgList &Args,
@@ -958,7 +1075,7 @@ void Clang::AddX86TargetArgs(const ArgList &Args,
// FIXME: We should also incorporate the detected target features for use
// with -native.
std::string CPU = llvm::sys::getHostCPUName();
- if (!CPU.empty())
+ if (!CPU.empty() && CPU != "generic")
CPUName = Args.MakeArgString(CPU);
} else
CPUName = A->getValue(Args);
@@ -982,6 +1099,11 @@ void Clang::AddX86TargetArgs(const ArgList &Args,
CPUName = "x86-64";
else if (getToolChain().getArch() == llvm::Triple::x86)
CPUName = "i486";
+ } else if (getToolChain().getOS().startswith("bitrig")) {
+ if (getToolChain().getArch() == llvm::Triple::x86_64)
+ CPUName = "x86-64";
+ else if (getToolChain().getArch() == llvm::Triple::x86)
+ CPUName = "i686";
} else if (getToolChain().getOS().startswith("freebsd")) {
if (getToolChain().getArch() == llvm::Triple::x86_64)
CPUName = "x86-64";
@@ -1088,7 +1210,7 @@ void Clang::AddHexagonTargetArgs(const ArgList &Args,
CmdArgs.push_back("-fno-signed-char");
CmdArgs.push_back("-nobuiltininc");
- if (Args.hasArg(options::OPT_mqdsp6_compat))
+ if (Args.hasArg(options::OPT_mqdsp6_compat))
CmdArgs.push_back("-mqdsp6-compat");
if (Arg *A = Args.getLastArg(options::OPT_G,
@@ -1100,18 +1222,23 @@ void Clang::AddHexagonTargetArgs(const ArgList &Args,
A->claim();
}
+ if (!Args.hasArg(options::OPT_fno_short_enums))
+ CmdArgs.push_back("-fshort-enums");
+ if (Args.getLastArg(options::OPT_mieee_rnd_near)) {
+ CmdArgs.push_back ("-mllvm");
+ CmdArgs.push_back ("-enable-hexagon-ieee-rnd-near");
+ }
CmdArgs.push_back ("-mllvm");
CmdArgs.push_back ("-machine-sink-split=0");
}
static bool
-shouldUseExceptionTablesForObjCExceptions(unsigned objcABIVersion,
+shouldUseExceptionTablesForObjCExceptions(const ObjCRuntime &runtime,
const llvm::Triple &Triple) {
// We use the zero-cost exception tables for Objective-C if the non-fragile
// ABI is enabled or when compiling for x86_64 and ARM on Snow Leopard and
// later.
-
- if (objcABIVersion >= 2)
+ if (runtime.isNonFragile())
return true;
if (!Triple.isOSDarwin())
@@ -1130,7 +1257,7 @@ shouldUseExceptionTablesForObjCExceptions(unsigned objcABIVersion,
static void addExceptionArgs(const ArgList &Args, types::ID InputType,
const llvm::Triple &Triple,
bool KernelOrKext,
- unsigned objcABIVersion,
+ const ObjCRuntime &objcRuntime,
ArgStringList &CmdArgs) {
if (KernelOrKext) {
// -mkernel and -fapple-kext imply no exceptions, so claim exception related
@@ -1176,7 +1303,7 @@ static void addExceptionArgs(const ArgList &Args, types::ID InputType,
CmdArgs.push_back("-fobjc-exceptions");
ShouldUseExceptionTables |=
- shouldUseExceptionTablesForObjCExceptions(objcABIVersion, Triple);
+ shouldUseExceptionTablesForObjCExceptions(objcRuntime, Triple);
}
if (types::isCXX(InputType)) {
@@ -1269,22 +1396,56 @@ static bool UseRelaxAll(Compilation &C, const ArgList &Args) {
/// 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) {
- // Add asan linker flags when linking an executable, but not a shared object.
- if (Args.hasArg(options::OPT_shared) ||
- !Args.hasFlag(options::OPT_faddress_sanitizer,
+ if (!Args.hasFlag(options::OPT_faddress_sanitizer,
options::OPT_fno_address_sanitizer, false))
return;
+ if(TC.getTriple().getEnvironment() == llvm::Triple::ANDROIDEABI) {
+ if (!Args.hasArg(options::OPT_shared)) {
+ if (!Args.hasArg(options::OPT_pie))
+ TC.getDriver().Diag(diag::err_drv_asan_android_requires_pie);
+ // For an executable, we add a .preinit_array stub.
+ CmdArgs.push_back("-u");
+ CmdArgs.push_back("__asan_preinit");
+ CmdArgs.push_back("-lasan");
+ }
- // LibAsan is "libclang_rt.asan-<ArchName>.a" in the Linux library resource
- // directory.
- SmallString<128> LibAsan(TC.getDriver().ResourceDir);
- llvm::sys::path::append(LibAsan, "lib", "linux",
- (Twine("libclang_rt.asan-") +
- TC.getArchName() + ".a"));
- CmdArgs.push_back(Args.MakeArgString(LibAsan));
- CmdArgs.push_back("-lpthread");
- CmdArgs.push_back("-ldl");
- CmdArgs.push_back("-export-dynamic");
+ CmdArgs.push_back("-lasan_preload");
+ CmdArgs.push_back("-ldl");
+ } else {
+ if (!Args.hasArg(options::OPT_shared)) {
+ // LibAsan is "libclang_rt.asan-<ArchName>.a" in the Linux library
+ // resource directory.
+ SmallString<128> LibAsan(TC.getDriver().ResourceDir);
+ llvm::sys::path::append(LibAsan, "lib", "linux",
+ (Twine("libclang_rt.asan-") +
+ TC.getArchName() + ".a"));
+ CmdArgs.push_back(Args.MakeArgString(LibAsan));
+ CmdArgs.push_back("-lpthread");
+ CmdArgs.push_back("-ldl");
+ CmdArgs.push_back("-export-dynamic");
+ }
+ }
+}
+
+/// 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) {
+ if (!Args.hasFlag(options::OPT_fthread_sanitizer,
+ options::OPT_fno_thread_sanitizer, false))
+ return;
+ if (!Args.hasArg(options::OPT_shared)) {
+ // LibTsan is "libclang_rt.tsan-<ArchName>.a" in the Linux library
+ // resource directory.
+ SmallString<128> LibTsan(TC.getDriver().ResourceDir);
+ llvm::sys::path::append(LibTsan, "lib", "linux",
+ (Twine("libclang_rt.tsan-") +
+ TC.getArchName() + ".a"));
+ CmdArgs.push_back(Args.MakeArgString(LibTsan));
+ CmdArgs.push_back("-lpthread");
+ CmdArgs.push_back("-ldl");
+ CmdArgs.push_back("-export-dynamic");
+ }
}
static bool shouldUseFramePointer(const ArgList &Args,
@@ -1328,8 +1489,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(Args.MakeArgString(TripleStr));
// Select the appropriate action.
- bool IsRewriter = false;
- bool IsModernRewriter = false;
+ RewriteKind rewriteKind = RK_None;
if (isa<AnalyzeJobAction>(JA)) {
assert(JA.getType() == types::TY_Plist && "Invalid output type.");
@@ -1380,7 +1540,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// Use PCH if the user requested it.
bool UsePCH = D.CCCUsePCH;
- if (UsePCH)
+ if (JA.getType() == types::TY_Nothing)
+ CmdArgs.push_back("-fsyntax-only");
+ else if (UsePCH)
CmdArgs.push_back("-emit-pch");
else
CmdArgs.push_back("-emit-pth");
@@ -1401,10 +1563,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-emit-pch");
} else if (JA.getType() == types::TY_RewrittenObjC) {
CmdArgs.push_back("-rewrite-objc");
- IsModernRewriter = true;
+ rewriteKind = RK_NonFragile;
} else if (JA.getType() == types::TY_RewrittenLegacyObjC) {
CmdArgs.push_back("-rewrite-objc");
- IsRewriter = true;
+ rewriteKind = RK_Fragile;
} else {
assert(JA.getType() == types::TY_PP_Asm &&
"Unexpected output type!");
@@ -1488,22 +1650,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// This comes from the default translation the driver + cc1
// would do to enable flag_pic.
- //
- // FIXME: Centralize this code.
- Arg *LastPICArg = 0;
- for (ArgList::const_iterator I = Args.begin(), E = Args.end(); I != E; ++I) {
- if ((*I)->getOption().matches(options::OPT_fPIC) ||
- (*I)->getOption().matches(options::OPT_fno_PIC) ||
- (*I)->getOption().matches(options::OPT_fpic) ||
- (*I)->getOption().matches(options::OPT_fno_pic) ||
- (*I)->getOption().matches(options::OPT_fPIE) ||
- (*I)->getOption().matches(options::OPT_fno_PIE) ||
- (*I)->getOption().matches(options::OPT_fpie) ||
- (*I)->getOption().matches(options::OPT_fno_pie)) {
- LastPICArg = *I;
- (*I)->claim();
- }
- }
+
+ 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);
bool PICDisabled = false;
bool PICEnabled = false;
bool PICForPIE = false;
@@ -1606,16 +1757,14 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
A->getOption().getID() != options::OPT_fhonor_nans)
CmdArgs.push_back("-menable-no-nans");
- // -fno-math-errno is default.
- bool MathErrno = false;
+ // -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,
options::OPT_fmath_errno,
- options::OPT_fno_math_errno)) {
- if (A->getOption().getID() == options::OPT_fmath_errno) {
- CmdArgs.push_back("-fmath-errno");
- MathErrno = true;
- }
- }
+ options::OPT_fno_math_errno))
+ MathErrno = A->getOption().getID() == options::OPT_fmath_errno;
+ if (MathErrno)
+ CmdArgs.push_back("-fmath-errno");
// There are several flags which require disabling very specific
// optimizations. Any of these being disabled forces us to turn off the
@@ -1661,12 +1810,33 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
!TrappingMath)
CmdArgs.push_back("-menable-unsafe-fp-math");
- // We separately look for the '-ffast-math' flag, and if we find it, tell the
- // frontend to provide the appropriate preprocessor macros. This is distinct
- // from enabling any optimizations as it induces a language change which must
- // survive serialization and deserialization, etc.
+
+ // Validate and pass through -fp-contract option.
+ if (Arg *A = Args.getLastArg(options::OPT_ffast_math,
+ options::OPT_ffp_contract)) {
+ if (A->getOption().getID() == options::OPT_ffp_contract) {
+ StringRef Val = A->getValue(Args);
+ if (Val == "fast" || Val == "on" || Val == "off") {
+ CmdArgs.push_back(Args.MakeArgString("-ffp-contract=" + Val));
+ } else {
+ D.Diag(diag::err_drv_unsupported_option_argument)
+ << A->getOption().getName() << Val;
+ }
+ } else { // A is OPT_ffast_math
+ // If fast-math is set then set the fp-contract mode to fast.
+ CmdArgs.push_back(Args.MakeArgString("-ffp-contract=fast"));
+ }
+ }
+
+ // We separately look for the '-ffast-math' and '-ffinite-math-only' flags,
+ // and if we find them, tell the frontend to provide the appropriate
+ // preprocessor macros. This is distinct from enabling any optimizations as
+ // these options induce language changes which must survive serialization
+ // and deserialization, etc.
if (Args.hasArg(options::OPT_ffast_math))
CmdArgs.push_back("-ffast-math");
+ if (Args.hasArg(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.
@@ -1711,6 +1881,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
AsynchronousUnwindTables))
CmdArgs.push_back("-munwind-tables");
+ getToolChain().addClangTargetOptions(CmdArgs);
+
if (Arg *A = Args.getLastArg(options::OPT_flimited_precision_EQ)) {
CmdArgs.push_back("-mlimit-float-precision");
CmdArgs.push_back(A->getValue(Args));
@@ -1741,6 +1913,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
AddMIPSTargetArgs(Args, CmdArgs);
break;
+ case llvm::Triple::ppc:
+ case llvm::Triple::ppc64:
+ AddPPCTargetArgs(Args, CmdArgs);
+ break;
+
case llvm::Triple::sparc:
AddSparcTargetArgs(Args, CmdArgs);
break;
@@ -1800,13 +1977,20 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
D.CCLogDiagnosticsFilename : "-");
}
- // Special case debug options to only pass -g to clang. This is
- // wrong.
+ // Use the last option from "-g" group. "-gline-tables-only" is
+ // 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_g0)) {
+ if (Arg *A = Args.getLastArg(options::OPT_g_Group)) {
+ if (A->getOption().matches(options::OPT_gline_tables_only)) {
+ CmdArgs.push_back("-gline-tables-only");
+ } else if (!A->getOption().matches(options::OPT_g0) &&
+ !A->getOption().matches(options::OPT_ggdb0)) {
CmdArgs.push_back("-g");
}
+ }
+
+ // We ignore flags -gstrict-dwarf and -grecord-gcc-switches for now.
+ Args.ClaimAllArgs(options::OPT_g_flags_Group);
Args.AddAllArgs(CmdArgs, options::OPT_ffunction_sections);
Args.AddAllArgs(CmdArgs, options::OPT_fdata_sections);
@@ -1917,7 +2101,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
}
Args.AddAllArgs(CmdArgs, options::OPT_W_Group);
- Args.AddLastArg(CmdArgs, options::OPT_pedantic);
+ if (Args.hasFlag(options::OPT_pedantic, options::OPT_no_pedantic, false))
+ CmdArgs.push_back("-pedantic");
Args.AddLastArg(CmdArgs, options::OPT_pedantic_errors);
Args.AddLastArg(CmdArgs, options::OPT_w);
@@ -2007,11 +2192,20 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (Arg *A = Args.getLastArg(options::OPT_Wlarge_by_value_copy_EQ,
options::OPT_Wlarge_by_value_copy_def)) {
- CmdArgs.push_back("-Wlarge-by-value-copy");
- if (A->getNumValues())
- CmdArgs.push_back(A->getValue(Args));
- else
- CmdArgs.push_back("64"); // default value for -Wlarge-by-value-copy.
+ if (A->getNumValues()) {
+ StringRef bytes = A->getValue(Args);
+ CmdArgs.push_back(Args.MakeArgString("-Wlarge-by-value-copy=" + bytes));
+ } else
+ CmdArgs.push_back("-Wlarge-by-value-copy=64"); // default value
+ }
+
+ if (Arg *A = Args.getLastArg(options::OPT_fbounds_checking,
+ options::OPT_fbounds_checking_EQ)) {
+ if (A->getNumValues()) {
+ StringRef val = A->getValue(Args);
+ CmdArgs.push_back(Args.MakeArgString("-fbounds-checking=" + val));
+ } else
+ CmdArgs.push_back("-fbounds-checking=1");
}
if (Args.hasArg(options::OPT__relocatable_pch))
@@ -2066,6 +2260,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddLastArg(CmdArgs, options::OPT_fvisibility_inlines_hidden);
+ Args.AddLastArg(CmdArgs, options::OPT_ftlsmodel_EQ);
+
// -fhosted is default.
if (Args.hasFlag(options::OPT_ffreestanding, options::OPT_fhosted, false) ||
KernelOrKext)
@@ -2079,6 +2275,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddLastArg(CmdArgs, options::OPT_fno_limit_debug_info);
Args.AddLastArg(CmdArgs, options::OPT_fno_operator_names);
Args.AddLastArg(CmdArgs, options::OPT_faltivec);
+ Args.AddLastArg(CmdArgs, options::OPT_fdiagnostics_show_template_tree);
+ Args.AddLastArg(CmdArgs, options::OPT_fno_elide_type);
// Report and error for -faltivec on anything other then PowerPC.
if (const Arg *A = Args.getLastArg(options::OPT_faltivec))
@@ -2106,6 +2304,10 @@ 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);
@@ -2259,6 +2461,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
getToolChain().getTriple().getOS() == llvm::Triple::Win32))
CmdArgs.push_back("-fms-extensions");
+ // -fms-inline-asm.
+ if (Args.hasArg(options::OPT_fenable_experimental_ms_inline_asm))
+ CmdArgs.push_back("-fenable-experimental-ms-inline-asm");
+
// -fms-compatibility=0 is default.
if (Args.hasFlag(options::OPT_fms_compatibility,
options::OPT_fno_ms_compatibility,
@@ -2309,83 +2515,15 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (Args.hasArg(options::OPT_fno_inline_functions))
CmdArgs.push_back("-fno-inline-functions");
- // -fobjc-nonfragile-abi=0 is default.
- ObjCRuntime objCRuntime;
- unsigned objcABIVersion = 0;
- bool NeXTRuntimeIsDefault
- = (IsRewriter || IsModernRewriter ||
- getToolChain().getTriple().isOSDarwin());
- if (Args.hasFlag(options::OPT_fnext_runtime, options::OPT_fgnu_runtime,
- NeXTRuntimeIsDefault)) {
- objCRuntime.setKind(ObjCRuntime::NeXT);
- } else {
- CmdArgs.push_back("-fgnu-runtime");
- objCRuntime.setKind(ObjCRuntime::GNU);
- }
- getToolChain().configureObjCRuntime(objCRuntime);
- if (objCRuntime.HasARC)
- CmdArgs.push_back("-fobjc-runtime-has-arc");
- if (objCRuntime.HasWeak)
- CmdArgs.push_back("-fobjc-runtime-has-weak");
- if (objCRuntime.HasTerminate)
- CmdArgs.push_back("-fobjc-runtime-has-terminate");
-
- // Compute the Objective-C ABI "version" to use. Version numbers are
- // slightly confusing for historical reasons:
- // 1 - Traditional "fragile" ABI
- // 2 - Non-fragile ABI, version 1
- // 3 - Non-fragile ABI, version 2
- objcABIVersion = 1;
- // If -fobjc-abi-version= is present, use that to set the version.
- if (Arg *A = Args.getLastArg(options::OPT_fobjc_abi_version_EQ)) {
- if (StringRef(A->getValue(Args)) == "1")
- objcABIVersion = 1;
- else if (StringRef(A->getValue(Args)) == "2")
- objcABIVersion = 2;
- else if (StringRef(A->getValue(Args)) == "3")
- objcABIVersion = 3;
- else
- D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args);
- } else {
- // Otherwise, determine if we are using the non-fragile ABI.
- bool NonFragileABIIsDefault =
- (IsModernRewriter ||
- (!IsRewriter && getToolChain().IsObjCNonFragileABIDefault()));
- if (Args.hasFlag(options::OPT_fobjc_nonfragile_abi,
- options::OPT_fno_objc_nonfragile_abi,
- NonFragileABIIsDefault)) {
- // Determine the non-fragile ABI version to use.
-#ifdef DISABLE_DEFAULT_NONFRAGILEABI_TWO
- unsigned NonFragileABIVersion = 1;
-#else
- unsigned NonFragileABIVersion = 2;
-#endif
-
- if (Arg *A = Args.getLastArg(
- options::OPT_fobjc_nonfragile_abi_version_EQ)) {
- if (StringRef(A->getValue(Args)) == "1")
- NonFragileABIVersion = 1;
- else if (StringRef(A->getValue(Args)) == "2")
- NonFragileABIVersion = 2;
- else
- D.Diag(diag::err_drv_clang_unsupported)
- << A->getAsString(Args);
- }
-
- objcABIVersion = 1 + NonFragileABIVersion;
- } else {
- objcABIVersion = 1;
- }
- }
+ ObjCRuntime objcRuntime = AddObjCRuntimeArgs(Args, CmdArgs, rewriteKind);
- if (objcABIVersion == 1) {
- CmdArgs.push_back("-fobjc-fragile-abi");
- } else {
- // -fobjc-dispatch-method is only relevant with the nonfragile-abi, and
- // legacy is the default.
+ // -fobjc-dispatch-method is only relevant with the nonfragile-abi, and
+ // legacy is the default.
+ if (objcRuntime.isNonFragile()) {
if (!Args.hasFlag(options::OPT_fobjc_legacy_dispatch,
options::OPT_fno_objc_legacy_dispatch,
- getToolChain().IsObjCLegacyDispatchDefault())) {
+ objcRuntime.isLegacyDispatchDefaultForArch(
+ getToolChain().getTriple().getArch()))) {
if (getToolChain().UseObjCMixedDispatch())
CmdArgs.push_back("-fobjc-dispatch-method=mixed");
else
@@ -2428,7 +2566,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// -fobjc-infer-related-result-type is the default, except in the Objective-C
// rewriter.
- if (IsRewriter || IsModernRewriter)
+ if (rewriteKind != RK_None)
CmdArgs.push_back("-fno-objc-infer-related-result-type");
// Handle -fobjc-gc and -fobjc-gc-only. They are exclusive, and -fobjc-gc-only
@@ -2451,7 +2589,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// Add exception args.
addExceptionArgs(Args, InputType, getToolChain().getTriple(),
- KernelOrKext, objcABIVersion, CmdArgs);
+ KernelOrKext, objcRuntime, CmdArgs);
if (getToolChain().UseSjLjExceptions())
CmdArgs.push_back("-fsjlj-exceptions");
@@ -2490,12 +2628,12 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// Honor -fpack-struct= and -fpack-struct, if given. Note that
// -fno-pack-struct doesn't apply to -fpack-struct=.
if (Arg *A = Args.getLastArg(options::OPT_fpack_struct_EQ)) {
- CmdArgs.push_back("-fpack-struct");
- CmdArgs.push_back(A->getValue(Args));
+ std::string PackStructStr = "-fpack-struct=";
+ PackStructStr += A->getValue(Args);
+ CmdArgs.push_back(Args.MakeArgString(PackStructStr));
} else if (Args.hasFlag(options::OPT_fpack_struct,
options::OPT_fno_pack_struct, false)) {
- CmdArgs.push_back("-fpack-struct");
- CmdArgs.push_back("1");
+ CmdArgs.push_back("-fpack-struct=1");
}
if (Args.hasArg(options::OPT_mkernel) ||
@@ -2729,7 +2867,7 @@ void ClangAs::AddARMTargetArgs(const ArgList &Args,
// Set the CPU based on -march= and -mcpu=.
CmdArgs.push_back("-target-cpu");
- CmdArgs.push_back(getARMTargetCPU(Args, Triple));
+ CmdArgs.push_back(Args.MakeArgString(getARMTargetCPU(Args, Triple)));
// Honor -mfpu=.
if (const Arg *A = Args.getLastArg(options::OPT_mfpu_EQ))
@@ -2740,6 +2878,131 @@ void ClangAs::AddARMTargetArgs(const ArgList &Args,
addFPMathArgs(D, A, Args, CmdArgs, getARMTargetCPU(Args, Triple));
}
+/// Add options related to the Objective-C runtime/ABI.
+///
+/// Returns true if the runtime is non-fragile.
+ObjCRuntime Clang::AddObjCRuntimeArgs(const ArgList &args,
+ ArgStringList &cmdArgs,
+ RewriteKind rewriteKind) const {
+ // Look for the controlling runtime option.
+ Arg *runtimeArg = args.getLastArg(options::OPT_fnext_runtime,
+ options::OPT_fgnu_runtime,
+ options::OPT_fobjc_runtime_EQ);
+
+ // Just forward -fobjc-runtime= to the frontend. This supercedes
+ // options about fragility.
+ if (runtimeArg &&
+ runtimeArg->getOption().matches(options::OPT_fobjc_runtime_EQ)) {
+ ObjCRuntime runtime;
+ StringRef value = runtimeArg->getValue(args);
+ if (runtime.tryParse(value)) {
+ getToolChain().getDriver().Diag(diag::err_drv_unknown_objc_runtime)
+ << value;
+ }
+
+ runtimeArg->render(args, cmdArgs);
+ return runtime;
+ }
+
+ // Otherwise, we'll need the ABI "version". Version numbers are
+ // slightly confusing for historical reasons:
+ // 1 - Traditional "fragile" ABI
+ // 2 - Non-fragile ABI, version 1
+ // 3 - Non-fragile ABI, version 2
+ unsigned objcABIVersion = 1;
+ // If -fobjc-abi-version= is present, use that to set the version.
+ if (Arg *abiArg = args.getLastArg(options::OPT_fobjc_abi_version_EQ)) {
+ StringRef value = abiArg->getValue(args);
+ if (value == "1")
+ objcABIVersion = 1;
+ else if (value == "2")
+ objcABIVersion = 2;
+ else if (value == "3")
+ objcABIVersion = 3;
+ else
+ getToolChain().getDriver().Diag(diag::err_drv_clang_unsupported)
+ << value;
+ } else {
+ // Otherwise, determine if we are using the non-fragile ABI.
+ bool nonFragileABIIsDefault =
+ (rewriteKind == RK_NonFragile ||
+ (rewriteKind == RK_None &&
+ getToolChain().IsObjCNonFragileABIDefault()));
+ if (args.hasFlag(options::OPT_fobjc_nonfragile_abi,
+ options::OPT_fno_objc_nonfragile_abi,
+ nonFragileABIIsDefault)) {
+ // Determine the non-fragile ABI version to use.
+#ifdef DISABLE_DEFAULT_NONFRAGILEABI_TWO
+ unsigned nonFragileABIVersion = 1;
+#else
+ unsigned nonFragileABIVersion = 2;
+#endif
+
+ if (Arg *abiArg = args.getLastArg(
+ options::OPT_fobjc_nonfragile_abi_version_EQ)) {
+ StringRef value = abiArg->getValue(args);
+ if (value == "1")
+ nonFragileABIVersion = 1;
+ else if (value == "2")
+ nonFragileABIVersion = 2;
+ else
+ getToolChain().getDriver().Diag(diag::err_drv_clang_unsupported)
+ << value;
+ }
+
+ objcABIVersion = 1 + nonFragileABIVersion;
+ } else {
+ objcABIVersion = 1;
+ }
+ }
+
+ // We don't actually care about the ABI version other than whether
+ // it's non-fragile.
+ bool isNonFragile = objcABIVersion != 1;
+
+ // If we have no runtime argument, ask the toolchain for its default runtime.
+ // However, the rewriter only really supports the Mac runtime, so assume that.
+ ObjCRuntime runtime;
+ if (!runtimeArg) {
+ switch (rewriteKind) {
+ case RK_None:
+ runtime = getToolChain().getDefaultObjCRuntime(isNonFragile);
+ break;
+ case RK_Fragile:
+ runtime = ObjCRuntime(ObjCRuntime::FragileMacOSX, VersionTuple());
+ break;
+ case RK_NonFragile:
+ runtime = ObjCRuntime(ObjCRuntime::MacOSX, VersionTuple());
+ break;
+ }
+
+ // -fnext-runtime
+ } else if (runtimeArg->getOption().matches(options::OPT_fnext_runtime)) {
+ // On Darwin, make this use the default behavior for the toolchain.
+ if (getToolChain().getTriple().isOSDarwin()) {
+ runtime = getToolChain().getDefaultObjCRuntime(isNonFragile);
+
+ // Otherwise, build for a generic macosx port.
+ } else {
+ runtime = ObjCRuntime(ObjCRuntime::MacOSX, VersionTuple());
+ }
+
+ // -fgnu-runtime
+ } else {
+ assert(runtimeArg->getOption().matches(options::OPT_fgnu_runtime));
+ // Legacy behaviour is to target the gnustep runtime if we are i
+ // non-fragile mode or the GCC runtime in fragile mode.
+ if (isNonFragile)
+ runtime = ObjCRuntime(ObjCRuntime::GNUstep, VersionTuple());
+ else
+ runtime = ObjCRuntime(ObjCRuntime::GCC, VersionTuple());
+ }
+
+ cmdArgs.push_back(args.MakeArgString(
+ "-fobjc-runtime=" + runtime.getAsString()));
+ return runtime;
+}
+
void ClangAs::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
@@ -4024,9 +4287,6 @@ void darwin::Link::AddLinkArgs(Compilation &C,
} else if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) {
CmdArgs.push_back("-syslibroot");
CmdArgs.push_back(A->getValue(Args));
- } else if (getDarwinToolChain().isTargetIPhoneOS()) {
- CmdArgs.push_back("-syslibroot");
- CmdArgs.push_back("/Developer/SDKs/Extra");
}
Args.AddLastArg(CmdArgs, options::OPT_twolevel__namespace);
@@ -4085,7 +4345,6 @@ void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddAllArgs(CmdArgs, options::OPT_t);
Args.AddAllArgs(CmdArgs, options::OPT_Z_Flag);
Args.AddAllArgs(CmdArgs, options::OPT_u_Group);
- Args.AddAllArgs(CmdArgs, options::OPT_A);
Args.AddLastArg(CmdArgs, options::OPT_e);
Args.AddAllArgs(CmdArgs, options::OPT_m_Separate);
Args.AddAllArgs(CmdArgs, options::OPT_r);
@@ -4099,8 +4358,7 @@ void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename());
- if (!Args.hasArg(options::OPT_A) &&
- !Args.hasArg(options::OPT_nostdlib) &&
+ if (!Args.hasArg(options::OPT_nostdlib) &&
!Args.hasArg(options::OPT_nostartfiles)) {
// Derived from startfile spec.
if (Args.hasArg(options::OPT_dynamiclib)) {
@@ -4144,6 +4402,14 @@ void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA,
// 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) ||
@@ -4201,30 +4467,30 @@ void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA,
// This is more complicated in gcc...
CmdArgs.push_back("-lgomp");
- getDarwinToolChain().AddLinkSearchPathArgs(Args, CmdArgs);
-
- if (isObjCRuntimeLinked(Args)) {
+ 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().getArchName() != "i386") {
// 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().configureObjCRuntime(runtime);
+ ObjCRuntime runtime =
+ getDarwinToolChain().getDefaultObjCRuntime(/*nonfragile*/ true);
// We use arclite library for both ARC and subscripting support.
- if ((!runtime.HasARC && isObjCAutoRefCount(Args)) ||
- !runtime.HasSubscripting)
+ if ((!runtime.hasARC() && isObjCAutoRefCount(Args)) ||
+ !runtime.hasSubscripting())
getDarwinToolChain().AddLinkARCArgs(Args, CmdArgs);
- CmdArgs.push_back("-framework");
- CmdArgs.push_back("Foundation");
}
+ CmdArgs.push_back("-framework");
+ CmdArgs.push_back("Foundation");
// Link libobj.
CmdArgs.push_back("-lobjc");
}
- AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);
-
if (LinkingOutput) {
CmdArgs.push_back("-arch_multiple");
CmdArgs.push_back("-final_output");
@@ -4245,8 +4511,7 @@ void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA,
getDarwinToolChain().AddLinkRuntimeLibArgs(Args, CmdArgs);
}
- if (!Args.hasArg(options::OPT_A) &&
- !Args.hasArg(options::OPT_nostdlib) &&
+ if (!Args.hasArg(options::OPT_nostdlib) &&
!Args.hasArg(options::OPT_nostartfiles)) {
// endfile_spec is empty.
}
@@ -4698,6 +4963,142 @@ void openbsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}
+void bitrig::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ ArgStringList 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;
+ CmdArgs.push_back(II.getFilename());
+ }
+
+ const char *Exec =
+ Args.MakeArgString(getToolChain().GetProgramPath("as"));
+ C.addCommand(new Command(JA, *this, Exec, CmdArgs));
+}
+
+void bitrig::Link::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ const Driver &D = getToolChain().getDriver();
+ ArgStringList CmdArgs;
+
+ if ((!Args.hasArg(options::OPT_nostdlib)) &&
+ (!Args.hasArg(options::OPT_shared))) {
+ CmdArgs.push_back("-e");
+ CmdArgs.push_back("__start");
+ }
+
+ 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");
+ CmdArgs.push_back("-Bdynamic");
+ if (Args.hasArg(options::OPT_shared)) {
+ CmdArgs.push_back("-shared");
+ } else {
+ CmdArgs.push_back("-dynamic-linker");
+ CmdArgs.push_back("/usr/libexec/ld.so");
+ }
+ }
+
+ if (Output.isFilename()) {
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back(Output.getFilename());
+ } else {
+ assert(Output.isNothing() && "Invalid output.");
+ }
+
+ if (!Args.hasArg(options::OPT_nostdlib) &&
+ !Args.hasArg(options::OPT_nostartfiles)) {
+ if (!Args.hasArg(options::OPT_shared)) {
+ if (Args.hasArg(options::OPT_pg))
+ CmdArgs.push_back(Args.MakeArgString(
+ getToolChain().GetFilePath("gcrt0.o")));
+ else
+ CmdArgs.push_back(Args.MakeArgString(
+ getToolChain().GetFilePath("crt0.o")));
+ CmdArgs.push_back(Args.MakeArgString(
+ getToolChain().GetFilePath("crtbegin.o")));
+ } else {
+ CmdArgs.push_back(Args.MakeArgString(
+ getToolChain().GetFilePath("crtbeginS.o")));
+ }
+ }
+
+ Args.AddAllArgs(CmdArgs, options::OPT_L);
+ Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
+ Args.AddAllArgs(CmdArgs, options::OPT_e);
+
+ AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);
+
+ if (!Args.hasArg(options::OPT_nostdlib) &&
+ !Args.hasArg(options::OPT_nodefaultlibs)) {
+ if (D.CCCIsCXX) {
+ getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
+ if (Args.hasArg(options::OPT_pg))
+ CmdArgs.push_back("-lm_p");
+ else
+ CmdArgs.push_back("-lm");
+ }
+
+ if (Args.hasArg(options::OPT_pthread))
+ CmdArgs.push_back("-lpthread");
+ if (!Args.hasArg(options::OPT_shared)) {
+ if (Args.hasArg(options::OPT_pg))
+ CmdArgs.push_back("-lc_p");
+ else
+ CmdArgs.push_back("-lc");
+ }
+
+ std::string myarch = "-lclang_rt.";
+ const llvm::Triple &T = getToolChain().getTriple();
+ llvm::Triple::ArchType Arch = T.getArch();
+ switch (Arch) {
+ case llvm::Triple::arm:
+ myarch += ("arm");
+ break;
+ case llvm::Triple::x86:
+ myarch += ("i386");
+ break;
+ case llvm::Triple::x86_64:
+ myarch += ("amd64");
+ break;
+ default:
+ assert(0 && "Unsupported architecture");
+ }
+ CmdArgs.push_back(Args.MakeArgString(myarch));
+ }
+
+ if (!Args.hasArg(options::OPT_nostdlib) &&
+ !Args.hasArg(options::OPT_nostartfiles)) {
+ if (!Args.hasArg(options::OPT_shared))
+ CmdArgs.push_back(Args.MakeArgString(
+ getToolChain().GetFilePath("crtend.o")));
+ else
+ CmdArgs.push_back(Args.MakeArgString(
+ getToolChain().GetFilePath("crtendS.o")));
+ }
+
+ const char *Exec =
+ Args.MakeArgString(getToolChain().GetProgramPath("ld"));
+ C.addCommand(new Command(JA, *this, Exec, CmdArgs));
+}
+
void freebsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
@@ -4744,6 +5145,14 @@ void freebsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
const Driver &D = getToolChain().getDriver();
ArgStringList CmdArgs;
+ // Silence warning for "clang -g foo.o -o foo"
+ Args.ClaimAllArgs(options::OPT_g_Group);
+ // and "clang -emit-llvm foo.o -o foo"
+ Args.ClaimAllArgs(options::OPT_emit_llvm);
+ // and for "clang -w foo.o -o foo". Other warning options are already
+ // handled somewhere else.
+ Args.ClaimAllArgs(options::OPT_w);
+
if (!D.SysRoot.empty())
CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));
@@ -4759,6 +5168,14 @@ void freebsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-dynamic-linker");
CmdArgs.push_back("/libexec/ld-elf.so.1");
}
+ if (getToolChain().getTriple().getOSMajorVersion() >= 9) {
+ llvm::Triple::ArchType Arch = getToolChain().getArch();
+ if (Arch == llvm::Triple::arm || Arch == llvm::Triple::sparc ||
+ Arch == llvm::Triple::x86 || Arch == llvm::Triple::x86_64) {
+ CmdArgs.push_back("--hash-style=both");
+ }
+ }
+ CmdArgs.push_back("--enable-new-dtags");
}
// When building 32-bit code on FreeBSD/amd64, we have to explicitly
@@ -5064,6 +5481,14 @@ void linuxtools::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
StringRef MArch = getToolChain().getArchName();
if (MArch == "armv7" || MArch == "armv7a" || MArch == "armv7-a")
CmdArgs.push_back("-mfpu=neon");
+
+ StringRef ARMFloatABI = 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);
+ Args.AddLastArg(CmdArgs, options::OPT_mfpu_EQ);
} else if (getToolChain().getArch() == llvm::Triple::mips ||
getToolChain().getArch() == llvm::Triple::mipsel ||
getToolChain().getArch() == llvm::Triple::mips64 ||
@@ -5089,11 +5514,19 @@ void linuxtools::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-EB");
else
CmdArgs.push_back("-EL");
- }
- Args.AddLastArg(CmdArgs, options::OPT_march_EQ);
- Args.AddLastArg(CmdArgs, options::OPT_mcpu_EQ);
- Args.AddLastArg(CmdArgs, options::OPT_mfpu_EQ);
+ Arg *LastPICArg = Args.getLastArg(options::OPT_fPIC, options::OPT_fno_PIC,
+ options::OPT_fpic, options::OPT_fno_pic,
+ options::OPT_fPIE, options::OPT_fno_PIE,
+ options::OPT_fpie, options::OPT_fno_pie);
+ if (LastPICArg &&
+ (LastPICArg->getOption().matches(options::OPT_fPIC) ||
+ LastPICArg->getOption().matches(options::OPT_fpic) ||
+ LastPICArg->getOption().matches(options::OPT_fPIE) ||
+ LastPICArg->getOption().matches(options::OPT_fpie))) {
+ CmdArgs.push_back("-KPIC");
+ }
+ }
Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,
options::OPT_Xassembler);
@@ -5112,9 +5545,10 @@ void linuxtools::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}
-static void AddLibgcc(const Driver &D, ArgStringList &CmdArgs,
- const ArgList &Args) {
- bool StaticLibgcc = Args.hasArg(options::OPT_static) ||
+static void AddLibgcc(llvm::Triple Triple, const Driver &D,
+ ArgStringList &CmdArgs, const ArgList &Args) {
+ bool isAndroid = Triple.getEnvironment() == llvm::Triple::ANDROIDEABI;
+ bool StaticLibgcc = isAndroid || Args.hasArg(options::OPT_static) ||
Args.hasArg(options::OPT_static_libgcc);
if (!D.CCCIsCXX)
CmdArgs.push_back("-lgcc");
@@ -5130,7 +5564,7 @@ static void AddLibgcc(const Driver &D, ArgStringList &CmdArgs,
CmdArgs.push_back("--no-as-needed");
}
- if (StaticLibgcc)
+ if (StaticLibgcc && !isAndroid)
CmdArgs.push_back("-lgcc_eh");
else if (!Args.hasArg(options::OPT_shared) && D.CCCIsCXX)
CmdArgs.push_back("-lgcc");
@@ -5144,13 +5578,16 @@ void linuxtools::Link::ConstructJob(Compilation &C, const JobAction &JA,
const toolchains::Linux& ToolChain =
static_cast<const toolchains::Linux&>(getToolChain());
const Driver &D = ToolChain.getDriver();
+ const bool isAndroid = ToolChain.getTriple().getEnvironment() ==
+ llvm::Triple::ANDROIDEABI;
+
ArgStringList CmdArgs;
// Silence warning for "clang -g foo.o -o foo"
Args.ClaimAllArgs(options::OPT_g_Group);
// and "clang -emit-llvm foo.o -o foo"
Args.ClaimAllArgs(options::OPT_emit_llvm);
- // and for "clang -g foo.o -o foo". Other warning options are already
+ // and for "clang -w foo.o -o foo". Other warning options are already
// handled somewhere else.
Args.ClaimAllArgs(options::OPT_w);
@@ -5204,6 +5641,10 @@ void linuxtools::Link::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-static");
} else if (Args.hasArg(options::OPT_shared)) {
CmdArgs.push_back("-shared");
+ if ((ToolChain.getArch() == llvm::Triple::arm
+ || ToolChain.getArch() == llvm::Triple::thumb) && isAndroid) {
+ CmdArgs.push_back("-Bsymbolic");
+ }
}
if (ToolChain.getArch() == llvm::Triple::arm ||
@@ -5211,11 +5652,17 @@ void linuxtools::Link::ConstructJob(Compilation &C, const JobAction &JA,
(!Args.hasArg(options::OPT_static) &&
!Args.hasArg(options::OPT_shared))) {
CmdArgs.push_back("-dynamic-linker");
- if (ToolChain.getArch() == llvm::Triple::x86)
+ if (isAndroid)
+ CmdArgs.push_back("/system/bin/linker");
+ else if (ToolChain.getArch() == llvm::Triple::x86)
CmdArgs.push_back("/lib/ld-linux.so.2");
else if (ToolChain.getArch() == llvm::Triple::arm ||
- ToolChain.getArch() == llvm::Triple::thumb)
- CmdArgs.push_back("/lib/ld-linux.so.3");
+ ToolChain.getArch() == llvm::Triple::thumb) {
+ if (ToolChain.getTriple().getEnvironment() == llvm::Triple::GNUEABIHF)
+ CmdArgs.push_back("/lib/ld-linux-armhf.so.3");
+ else
+ CmdArgs.push_back("/lib/ld-linux.so.3");
+ }
else if (ToolChain.getArch() == llvm::Triple::mips ||
ToolChain.getArch() == llvm::Triple::mipsel)
CmdArgs.push_back("/lib/ld.so.1");
@@ -5235,25 +5682,27 @@ void linuxtools::Link::ConstructJob(Compilation &C, const JobAction &JA,
if (!Args.hasArg(options::OPT_nostdlib) &&
!Args.hasArg(options::OPT_nostartfiles)) {
- const char *crt1 = NULL;
- if (!Args.hasArg(options::OPT_shared)){
- if (Args.hasArg(options::OPT_pie))
- crt1 = "Scrt1.o";
- else
- crt1 = "crt1.o";
- }
- if (crt1)
- CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crt1)));
+ if (!isAndroid) {
+ const char *crt1 = NULL;
+ if (!Args.hasArg(options::OPT_shared)){
+ if (Args.hasArg(options::OPT_pie))
+ crt1 = "Scrt1.o";
+ else
+ crt1 = "crt1.o";
+ }
+ if (crt1)
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crt1)));
- CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crti.o")));
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crti.o")));
+ }
const char *crtbegin;
if (Args.hasArg(options::OPT_static))
- crtbegin = "crtbeginT.o";
+ crtbegin = isAndroid ? "crtbegin_static.o" : "crtbeginT.o";
else if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_pie))
- crtbegin = "crtbeginS.o";
+ crtbegin = isAndroid ? "crtbegin_so.o" : "crtbeginS.o";
else
- crtbegin = "crtbegin.o";
+ crtbegin = isAndroid ? "crtbegin_dynamic.o" : "crtbegin.o";
CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtbegin)));
}
@@ -5276,7 +5725,9 @@ void linuxtools::Link::ConstructJob(Compilation &C, const JobAction &JA,
AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs);
- if (D.CCCIsCXX && !Args.hasArg(options::OPT_nostdlib)) {
+ if (D.CCCIsCXX &&
+ !Args.hasArg(options::OPT_nostdlib) &&
+ !Args.hasArg(options::OPT_nodefaultlibs)) {
bool OnlyLibstdcxxStatic = Args.hasArg(options::OPT_static_libstdcxx) &&
!Args.hasArg(options::OPT_static);
if (OnlyLibstdcxxStatic)
@@ -5289,34 +5740,37 @@ void linuxtools::Link::ConstructJob(Compilation &C, const JobAction &JA,
// Call this before we add the C run-time.
addAsanRTLinux(getToolChain(), Args, CmdArgs);
+ addTsanRTLinux(getToolChain(), Args, CmdArgs);
if (!Args.hasArg(options::OPT_nostdlib)) {
- if (Args.hasArg(options::OPT_static))
- CmdArgs.push_back("--start-group");
+ if (!Args.hasArg(options::OPT_nodefaultlibs)) {
+ if (Args.hasArg(options::OPT_static))
+ CmdArgs.push_back("--start-group");
- AddLibgcc(D, CmdArgs, Args);
+ AddLibgcc(ToolChain.getTriple(), D, CmdArgs, Args);
- if (Args.hasArg(options::OPT_pthread) ||
- Args.hasArg(options::OPT_pthreads))
- CmdArgs.push_back("-lpthread");
-
- CmdArgs.push_back("-lc");
+ if (Args.hasArg(options::OPT_pthread) ||
+ Args.hasArg(options::OPT_pthreads))
+ CmdArgs.push_back("-lpthread");
- if (Args.hasArg(options::OPT_static))
- CmdArgs.push_back("--end-group");
- else
- AddLibgcc(D, CmdArgs, Args);
+ CmdArgs.push_back("-lc");
+ if (Args.hasArg(options::OPT_static))
+ CmdArgs.push_back("--end-group");
+ else
+ AddLibgcc(ToolChain.getTriple(), D, CmdArgs, Args);
+ }
if (!Args.hasArg(options::OPT_nostartfiles)) {
const char *crtend;
if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_pie))
- crtend = "crtendS.o";
+ crtend = isAndroid ? "crtend_so.o" : "crtendS.o";
else
- crtend = "crtend.o";
+ crtend = isAndroid ? "crtend_android.o" : "crtend.o";
CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtend)));
- CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtn.o")));
+ if (!isAndroid)
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtn.o")));
}
}
@@ -5581,7 +6035,14 @@ void visualstudio::Link::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-nologo");
- AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);
+ Args.AddAllArgValues(CmdArgs, options::OPT_l);
+
+ // Add filenames immediately.
+ for (InputInfoList::const_iterator
+ it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
+ if (it->isFilename())
+ CmdArgs.push_back(it->getFilename());
+ }
const char *Exec =
Args.MakeArgString(getToolChain().GetProgramPath("link.exe"));
OpenPOWER on IntegriCloud