diff options
author | John McCall <rjmccall@apple.com> | 2011-06-15 23:02:42 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2011-06-15 23:02:42 +0000 |
commit | f85e193739c953358c865005855253af4f68a497 (patch) | |
tree | e242284beb7fd2b88a2f3ce08644585497d5910d /lib/Driver | |
parent | 204e13395d83524e9a557c3f3fd6df2e2f353b9d (diff) |
Automatic Reference Counting.
Language-design credit goes to a lot of people, but I particularly want
to single out Blaine Garst and Patrick Beard for their contributions.
Compiler implementation credit goes to Argyrios, Doug, Fariborz, and myself,
in no particular order.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@133103 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Driver')
-rw-r--r-- | lib/Driver/ToolChain.cpp | 9 | ||||
-rw-r--r-- | lib/Driver/ToolChains.cpp | 97 | ||||
-rw-r--r-- | lib/Driver/ToolChains.h | 18 | ||||
-rw-r--r-- | lib/Driver/Tools.cpp | 44 |
4 files changed, 163 insertions, 5 deletions
diff --git a/lib/Driver/ToolChain.cpp b/lib/Driver/ToolChain.cpp index d919915410..8079e1983f 100644 --- a/lib/Driver/ToolChain.cpp +++ b/lib/Driver/ToolChain.cpp @@ -201,7 +201,8 @@ ToolChain::CXXStdlibType ToolChain::GetCXXStdlibType(const ArgList &Args) const{ } void ToolChain::AddClangCXXStdlibIncludeArgs(const ArgList &Args, - ArgStringList &CmdArgs) const { + ArgStringList &CmdArgs, + bool ObjCXXAutoRefCount) const { CXXStdlibType Type = GetCXXStdlibType(Args); switch (Type) { @@ -209,10 +210,16 @@ void ToolChain::AddClangCXXStdlibIncludeArgs(const ArgList &Args, CmdArgs.push_back("-nostdinc++"); CmdArgs.push_back("-cxx-isystem"); CmdArgs.push_back("/usr/include/c++/v1"); + + if (ObjCXXAutoRefCount) + CmdArgs.push_back("-fobjc-arc-cxxlib=libc++"); break; case ToolChain::CST_Libstdcxx: // Currently handled by the mass of goop in InitHeaderSearch. + + if (ObjCXXAutoRefCount) + CmdArgs.push_back("-fobjc-arc-cxxlib=libstdc++"); break; } } diff --git a/lib/Driver/ToolChains.cpp b/lib/Driver/ToolChains.cpp index ca613e3d6c..35e7d80c29 100644 --- a/lib/Driver/ToolChains.cpp +++ b/lib/Driver/ToolChains.cpp @@ -26,6 +26,7 @@ #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/MemoryBuffer.h" @@ -41,7 +42,8 @@ using namespace clang::driver::toolchains; /// Darwin - Darwin tool chain for i386 and x86_64. Darwin::Darwin(const HostInfo &Host, const llvm::Triple& Triple) - : ToolChain(Host, Triple), TargetInitialized(false) + : ToolChain(Host, Triple), TargetInitialized(false), + ARCRuntimeForSimulator(ARCSimulator_None) { // Compute the initial Darwin version based on the host. bool HadExtra; @@ -70,6 +72,25 @@ bool Darwin::HasNativeLLVMSupport() const { return true; } +/// Darwin provides an ARC runtime starting in MacOS X 10.7 and iOS 5.0. +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); +} + // FIXME: Can we tablegen this? static const char *GetArmArchForMArch(llvm::StringRef Value) { if (Value == "armv6k") @@ -320,6 +341,30 @@ void DarwinClang::AddLinkSearchPathArgs(const ArgList &Args, CmdArgs.push_back(Args.MakeArgString("-L" + P.str())); } +void DarwinClang::AddLinkARCArgs(const ArgList &Args, + ArgStringList &CmdArgs) const { + + CmdArgs.push_back("-force_load"); + llvm::sys::Path P(getDriver().ClangExecutable); + P.eraseComponent(); // 'clang' + P.eraseComponent(); // 'bin' + P.appendComponent("lib"); + P.appendComponent("arc"); + P.appendComponent("libarclite_"); + std::string s = P.str(); + // Mash in the platform. + if (isTargetIPhoneOS()) + s += "iphoneos"; + // FIXME: isTargetIphoneOSSimulator() is not returning true. + else if (ARCRuntimeForSimulator != ARCSimulator_None) + s += "iphonesimulator"; + else + s += "macosx"; + s += ".a"; + + CmdArgs.push_back(Args.MakeArgString(s)); +} + void DarwinClang::AddLinkRuntimeLibArgs(const ArgList &Args, ArgStringList &CmdArgs) const { // Darwin doesn't support real static executables, don't link any runtime @@ -389,6 +434,35 @@ void DarwinClang::AddLinkRuntimeLibArgs(const ArgList &Args, } } +static inline llvm::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(llvm::StringRef define, + unsigned &Major, unsigned &Minor, + unsigned &Micro) { + assert(define.startswith(SimulatorVersionDefineName())); + llvm::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(); @@ -396,6 +470,27 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const { 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) { + for (arg_iterator it = Args.filtered_begin(options::OPT_D), + ie = Args.filtered_end(); it != ie; ++it) { + llvm::StringRef define = (*it)->getValue(Args); + if (define.startswith(SimulatorVersionDefineName())) { + unsigned Major, Minor, Micro; + if (GetVersionFromSimulatorDefine(define, Major, Minor, Micro) && + Major < 10 && Minor < 100 && Micro < 100) { + ARCRuntimeForSimulator = Major < 5 ? ARCSimulator_NoARCRuntime + : ARCSimulator_HasARCRuntime; + } + break; + } + } + } + if (OSXVersion && (iOSVersion || iOSSimVersion)) { getDriver().Diag(clang::diag::err_drv_argument_not_allowed_with) << OSXVersion->getAsString(Args) diff --git a/lib/Driver/ToolChains.h b/lib/Driver/ToolChains.h index ace9b84791..7325874473 100644 --- a/lib/Driver/ToolChains.h +++ b/lib/Driver/ToolChains.h @@ -57,6 +57,16 @@ 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; + +private: /// Whether we are targeting iPhoneOS target. mutable bool TargetIsIPhoneOS; @@ -157,6 +167,10 @@ public: virtual void AddLinkSearchPathArgs(const ArgList &Args, ArgStringList &CmdArgs) const = 0; + /// AddLinkARCArgs - Add the linker arguments to link the ARC runtime library. + virtual void AddLinkARCArgs(const ArgList &Args, + ArgStringList &CmdArgs) const = 0; + /// AddLinkRuntimeLibArgs - Add the linker arguments to link the compiler /// runtime library. virtual void AddLinkRuntimeLibArgs(const ArgList &Args, @@ -170,6 +184,8 @@ public: virtual bool HasNativeLLVMSupport() const; + virtual bool HasARCRuntime() const; + virtual DerivedArgList *TranslateArgs(const DerivedArgList &Args, const char *BoundArch) const; @@ -257,6 +273,8 @@ public: virtual void AddCCKextLibArgs(const ArgList &Args, ArgStringList &CmdArgs) const; + virtual void AddLinkARCArgs(const ArgList &Args, + ArgStringList &CmdArgs) const; /// } }; diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp index 0e85a9fd4f..1947827438 100644 --- a/lib/Driver/Tools.cpp +++ b/lib/Driver/Tools.cpp @@ -30,6 +30,7 @@ #include "llvm/Support/raw_ostream.h" #include "llvm/Support/Host.h" #include "llvm/Support/Process.h" +#include "llvm/Support/ErrorHandling.h" #include "InputInfo.h" #include "ToolChains.h" @@ -147,6 +148,12 @@ static void AddLinkerInputs(const ToolChain &TC, } } +/// \brief Determine whether Objective-C automated reference counting is +/// enabled. +static bool isObjCAutoRefCount(const ArgList &Args) { + return Args.hasFlag(options::OPT_fobjc_arc, options::OPT_fno_objc_arc, false); +} + static void addProfileRT(const ToolChain &TC, const ArgList &Args, ArgStringList &CmdArgs) { if (Args.hasArg(options::OPT_fprofile_arcs) || @@ -318,8 +325,12 @@ void Clang::AddPreprocessingOptions(const Driver &D, // Add C++ include arguments, if needed. types::ID InputType = Inputs[0].getType(); - if (types::isCXX(InputType)) - getToolChain().AddClangCXXStdlibIncludeArgs(Args, CmdArgs); + if (types::isCXX(InputType)) { + bool ObjCXXAutoRefCount + = types::isObjC(InputType) && isObjCAutoRefCount(Args); + getToolChain().AddClangCXXStdlibIncludeArgs(Args, CmdArgs, + ObjCXXAutoRefCount); + } // Add -Wp, and -Xassembler if using the preprocessor. @@ -1542,6 +1553,24 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, options::OPT_fno_lax_vector_conversions)) CmdArgs.push_back("-fno-lax-vector-conversions"); + // Allow -fno-objc-arr to trump -fobjc-arr/-fobjc-arc. + // NOTE: This logic is duplicated in ToolChains.cpp. + bool ARC = isObjCAutoRefCount(Args); + if (ARC) { + CmdArgs.push_back("-fobjc-arc"); + + // Certain deployment targets don't have runtime support. + if (!getToolChain().HasARCRuntime()) + CmdArgs.push_back("-fobjc-no-arc-runtime"); + + // Allow the user to enable full exceptions code emission. + // We define off for Objective-CC, on for Objective-C++. + if (Args.hasFlag(options::OPT_fobjc_arc_exceptions, + options::OPT_fno_objc_arc_exceptions, + /*default*/ types::isCXX(InputType))) + CmdArgs.push_back("-fobjc-arc-exceptions"); + } + // -fobjc-infer-related-result-type is the default, except in the Objective-C // rewriter. if (IsRewriter) @@ -1553,7 +1582,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (!GCArg) GCArg = Args.getLastArg(options::OPT_fobjc_gc); if (GCArg) { - if (getToolChain().SupportsObjCGC()) { + if (ARC) { + D.Diag(clang::diag::err_drv_objc_gc_arr) + << GCArg->getAsString(Args); + } else if (getToolChain().SupportsObjCGC()) { GCArg->render(Args, CmdArgs); } else { // FIXME: We should move this to a hard error. @@ -3141,6 +3173,12 @@ void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA, getDarwinToolChain().AddLinkSearchPathArgs(Args, CmdArgs); + // In ARC, if we don't have 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. + if (!getDarwinToolChain().HasARCRuntime() && isObjCAutoRefCount(Args)) + getDarwinToolChain().AddLinkARCArgs(Args, CmdArgs); + AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs); if (LinkingOutput) { |