]> granicus.if.org Git - clang/commitdiff
Treat the weak export of block runtime symbols as a deployment-target
authorJohn McCall <rjmccall@apple.com>
Fri, 9 Sep 2011 20:41:01 +0000 (20:41 +0000)
committerJohn McCall <rjmccall@apple.com>
Fri, 9 Sep 2011 20:41:01 +0000 (20:41 +0000)
feature akin to the ARC runtime checks.  Removes a terrible hack where
IR gen needed to find the declarations of those symbols in the translation
unit.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@139404 91177308-0d34-0410-b5e6-96231b3b80d8

12 files changed:
include/clang/Basic/LangOptions.h
include/clang/Driver/CC1Options.td
include/clang/Driver/ToolChain.h
lib/CodeGen/CGBlocks.cpp
lib/CodeGen/CodeGenModule.cpp
lib/Driver/ToolChains.cpp
lib/Driver/ToolChains.h
lib/Driver/Tools.cpp
lib/Frontend/CompilerInvocation.cpp
test/CodeGen/block-decl-merging.c [deleted file]
test/PCH/block-decl-merging.c [deleted file]
test/PCH/block-decl-merging.cpp [deleted file]

index 4267eecf23a6847b55a0a1c750b906d3484c2dd0..eb91cf32ae9ae4a108971bb8835f1b58dce001d9 100644 (file)
@@ -139,6 +139,7 @@ public:
 
   unsigned MRTD : 1;            // -mrtd calling convention
   unsigned DelayedTemplateParsing : 1;  // Delayed template parsing
+  unsigned BlocksRuntimeOptional : 1; // The blocks runtime is not guaranteed
 
 private:
   // We declare multibit enums as unsigned because MSVC insists on making enums
@@ -198,7 +199,7 @@ public:
 
     ThreadsafeStatics = 1;
     POSIXThreads = 0;
-    Blocks = 0;
+    Blocks = BlocksRuntimeOptional = 0;
     EmitAllDecls = 0;
     MathErrno = 1;
     SignedOverflowBehavior = SOB_Undefined;
index 32de34c82ff428de504095dfe94c79f0ae431927..c1ceba87d1c19d85dbe205a93308a6380618e03c 100644 (file)
@@ -450,7 +450,9 @@ def fno_dollars_in_identifiers : Flag<"-fno-dollars-in-identifiers">,
 def femit_all_decls : Flag<"-femit-all-decls">,
   HelpText<"Emit all declarations, even if unused">;
 def fblocks : Flag<"-fblocks">,
-  HelpText<"enable the 'blocks' language feature">;
+  HelpText<"Enable the 'blocks' language feature">;
+def fblocks_runtime_optional : Flag<"-fblocks-runtime-optional">,
+  HelpText<"Weakly link in the blocks runtime">;
 def fheinous_gnu_extensions : Flag<"-fheinous-gnu-extensions">;
 def fexceptions : Flag<"-fexceptions">,
   HelpText<"Enable support for exception handling">;
index 767b7439bfb32886bb297c7921e8a061a563febd..a578778aff161ab19eff9d785a5a525e837bef9c 100644 (file)
@@ -183,9 +183,16 @@ public:
   /// configureObjCRuntime - Configure the known properties of the
   /// Objective-C runtime for this platform.
   ///
-  /// FIXME: this doesn't really belong here.
+  /// FIXME: this really belongs on some sort of DeploymentTarget abstraction
   virtual void configureObjCRuntime(ObjCRuntime &runtime) const;
 
+  /// hasBlocksRuntime - Given that the user is compiling with
+  /// -fblocks, does this tool chain guarantee the existence of a
+  /// blocks runtime?
+  ///
+  /// FIXME: this really belongs on some sort of DeploymentTarget abstraction
+  virtual bool hasBlocksRuntime() const { return true; }
+
   // GetCXXStdlibType - Determine the C++ standard library type to use with the
   // given compilation arguments.
   virtual CXXStdlibType GetCXXStdlibType(const ArgList &Args) const;
index b795ef1befcf8e42f06879ccfee96e7e5451af34..fd93255e5c286895dfe85020040663e3e3a463e3 100644 (file)
@@ -1809,3 +1809,58 @@ void CodeGenFunction::enterByrefCleanup(const AutoVarEmission &emission) {
 
   EHStack.pushCleanup<CallBlockRelease>(NormalAndEHCleanup, emission.Address);
 }
+
+/// Adjust the declaration of something from the blocks API.
+static void configureBlocksRuntimeObject(CodeGenModule &CGM,
+                                         llvm::Constant *C) {
+  if (!CGM.getLangOptions().BlocksRuntimeOptional) return;
+
+  llvm::GlobalValue *GV = cast<llvm::GlobalValue>(C->stripPointerCasts());
+  if (GV->isDeclaration() &&
+      GV->getLinkage() == llvm::GlobalValue::ExternalLinkage)
+    GV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
+}
+
+llvm::Constant *CodeGenModule::getBlockObjectDispose() {
+  if (BlockObjectDispose)
+    return BlockObjectDispose;
+
+  llvm::Type *args[] = { Int8PtrTy, Int32Ty };
+  llvm::FunctionType *fty
+    = llvm::FunctionType::get(VoidTy, args, false);
+  BlockObjectDispose = CreateRuntimeFunction(fty, "_Block_object_dispose");
+  configureBlocksRuntimeObject(*this, BlockObjectDispose);
+  return BlockObjectDispose;
+}
+
+llvm::Constant *CodeGenModule::getBlockObjectAssign() {
+  if (BlockObjectAssign)
+    return BlockObjectAssign;
+
+  llvm::Type *args[] = { Int8PtrTy, Int8PtrTy, Int32Ty };
+  llvm::FunctionType *fty
+    = llvm::FunctionType::get(VoidTy, args, false);
+  BlockObjectAssign = CreateRuntimeFunction(fty, "_Block_object_assign");
+  configureBlocksRuntimeObject(*this, BlockObjectAssign);
+  return BlockObjectAssign;
+}
+
+llvm::Constant *CodeGenModule::getNSConcreteGlobalBlock() {
+  if (NSConcreteGlobalBlock)
+    return NSConcreteGlobalBlock;
+
+  NSConcreteGlobalBlock = GetOrCreateLLVMGlobal("_NSConcreteGlobalBlock",
+                                                Int8PtrTy->getPointerTo(), 0);
+  configureBlocksRuntimeObject(*this, NSConcreteGlobalBlock);
+  return NSConcreteGlobalBlock;
+}
+
+llvm::Constant *CodeGenModule::getNSConcreteStackBlock() {
+  if (NSConcreteStackBlock)
+    return NSConcreteStackBlock;
+
+  NSConcreteStackBlock = GetOrCreateLLVMGlobal("_NSConcreteStackBlock",
+                                               Int8PtrTy->getPointerTo(), 0);
+  configureBlocksRuntimeObject(*this, NSConcreteStackBlock);
+  return NSConcreteStackBlock;  
+}
index 7ccae084648b138f0d83aa56cbb1c635acc70fe0..6df03c886feaf12a9d50b6992b40cca6055ffea9 100644 (file)
@@ -2396,93 +2396,3 @@ void CodeGenModule::EmitCoverageFile() {
     }
   }
 }
-
-///@name Custom Runtime Function Interfaces
-///@{
-//
-// FIXME: These can be eliminated once we can have clients just get the required
-// AST nodes from the builtin tables.
-
-llvm::Constant *CodeGenModule::getBlockObjectDispose() {
-  if (BlockObjectDispose)
-    return BlockObjectDispose;
-
-  DeclarationName DName(&Context.Idents.get("_Block_object_dispose"));
-  DeclContext::lookup_result
-    Lookup = Context.getTranslationUnitDecl()->lookup(DName);
-
-  // If there is an explicit decl, use that.
-  if (Lookup.first != Lookup.second)
-    if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(*Lookup.first))
-      return BlockObjectDispose =
-          GetAddrOfFunction(FD, getTypes().GetFunctionType(FD));
-
-  // Otherwise construct the function by hand.
-  llvm::Type *args[] = { Int8PtrTy, Int32Ty };
-  llvm::FunctionType *fty
-    = llvm::FunctionType::get(VoidTy, args, false);
-  return BlockObjectDispose =
-    CreateRuntimeFunction(fty, "_Block_object_dispose");
-}
-
-llvm::Constant *CodeGenModule::getBlockObjectAssign() {
-  if (BlockObjectAssign)
-    return BlockObjectAssign;
-
-  DeclarationName DName(&Context.Idents.get("_Block_object_assign"));
-  DeclContext::lookup_result
-    Lookup = Context.getTranslationUnitDecl()->lookup(DName);
-
-  // If there is an explicit decl, use that.
-  if (Lookup.first != Lookup.second)
-    if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(*Lookup.first))
-      return BlockObjectAssign =
-          GetAddrOfFunction(FD, getTypes().GetFunctionType(FD));
-
-  // Otherwise construct the function by hand.
-  llvm::Type *args[] = { Int8PtrTy, Int8PtrTy, Int32Ty };
-  llvm::FunctionType *fty
-    = llvm::FunctionType::get(VoidTy, args, false);
-  return BlockObjectAssign =
-    CreateRuntimeFunction(fty, "_Block_object_assign");
-}
-
-llvm::Constant *CodeGenModule::getNSConcreteGlobalBlock() {
-  if (NSConcreteGlobalBlock)
-    return NSConcreteGlobalBlock;
-
-  DeclarationName DName(&Context.Idents.get("_NSConcreteGlobalBlock"));
-  DeclContext::lookup_result
-    Lookup = Context.getTranslationUnitDecl()->lookup(DName);
-
-  // If there is an explicit decl, use that.
-  if (Lookup.first != Lookup.second)
-    if (const VarDecl *VD = dyn_cast<VarDecl>(*Lookup.first))
-      return NSConcreteGlobalBlock =
-          GetAddrOfGlobalVar(VD, getTypes().ConvertType(VD->getType()));
-
-  // Otherwise construct the variable by hand.
-  return NSConcreteGlobalBlock =
-    CreateRuntimeVariable(Int8PtrTy, "_NSConcreteGlobalBlock");
-}
-
-llvm::Constant *CodeGenModule::getNSConcreteStackBlock() {
-  if (NSConcreteStackBlock)
-    return NSConcreteStackBlock;
-
-  DeclarationName DName(&Context.Idents.get("_NSConcreteStackBlock"));
-  DeclContext::lookup_result
-    Lookup = Context.getTranslationUnitDecl()->lookup(DName);
-
-  // If there is an explicit decl, use that.
-  if (Lookup.first != Lookup.second)
-    if (const VarDecl *VD = dyn_cast<VarDecl>(*Lookup.first))
-      return NSConcreteStackBlock =
-          GetAddrOfGlobalVar(VD, getTypes().ConvertType(VD->getType()));
-
-  // Otherwise construct the variable by hand.
-  return NSConcreteStackBlock =
-    CreateRuntimeVariable(Int8PtrTy, "_NSConcreteStackBlock");
-}
-
-///@}
index 7b5183c1066987537ad32b3e75b82a1185208b8a..bcd540084dc599651a31098124c8bd23817d0301 100644 (file)
@@ -109,6 +109,14 @@ void Darwin::configureObjCRuntime(ObjCRuntime &runtime) const {
     runtime.HasTerminate = false;
 }
 
+/// Darwin provides a blocks runtime starting in MacOS X 10.6 and iOS 3.2.
+bool Darwin::hasBlocksRuntime() const {
+  if (isTargetIPhoneOS())
+    return !isIPhoneOSVersionLT(3, 2);
+  else
+    return !isMacosxVersionLT(10, 6);
+}
+
 // FIXME: Can we tablegen this?
 static const char *GetArmArchForMArch(StringRef Value) {
   if (Value == "armv6k")
index cfb8869f47ef66670a26344bfbf9e1c0988383fc..10c416a5fb9f334c2ac7d9e48160a693b858e768 100644 (file)
@@ -187,6 +187,7 @@ public:
   virtual bool HasNativeLLVMSupport() const;
 
   virtual void configureObjCRuntime(ObjCRuntime &runtime) const;
+  virtual bool hasBlocksRuntime() const;
 
   virtual DerivedArgList *TranslateArgs(const DerivedArgList &Args,
                                         const char *BoundArch) const;
index 3158a517fbdee940acfb4d1d08dd229ed08f48bd..691e96cb115ea42cc8061b0aecf7d7c45f7e49da 100644 (file)
@@ -1718,6 +1718,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
          Args.hasArg(options::OPT_fobjc_nonfragile_abi) &&
          !Args.hasArg(options::OPT_fno_blocks))) {
     CmdArgs.push_back("-fblocks");
+
+    if (!Args.hasArg(options::OPT_fgnu_runtime) && 
+        !getToolChain().hasBlocksRuntime())
+      CmdArgs.push_back("-fblocks-runtime-optional");
   }
 
   // -faccess-control is default.
index 426db565873887069e22b5eca79538cc186499bc..7ea31613bd3b401c982e6d2f233d81471320fae4 100644 (file)
@@ -665,6 +665,8 @@ static void LangOptsToArgs(const LangOptions &Opts,
     Res.push_back("-pthread");
   if (Opts.Blocks)
     Res.push_back("-fblocks");
+  if (Opts.BlocksRuntimeOptional)
+    Res.push_back("-fblocks-runtime-optional");
   if (Opts.EmitAllDecls)
     Res.push_back("-femit-all-decls");
   if (Opts.MathErrno)
@@ -1667,6 +1669,7 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
 
   Opts.RTTI = !Args.hasArg(OPT_fno_rtti);
   Opts.Blocks = Args.hasArg(OPT_fblocks);
+  Opts.BlocksRuntimeOptional = Args.hasArg(OPT_fblocks_runtime_optional);
   Opts.CharIsSigned = !Args.hasArg(OPT_fno_signed_char);
   Opts.ShortWChar = Args.hasArg(OPT_fshort_wchar);
   Opts.ShortEnums = Args.hasArg(OPT_fshort_enums);
diff --git a/test/CodeGen/block-decl-merging.c b/test/CodeGen/block-decl-merging.c
deleted file mode 100644 (file)
index 1e7a9f4..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-// RUN: %clang_cc1 -triple i386-apple-darwin10 -fblocks -emit-llvm -o - %s | \
-// RUN:   FileCheck %s
-
-// CHECK: @_NSConcreteGlobalBlock = extern_weak global
-extern void * _NSConcreteStackBlock[32] __attribute__((weak_import));
-// CHECK: @_NSConcreteStackBlock = extern_weak global
-extern void * _NSConcreteGlobalBlock[32] __attribute__((weak_import));
-extern void _Block_object_dispose(const void *, const int) __attribute__((weak_import));
-// CHECK: declare extern_weak void @_Block_object_assign
-extern void _Block_object_assign(void *, const void *, const int) __attribute__((weak_import));
-// CHECK: declare extern_weak void @_Block_object_dispose
-
-void *x = ^(){};
-
-void f1(void (^a0)(void));
-
-void f0() {
-  __block int x;
-  f1(^(void){ x = 1; });
-}
diff --git a/test/PCH/block-decl-merging.c b/test/PCH/block-decl-merging.c
deleted file mode 100644 (file)
index 9612b2e..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-// RUN: %clang_cc1 -triple i386-apple-darwin10 -fblocks %s -emit-pch -o %t
-// RUN: %clang_cc1 -triple i386-apple-darwin10 -fblocks %s -include-pch %t -emit-llvm -o - | \
-// RUN:   FileCheck %s
-
-#ifndef HEADER
-#define HEADER
-
-// CHECK: @_NSConcreteGlobalBlock = extern_weak global
-extern void * _NSConcreteStackBlock[32] __attribute__((weak_import));
-// CHECK: @_NSConcreteStackBlock = extern_weak global
-extern void * _NSConcreteGlobalBlock[32] __attribute__((weak_import));
-extern void _Block_object_dispose(const void *, const int) __attribute__((weak_import));
-// CHECK: declare extern_weak void @_Block_object_assign
-extern void _Block_object_assign(void *, const void *, const int) __attribute__((weak_import));
-// CHECK: declare extern_weak void @_Block_object_dispose
-
-#else
-
-void *x = ^(){};
-
-void f1(void (^a0)(void));
-
-void f0() {
-  __block int x;
-  f1(^(void){ x = 1; });
-}
-
-#endif
diff --git a/test/PCH/block-decl-merging.cpp b/test/PCH/block-decl-merging.cpp
deleted file mode 100644 (file)
index 3c0dac6..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-// RUN: %clang_cc1 -triple i386-apple-darwin10 -fblocks %s -emit-pch -o %t
-// RUN: %clang_cc1 -triple i386-apple-darwin10 -fblocks %s -include-pch %t -emit-llvm -o - | \
-// RUN:   FileCheck %s
-
-#ifndef HEADER
-#define HEADER
-
-extern "C" {
-// CHECK: @_NSConcreteGlobalBlock = extern_weak global
-extern void * _NSConcreteStackBlock[32] __attribute__((weak_import));
-// CHECK: @_NSConcreteStackBlock = extern_weak global
-extern void * _NSConcreteGlobalBlock[32] __attribute__((weak_import));
-extern void _Block_object_dispose(const void *, const int) __attribute__((weak_import));
-// CHECK: declare extern_weak void @_Block_object_assign
-extern void _Block_object_assign(void *, const void *, const int) __attribute__((weak_import));
-// CHECK: declare extern_weak void @_Block_object_dispose
-}
-
-#else
-
-void *x = ^(){};
-
-void f1(void (^a0)(void));
-
-void f0() {
-  __block int x;
-  f1(^(void){ x = 1; });
-}
-
-#endif