1*67e74705SXin Li// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-runtime=macosx-10.10 -emit-llvm -fblocks -fobjc-weak -o - %s | FileCheck %s -check-prefix=CHECK -check-prefix=CHECK-MODERN 2*67e74705SXin Li// RUN: %clang_cc1 -triple i386-apple-darwin10 -fobjc-runtime=macosx-fragile-10.10 -emit-llvm -fblocks -fobjc-weak -o - %s | FileCheck %s -check-prefix=CHECK -check-prefix=CHECK-FRAGILE 3*67e74705SXin Li 4*67e74705SXin Li@interface Object 5*67e74705SXin Li- (instancetype) retain; 6*67e74705SXin Li- (void) run; 7*67e74705SXin Li@end 8*67e74705SXin Li 9*67e74705SXin Li// The ivars in HighlyAlignedSubclass should be placed in the tail-padding 10*67e74705SXin Li// of the superclass. Ensure that they're still covered by layouts. 11*67e74705SXin Li@interface HighlyAligned : Object { 12*67e74705SXin Li __attribute__((aligned(32))) void *array[2]; 13*67e74705SXin Li} 14*67e74705SXin Li@end 15*67e74705SXin Li// CHECK-MODERN: @"OBJC_IVAR_$_HighlyAlignedSubclass.ivar2" = global i64 24, 16*67e74705SXin Li// CHECK-MODERN: @"OBJC_IVAR_$_HighlyAlignedSubclass.ivar" = global i64 16, 17*67e74705SXin Li// CHECK-MODERN: @OBJC_CLASS_NAME_{{.*}} = {{.*}} c"\02\00" 18*67e74705SXin Li// CHECK-MODERN: @"\01l_OBJC_CLASS_RO_$_HighlyAlignedSubclass" = {{.*}} { 19*67e74705SXin Li// CHECK-FRAGILE: @OBJC_INSTANCE_VARIABLES_HighlyAlignedSubclass = {{.*}}, i32 8 }, {{.*}}, i32 12 }] 20*67e74705SXin Li// CHECK-FRAGILE: @OBJC_CLASS_NAME_{{.*}} = {{.*}} c"\02\00" 21*67e74705SXin Li// CHECK-FRAGILE: @OBJC_CLASS_HighlyAlignedSubclass 22*67e74705SXin Li@interface HighlyAlignedSubclass : HighlyAligned { 23*67e74705SXin Li __weak id ivar; 24*67e74705SXin Li __weak id ivar2; 25*67e74705SXin Li} 26*67e74705SXin Li@end 27*67e74705SXin Li@implementation HighlyAlignedSubclass @end 28*67e74705SXin Li 29*67e74705SXin Li// CHECK-MODERN: @OBJC_CLASS_NAME_{{.*}} = {{.*}} c"\01\00" 30*67e74705SXin Li// CHECK-MODERN: @"\01l_OBJC_CLASS_RO_$_Foo" = {{.*}} { i32 772 31*67e74705SXin Li// 772 == 0x304 32*67e74705SXin Li// ^ HasMRCWeakIvars 33*67e74705SXin Li// ^ HasCXXDestructorOnly 34*67e74705SXin Li// ^ HasCXXStructors 35*67e74705SXin Li 36*67e74705SXin Li// CHECK-FRAGILE: @OBJC_CLASS_NAME_{{.*}} = {{.*}} c"\01\00" 37*67e74705SXin Li// CHECK-FRAGILE: @OBJC_CLASS_Foo = {{.*}} i32 134225921, 38*67e74705SXin Li// 134225921 == 0x08002001 39*67e74705SXin Li// ^ HasMRCWeakIvars 40*67e74705SXin Li// ^ HasCXXStructors 41*67e74705SXin Li// ^ Factory 42*67e74705SXin Li@interface Foo : Object { 43*67e74705SXin Li __weak id ivar; 44*67e74705SXin Li} 45*67e74705SXin Li@end 46*67e74705SXin Li 47*67e74705SXin Li@implementation Foo 48*67e74705SXin Li// CHECK-LABEL: define internal void @"\01-[Foo .cxx_destruct]" 49*67e74705SXin Li// CHECK: call void @objc_destroyWeak 50*67e74705SXin Li@end 51*67e74705SXin Li 52*67e74705SXin Li 53*67e74705SXin Livoid test1(__weak id x) {} 54*67e74705SXin Li// CHECK-LABEL: define void @test1 55*67e74705SXin Li// CHECK: [[X:%.*]] = alloca i8*, 56*67e74705SXin Li// CHECK-NEXT: objc_initWeak 57*67e74705SXin Li// CHECK-NEXT: objc_destroyWeak 58*67e74705SXin Li// CHECK-NEXT: ret void 59*67e74705SXin Li 60*67e74705SXin Livoid test2(id y) { 61*67e74705SXin Li __weak id z = y; 62*67e74705SXin Li} 63*67e74705SXin Li// CHECK-LABEL: define void @test2 64*67e74705SXin Li// CHECK: [[Y:%.*]] = alloca i8*, 65*67e74705SXin Li// CHECK-NEXT: [[Z:%.*]] = alloca i8*, 66*67e74705SXin Li// CHECK-NEXT: store 67*67e74705SXin Li// CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[Y]] 68*67e74705SXin Li// CHECK-NEXT: call i8* @objc_initWeak(i8** [[Z]], i8* [[T0]]) 69*67e74705SXin Li// CHECK-NEXT: call void @objc_destroyWeak(i8** [[Z]]) 70*67e74705SXin Li// CHECK-NEXT: ret void 71*67e74705SXin Li 72*67e74705SXin Livoid test3(id y) { 73*67e74705SXin Li __weak id z; 74*67e74705SXin Li z = y; 75*67e74705SXin Li} 76*67e74705SXin Li// CHECK-LABEL: define void @test3 77*67e74705SXin Li// CHECK: [[Y:%.*]] = alloca i8*, 78*67e74705SXin Li// CHECK-NEXT: [[Z:%.*]] = alloca i8*, 79*67e74705SXin Li// CHECK-NEXT: store 80*67e74705SXin Li// CHECK-NEXT: store i8* null, i8** [[Z]] 81*67e74705SXin Li// CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[Y]] 82*67e74705SXin Li// CHECK-NEXT: call i8* @objc_storeWeak(i8** [[Z]], i8* [[T0]]) 83*67e74705SXin Li// CHECK-NEXT: call void @objc_destroyWeak(i8** [[Z]]) 84*67e74705SXin Li// CHECK-NEXT: ret void 85*67e74705SXin Li 86*67e74705SXin Livoid test4(__weak id *p) { 87*67e74705SXin Li id y = *p; 88*67e74705SXin Li} 89*67e74705SXin Li// CHECK-LABEL: define void @test4 90*67e74705SXin Li// CHECK: [[P:%.*]] = alloca i8**, 91*67e74705SXin Li// CHECK-NEXT: [[Y:%.*]] = alloca i8*, 92*67e74705SXin Li// CHECK-NEXT: store 93*67e74705SXin Li// CHECK-NEXT: [[T0:%.*]] = load i8**, i8*** [[P]] 94*67e74705SXin Li// CHECK-NEXT: [[T1:%.*]] = call i8* @objc_loadWeak(i8** [[T0]]) 95*67e74705SXin Li// CHECK-NEXT: store i8* [[T1]], i8** [[Y]] 96*67e74705SXin Li// CHECK-NEXT: ret void 97*67e74705SXin Li 98*67e74705SXin Livoid test5(__weak id *p) { 99*67e74705SXin Li id y = [*p retain]; 100*67e74705SXin Li} 101*67e74705SXin Li// CHECK-LABEL: define void @test5 102*67e74705SXin Li// CHECK: [[P:%.*]] = alloca i8**, 103*67e74705SXin Li// CHECK-NEXT: [[Y:%.*]] = alloca i8*, 104*67e74705SXin Li// CHECK-NEXT: store 105*67e74705SXin Li// CHECK-NEXT: [[T0:%.*]] = load i8**, i8*** [[P]] 106*67e74705SXin Li// CHECK-NEXT: [[T1:%.*]] = call i8* @objc_loadWeakRetained(i8** [[T0]]) 107*67e74705SXin Li// CHECK-NEXT: store i8* [[T1]], i8** [[Y]] 108*67e74705SXin Li// CHECK-NEXT: ret void 109*67e74705SXin Li 110*67e74705SXin Livoid test6(__weak Foo **p) { 111*67e74705SXin Li Foo *y = [*p retain]; 112*67e74705SXin Li} 113*67e74705SXin Li// CHECK-LABEL: define void @test6 114*67e74705SXin Li// CHECK: [[P:%.*]] = alloca [[FOO:%.*]]**, 115*67e74705SXin Li// CHECK-NEXT: [[Y:%.*]] = alloca [[FOO]]*, 116*67e74705SXin Li// CHECK-NEXT: store 117*67e74705SXin Li// CHECK-NEXT: [[T0:%.*]] = load [[FOO]]**, [[FOO]]*** [[P]] 118*67e74705SXin Li// CHECK-NEXT: [[T1:%.*]] = bitcast [[FOO]]** [[T0]] to i8** 119*67e74705SXin Li// CHECK-NEXT: [[T2:%.*]] = call i8* @objc_loadWeakRetained(i8** [[T1]]) 120*67e74705SXin Li// CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[FOO]]* 121*67e74705SXin Li// CHECK-NEXT: store [[FOO]]* [[T3]], [[FOO]]** [[Y]] 122*67e74705SXin Li// CHECK-NEXT: ret void 123*67e74705SXin Li 124*67e74705SXin Liextern id get_object(void); 125*67e74705SXin Liextern void use_block(void (^)(void)); 126*67e74705SXin Li 127*67e74705SXin Livoid test7(void) { 128*67e74705SXin Li __weak Foo *p = get_object(); 129*67e74705SXin Li use_block(^{ [p run ]; }); 130*67e74705SXin Li} 131*67e74705SXin Li// CHECK-LABEL: define void @test7 132*67e74705SXin Li// CHECK: [[P:%.*]] = alloca [[FOO]]*, 133*67e74705SXin Li// CHECK: [[T0:%.*]] = call i8* @get_object() 134*67e74705SXin Li// CHECK-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to [[FOO]]* 135*67e74705SXin Li// CHECK-NEXT: [[T2:%.*]] = bitcast [[FOO]]** [[P]] to i8** 136*67e74705SXin Li// CHECK-NEXT: [[T3:%.*]] = bitcast [[FOO]]* [[T1]] to i8* 137*67e74705SXin Li// CHECK-NEXT: call i8* @objc_initWeak(i8** [[T2]], i8* [[T3]]) 138*67e74705SXin Li// CHECK: call void @objc_copyWeak 139*67e74705SXin Li// CHECK: call void @use_block 140*67e74705SXin Li// CHECK: call void @objc_destroyWeak 141*67e74705SXin Li 142*67e74705SXin Li// CHECK-LABEL: define internal void @__copy_helper_block 143*67e74705SXin Li// CHECK: @objc_copyWeak 144*67e74705SXin Li 145*67e74705SXin Li// CHECK-LABEL: define internal void @__destroy_helper_block 146*67e74705SXin Li// CHECK: @objc_destroyWeak 147*67e74705SXin Li 148*67e74705SXin Livoid test8(void) { 149*67e74705SXin Li __block __weak Foo *p = get_object(); 150*67e74705SXin Li use_block(^{ [p run ]; }); 151*67e74705SXin Li} 152*67e74705SXin Li// CHECK-LABEL: define void @test8 153*67e74705SXin Li// CHECK: call i8* @objc_initWeak 154*67e74705SXin Li// CHECK-NOT: call void @objc_copyWeak 155*67e74705SXin Li// CHECK: call void @use_block 156*67e74705SXin Li// CHECK: call void @objc_destroyWeak 157*67e74705SXin Li 158*67e74705SXin Li// CHECK-LABEL: define internal void @__Block_byref_object_copy 159*67e74705SXin Li// CHECK: call void @objc_moveWeak 160*67e74705SXin Li 161*67e74705SXin Li// CHECK-LABEL: define internal void @__Block_byref_object_dispose 162*67e74705SXin Li// CHECK: call void @objc_destroyWeak 163*67e74705SXin Li 164*67e74705SXin Li// CHECK-LABEL: define void @test9_baseline() 165*67e74705SXin Li// CHECK: define internal void @__copy_helper 166*67e74705SXin Li// CHECK: define internal void @__destroy_helper 167*67e74705SXin Livoid test9_baseline(void) { 168*67e74705SXin Li Foo *p = get_object(); 169*67e74705SXin Li use_block(^{ [p run]; }); 170*67e74705SXin Li} 171*67e74705SXin Li 172*67e74705SXin Li// CHECK-LABEL: define void @test9() 173*67e74705SXin Li// CHECK-NOT: define internal void @__copy_helper 174*67e74705SXin Li// CHECK-NOT: define internal void @__destroy_helper 175*67e74705SXin Li// CHECK: define void @test9_fin() 176*67e74705SXin Livoid test9(void) { 177*67e74705SXin Li __unsafe_unretained Foo *p = get_object(); 178*67e74705SXin Li use_block(^{ [p run]; }); 179*67e74705SXin Li} 180*67e74705SXin Livoid test9_fin() {} 181*67e74705SXin Li 182*67e74705SXin Li// CHECK-LABEL: define void @test10() 183*67e74705SXin Li// CHECK-NOT: define internal void @__copy_helper 184*67e74705SXin Li// CHECK-NOT: define internal void @__destroy_helper 185*67e74705SXin Li// CHECK: define void @test10_fin() 186*67e74705SXin Livoid test10(void) { 187*67e74705SXin Li typedef __unsafe_unretained Foo *UnsafeFooPtr; 188*67e74705SXin Li UnsafeFooPtr p = get_object(); 189*67e74705SXin Li use_block(^{ [p run]; }); 190*67e74705SXin Li} 191*67e74705SXin Livoid test10_fin() {} 192