[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