aboutsummaryrefslogtreecommitdiff
path: root/lib/Driver
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2011-06-15 23:02:42 +0000
committerJohn McCall <rjmccall@apple.com>2011-06-15 23:02:42 +0000
commitf85e193739c953358c865005855253af4f68a497 (patch)
treee242284beb7fd2b88a2f3ce08644585497d5910d /lib/Driver
parent204e13395d83524e9a557c3f3fd6df2e2f353b9d (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.cpp9
-rw-r--r--lib/Driver/ToolChains.cpp97
-rw-r--r--lib/Driver/ToolChains.h18
-rw-r--r--lib/Driver/Tools.cpp44
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) {