[cfe-commits] r125823 - in /cfe/trunk: lib/CodeGen/CGDecl.cpp test/CodeGenObjC/blocks-2.m test/CodeGenObjC/blocks.m

John McCall rjmccall at apple.com
Thu Feb 17 18:58:32 PST 2011


Author: rjmccall
Date: Thu Feb 17 20:58:31 2011
New Revision: 125823

URL: http://llvm.org/viewvc/llvm-project?rev=125823&view=rev
Log:
The flags we're supposed to write into a byref struct are *not* the
_Block_object_* flags;  it's just BLOCK_HAS_COPY_DISPOSE or not.

Also, we don't need to chase forwarding pointers prior to calling
_Block_object_dispose;  _Block_object_dispose in fact already does
this.

rdar://problem/9006315


Modified:
    cfe/trunk/lib/CodeGen/CGDecl.cpp
    cfe/trunk/test/CodeGenObjC/blocks-2.m
    cfe/trunk/test/CodeGenObjC/blocks.m

Modified: cfe/trunk/lib/CodeGen/CGDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDecl.cpp?rev=125823&r1=125822&r2=125823&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGDecl.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGDecl.cpp Thu Feb 17 20:58:31 2011
@@ -504,9 +504,7 @@
     CallBlockRelease(llvm::Value *Addr) : Addr(Addr) {}
 
     void Emit(CodeGenFunction &CGF, bool IsForEH) {
-      llvm::Value *V = CGF.Builder.CreateStructGEP(Addr, 1, "forwarding");
-      V = CGF.Builder.CreateLoad(V);
-      CGF.BuildBlockRelease(V, BLOCK_FIELD_IS_BYREF);
+      CGF.BuildBlockRelease(Addr, BLOCK_FIELD_IS_BYREF);
     }
   };
 }
@@ -743,10 +741,6 @@
 
   if (isByRef) {
     EnsureInsertPoint();
-    llvm::Value *isa_field = Builder.CreateStructGEP(DeclPtr, 0);
-    llvm::Value *forwarding_field = Builder.CreateStructGEP(DeclPtr, 1);
-    llvm::Value *flags_field = Builder.CreateStructGEP(DeclPtr, 2);
-    llvm::Value *size_field = Builder.CreateStructGEP(DeclPtr, 3);
     llvm::Value *V;
 
     BlockFieldFlags fieldFlags;
@@ -776,16 +770,23 @@
     if (fieldFlags & BLOCK_FIELD_IS_WEAK)
       isa = 1;
     V = Builder.CreateIntToPtr(Builder.getInt32(isa), Int8PtrTy, "isa");
-    Builder.CreateStore(V, isa_field);
+    Builder.CreateStore(V, Builder.CreateStructGEP(DeclPtr, 0, "byref.isa"));
 
-    Builder.CreateStore(DeclPtr, forwarding_field);
+    Builder.CreateStore(DeclPtr, Builder.CreateStructGEP(DeclPtr, 1,
+                                                         "byref.forwarding"));
 
-    Builder.CreateStore(Builder.getInt32(fieldFlags.getBitMask()), flags_field);
+    // Blocks ABI:
+    //   c) the flags field is set to either 0 if no helper functions are
+    //      needed or BLOCK_HAS_COPY_DISPOSE if they are,
+    BlockFlags flags;
+    if (fieldNeedsCopyDispose) flags |= BLOCK_HAS_COPY_DISPOSE;
+    Builder.CreateStore(llvm::ConstantInt::get(IntTy, flags.getBitMask()),
+                        Builder.CreateStructGEP(DeclPtr, 2, "byref.flags"));
 
     const llvm::Type *V1;
     V1 = cast<llvm::PointerType>(DeclPtr->getType())->getElementType();
-    V = Builder.getInt32(CGM.GetTargetTypeStoreSize(V1).getQuantity());
-    Builder.CreateStore(V, size_field);
+    V = llvm::ConstantInt::get(IntTy, CGM.GetTargetTypeStoreSize(V1).getQuantity());
+    Builder.CreateStore(V, Builder.CreateStructGEP(DeclPtr, 3, "byref.size"));
 
     if (fieldNeedsCopyDispose) {
       llvm::Value *copy_helper = Builder.CreateStructGEP(DeclPtr, 4);

Modified: cfe/trunk/test/CodeGenObjC/blocks-2.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/blocks-2.m?rev=125823&r1=125822&r2=125823&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenObjC/blocks-2.m (original)
+++ cfe/trunk/test/CodeGenObjC/blocks-2.m Thu Feb 17 20:58:31 2011
@@ -26,16 +26,12 @@
   // CHECK:      invoke void @{{.*}}test1_help
   test1_help(^{ n = 20; });
 
-  // CHECK:      [[FORWARDING:%.*]] = getelementptr inbounds [[N_T]]* [[N]], i32 0, i32 1
-  // CHECK-NEXT: [[T0:%.*]] = load [[N_T]]** [[FORWARDING]]
-  // CHECK-NEXT: [[T1:%.*]] = bitcast [[N_T]]* [[T0]] to i8*
+  // CHECK:      [[T1:%.*]] = bitcast [[N_T]]* [[N]] to i8*
   // CHECK-NEXT: call void @_Block_object_dispose(i8* [[T1]], i32 8)
   // CHECK-NEXT: ret void
 
   // CHECK:      call i8* @llvm.eh.exception()
-  // CHECK:      [[FORWARDING:%.*]] = getelementptr inbounds [[N_T]]* [[N]], i32 0, i32 1
-  // CHECK-NEXT: [[T0:%.*]] = load [[N_T]]** [[FORWARDING]]
-  // CHECK-NEXT: [[T1:%.*]] = bitcast [[N_T]]* [[T0]] to i8*
+  // CHECK:      [[T1:%.*]] = bitcast [[N_T]]* [[N]] to i8*
   // CHECK-NEXT: call void @_Block_object_dispose(i8* [[T1]], i32 8)
   // CHECK:      call void @_Unwind_Resume_or_Rethrow(
 }

Modified: cfe/trunk/test/CodeGenObjC/blocks.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/blocks.m?rev=125823&r1=125822&r2=125823&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenObjC/blocks.m (original)
+++ cfe/trunk/test/CodeGenObjC/blocks.m Thu Feb 17 20:58:31 2011
@@ -1,13 +1,12 @@
-// RUN: %clang_cc1 -triple i386-apple-darwin9 -emit-llvm -fblocks -o %t %s
-// rdar://6676764
+// RUN: %clang_cc1 -triple i386-apple-darwin9 -emit-llvm -fblocks -o - %s | FileCheck %s
 
+// test1.  All of this is somehow testing rdar://6676764
 struct S {
   void (^F)(struct S*);
 } P;
 
 
 @interface T
-
   - (int)foo: (T (^)(T*)) x;
 @end
 
@@ -19,7 +18,7 @@
 -(void) im0;
 @end
 
-// RUN: grep 'define internal i32 @"__8-\[A im0\]_block_invoke_0"' %t
+// CHECK: define internal i32 @"__8-[A im0]_block_invoke_0"(
 @implementation A
 -(void) im0 {
   (void) ^{ return 1; }();
@@ -39,3 +38,52 @@
 }
 @end
 
+// rdar://problem/9006315
+// In-depth test for the initialization of a __weak __block variable.
+ at interface Test2 -(void) destroy; @end
+void test2(Test2 *x) {
+  extern void test2_helper(void (^)(void));
+  // CHECK:    define void @test2(
+  // CHECK:      [[X:%.*]] = alloca [[TEST2:%.*]]*,
+  // CHECK-NEXT: [[WEAKX:%.*]] = alloca [[WEAK_T:%.*]],
+  // CHECK-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:%.*]],
+  // CHECK-NEXT: store [[TEST2]]*
+
+  // isa=1 for weak byrefs.
+  // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[WEAK_T]]* [[WEAKX]], i32 0, i32 0
+  // CHECK-NEXT: store i8* inttoptr (i32 1 to i8*), i8** [[T0]]
+
+  // Forwarding.
+  // CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[WEAK_T]]* [[WEAKX]], i32 0, i32 1
+  // CHECK-NEXT: store [[WEAK_T]]* [[WEAKX]], [[WEAK_T]]** [[T1]]
+
+  // Flags.  This is just BLOCK_HAS_COPY_DISPOSE.
+  // CHECK-NEXT: [[T2:%.*]] = getelementptr inbounds [[WEAK_T]]* [[WEAKX]], i32 0, i32 2
+  // CHECK-NEXT: store i32 33554432, i32* [[T2]]
+
+  // Size.
+  // CHECK-NEXT: [[T3:%.*]] = getelementptr inbounds [[WEAK_T]]* [[WEAKX]], i32 0, i32 3
+  // CHECK-NEXT: store i32 28, i32* [[T3]]
+
+  // Copy and dipose helpers.
+  // CHECK-NEXT: [[T4:%.*]] = getelementptr inbounds [[WEAK_T]]* [[WEAKX]], i32 0, i32 4
+  // CHECK-NEXT: store i8* bitcast (void (i8*, i8*)* @__Block_byref_object_copy_{{.*}} to i8*), i8** [[T4]]
+  // CHECK-NEXT: [[T5:%.*]] = getelementptr inbounds [[WEAK_T]]* [[WEAKX]], i32 0, i32 5
+  // CHECK-NEXT: store i8* bitcast (void (i8*)* @__Block_byref_object_dispose_{{.*}} to i8*), i8** [[T5]]
+
+  // Actually capture the value.
+  // CHECK-NEXT: [[CAPTURE:%.*]] = load [[TEST2]]** [[X]]
+  // CHECK-NEXT: [[T6:%.*]] = getelementptr inbounds [[WEAK_T]]* [[WEAKX]], i32 0, i32 6
+  // CHECK-NEXT: store [[TEST2]]* [[CAPTURE]], [[TEST2]]** [[T6]]
+
+  // Then we initialize the block, blah blah blah.
+  // CHECK:      call void @test2_helper(
+
+  // Finally, kill the variable with BLOCK_FIELD_IS_BYREF.  We're not
+  // supposed to pass BLOCK_FIELD_IS_WEAK here.
+  // CHECK:      [[T0:%.*]] = bitcast [[WEAK_T]]* [[WEAKX]] to i8*
+  // CHECK:      call void @_Block_object_dispose(i8* [[T0]], i32 8)
+
+  __weak __block Test2 *weakX = x;
+  test2_helper(^{ [weakX destroy]; });
+}





More information about the cfe-commits mailing list