diff options
Diffstat (limited to 'lib/Driver')
-rw-r--r-- | lib/Driver/ToolChain.cpp | 24 | ||||
-rw-r--r-- | lib/Driver/ToolChains.cpp | 87 | ||||
-rw-r--r-- | lib/Driver/ToolChains.h | 29 | ||||
-rw-r--r-- | lib/Driver/Tools.cpp | 227 | ||||
-rw-r--r-- | lib/Driver/Tools.h | 7 |
5 files changed, 185 insertions, 189 deletions
diff --git a/lib/Driver/ToolChain.cpp b/lib/Driver/ToolChain.cpp index 2e3523cf1d..21aefb6439 100644 --- a/lib/Driver/ToolChain.cpp +++ b/lib/Driver/ToolChain.cpp @@ -14,10 +14,10 @@ #include "clang/Driver/ArgList.h" #include "clang/Driver/Driver.h" #include "clang/Driver/DriverDiagnostic.h" -#include "clang/Driver/ObjCRuntime.h" #include "clang/Driver/Options.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/Support/ErrorHandling.h" +#include "clang/Basic/ObjCRuntime.h" using namespace clang::driver; using namespace clang; @@ -49,25 +49,9 @@ bool ToolChain::HasNativeLLVMSupport() const { return false; } -void ToolChain::configureObjCRuntime(ObjCRuntime &runtime) const { - switch (runtime.getKind()) { - case ObjCRuntime::NeXT: - // Assume a minimal NeXT runtime. - runtime.HasARC = false; - runtime.HasWeak = false; - runtime.HasSubscripting = false; - runtime.HasTerminate = false; - return; - - case ObjCRuntime::GNU: - // Assume a maximal GNU runtime. - runtime.HasARC = true; - runtime.HasWeak = true; - runtime.HasSubscripting = false; // to be added - runtime.HasTerminate = false; // to be added - return; - } - llvm_unreachable("invalid runtime kind!"); +ObjCRuntime ToolChain::getDefaultObjCRuntime(bool isNonFragile) const { + return ObjCRuntime(isNonFragile ? ObjCRuntime::GNU : ObjCRuntime::FragileGNU, + VersionTuple()); } /// getARMTargetCPU - Get the (LLVM) name of the ARM cpu we are targeting. diff --git a/lib/Driver/ToolChains.cpp b/lib/Driver/ToolChains.cpp index 7c75583eea..1a0cd939dd 100644 --- a/lib/Driver/ToolChains.cpp +++ b/lib/Driver/ToolChains.cpp @@ -14,10 +14,10 @@ #include "clang/Driver/Compilation.h" #include "clang/Driver/Driver.h" #include "clang/Driver/DriverDiagnostic.h" -#include "clang/Driver/ObjCRuntime.h" #include "clang/Driver/OptTable.h" #include "clang/Driver/Option.h" #include "clang/Driver/Options.h" +#include "clang/Basic/ObjCRuntime.h" #include "clang/Basic/Version.h" #include "llvm/ADT/SmallString.h" @@ -42,9 +42,7 @@ using namespace clang; /// Darwin - Darwin tool chain for i386 and x86_64. Darwin::Darwin(const Driver &D, const llvm::Triple& Triple) - : ToolChain(D, Triple), TargetInitialized(false), - ARCRuntimeForSimulator(ARCSimulator_None), - LibCXXForSimulator(LibCXXSimulator_None) + : ToolChain(D, Triple), TargetInitialized(false) { // Compute the initial Darwin version from the triple unsigned Major, Minor, Micro; @@ -80,42 +78,19 @@ bool Darwin::HasNativeLLVMSupport() const { return true; } -bool Darwin::hasARCRuntime() const { - // FIXME: Remove this once there is a proper way to detect an ARC runtime - // for the simulator. - switch (ARCRuntimeForSimulator) { - case ARCSimulator_None: - break; - case ARCSimulator_HasARCRuntime: - return true; - case ARCSimulator_NoARCRuntime: - return false; - } - - if (isTargetIPhoneOS()) - return !isIPhoneOSVersionLT(5); - else - return !isMacosxVersionLT(10, 7); -} - -bool Darwin::hasSubscriptingRuntime() const { - return !isTargetIPhoneOS() && !isMacosxVersionLT(10, 8); -} - /// Darwin provides an ARC runtime starting in MacOS X 10.7 and iOS 5.0. -void Darwin::configureObjCRuntime(ObjCRuntime &runtime) const { - if (runtime.getKind() != ObjCRuntime::NeXT) - return ToolChain::configureObjCRuntime(runtime); - - runtime.HasARC = runtime.HasWeak = hasARCRuntime(); - runtime.HasSubscripting = hasSubscriptingRuntime(); - - // So far, objc_terminate is only available in iOS 5. - // FIXME: do the simulator logic properly. - if (!ARCRuntimeForSimulator && isTargetIPhoneOS()) - runtime.HasTerminate = !isIPhoneOSVersionLT(5); - else - runtime.HasTerminate = false; +ObjCRuntime Darwin::getDefaultObjCRuntime(bool isNonFragile) const { + 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); + } + } } /// Darwin provides a blocks runtime starting in MacOS X 10.6 and iOS 3.2. @@ -313,7 +288,7 @@ void DarwinClang::AddLinkARCArgs(const ArgList &Args, else if (isTargetIPhoneOS()) s += "iphoneos"; // FIXME: Remove this once we depend fully on -mios-simulator-version-min. - else if (ARCRuntimeForSimulator != ARCSimulator_None) + else if (TargetSimulatorVersionFromDefines != VersionTuple()) s += "iphonesimulator"; else s += "macosx"; @@ -484,10 +459,7 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const { unsigned Major = 0, Minor = 0, Micro = 0; if (GetVersionFromSimulatorDefine(define, Major, Minor, Micro) && Major < 10 && Minor < 100 && Micro < 100) { - ARCRuntimeForSimulator = Major < 5 ? ARCSimulator_NoARCRuntime - : ARCSimulator_HasARCRuntime; - LibCXXForSimulator = Major < 5 ? LibCXXSimulator_NotAvailable - : LibCXXSimulator_Available; + TargetSimulatorVersionFromDefines = VersionTuple(Major, Minor, Micro); } break; } @@ -901,22 +873,19 @@ DerivedArgList *Darwin::TranslateArgs(const DerivedArgList &Args, // Validate the C++ standard library choice. CXXStdlibType Type = GetCXXStdlibType(*DAL); if (Type == ToolChain::CST_Libcxx) { - switch (LibCXXForSimulator) { - case LibCXXSimulator_None: - // Handle non-simulator cases. - if (isTargetIPhoneOS()) { - if (isIPhoneOSVersionLT(5, 0)) { - getDriver().Diag(clang::diag::err_drv_invalid_libcxx_deployment) - << "iOS 5.0"; - } - } - break; - case LibCXXSimulator_NotAvailable: + // Check whether the target provides libc++. + StringRef where; + + // Complain about targetting iOS < 5.0 in any way. + if ((TargetSimulatorVersionFromDefines != VersionTuple() && + TargetSimulatorVersionFromDefines < VersionTuple(5, 0)) || + (isTargetIPhoneOS() && isIPhoneOSVersionLT(5, 0))) { + where = "iOS 5.0"; + } + + if (where != StringRef()) { getDriver().Diag(clang::diag::err_drv_invalid_libcxx_deployment) - << "iOS 5.0"; - break; - case LibCXXSimulator_Available: - break; + << where; } } diff --git a/lib/Driver/ToolChains.h b/lib/Driver/ToolChains.h index 3fdcba04dd..dce3b6d8e9 100644 --- a/lib/Driver/ToolChains.h +++ b/lib/Driver/ToolChains.h @@ -176,22 +176,6 @@ private: // the argument translation business. mutable bool TargetInitialized; - // FIXME: Remove this once there is a proper way to detect an ARC runtime - // for the simulator. - public: - mutable enum { - ARCSimulator_None, - ARCSimulator_HasARCRuntime, - ARCSimulator_NoARCRuntime - } ARCRuntimeForSimulator; - - mutable enum { - LibCXXSimulator_None, - LibCXXSimulator_NotAvailable, - LibCXXSimulator_Available - } LibCXXForSimulator; - -private: /// Whether we are targeting iPhoneOS target. mutable bool TargetIsIPhoneOS; @@ -201,6 +185,12 @@ private: /// The OS version we are targeting. mutable VersionTuple TargetVersion; +protected: + // FIXME: Remove this once there is a proper way to detect an ARC runtime + // for the simulator. + mutable VersionTuple TargetSimulatorVersionFromDefines; + +private: /// The default macosx-version-min of this tool chain; empty until /// initialized. std::string MacosxVersionMin; @@ -209,9 +199,6 @@ private: /// initialized. std::string iOSVersionMin; - bool hasARCRuntime() const; - bool hasSubscriptingRuntime() const; - private: void AddDeploymentTarget(DerivedArgList &Args) const; @@ -258,7 +245,7 @@ public: bool isTargetMacOS() const { return !isTargetIOSSimulator() && !isTargetIPhoneOS() && - ARCRuntimeForSimulator == ARCSimulator_None; + TargetSimulatorVersionFromDefines == VersionTuple(); } bool isTargetInitialized() const { return TargetInitialized; } @@ -300,7 +287,7 @@ public: virtual bool HasNativeLLVMSupport() const; - virtual void configureObjCRuntime(ObjCRuntime &runtime) const; + virtual ObjCRuntime getDefaultObjCRuntime(bool isNonFragile) const; virtual bool hasBlocksRuntime() const; virtual DerivedArgList *TranslateArgs(const DerivedArgList &Args, diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp index 1669fd515d..aff9688818 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" @@ -1187,13 +1187,12 @@ void Clang::AddHexagonTargetArgs(const ArgList &Args, } 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()) @@ -1212,7 +1211,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 @@ -1258,7 +1257,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)) { @@ -1444,8 +1443,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."); @@ -1517,10 +1515,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!"); @@ -2442,80 +2440,11 @@ 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())) { @@ -2561,7 +2490,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 @@ -2584,7 +2513,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"); @@ -2873,6 +2802,126 @@ 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)); + runtime = ObjCRuntime(ObjCRuntime::GNU, 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, @@ -4340,11 +4389,11 @@ void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA, // 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"); diff --git a/lib/Driver/Tools.h b/lib/Driver/Tools.h index aa15f3551c..0fc0690db5 100644 --- a/lib/Driver/Tools.h +++ b/lib/Driver/Tools.h @@ -18,6 +18,8 @@ #include "llvm/Support/Compiler.h" namespace clang { + class ObjCRuntime; + namespace driver { class Driver; @@ -44,6 +46,11 @@ namespace tools { void AddX86TargetArgs(const ArgList &Args, ArgStringList &CmdArgs) const; void AddHexagonTargetArgs (const ArgList &Args, ArgStringList &CmdArgs) const; + enum RewriteKind { RK_None, RK_Fragile, RK_NonFragile }; + + ObjCRuntime AddObjCRuntimeArgs(const ArgList &args, ArgStringList &cmdArgs, + RewriteKind rewrite) const; + public: Clang(const ToolChain &TC) : Tool("clang", "clang frontend", TC) {} |