1// RUN: %clang_cc1 -triple i386-apple-darwin10 -emit-llvm -fblocks -fobjc-arc -fobjc-exceptions -fobjc-runtime=macosx-fragile-10.10 -o - %s | FileCheck %s 2// RUN: %clang_cc1 -triple i386-apple-darwin10 -emit-llvm -fblocks -fobjc-arc -fobjc-exceptions -fobjc-runtime=macosx-fragile-10.10 -o - %s | FileCheck %s -check-prefix=GLOBALS 3 4@class Opaque; 5 6@interface Root { 7 Class isa; 8} 9@end 10 11@interface A : Root { 12 Opaque *strong; 13 __weak Opaque *weak; 14} 15@end 16 17// GLOBALS-LABEL @OBJC_METACLASS_A 18// Strong layout: scan the first word. 19// GLOBALS: @OBJC_CLASS_NAME_{{.*}} = private global [2 x i8] c"\01\00" 20// Weak layout: skip the first word, scan the second word. 21// GLOBALS: @OBJC_CLASS_NAME_{{.*}} = private global [2 x i8] c"\11\00" 22 23// 0x04002001 24// ^ is compiled by ARC (controls interpretation of layouts) 25// ^ has C++ structors (no distinction for zero-initializable) 26// ^ factory (always set on non-metaclasses) 27// GLOBALS: @OBJC_CLASS_A = private global {{.*}} i32 67117057 28 29@implementation A 30// CHECK-LABEL: define internal void @"\01-[A testStrong]" 31// CHECK: [[SELFVAR:%.*]] = alloca [[A:%.*]]*, align 4 32- (void) testStrong { 33// CHECK: [[X:%.*]] = alloca [[OPAQUE:%.*]]*, align 4 34// CHECK: [[SELF:%.*]] = load [[A]]*, [[A]]** [[SELFVAR]] 35// CHECK-NEXT: [[T0:%.*]] = bitcast [[A]]* [[SELF]] to i8* 36// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i8, i8* [[T0]], i32 4 37// CHECK-NEXT: [[IVAR:%.*]] = bitcast i8* [[T1]] to [[OPAQUE]]** 38// CHECK-NEXT: [[T0:%.*]] = load [[OPAQUE]]*, [[OPAQUE]]** [[IVAR]] 39// CHECK-NEXT: [[T1:%.*]] = bitcast [[OPAQUE]]* [[T0]] to i8* 40// CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retain(i8* [[T1]]) 41// CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[OPAQUE]]* 42// CHECK-NEXT: store [[OPAQUE]]* [[T3]], [[OPAQUE]]** [[X]] 43 Opaque *x = strong; 44// CHECK-NEXT: [[VALUE:%.*]] = load [[OPAQUE]]*, [[OPAQUE]]** [[X]] 45// CHECK-NEXT: [[SELF:%.*]] = load [[A]]*, [[A]]** [[SELFVAR]] 46// CHECK-NEXT: [[T0:%.*]] = bitcast [[A]]* [[SELF]] to i8* 47// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i8, i8* [[T0]], i32 4 48// CHECK-NEXT: [[IVAR:%.*]] = bitcast i8* [[T1]] to [[OPAQUE]]** 49// CHECK-NEXT: [[T0:%.*]] = bitcast [[OPAQUE]]** [[IVAR]] to i8** 50// CHECK-NEXT: [[T1:%.*]] = bitcast [[OPAQUE]]* [[VALUE]] to i8* 51// CHECK-NEXT: call void @objc_storeStrong(i8** [[T0]], i8* [[T1]]) 52 strong = x; 53// CHECK-NEXT: [[T0:%.*]] = bitcast [[OPAQUE]]** [[X]] to i8** 54// CHECK-NEXT: call void @objc_storeStrong(i8** [[T0]], i8* null) 55// CHECK-NEXT: ret void 56} 57 58// CHECK-LABEL: define internal void @"\01-[A testWeak]" 59// CHECK: [[SELFVAR:%.*]] = alloca [[A]]*, align 4 60- (void) testWeak { 61// CHECK: [[X:%.*]] = alloca [[OPAQUE]]*, align 4 62// CHECK: [[SELF:%.*]] = load [[A]]*, [[A]]** [[SELFVAR]] 63// CHECK-NEXT: [[T0:%.*]] = bitcast [[A]]* [[SELF]] to i8* 64// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i8, i8* [[T0]], i32 8 65// CHECK-NEXT: [[IVAR:%.*]] = bitcast i8* [[T1]] to [[OPAQUE]]** 66// CHECK-NEXT: [[T0:%.*]] = bitcast [[OPAQUE]]** [[IVAR]] to i8** 67// CHECK-NEXT: [[T1:%.*]] = call i8* @objc_loadWeakRetained(i8** [[T0]]) 68// CHECK-NEXT: [[T2:%.*]] = bitcast i8* [[T1]] to [[OPAQUE]]* 69// CHECK-NEXT: store [[OPAQUE]]* [[T2]], [[OPAQUE]]** [[X]] 70 Opaque *x = weak; 71// CHECK-NEXT: [[VALUE:%.*]] = load [[OPAQUE]]*, [[OPAQUE]]** [[X]] 72// CHECK-NEXT: [[SELF:%.*]] = load [[A]]*, [[A]]** [[SELFVAR]] 73// CHECK-NEXT: [[T0:%.*]] = bitcast [[A]]* [[SELF]] to i8* 74// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i8, i8* [[T0]], i32 8 75// CHECK-NEXT: [[IVAR:%.*]] = bitcast i8* [[T1]] to [[OPAQUE]]** 76// CHECK-NEXT: [[T0:%.*]] = bitcast [[OPAQUE]]** [[IVAR]] to i8** 77// CHECK-NEXT: [[T1:%.*]] = bitcast [[OPAQUE]]* [[VALUE]] to i8* 78// CHECK-NEXT: call i8* @objc_storeWeak(i8** [[T0]], i8* [[T1]]) 79 weak = x; 80// CHECK-NEXT: [[T0:%.*]] = bitcast [[OPAQUE]]** [[X]] to i8** 81// CHECK-NEXT: call void @objc_storeStrong(i8** [[T0]], i8* null) 82// CHECK-NEXT: ret void 83} 84 85// CHECK-LABEL: define internal void @"\01-[A .cxx_destruct]" 86// CHECK: [[SELFVAR:%.*]] = alloca [[A]]*, align 4 87// CHECK: [[SELF:%.*]] = load [[A]]*, [[A]]** [[SELFVAR]] 88// CHECK-NEXT: [[T0:%.*]] = bitcast [[A]]* [[SELF]] to i8* 89// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i8, i8* [[T0]], i32 8 90// CHECK-NEXT: [[IVAR:%.*]] = bitcast i8* [[T1]] to [[OPAQUE]]** 91// CHECK-NEXT: [[T0:%.*]] = bitcast [[OPAQUE]]** [[IVAR]] to i8** 92// CHECK-NEXT: call void @objc_destroyWeak(i8** [[T0]]) 93// CHECK-NEXT: [[T0:%.*]] = bitcast [[A]]* [[SELF]] to i8* 94// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i8, i8* [[T0]], i32 4 95// CHECK-NEXT: [[IVAR:%.*]] = bitcast i8* [[T1]] to [[OPAQUE]]** 96// CHECK-NEXT: [[T0:%.*]] = bitcast [[OPAQUE]]** [[IVAR]] to i8** 97// CHECK-NEXT: call void @objc_storeStrong(i8** [[T0]], i8* null) 98// CHECK-NEXT: ret void 99@end 100 101// Test case for corner case of ivar layout. 102@interface B : A { 103 char _b_flag; 104} 105@end 106 107@interface C : B { 108 char _c_flag; 109 __unsafe_unretained id c_unsafe[5]; 110 id c_strong[4]; 111 __weak id c_weak[3]; 112 id c_strong2[7]; 113} 114@end 115@implementation C @end 116 117// Note that these layouts implicitly start at the end of the previous 118// class rounded up to pointer alignment. 119// GLOBALS-LABEL: @OBJC_METACLASS_C 120// Strong layout: skip five, scan four, skip three, scan seven 121// 'T' == 0x54, '7' == 0x37 122// GLOBALS: @OBJC_CLASS_NAME_{{.*}} = private global [3 x i8] c"T7\00" 123// Weak layout: skip nine, scan three 124// GLOBALS: @OBJC_CLASS_NAME_{{.*}} = private global [2 x i8] c"\93\00" 125 126extern void useBlock(void (^block)(void)); 127 128// 256 == 0x100 == starts with 1 strong 129// GLOBALS: @__block_descriptor_tmp{{.*}} = internal constant {{.*}}, i32 256 } 130void testBlockLayoutStrong(id x) { 131 useBlock(^{ (void) x; }); 132} 133 134// 1 == 0x001 == starts with 1 weak 135// GLOBALS: @__block_descriptor_tmp{{.*}} = internal constant {{.*}}, i32 1 } 136void testBlockLayoutWeak(__weak id x) { 137 useBlock(^{ (void) x; }); 138} 139 140// CHECK-LABEL: define void @testCatch() 141// CHECK: [[X:%.*]] = alloca [[A:%.*]]*, align 4 142// CHECK: [[Y:%.*]] = alloca i8*, align 4 143// CHECK: call void @objc_exception_try_enter 144// CHECK: br i1 145// CHECK: call void @checkpoint(i32 0) 146// CHECK: call void @objc_exception_try_exit 147// CHECK: br label 148// CHECK: call void @checkpoint(i32 3) 149// CHECK: [[EXN:%.*]] = call i8* @objc_exception_extract 150// CHECK: call i32 @objc_exception_match( 151// CHECK: br i1 152// CHECK: [[T0:%.*]] = bitcast i8* [[EXN]] to [[A]]* 153// CHECK: [[T1:%.*]] = bitcast [[A]]* [[T0]] to i8* 154// CHECK: [[T2:%.*]] = call i8* @objc_retain(i8* [[T1]]) 155// CHECK: [[T3:%.*]] = bitcast i8* [[T2]] to [[A]]* 156// CHECK: store [[A]]* [[T3]], [[A]]** [[X]] 157// CHECK: call void @checkpoint(i32 1) 158// CHECK: [[T0:%.*]] = bitcast [[A]]** [[X]] to i8** 159// CHECK: call void @objc_storeStrong(i8** [[T0]], i8* null) 160// CHECK: br label 161// CHECK: [[T0:%.*]] = call i8* @objc_retain(i8* [[EXN]]) 162// CHECK: store i8* [[T0]], i8** [[Y]] 163// CHECK: call void @checkpoint(i32 2) 164// CHECK: call void @objc_storeStrong(i8** [[Y]], i8* null) 165extern void checkpoint(int n); 166void testCatch() { 167 @try { 168 checkpoint(0); 169 } @catch (A *x) { 170 checkpoint(1); 171 } @catch (id y) { 172 checkpoint(2); 173 } 174 checkpoint(3); 175} 176