diff options
author | dim <dim@FreeBSD.org> | 2012-12-02 13:20:44 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2012-12-02 13:20:44 +0000 |
commit | 056abd2059c65a3e908193aeae16fad98017437c (patch) | |
tree | 2732d02d7d51218d6eed98ac7fcfc5b8794896b5 /lib/Driver/ToolChains.cpp | |
parent | cc73504950eb7b5dff2dded9bedd67bc36d64641 (diff) | |
download | FreeBSD-src-056abd2059c65a3e908193aeae16fad98017437c.zip FreeBSD-src-056abd2059c65a3e908193aeae16fad98017437c.tar.gz |
Vendor import of clang release_32 branch r168974 (effectively, 3.2 RC2):
http://llvm.org/svn/llvm-project/cfe/branches/release_32@168974
Diffstat (limited to 'lib/Driver/ToolChains.cpp')
-rw-r--r-- | lib/Driver/ToolChains.cpp | 481 |
1 files changed, 265 insertions, 216 deletions
diff --git a/lib/Driver/ToolChains.cpp b/lib/Driver/ToolChains.cpp index 01c6623..a2ccb35 100644 --- a/lib/Driver/ToolChains.cpp +++ b/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; } } |