]> granicus.if.org Git - clang/commitdiff
Add codegen support for __block variables to call _Block_object_dispose as necessary.
authorMike Stump <mrs@apple.com>
Thu, 5 Mar 2009 01:23:13 +0000 (01:23 +0000)
committerMike Stump <mrs@apple.com>
Thu, 5 Mar 2009 01:23:13 +0000 (01:23 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@66117 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGBlocks.cpp
lib/CodeGen/CGBlocks.h
lib/CodeGen/CGDecl.cpp
lib/CodeGen/CodeGenFunction.cpp
test/CodeGen/blocks-1.c

index 00bda4689c4c8dc46d94c344dbce175a3b47fc8f..89b2b5ff13a7bf28318573f67a3b7a8ddc01cf72 100644 (file)
@@ -34,8 +34,6 @@ Enable__block("f__block",
 
 
 llvm::Constant *CodeGenFunction::BuildDescriptorBlockDecl(uint64_t Size) {
-  const llvm::PointerType *PtrToInt8Ty
-    = llvm::PointerType::getUnqual(llvm::Type::Int8Ty);
   const llvm::Type *UnsignedLongTy
     = CGM.getTypes().ConvertType(getContext().UnsignedLongTy);
   llvm::Constant *C;
@@ -78,8 +76,6 @@ llvm::Constant *BlockModule::getNSConcreteGlobalBlock() {
   if (NSConcreteGlobalBlock)
     return NSConcreteGlobalBlock;
 
-  const llvm::PointerType *PtrToInt8Ty
-    = llvm::PointerType::getUnqual(llvm::Type::Int8Ty);
   // FIXME: We should have a CodeGenModule::AddRuntimeVariable that does the
   // same thing as CreateRuntimeFunction if there's already a variable with the
   // same name.
@@ -96,8 +92,6 @@ llvm::Constant *BlockModule::getNSConcreteStackBlock() {
   if (NSConcreteStackBlock)
     return NSConcreteStackBlock;
 
-  const llvm::PointerType *PtrToInt8Ty
-    = llvm::PointerType::getUnqual(llvm::Type::Int8Ty);
   // FIXME: We should have a CodeGenModule::AddRuntimeVariable that does the
   // same thing as CreateRuntimeFunction if there's already a variable with the
   // same name.
@@ -164,8 +158,6 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) {
 
     // __isa
     C = CGM.getNSConcreteStackBlock();
-    const llvm::PointerType *PtrToInt8Ty
-      = llvm::PointerType::getUnqual(llvm::Type::Int8Ty);
     C = llvm::ConstantExpr::getBitCast(C, PtrToInt8Ty);
     Elts.push_back(C);
 
@@ -335,9 +327,6 @@ const llvm::Type *BlockModule::getGenericBlockLiteralType() {
   if (GenericBlockLiteralType)
     return GenericBlockLiteralType;
 
-  const llvm::Type *Int8PtrTy =
-    llvm::PointerType::getUnqual(llvm::Type::Int8Ty);
-
   const llvm::Type *BlockDescPtrTy =
     llvm::PointerType::getUnqual(getBlockDescriptorType());
 
@@ -351,10 +340,10 @@ const llvm::Type *BlockModule::getGenericBlockLiteralType() {
   //   void (*__invoke)(void *);
   //   struct __block_descriptor *__descriptor;
   // };
-  GenericBlockLiteralType = llvm::StructType::get(Int8PtrTy,
+  GenericBlockLiteralType = llvm::StructType::get(PtrToInt8Ty,
                                                   IntTy,
                                                   IntTy,
-                                                  Int8PtrTy,
+                                                  PtrToInt8Ty,
                                                   BlockDescPtrTy,
                                                   NULL);
 
@@ -368,9 +357,6 @@ const llvm::Type *BlockModule::getGenericExtendedBlockLiteralType() {
   if (GenericExtendedBlockLiteralType)
     return GenericExtendedBlockLiteralType;
 
-  const llvm::Type *Int8PtrTy =
-    llvm::PointerType::getUnqual(llvm::Type::Int8Ty);
-
   const llvm::Type *BlockDescPtrTy =
     llvm::PointerType::getUnqual(getBlockDescriptorType());
 
@@ -386,13 +372,13 @@ const llvm::Type *BlockModule::getGenericExtendedBlockLiteralType() {
   //   void *__copy_func_helper_decl;
   //   void *__destroy_func_decl;
   // };
-  GenericExtendedBlockLiteralType = llvm::StructType::get(Int8PtrTy,
+  GenericExtendedBlockLiteralType = llvm::StructType::get(PtrToInt8Ty,
                                                           IntTy,
                                                           IntTy,
-                                                          Int8PtrTy,
+                                                          PtrToInt8Ty,
                                                           BlockDescPtrTy,
-                                                          Int8PtrTy,
-                                                          Int8PtrTy,
+                                                          PtrToInt8Ty,
+                                                          PtrToInt8Ty,
                                                           NULL);
 
   getModule().addTypeName("struct.__block_literal_extended_generic",
@@ -678,8 +664,6 @@ uint64_t CodeGenFunction::getBlockOffset(const BlockDeclRefExpr *BDRE) {
 }
 
 llvm::Value *BlockFunction::BuildCopyHelper(int flag) {
-  const llvm::PointerType *PtrToInt8Ty
-    = llvm::PointerType::getUnqual(llvm::Type::Int8Ty);
   // FIXME: implement
   llvm::Value *V = llvm::ConstantInt::get(llvm::Type::Int32Ty, 43);
   V = Builder.CreateIntToPtr(V, PtrToInt8Ty, "tmp");
@@ -688,11 +672,33 @@ llvm::Value *BlockFunction::BuildCopyHelper(int flag) {
 }
 
 llvm::Value *BlockFunction::BuildDestroyHelper(int flag) {
-  const llvm::PointerType *PtrToInt8Ty
-    = llvm::PointerType::getUnqual(llvm::Type::Int8Ty);
   // FIXME: implement
   llvm::Value *V = llvm::ConstantInt::get(llvm::Type::Int32Ty, 44);
   V = Builder.CreateIntToPtr(V, PtrToInt8Ty, "tmp");
   V = Builder.CreateBitCast(V, PtrToInt8Ty, "tmp");
   return V;
 }
+
+llvm::Value *BlockFunction::getBlockObjectDispose() {
+  if (CGM.BlockObjectDispose == 0) {
+    const llvm::FunctionType *FTy;
+    std::vector<const llvm::Type*> ArgTys;
+    const llvm::Type *ResultType = llvm::Type::VoidTy;
+    ArgTys.push_back(PtrToInt8Ty);
+    ArgTys.push_back(llvm::Type::Int32Ty);
+    FTy = llvm::FunctionType::get(ResultType, ArgTys, false);
+    CGM.BlockObjectDispose  
+      = CGM.CreateRuntimeFunction(FTy, "_Block_object_dispose");
+  }
+  return CGM.BlockObjectDispose;
+}
+
+void BlockFunction::BuildBlockRelease(const VarDecl &D, llvm::Value *DeclPtr) {
+  llvm::Value *F = getBlockObjectDispose();
+  llvm::Value *N, *V;
+  V = Builder.CreateStructGEP(DeclPtr, 1, "forwarding");
+  V = Builder.CreateLoad(V, false);
+  V = Builder.CreateBitCast(V, PtrToInt8Ty);
+  N = llvm::ConstantInt::get(llvm::Type::Int32Ty, BLOCK_FIELD_IS_BYREF);
+  Builder.CreateCall2(F, V, N);
+}
index bef745945fe74141f75d547271c882cf63f6cc7c..3b9cc5053b05bd2e128da7bec8281df3d9635a99 100644 (file)
@@ -94,19 +94,26 @@ public:
     int GlobalUniqueCount;
   } Block;
 
+  llvm::Value *BlockObjectDispose;
+  const llvm::Type *PtrToInt8Ty;
+
   BlockModule(ASTContext &C, llvm::Module &M, const llvm::TargetData &TD,
               CodeGenTypes &T, CodeGenModule &CodeGen)
     : Context(C), TheModule(M), TheTargetData(TD), Types(T),
       CGM(CodeGen),
       NSConcreteGlobalBlock(0), NSConcreteStackBlock(0), BlockDescriptorType(0),
-      GenericBlockLiteralType(0)  {
+      GenericBlockLiteralType(0), BlockObjectDispose(0) {
     Block.GlobalUniqueCount = 0;
+    PtrToInt8Ty = llvm::PointerType::getUnqual(llvm::Type::Int8Ty);
   }
 };
 
 class BlockFunction : public BlockBase {
+  CodeGenModule &CGM;
+
 public:
-    enum {
+  const llvm::Type *PtrToInt8Ty;
+  enum {
     BLOCK_FIELD_IS_OBJECT   =  3,  /* id, NSObject, __attribute__((NSObject)),
                                       block, ... */
     BLOCK_FIELD_IS_BLOCK    =  7,  /* a block variable */
@@ -140,7 +147,10 @@ public:
 
   CGBuilderTy &Builder;
 
-  BlockFunction(CGBuilderTy &B) : Builder(B) { }
+  BlockFunction(CodeGenModule &cgm, CGBuilderTy &B)
+    : CGM(cgm), Builder(B) {
+    PtrToInt8Ty = llvm::PointerType::getUnqual(llvm::Type::Int8Ty);
+  }
 
   ImplicitParamDecl *BlockStructDecl;
   ImplicitParamDecl *getBlockStructDecl() { return BlockStructDecl; }
@@ -148,6 +158,8 @@ public:
   llvm::Value *BuildCopyHelper(int flag);
   llvm::Value *BuildDestroyHelper(int flag);
 
+  llvm::Value *getBlockObjectDispose();
+  void BuildBlockRelease(const VarDecl &D, llvm::Value *DeclPtr);
 };
 
 }  // end namespace CodeGen
index 9cdb40b1218819ebb073545775614d1d62e2aa86..a01aad66b074ec22f561d62dddb96171772bbc27 100644 (file)
@@ -227,6 +227,7 @@ const llvm::Type *CodeGenFunction::BuildByRefType(QualType Ty,
 void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D) {
   QualType Ty = D.getType();
   bool isByRef = D.getAttr<BlocksAttr>();
+  bool needsDispose = false;
 
   llvm::Value *DeclPtr;
   if (Ty->isConstantSizeType()) {
@@ -371,6 +372,7 @@ void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D) {
 
       Builder.CreateStore(BuildDestroyHelper(flag), destroy_helper);
     }
+    needsDispose = true;
   }
 
   // Handle the cleanup attribute
@@ -388,6 +390,11 @@ void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D) {
       
     EmitCall(CGM.getTypes().getFunctionInfo(FD), F, Args);
   }
+
+  if (needsDispose) {
+    CleanupScope scope(*this);
+    BuildBlockRelease(D, DeclPtr);
+  }
 }
 
 /// Emit an alloca (or GlobalValue depending on target) 
index 0e9bf1a5bb9a6ad2786c9151e4f756e3046d3d88..b8e01029f7160e11cca4029519b8b096fbe62936 100644 (file)
@@ -24,7 +24,7 @@ using namespace clang;
 using namespace CodeGen;
 
 CodeGenFunction::CodeGenFunction(CodeGenModule &cgm) 
-  : BlockFunction(Builder), CGM(cgm), Target(CGM.getContext().Target),
+  : BlockFunction(cgm, Builder), CGM(cgm), Target(CGM.getContext().Target),
     DebugInfo(0), SwitchInsn(0), CaseRangeBlock(0), InvokeDest(0) {
   LLVMIntTy = ConvertType(getContext().IntTy);
   LLVMPointerWidth = Target.getPointerWidth(0);
index 725d71fbc95f8d512dde77b09d57e00ff2c0af5d..c397185e8802c22c60c9884e164acf8108037be9 100644 (file)
@@ -1,4 +1,5 @@
-// RUN: clang %s -emit-llvm -o %t -fblocks -f__block
+// RUN: clang %s -emit-llvm -o %t -fblocks -f__block &&
+// RUN: grep "_Block_object_dispose" %t | count 3
 #include <stdio.h>
 
 void test1() {