summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp')
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp481
1 files changed, 265 insertions, 216 deletions
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp
index 01c6623..a2ccb35 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp
@@ -31,6 +31,8 @@
#include "llvm/Support/Path.h"
#include "llvm/Support/system_error.h"
+#include "SanitizerArgs.h"
+
#include <cstdlib> // ::getenv
#include "clang/Config/config.h" // for GCC_INSTALL_PREFIX
@@ -80,17 +82,11 @@ bool Darwin::HasNativeLLVMSupport() const {
/// Darwin provides an ARC runtime starting in MacOS X 10.7 and iOS 5.0.
ObjCRuntime Darwin::getDefaultObjCRuntime(bool isNonFragile) const {
- if (isTargetIPhoneOS()) {
+ if (isTargetIPhoneOS())
return ObjCRuntime(ObjCRuntime::iOS, TargetVersion);
- } else if (TargetSimulatorVersionFromDefines != VersionTuple()) {
- return ObjCRuntime(ObjCRuntime::iOS, TargetSimulatorVersionFromDefines);
- } else {
- if (isNonFragile) {
- return ObjCRuntime(ObjCRuntime::MacOSX, TargetVersion);
- } else {
- return ObjCRuntime(ObjCRuntime::FragileMacOSX, TargetVersion);
- }
- }
+ if (isNonFragile)
+ return ObjCRuntime(ObjCRuntime::MacOSX, TargetVersion);
+ return ObjCRuntime(ObjCRuntime::FragileMacOSX, TargetVersion);
}
/// Darwin provides a blocks runtime starting in MacOS X 10.6 and iOS 3.2.
@@ -111,6 +107,9 @@ static const char *GetArmArchForMArch(StringRef Value) {
.Cases("armv7a", "armv7-a", "armv7")
.Cases("armv7r", "armv7-r", "armv7")
.Cases("armv7m", "armv7-m", "armv7")
+ .Cases("armv7f", "armv7-f", "armv7f")
+ .Cases("armv7k", "armv7-k", "armv7k")
+ .Cases("armv7s", "armv7-s", "armv7s")
.Default(0);
}
@@ -122,7 +121,10 @@ static const char *GetArmArchForMCpu(StringRef Value) {
.Case("xscale", "xscale")
.Cases("arm1136j-s", "arm1136jf-s", "arm1176jz-s",
"arm1176jzf-s", "cortex-m0", "armv6")
- .Cases("cortex-a8", "cortex-r4", "cortex-m3", "cortex-a9", "armv7")
+ .Cases("cortex-a8", "cortex-r4", "cortex-m3", "cortex-a9", "cortex-a15",
+ "armv7")
+ .Case("cortex-a9-mp", "armv7f")
+ .Case("swift", "armv7s")
.Default(0);
}
@@ -134,11 +136,11 @@ StringRef Darwin::getDarwinArchName(const ArgList &Args) const {
case llvm::Triple::thumb:
case llvm::Triple::arm: {
if (const Arg *A = Args.getLastArg(options::OPT_march_EQ))
- if (const char *Arch = GetArmArchForMArch(A->getValue(Args)))
+ if (const char *Arch = GetArmArchForMArch(A->getValue()))
return Arch;
if (const Arg *A = Args.getLastArg(options::OPT_mcpu_EQ))
- if (const char *Arch = GetArmArchForMCpu(A->getValue(Args)))
+ if (const char *Arch = GetArmArchForMCpu(A->getValue()))
return Arch;
return "arm";
@@ -175,24 +177,11 @@ void Generic_ELF::anchor() {}
Tool &Darwin::SelectTool(const Compilation &C, const JobAction &JA,
const ActionList &Inputs) const {
Action::ActionClass Key = JA.getKind();
- bool useClang = false;
if (getDriver().ShouldUseClangCompiler(C, JA, getTriple())) {
- useClang = true;
- // Fallback to llvm-gcc for i386 kext compiles, we don't support that ABI.
- if (!getDriver().shouldForceClangUse() &&
- Inputs.size() == 1 &&
- types::isCXX(Inputs[0]->getType()) &&
- getTriple().isOSDarwin() &&
- getTriple().getArch() == llvm::Triple::x86 &&
- (C.getArgs().getLastArg(options::OPT_fapple_kext) ||
- C.getArgs().getLastArg(options::OPT_mkernel)))
- useClang = false;
- }
-
- // FIXME: This seems like a hacky way to choose clang frontend.
- if (useClang)
+ // FIXME: This seems like a hacky way to choose clang frontend.
Key = Action::AnalyzeJobClass;
+ }
bool UseIntegratedAs = C.getArgs().hasFlag(options::OPT_integrated_as,
options::OPT_no_integrated_as,
@@ -245,30 +234,6 @@ DarwinClang::DarwinClang(const Driver &D, const llvm::Triple& Triple)
getProgramPaths().push_back(getDriver().getInstalledDir());
if (getDriver().getInstalledDir() != getDriver().Dir)
getProgramPaths().push_back(getDriver().Dir);
-
- // For fallback, we need to know how to find the GCC cc1 executables, so we
- // also add the GCC libexec paths. This is legacy code that can be removed
- // once fallback is no longer useful.
- AddGCCLibexecPath(DarwinVersion[0]);
- AddGCCLibexecPath(DarwinVersion[0] - 2);
- AddGCCLibexecPath(DarwinVersion[0] - 1);
- AddGCCLibexecPath(DarwinVersion[0] + 1);
- AddGCCLibexecPath(DarwinVersion[0] + 2);
-}
-
-void DarwinClang::AddGCCLibexecPath(unsigned darwinVersion) {
- std::string ToolChainDir = "i686-apple-darwin";
- ToolChainDir += llvm::utostr(darwinVersion);
- ToolChainDir += "/4.2.1";
-
- std::string Path = getDriver().Dir;
- Path += "/../llvm-gcc-4.2/libexec/gcc/";
- Path += ToolChainDir;
- getProgramPaths().push_back(Path);
-
- Path = "/usr/llvm-gcc-4.2/libexec/gcc/";
- Path += ToolChainDir;
- getProgramPaths().push_back(Path);
}
void DarwinClang::AddLinkARCArgs(const ArgList &Args,
@@ -287,9 +252,6 @@ void DarwinClang::AddLinkARCArgs(const ArgList &Args,
s += "iphonesimulator";
else if (isTargetIPhoneOS())
s += "iphoneos";
- // FIXME: Remove this once we depend fully on -mios-simulator-version-min.
- else if (TargetSimulatorVersionFromDefines != VersionTuple())
- s += "iphonesimulator";
else
s += "macosx";
s += ".a";
@@ -320,13 +282,15 @@ void DarwinClang::AddLinkRuntimeLibArgs(const ArgList &Args,
break;
default:
getDriver().Diag(diag::err_drv_unsupported_rtlib_for_platform)
- << Args.getLastArg(options::OPT_rtlib_EQ)->getValue(Args) << "darwin";
+ << Args.getLastArg(options::OPT_rtlib_EQ)->getValue() << "darwin";
return;
}
// Darwin doesn't support real static executables, don't link any runtime
// libraries with -static.
- if (Args.hasArg(options::OPT_static))
+ if (Args.hasArg(options::OPT_static) ||
+ Args.hasArg(options::OPT_fapple_kext) ||
+ Args.hasArg(options::OPT_mkernel))
return;
// Reject -static-libgcc for now, we can deal with this when and if someone
@@ -351,15 +315,16 @@ void DarwinClang::AddLinkRuntimeLibArgs(const ArgList &Args,
}
}
+ SanitizerArgs Sanitize(getDriver(), Args);
+
// Add ASAN runtime library, if required. Dynamic libraries and bundles
// should not be linked with the runtime library.
- if (Args.hasFlag(options::OPT_faddress_sanitizer,
- options::OPT_fno_address_sanitizer, false)) {
+ if (Sanitize.needsAsanRt()) {
if (Args.hasArg(options::OPT_dynamiclib) ||
Args.hasArg(options::OPT_bundle)) return;
if (isTargetIPhoneOS()) {
getDriver().Diag(diag::err_drv_clang_unsupported_per_platform)
- << "-faddress-sanitizer";
+ << "-fsanitize=address";
} else {
AddLinkRuntimeLib(Args, CmdArgs, "libclang_rt.asan_osx.a");
@@ -410,67 +375,28 @@ void DarwinClang::AddLinkRuntimeLibArgs(const ArgList &Args,
}
}
-static inline StringRef SimulatorVersionDefineName() {
- return "__IPHONE_OS_VERSION_MIN_REQUIRED";
-}
-
-/// \brief Parse the simulator version define:
-/// __IPHONE_OS_VERSION_MIN_REQUIRED=([0-9])([0-9][0-9])([0-9][0-9])
-// and return the grouped values as integers, e.g:
-// __IPHONE_OS_VERSION_MIN_REQUIRED=40201
-// will return Major=4, Minor=2, Micro=1.
-static bool GetVersionFromSimulatorDefine(StringRef define,
- unsigned &Major, unsigned &Minor,
- unsigned &Micro) {
- assert(define.startswith(SimulatorVersionDefineName()));
- StringRef name, version;
- llvm::tie(name, version) = define.split('=');
- if (version.empty())
- return false;
- std::string verstr = version.str();
- char *end;
- unsigned num = (unsigned) strtol(verstr.c_str(), &end, 10);
- if (*end != '\0')
- return false;
- Major = num / 10000;
- num = num % 10000;
- Minor = num / 100;
- Micro = num % 100;
- return true;
-}
-
void Darwin::AddDeploymentTarget(DerivedArgList &Args) const {
const OptTable &Opts = getDriver().getOpts();
+ // Support allowing the SDKROOT environment variable used by xcrun and other
+ // Xcode tools to define the default sysroot, by making it the default for
+ // isysroot.
+ if (!Args.hasArg(options::OPT_isysroot)) {
+ if (char *env = ::getenv("SDKROOT")) {
+ // We only use this value as the default if it is an absolute path and
+ // exists.
+ if (llvm::sys::path::is_absolute(env) && llvm::sys::fs::exists(env)) {
+ Args.append(Args.MakeSeparateArg(
+ 0, Opts.getOption(options::OPT_isysroot), env));
+ }
+ }
+ }
+
Arg *OSXVersion = Args.getLastArg(options::OPT_mmacosx_version_min_EQ);
Arg *iOSVersion = Args.getLastArg(options::OPT_miphoneos_version_min_EQ);
Arg *iOSSimVersion = Args.getLastArg(
options::OPT_mios_simulator_version_min_EQ);
- // FIXME: HACK! When compiling for the simulator we don't get a
- // '-miphoneos-version-min' to help us know whether there is an ARC runtime
- // or not; try to parse a __IPHONE_OS_VERSION_MIN_REQUIRED
- // define passed in command-line.
- if (!iOSVersion && !iOSSimVersion) {
- for (arg_iterator it = Args.filtered_begin(options::OPT_D),
- ie = Args.filtered_end(); it != ie; ++it) {
- StringRef define = (*it)->getValue(Args);
- if (define.startswith(SimulatorVersionDefineName())) {
- unsigned Major = 0, Minor = 0, Micro = 0;
- if (GetVersionFromSimulatorDefine(define, Major, Minor, Micro) &&
- Major < 10 && Minor < 100 && Micro < 100) {
- TargetSimulatorVersionFromDefines = VersionTuple(Major, Minor, Micro);
- }
- // When using the define to indicate the simulator, we force
- // 10.6 macosx target.
- const Option *O = Opts.getOption(options::OPT_mmacosx_version_min_EQ);
- OSXVersion = Args.MakeJoinedArg(0, O, "10.6");
- Args.append(OSXVersion);
- break;
- }
- }
- }
-
if (OSXVersion && (iOSVersion || iOSSimVersion)) {
getDriver().Diag(diag::err_drv_argument_not_allowed_with)
<< OSXVersion->getAsString(Args)
@@ -500,7 +426,7 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const {
if (iOSTarget.empty()) {
if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) {
StringRef first, second;
- StringRef isysroot = A->getValue(Args);
+ StringRef isysroot = A->getValue();
llvm::tie(first, second) = isysroot.split(StringRef("SDKs/iPhoneOS"));
if (second != "")
iOSTarget = second.substr(0,3);
@@ -510,7 +436,8 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const {
// If no OSX or iOS target has been specified and we're compiling for armv7,
// go ahead as assume we're targeting iOS.
if (OSXTarget.empty() && iOSTarget.empty() &&
- getDarwinArchName(Args) == "armv7")
+ (getDarwinArchName(Args) == "armv7" ||
+ getDarwinArchName(Args) == "armv7s"))
iOSTarget = iOSVersionMin;
// Handle conflicting deployment targets
@@ -536,21 +463,21 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const {
}
if (!OSXTarget.empty()) {
- const Option *O = Opts.getOption(options::OPT_mmacosx_version_min_EQ);
+ const Option O = Opts.getOption(options::OPT_mmacosx_version_min_EQ);
OSXVersion = Args.MakeJoinedArg(0, O, OSXTarget);
Args.append(OSXVersion);
} else if (!iOSTarget.empty()) {
- const Option *O = Opts.getOption(options::OPT_miphoneos_version_min_EQ);
+ const Option O = Opts.getOption(options::OPT_miphoneos_version_min_EQ);
iOSVersion = Args.MakeJoinedArg(0, O, iOSTarget);
Args.append(iOSVersion);
} else if (!iOSSimTarget.empty()) {
- const Option *O = Opts.getOption(
+ const Option O = Opts.getOption(
options::OPT_mios_simulator_version_min_EQ);
iOSSimVersion = Args.MakeJoinedArg(0, O, iOSSimTarget);
Args.append(iOSSimVersion);
} else {
// Otherwise, assume we are targeting OS X.
- const Option *O = Opts.getOption(options::OPT_mmacosx_version_min_EQ);
+ const Option O = Opts.getOption(options::OPT_mmacosx_version_min_EQ);
OSXVersion = Args.MakeJoinedArg(0, O, MacosxVersionMin);
Args.append(OSXVersion);
}
@@ -568,7 +495,7 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const {
bool HadExtra;
if (OSXVersion) {
assert((!iOSVersion && !iOSSimVersion) && "Unknown target platform!");
- if (!Driver::GetReleaseVersion(OSXVersion->getValue(Args), Major, Minor,
+ if (!Driver::GetReleaseVersion(OSXVersion->getValue(), Major, Minor,
Micro, HadExtra) || HadExtra ||
Major != 10 || Minor >= 100 || Micro >= 100)
getDriver().Diag(diag::err_drv_invalid_version_number)
@@ -576,7 +503,7 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const {
} else {
const Arg *Version = iOSVersion ? iOSVersion : iOSSimVersion;
assert(Version && "Unknown target platform!");
- if (!Driver::GetReleaseVersion(Version->getValue(Args), Major, Minor,
+ if (!Driver::GetReleaseVersion(Version->getValue(), Major, Minor,
Micro, HadExtra) || HadExtra ||
Major >= 10 || Minor >= 100 || Micro >= 100)
getDriver().Diag(diag::err_drv_invalid_version_number)
@@ -614,7 +541,7 @@ void DarwinClang::AddCXXStdlibLibArgs(const ArgList &Args,
// Check in the sysroot first.
bool Exists;
if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) {
- llvm::sys::Path P(A->getValue(Args));
+ llvm::sys::Path P(A->getValue());
P.appendComponent("usr");
P.appendComponent("lib");
P.appendComponent("libstdc++.dylib");
@@ -655,7 +582,14 @@ void DarwinClang::AddCCKextLibArgs(const ArgList &Args,
llvm::sys::Path P(getDriver().ResourceDir);
P.appendComponent("lib");
P.appendComponent("darwin");
- P.appendComponent("libclang_rt.cc_kext.a");
+
+ // Use the newer cc_kext for iOS ARM after 6.0.
+ if (!isTargetIPhoneOS() || isTargetIOSSimulator() ||
+ !isIPhoneOSVersionLT(6, 0)) {
+ P.appendComponent("libclang_rt.cc_kext.a");
+ } else {
+ P.appendComponent("libclang_rt.cc_kext_ios5.a");
+ }
// For now, allow missing resource libraries to support developers who may
// not have compiler-rt checked out or integrated into their build.
@@ -683,15 +617,15 @@ DerivedArgList *Darwin::TranslateArgs(const DerivedArgList &Args,
if (A->getOption().matches(options::OPT_Xarch__)) {
// Skip this argument unless the architecture matches either the toolchain
// triple arch, or the arch being bound.
- //
- // FIXME: Canonicalize name.
- StringRef XarchArch = A->getValue(Args, 0);
- if (!(XarchArch == getArchName() ||
- (BoundArch && XarchArch == BoundArch)))
+ llvm::Triple::ArchType XarchArch =
+ tools::darwin::getArchTypeForDarwinArchName(A->getValue(0));
+ if (!(XarchArch == getArch() ||
+ (BoundArch && XarchArch ==
+ tools::darwin::getArchTypeForDarwinArchName(BoundArch))))
continue;
Arg *OriginalArg = A;
- unsigned Index = Args.getBaseArgs().MakeIndex(A->getValue(Args, 1));
+ unsigned Index = Args.getBaseArgs().MakeIndex(A->getValue(1));
unsigned Prev = Index;
Arg *XarchArg = Opts.ParseOneArg(Args, Index);
@@ -707,7 +641,7 @@ DerivedArgList *Darwin::TranslateArgs(const DerivedArgList &Args,
getDriver().Diag(diag::err_drv_invalid_Xarch_argument_with_args)
<< A->getAsString(Args);
continue;
- } else if (XarchArg->getOption().isDriverOption()) {
+ } else if (XarchArg->getOption().hasFlag(options::DriverOption)) {
getDriver().Diag(diag::err_drv_invalid_Xarch_argument_isdriver)
<< A->getAsString(Args);
continue;
@@ -721,12 +655,12 @@ DerivedArgList *Darwin::TranslateArgs(const DerivedArgList &Args,
// Linker input arguments require custom handling. The problem is that we
// have already constructed the phase actions, so we can not treat them as
// "input arguments".
- if (A->getOption().isLinkerInput()) {
+ if (A->getOption().hasFlag(options::LinkerInput)) {
// Convert the argument into individual Zlinker_input_args.
for (unsigned i = 0, e = A->getNumValues(); i != e; ++i) {
DAL->AddSeparateArg(OriginalArg,
Opts.getOption(options::OPT_Zlinker_input),
- A->getValue(Args, i));
+ A->getValue(i));
}
continue;
@@ -749,7 +683,7 @@ DerivedArgList *Darwin::TranslateArgs(const DerivedArgList &Args,
case options::OPT_dependency_file:
DAL->AddSeparateArg(A, Opts.getOption(options::OPT_MF),
- A->getValue(Args));
+ A->getValue());
break;
case options::OPT_gfull:
@@ -805,8 +739,8 @@ DerivedArgList *Darwin::TranslateArgs(const DerivedArgList &Args,
// how the driver driver works.
if (BoundArch) {
StringRef Name = BoundArch;
- const Option *MCpu = Opts.getOption(options::OPT_mcpu_EQ);
- const Option *MArch = Opts.getOption(options::OPT_march_EQ);
+ const Option MCpu = Opts.getOption(options::OPT_mcpu_EQ);
+ const Option MArch = Opts.getOption(options::OPT_march_EQ);
// This code must be kept in sync with LLVM's getArchTypeForDarwinArch,
// which defines the list of which architectures we accept.
@@ -864,6 +798,12 @@ DerivedArgList *Darwin::TranslateArgs(const DerivedArgList &Args,
DAL->AddJoinedArg(0, MArch, "armv6k");
else if (Name == "armv7")
DAL->AddJoinedArg(0, MArch, "armv7a");
+ else if (Name == "armv7f")
+ DAL->AddJoinedArg(0, MArch, "armv7f");
+ else if (Name == "armv7k")
+ DAL->AddJoinedArg(0, MArch, "armv7k");
+ else if (Name == "armv7s")
+ DAL->AddJoinedArg(0, MArch, "armv7s");
else
llvm_unreachable("invalid Darwin arch");
@@ -875,6 +815,25 @@ DerivedArgList *Darwin::TranslateArgs(const DerivedArgList &Args,
if (BoundArch)
AddDeploymentTarget(*DAL);
+ // For iOS 6, undo the translation to add -static for -mkernel/-fapple-kext.
+ // FIXME: It would be far better to avoid inserting those -static arguments,
+ // but we can't check the deployment target in the translation code until
+ // it is set here.
+ if (isTargetIPhoneOS() && !isIPhoneOSVersionLT(6, 0)) {
+ for (ArgList::iterator it = DAL->begin(), ie = DAL->end(); it != ie; ) {
+ Arg *A = *it;
+ ++it;
+ if (A->getOption().getID() != options::OPT_mkernel &&
+ A->getOption().getID() != options::OPT_fapple_kext)
+ continue;
+ assert(it != ie && "unexpected argument translation");
+ A = *it;
+ assert(A->getOption().getID() == options::OPT_static &&
+ "missing expected -static argument");
+ it = DAL->getArgs().erase(it);
+ }
+ }
+
// Validate the C++ standard library choice.
CXXStdlibType Type = GetCXXStdlibType(*DAL);
if (Type == ToolChain::CST_Libcxx) {
@@ -882,13 +841,8 @@ DerivedArgList *Darwin::TranslateArgs(const DerivedArgList &Args,
StringRef where;
// Complain about targetting iOS < 5.0 in any way.
- if (TargetSimulatorVersionFromDefines != VersionTuple()) {
- if (TargetSimulatorVersionFromDefines < VersionTuple(5, 0))
- where = "iOS 5.0";
- } else if (isTargetIPhoneOS()) {
- if (isIPhoneOSVersionLT(5, 0))
- where = "iOS 5.0";
- }
+ if (isTargetIPhoneOS() && isIPhoneOSVersionLT(5, 0))
+ where = "iOS 5.0";
if (where != StringRef()) {
getDriver().Diag(clang::diag::err_drv_invalid_libcxx_deployment)
@@ -900,9 +854,7 @@ DerivedArgList *Darwin::TranslateArgs(const DerivedArgList &Args,
}
bool Darwin::IsUnwindTablesDefault() const {
- // FIXME: Gross; we should probably have some separate target
- // definition, possibly even reusing the one in clang.
- return getArchName() == "x86_64";
+ return getArch() == llvm::Triple::x86_64;
}
bool Darwin::UseDwarfDebugFlags() const {
@@ -917,19 +869,17 @@ bool Darwin::UseSjLjExceptions() const {
getTriple().getArch() == llvm::Triple::thumb);
}
-const char *Darwin::GetDefaultRelocationModel() const {
- return "pic";
+bool Darwin::isPICDefault() const {
+ return true;
}
-const char *Darwin::GetForcedPicModel() const {
- if (getArchName() == "x86_64")
- return "pic";
- return 0;
+bool Darwin::isPICDefaultForced() const {
+ return getArch() == llvm::Triple::x86_64;
}
bool Darwin::SupportsProfiling() const {
// Profiling instrumentation is only supported on x86.
- return getArchName() == "i386" || getArchName() == "x86_64";
+ return getArch() == llvm::Triple::x86 || getArch() == llvm::Triple::x86_64;
}
bool Darwin::SupportsObjCGC() const {
@@ -937,8 +887,10 @@ bool Darwin::SupportsObjCGC() const {
return !isTargetIPhoneOS();
}
-bool Darwin::SupportsObjCARC() const {
- return isTargetIPhoneOS() || !isMacosxVersionLT(10, 6);
+void Darwin::CheckObjCARC() const {
+ if (isTargetIPhoneOS() || !isMacosxVersionLT(10, 6))
+ return;
+ getDriver().Diag(diag::err_arc_unsupported_on_toolchain);
}
std::string
@@ -1013,7 +965,7 @@ bool Generic_GCC::GCCVersion::operator<(const GCCVersion &RHS) const {
static StringRef getGCCToolchainDir(const ArgList &Args) {
const Arg *A = Args.getLastArg(options::OPT_gcc_toolchain);
if (A)
- return A->getValue(Args);
+ return A->getValue();
return GCC_INSTALL_PREFIX;
}
@@ -1072,7 +1024,8 @@ Generic_GCC::GCCInstallationDetector::GCCInstallationDetector(
if (!llvm::sys::fs::exists(LibDir))
continue;
for (unsigned k = 0, ke = CandidateTripleAliases.size(); k < ke; ++k)
- ScanLibDirForGCCTriple(TargetArch, LibDir, CandidateTripleAliases[k]);
+ ScanLibDirForGCCTriple(TargetArch, Args, LibDir,
+ CandidateTripleAliases[k]);
}
for (unsigned j = 0, je = CandidateMultiarchLibDirs.size(); j < je; ++j) {
const std::string LibDir
@@ -1081,7 +1034,7 @@ Generic_GCC::GCCInstallationDetector::GCCInstallationDetector(
continue;
for (unsigned k = 0, ke = CandidateMultiarchTripleAliases.size(); k < ke;
++k)
- ScanLibDirForGCCTriple(TargetArch, LibDir,
+ ScanLibDirForGCCTriple(TargetArch, Args, LibDir,
CandidateMultiarchTripleAliases[k],
/*NeedsMultiarchSuffix=*/true);
}
@@ -1136,7 +1089,10 @@ Generic_GCC::GCCInstallationDetector::GCCInstallationDetector(
static const char *const MIPSLibDirs[] = { "/lib" };
static const char *const MIPSTriples[] = { "mips-linux-gnu" };
static const char *const MIPSELLibDirs[] = { "/lib" };
- static const char *const MIPSELTriples[] = { "mipsel-linux-gnu" };
+ static const char *const MIPSELTriples[] = {
+ "mipsel-linux-gnu",
+ "mipsel-linux-android"
+ };
static const char *const MIPS64LibDirs[] = { "/lib64", "/lib" };
static const char *const MIPS64Triples[] = { "mips64-linux-gnu" };
@@ -1264,8 +1220,32 @@ Generic_GCC::GCCInstallationDetector::GCCInstallationDetector(
MultiarchTripleAliases.push_back(MultiarchTriple.str());
}
+// FIXME: There is the same routine in the Tools.cpp.
+static bool hasMipsN32ABIArg(const ArgList &Args) {
+ Arg *A = Args.getLastArg(options::OPT_mabi_EQ);
+ return A && (A->getValue() == StringRef("n32"));
+}
+
+static StringRef getTargetMultiarchSuffix(llvm::Triple::ArchType TargetArch,
+ const ArgList &Args) {
+ if (TargetArch == llvm::Triple::x86_64 ||
+ TargetArch == llvm::Triple::ppc64)
+ return "/64";
+
+ if (TargetArch == llvm::Triple::mips64 ||
+ TargetArch == llvm::Triple::mips64el) {
+ if (hasMipsN32ABIArg(Args))
+ return "/n32";
+ else
+ return "/64";
+ }
+
+ return "/32";
+}
+
void Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple(
- llvm::Triple::ArchType TargetArch, const std::string &LibDir,
+ llvm::Triple::ArchType TargetArch, const ArgList &Args,
+ const std::string &LibDir,
StringRef CandidateTriple, bool NeedsMultiarchSuffix) {
// There are various different suffixes involving the triple we
// check for. We also record what is necessary to walk from each back
@@ -1274,6 +1254,10 @@ void Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple(
"/gcc/" + CandidateTriple.str(),
"/" + CandidateTriple.str() + "/gcc/" + CandidateTriple.str(),
+ // The Freescale PPC SDK has the gcc libraries in
+ // <sysroot>/usr/lib/<triple>/x.y.z so have a look there as well.
+ "/" + CandidateTriple.str(),
+
// Ubuntu has a strange mis-matched pair of triples that this happens to
// match.
// FIXME: It may be worthwhile to generalize this and look for a second
@@ -1283,6 +1267,7 @@ void Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple(
const std::string InstallSuffixes[] = {
"/../../..",
"/../../../..",
+ "/../..",
"/../../../.."
};
// Only look at the final, weird Ubuntu suffix for i386-linux-gnu.
@@ -1307,11 +1292,7 @@ void Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple(
// *if* there is a subdirectory of the right name with crtbegin.o in it,
// we use that. If not, and if not a multiarch triple, we look for
// crtbegin.o without the subdirectory.
- StringRef MultiarchSuffix
- = (TargetArch == llvm::Triple::x86_64 ||
- TargetArch == llvm::Triple::ppc64 ||
- TargetArch == llvm::Triple::mips64 ||
- TargetArch == llvm::Triple::mips64el) ? "/64" : "/32";
+ StringRef MultiarchSuffix = getTargetMultiarchSuffix(TargetArch, Args);
if (llvm::sys::fs::exists(LI->path() + MultiarchSuffix + "/crtbegin.o")) {
GCCMultiarchSuffix = MultiarchSuffix.str();
} else {
@@ -1392,18 +1373,17 @@ Tool &Generic_GCC::SelectTool(const Compilation &C,
}
bool Generic_GCC::IsUnwindTablesDefault() const {
- // FIXME: Gross; we should probably have some separate target
- // definition, possibly even reusing the one in clang.
- return getArchName() == "x86_64";
+ return getArch() == llvm::Triple::x86_64;
}
-const char *Generic_GCC::GetDefaultRelocationModel() const {
- return "static";
+bool Generic_GCC::isPICDefault() const {
+ return false;
}
-const char *Generic_GCC::GetForcedPicModel() const {
- return 0;
+bool Generic_GCC::isPICDefaultForced() const {
+ return false;
}
+
/// Hexagon Toolchain
Hexagon_TC::Hexagon_TC(const Driver &D, const llvm::Triple& Triple)
@@ -1457,21 +1437,14 @@ Tool &Hexagon_TC::SelectTool(const Compilation &C,
return *T;
}
-bool Hexagon_TC::IsUnwindTablesDefault() const {
- // FIXME: Gross; we should probably have some separate target
- // definition, possibly even reusing the one in clang.
- return getArchName() == "x86_64";
+bool Hexagon_TC::isPICDefault() const {
+ return false;
}
-const char *Hexagon_TC::GetDefaultRelocationModel() const {
- return "static";
+bool Hexagon_TC::isPICDefaultForced() const {
+ return false;
}
-const char *Hexagon_TC::GetForcedPicModel() const {
- return 0;
-} // End Hexagon
-
-
/// TCEToolChain - A tool chain using the llvm bitcode tools to perform
/// all subcommands. See http://tce.cs.tut.fi for our peculiar target.
/// Currently does not support anything else but compilation.
@@ -1495,16 +1468,12 @@ bool TCEToolChain::IsMathErrnoDefault() const {
return true;
}
-bool TCEToolChain::IsUnwindTablesDefault() const {
+bool TCEToolChain::isPICDefault() const {
return false;
}
-const char *TCEToolChain::GetDefaultRelocationModel() const {
- return "static";
-}
-
-const char *TCEToolChain::GetForcedPicModel() const {
- return 0;
+bool TCEToolChain::isPICDefaultForced() const {
+ return false;
}
Tool &TCEToolChain::SelectTool(const Compilation &C,
@@ -1613,19 +1582,43 @@ void Bitrig::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
DriverArgs.hasArg(options::OPT_nostdincxx))
return;
- std::string Triple = getTriple().str();
- if (Triple.substr(0, 5) == "amd64")
- Triple.replace(0, 5, "x86_64");
-
- addSystemInclude(DriverArgs, CC1Args, "/usr/include/c++/4.6.2");
- addSystemInclude(DriverArgs, CC1Args, "/usr/include/c++/4.6.2/backward");
- addSystemInclude(DriverArgs, CC1Args, "/usr/include/c++/4.6.2/" + Triple);
+ switch (GetCXXStdlibType(DriverArgs)) {
+ case ToolChain::CST_Libcxx:
+ addSystemInclude(DriverArgs, CC1Args,
+ getDriver().SysRoot + "/usr/include/c++/");
+ break;
+ case ToolChain::CST_Libstdcxx:
+ addSystemInclude(DriverArgs, CC1Args,
+ getDriver().SysRoot + "/usr/include/c++/stdc++");
+ addSystemInclude(DriverArgs, CC1Args,
+ getDriver().SysRoot + "/usr/include/c++/stdc++/backward");
+ StringRef Triple = getTriple().str();
+ if (Triple.startswith("amd64"))
+ addSystemInclude(DriverArgs, CC1Args,
+ getDriver().SysRoot + "/usr/include/c++/stdc++/x86_64" +
+ Triple.substr(5));
+ else
+ addSystemInclude(DriverArgs, CC1Args,
+ getDriver().SysRoot + "/usr/include/c++/stdc++/" +
+ Triple);
+ break;
+ }
}
void Bitrig::AddCXXStdlibLibArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
- CmdArgs.push_back("-lstdc++");
+ switch (GetCXXStdlibType(Args)) {
+ case ToolChain::CST_Libcxx:
+ CmdArgs.push_back("-lc++");
+ CmdArgs.push_back("-lcxxrt");
+ // Include supc++ to provide Unwind until provided by libcxx.
+ CmdArgs.push_back("-lgcc");
+ break;
+ case ToolChain::CST_Libstdcxx:
+ CmdArgs.push_back("-lstdc++");
+ break;
+ }
}
/// FreeBSD - FreeBSD tool chain which can call as(1) and ld(1) directly.
@@ -2020,6 +2013,46 @@ static void addPathIfExists(Twine Path, ToolChain::path_list &Paths) {
if (llvm::sys::fs::exists(Path)) Paths.push_back(Path.str());
}
+static bool isMipsArch(llvm::Triple::ArchType Arch) {
+ return Arch == llvm::Triple::mips ||
+ Arch == llvm::Triple::mipsel ||
+ Arch == llvm::Triple::mips64 ||
+ Arch == llvm::Triple::mips64el;
+}
+
+static bool isMipsR2Arch(llvm::Triple::ArchType Arch,
+ const ArgList &Args) {
+ if (Arch != llvm::Triple::mips &&
+ Arch != llvm::Triple::mipsel)
+ return false;
+
+ Arg *A = Args.getLastArg(options::OPT_march_EQ,
+ options::OPT_mcpu_EQ,
+ options::OPT_mips_CPUs_Group);
+
+ if (!A)
+ return false;
+
+ if (A->getOption().matches(options::OPT_mips_CPUs_Group))
+ return A->getOption().matches(options::OPT_mips32r2);
+
+ return A->getValue() == StringRef("mips32r2");
+}
+
+static StringRef getMultilibDir(const llvm::Triple &Triple,
+ const ArgList &Args) {
+ if (!isMipsArch(Triple.getArch()))
+ return Triple.isArch32Bit() ? "lib32" : "lib64";
+
+ // lib32 directory has a special meaning on MIPS targets.
+ // It contains N32 ABI binaries. Use this folder if produce
+ // code for N32 ABI only.
+ if (hasMipsN32ABIArg(Args))
+ return "lib32";
+
+ return Triple.isArch32Bit() ? "lib" : "lib64";
+}
+
Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
: Generic_ELF(D, Triple, Args) {
llvm::Triple::ArchType Arch = Triple.getArch();
@@ -2043,19 +2076,14 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
if (Arch == llvm::Triple::arm || Arch == llvm::Triple::thumb)
ExtraOpts.push_back("-X");
- const bool IsMips = Arch == llvm::Triple::mips ||
- Arch == llvm::Triple::mipsel ||
- Arch == llvm::Triple::mips64 ||
- Arch == llvm::Triple::mips64el;
-
- const bool IsAndroid = Triple.getEnvironment() == llvm::Triple::ANDROIDEABI;
+ const bool IsAndroid = Triple.getEnvironment() == llvm::Triple::Android;
// Do not use 'gnu' hash style for Mips targets because .gnu.hash
// and the MIPS ABI require .dynsym to be sorted in different ways.
// .gnu.hash needs symbols to be grouped by hash code whereas the MIPS
// ABI requires a mapping between the GOT and the symbol table.
// Android loader does not support .gnu.hash.
- if (!IsMips && !IsAndroid) {
+ if (!isMipsArch(Arch) && !IsAndroid) {
if (IsRedhat(Distro) || IsOpenSuse(Distro) ||
(IsUbuntu(Distro) && Distro >= UbuntuMaverick))
ExtraOpts.push_back("--hash-style=gnu");
@@ -2084,16 +2112,23 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
// to the link paths.
path_list &Paths = getFilePaths();
- const std::string Multilib = Triple.isArch32Bit() ? "lib32" : "lib64";
+ const std::string Multilib = getMultilibDir(Triple, Args);
const std::string MultiarchTriple = getMultiarchTriple(Triple, SysRoot);
// Add the multilib suffixed paths where they are available.
if (GCCInstallation.isValid()) {
const llvm::Triple &GCCTriple = GCCInstallation.getTriple();
const std::string &LibPath = GCCInstallation.getParentLibPath();
- addPathIfExists((GCCInstallation.getInstallPath() +
- GCCInstallation.getMultiarchSuffix()),
- Paths);
+
+ if (IsAndroid && isMipsR2Arch(Triple.getArch(), Args))
+ addPathIfExists(GCCInstallation.getInstallPath() +
+ GCCInstallation.getMultiarchSuffix() +
+ "/mips-r2",
+ Paths);
+ else
+ addPathIfExists((GCCInstallation.getInstallPath() +
+ GCCInstallation.getMultiarchSuffix()),
+ Paths);
// If the GCC installation we found is inside of the sysroot, we want to
// prefer libraries installed in the parent prefix of the GCC installation.
@@ -2108,6 +2143,11 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
addPathIfExists(LibPath + "/" + MultiarchTriple, Paths);
addPathIfExists(LibPath + "/../" + Multilib, Paths);
}
+ // On Android, libraries in the parent prefix of the GCC installation are
+ // preferred to the ones under sysroot.
+ if (IsAndroid) {
+ addPathIfExists(LibPath + "/../" + GCCTriple.str() + "/lib", Paths);
+ }
}
addPathIfExists(SysRoot + "/lib/" + MultiarchTriple, Paths);
addPathIfExists(SysRoot + "/lib/../" + Multilib, Paths);
@@ -2326,16 +2366,25 @@ void Linux::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
StringRef LibDir = GCCInstallation.getParentLibPath();
StringRef InstallDir = GCCInstallation.getInstallPath();
StringRef Version = GCCInstallation.getVersion().Text;
- if (!addLibStdCXXIncludePaths(LibDir + "/../include/c++/" + Version,
- (GCCInstallation.getTriple().str() +
- GCCInstallation.getMultiarchSuffix()),
- DriverArgs, CC1Args)) {
+ StringRef TripleStr = GCCInstallation.getTriple().str();
+
+ const std::string IncludePathCandidates[] = {
+ LibDir.str() + "/../include/c++/" + Version.str(),
// Gentoo is weird and places its headers inside the GCC install, so if the
// first attempt to find the headers fails, try this pattern.
- addLibStdCXXIncludePaths(InstallDir + "/include/g++-v4",
- (GCCInstallation.getTriple().str() +
- GCCInstallation.getMultiarchSuffix()),
- DriverArgs, CC1Args);
+ InstallDir.str() + "/include/g++-v4",
+ // Android standalone toolchain has C++ headers in yet another place.
+ LibDir.str() + "/../" + TripleStr.str() + "/include/c++/" + Version.str(),
+ // Freescale SDK C++ headers are directly in <sysroot>/usr/include/c++,
+ // without a subdirectory corresponding to the gcc version.
+ LibDir.str() + "/../include/c++",
+ };
+
+ for (unsigned i = 0; i < llvm::array_lengthof(IncludePathCandidates); ++i) {
+ if (addLibStdCXXIncludePaths(IncludePathCandidates[i], (TripleStr +
+ GCCInstallation.getMultiarchSuffix()),
+ DriverArgs, CC1Args))
+ break;
}
}
OpenPOWER on IntegriCloud