1f4a2713aSLionel Sambuc// RUN: %clang_cc1 -triple i386-apple-darwin9 -fobjc-runtime=macosx-fragile-10.5 -emit-llvm -fblocks -o - %s | FileCheck %s 2f4a2713aSLionel Sambuc 3f4a2713aSLionel Sambuc// test1. All of this is somehow testing rdar://6676764 4f4a2713aSLionel Sambucstruct S { 5f4a2713aSLionel Sambuc void (^F)(struct S*); 6f4a2713aSLionel Sambuc} P; 7f4a2713aSLionel Sambuc 8f4a2713aSLionel Sambuc 9f4a2713aSLionel Sambuc@interface T 10f4a2713aSLionel Sambuc - (int)foo: (T* (^)(T*)) x; 11f4a2713aSLionel Sambuc@end 12f4a2713aSLionel Sambuc 13f4a2713aSLionel Sambucvoid foo(T *P) { 14f4a2713aSLionel Sambuc [P foo: 0]; 15f4a2713aSLionel Sambuc} 16f4a2713aSLionel Sambuc 17f4a2713aSLionel Sambuc@interface A 18f4a2713aSLionel Sambuc-(void) im0; 19f4a2713aSLionel Sambuc@end 20f4a2713aSLionel Sambuc 21f4a2713aSLionel Sambuc// CHECK: define internal i32 @"__8-[A im0]_block_invoke"( 22f4a2713aSLionel Sambuc@implementation A 23f4a2713aSLionel Sambuc-(void) im0 { 24f4a2713aSLionel Sambuc (void) ^{ return 1; }(); 25f4a2713aSLionel Sambuc} 26f4a2713aSLionel Sambuc@end 27f4a2713aSLionel Sambuc 28f4a2713aSLionel Sambuc@interface B : A @end 29f4a2713aSLionel Sambuc@implementation B 30f4a2713aSLionel Sambuc-(void) im1 { 31f4a2713aSLionel Sambuc ^(void) { [self im0]; }(); 32f4a2713aSLionel Sambuc} 33f4a2713aSLionel Sambuc-(void) im2 { 34f4a2713aSLionel Sambuc ^{ [super im0]; }(); 35f4a2713aSLionel Sambuc} 36f4a2713aSLionel Sambuc-(void) im3 { 37f4a2713aSLionel Sambuc ^{ ^{[super im0];}(); }(); 38f4a2713aSLionel Sambuc} 39f4a2713aSLionel Sambuc@end 40f4a2713aSLionel Sambuc 41f4a2713aSLionel Sambuc// rdar://problem/9006315 42f4a2713aSLionel Sambuc// In-depth test for the initialization of a __weak __block variable. 43f4a2713aSLionel Sambuc@interface Test2 -(void) destroy; @end 44f4a2713aSLionel Sambucvoid test2(Test2 *x) { 45f4a2713aSLionel Sambuc extern void test2_helper(void (^)(void)); 46f4a2713aSLionel Sambuc // CHECK-LABEL: define void @test2( 47f4a2713aSLionel Sambuc // CHECK: [[X:%.*]] = alloca [[TEST2:%.*]]*, 48f4a2713aSLionel Sambuc // CHECK-NEXT: [[WEAKX:%.*]] = alloca [[WEAK_T:%.*]], 49f4a2713aSLionel Sambuc // CHECK-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]], 50f4a2713aSLionel Sambuc // CHECK-NEXT: store [[TEST2]]* 51f4a2713aSLionel Sambuc 52f4a2713aSLionel Sambuc // isa=1 for weak byrefs. 53f4a2713aSLionel Sambuc // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[WEAK_T]]* [[WEAKX]], i32 0, i32 0 54f4a2713aSLionel Sambuc // CHECK-NEXT: store i8* inttoptr (i32 1 to i8*), i8** [[T0]] 55f4a2713aSLionel Sambuc 56f4a2713aSLionel Sambuc // Forwarding. 57f4a2713aSLionel Sambuc // CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[WEAK_T]]* [[WEAKX]], i32 0, i32 1 58f4a2713aSLionel Sambuc // CHECK-NEXT: store [[WEAK_T]]* [[WEAKX]], [[WEAK_T]]** [[T1]] 59f4a2713aSLionel Sambuc 60f4a2713aSLionel Sambuc // Flags. This is just BLOCK_HAS_COPY_DISPOSE BLOCK_BYREF_LAYOUT_UNRETAINED 61f4a2713aSLionel Sambuc // CHECK-NEXT: [[T2:%.*]] = getelementptr inbounds [[WEAK_T]]* [[WEAKX]], i32 0, i32 2 62f4a2713aSLionel Sambuc // CHECK-NEXT: store i32 1375731712, i32* [[T2]] 63f4a2713aSLionel Sambuc 64f4a2713aSLionel Sambuc // Size. 65f4a2713aSLionel Sambuc // CHECK-NEXT: [[T3:%.*]] = getelementptr inbounds [[WEAK_T]]* [[WEAKX]], i32 0, i32 3 66f4a2713aSLionel Sambuc // CHECK-NEXT: store i32 28, i32* [[T3]] 67f4a2713aSLionel Sambuc 68*0a6a1f1dSLionel Sambuc // Copy and dispose helpers. 69f4a2713aSLionel Sambuc // CHECK-NEXT: [[T4:%.*]] = getelementptr inbounds [[WEAK_T]]* [[WEAKX]], i32 0, i32 4 70f4a2713aSLionel Sambuc // CHECK-NEXT: store i8* bitcast (void (i8*, i8*)* @__Block_byref_object_copy_{{.*}} to i8*), i8** [[T4]] 71f4a2713aSLionel Sambuc // CHECK-NEXT: [[T5:%.*]] = getelementptr inbounds [[WEAK_T]]* [[WEAKX]], i32 0, i32 5 72f4a2713aSLionel Sambuc // CHECK-NEXT: store i8* bitcast (void (i8*)* @__Block_byref_object_dispose_{{.*}} to i8*), i8** [[T5]] 73f4a2713aSLionel Sambuc 74f4a2713aSLionel Sambuc // Actually capture the value. 75f4a2713aSLionel Sambuc // CHECK-NEXT: [[T6:%.*]] = getelementptr inbounds [[WEAK_T]]* [[WEAKX]], i32 0, i32 6 76f4a2713aSLionel Sambuc // CHECK-NEXT: [[CAPTURE:%.*]] = load [[TEST2]]** [[X]] 77f4a2713aSLionel Sambuc // CHECK-NEXT: store [[TEST2]]* [[CAPTURE]], [[TEST2]]** [[T6]] 78f4a2713aSLionel Sambuc 79f4a2713aSLionel Sambuc // Then we initialize the block, blah blah blah. 80f4a2713aSLionel Sambuc // CHECK: call void @test2_helper( 81f4a2713aSLionel Sambuc 82f4a2713aSLionel Sambuc // Finally, kill the variable with BLOCK_FIELD_IS_BYREF. We're not 83f4a2713aSLionel Sambuc // supposed to pass BLOCK_FIELD_IS_WEAK here. 84f4a2713aSLionel Sambuc // CHECK: [[T0:%.*]] = bitcast [[WEAK_T]]* [[WEAKX]] to i8* 85f4a2713aSLionel Sambuc // CHECK: call void @_Block_object_dispose(i8* [[T0]], i32 8) 86f4a2713aSLionel Sambuc 87f4a2713aSLionel Sambuc __weak __block Test2 *weakX = x; 88f4a2713aSLionel Sambuc test2_helper(^{ [weakX destroy]; }); 89f4a2713aSLionel Sambuc} 90f4a2713aSLionel Sambuc 91f4a2713aSLionel Sambuc// rdar://problem/9124263 92f4a2713aSLionel Sambuc// In the test above, check that the use in the invocation function 93f4a2713aSLionel Sambuc// doesn't require a read barrier. 94f4a2713aSLionel Sambuc// CHECK-LABEL: define internal void @__test2_block_invoke 95f4a2713aSLionel Sambuc// CHECK: [[BLOCK:%.*]] = bitcast i8* {{%.*}} to [[BLOCK_T]]* 96f4a2713aSLionel Sambuc// CHECK-NOT: bitcast 97f4a2713aSLionel Sambuc// CHECK: [[T0:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5 98f4a2713aSLionel Sambuc// CHECK-NEXT: [[T1:%.*]] = load i8** [[T0]] 99f4a2713aSLionel Sambuc// CHECK-NEXT: [[T2:%.*]] = bitcast i8* [[T1]] to [[WEAK_T]]{{.*}}* 100f4a2713aSLionel Sambuc// CHECK-NEXT: [[T3:%.*]] = getelementptr inbounds [[WEAK_T]]{{.*}}* [[T2]], i32 0, i32 1 101f4a2713aSLionel Sambuc// CHECK-NEXT: [[T4:%.*]] = load [[WEAK_T]]{{.*}}** [[T3]] 102f4a2713aSLionel Sambuc// CHECK-NEXT: [[WEAKX:%.*]] = getelementptr inbounds [[WEAK_T]]{{.*}}* [[T4]], i32 0, i32 6 103f4a2713aSLionel Sambuc// CHECK-NEXT: [[T0:%.*]] = load [[TEST2]]** [[WEAKX]], align 4 104f4a2713aSLionel Sambuc 105f4a2713aSLionel Sambuc// rdar://problem/12722954 106f4a2713aSLionel Sambuc// Make sure that ... is appropriately positioned in a block call. 107f4a2713aSLionel Sambucvoid test3(void (^block)(int, ...)) { 108f4a2713aSLionel Sambuc block(0, 1, 2, 3); 109f4a2713aSLionel Sambuc} 110f4a2713aSLionel Sambuc// CHECK-LABEL: define void @test3( 111f4a2713aSLionel Sambuc// CHECK: [[BLOCK:%.*]] = alloca void (i32, ...)*, align 4 112f4a2713aSLionel Sambuc// CHECK-NEXT: store void (i32, ...)* 113f4a2713aSLionel Sambuc// CHECK-NEXT: [[T0:%.*]] = load void (i32, ...)** [[BLOCK]], align 4 114f4a2713aSLionel Sambuc// CHECK-NEXT: [[T1:%.*]] = bitcast void (i32, ...)* [[T0]] to [[BLOCK_T:%.*]]* 115f4a2713aSLionel Sambuc// CHECK-NEXT: [[T2:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[T1]], i32 0, i32 3 116f4a2713aSLionel Sambuc// CHECK-NEXT: [[T3:%.*]] = bitcast [[BLOCK_T]]* [[T1]] to i8* 117f4a2713aSLionel Sambuc// CHECK-NEXT: [[T4:%.*]] = load i8** [[T2]] 118f4a2713aSLionel Sambuc// CHECK-NEXT: [[T5:%.*]] = bitcast i8* [[T4]] to void (i8*, i32, ...)* 119f4a2713aSLionel Sambuc// CHECK-NEXT: call void (i8*, i32, ...)* [[T5]](i8* [[T3]], i32 0, i32 1, i32 2, i32 3) 120f4a2713aSLionel Sambuc// CHECK-NEXT: ret void 121f4a2713aSLionel Sambuc 122f4a2713aSLionel Sambucvoid test4(void (^block)()) { 123f4a2713aSLionel Sambuc block(0, 1, 2, 3); 124f4a2713aSLionel Sambuc} 125f4a2713aSLionel Sambuc// CHECK-LABEL: define void @test4( 126f4a2713aSLionel Sambuc// CHECK: [[BLOCK:%.*]] = alloca void (...)*, align 4 127f4a2713aSLionel Sambuc// CHECK-NEXT: store void (...)* 128f4a2713aSLionel Sambuc// CHECK-NEXT: [[T0:%.*]] = load void (...)** [[BLOCK]], align 4 129f4a2713aSLionel Sambuc// CHECK-NEXT: [[T1:%.*]] = bitcast void (...)* [[T0]] to [[BLOCK_T:%.*]]* 130f4a2713aSLionel Sambuc// CHECK-NEXT: [[T2:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[T1]], i32 0, i32 3 131f4a2713aSLionel Sambuc// CHECK-NEXT: [[T3:%.*]] = bitcast [[BLOCK_T]]* [[T1]] to i8* 132f4a2713aSLionel Sambuc// CHECK-NEXT: [[T4:%.*]] = load i8** [[T2]] 133f4a2713aSLionel Sambuc// CHECK-NEXT: [[T5:%.*]] = bitcast i8* [[T4]] to void (i8*, i32, i32, i32, i32)* 134f4a2713aSLionel Sambuc// CHECK-NEXT: call void [[T5]](i8* [[T3]], i32 0, i32 1, i32 2, i32 3) 135f4a2713aSLionel Sambuc// CHECK-NEXT: ret void 136