Treat the weak export of block runtime symbols as a deployment-target
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
diff --git a/lib/CodeGen/CGBlocks.cpp b/lib/CodeGen/CGBlocks.cpp
index b795ef1..fd93255 100644
--- a/lib/CodeGen/CGBlocks.cpp
+++ b/lib/CodeGen/CGBlocks.cpp
@@ -1809,3 +1809,58 @@
 
   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;  
+}
diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp
index 7ccae08..6df03c8 100644
--- a/lib/CodeGen/CodeGenModule.cpp
+++ b/lib/CodeGen/CodeGenModule.cpp
@@ -2396,93 +2396,3 @@
     }
   }
 }
-
-///@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");
-}
-
-///@}