252
|
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
|
150
|
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
|
173
|
17 // GLOBALS-LABEL: @OBJC_METACLASS_A
|
150
|
18 // Strong layout: scan the first word.
|
|
19 // GLOBALS: @OBJC_CLASS_NAME_{{.*}} = private unnamed_addr constant [2 x i8] c"\01\00"
|
|
20 // Weak layout: skip the first word, scan the second word.
|
|
21 // GLOBALS: @OBJC_CLASS_NAME_{{.*}} = private unnamed_addr constant [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]"
|
252
|
31 // CHECK: [[SELFVAR:%.*]] = alloca ptr, align 4
|
150
|
32 - (void) testStrong {
|
252
|
33 // CHECK: [[X:%x]] = alloca ptr, align 4
|
|
34 // CHECK: [[SELF:%.*]] = load ptr, ptr [[SELFVAR]]
|
|
35 // CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i8, ptr [[SELF]], i32 4
|
|
36 // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[T1]]
|
|
37 // CHECK-NEXT: [[T2:%.*]] = call ptr @llvm.objc.retain(ptr [[T0]])
|
|
38 // CHECK-NEXT: store ptr [[T2]], ptr [[X]]
|
150
|
39 Opaque *x = strong;
|
252
|
40 // CHECK-NEXT: [[VALUE:%.*]] = load ptr, ptr [[X]]
|
|
41 // CHECK-NEXT: [[SELF:%.*]] = load ptr, ptr [[SELFVAR]]
|
|
42 // CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i8, ptr [[SELF]], i32 4
|
|
43 // CHECK-NEXT: call void @llvm.objc.storeStrong(ptr [[T1]], ptr [[VALUE]])
|
150
|
44 strong = x;
|
252
|
45 // CHECK-NEXT: call void @llvm.objc.storeStrong(ptr [[X]], ptr null)
|
150
|
46 // CHECK-NEXT: ret void
|
|
47 }
|
|
48
|
|
49 // CHECK-LABEL: define internal void @"\01-[A testWeak]"
|
252
|
50 // CHECK: [[SELFVAR:%.*]] = alloca ptr, align 4
|
150
|
51 - (void) testWeak {
|
252
|
52 // CHECK: [[X:%x]] = alloca ptr, align 4
|
|
53 // CHECK: [[SELF:%.*]] = load ptr, ptr [[SELFVAR]]
|
|
54 // CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i8, ptr [[SELF]], i32 8
|
|
55 // CHECK-NEXT: [[T2:%.*]] = call ptr @llvm.objc.loadWeakRetained(ptr [[T1]])
|
|
56 // CHECK-NEXT: store ptr [[T2]], ptr [[X]]
|
150
|
57 Opaque *x = weak;
|
252
|
58 // CHECK-NEXT: [[VALUE:%.*]] = load ptr, ptr [[X]]
|
|
59 // CHECK-NEXT: [[SELF:%.*]] = load ptr, ptr [[SELFVAR]]
|
|
60 // CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i8, ptr [[SELF]], i32 8
|
|
61 // CHECK-NEXT: call ptr @llvm.objc.storeWeak(ptr [[T1]], ptr [[VALUE]])
|
150
|
62 weak = x;
|
252
|
63 // CHECK-NEXT: call void @llvm.objc.storeStrong(ptr [[X]], ptr null)
|
150
|
64 // CHECK-NEXT: ret void
|
|
65 }
|
|
66
|
|
67 // CHECK-LABEL: define internal void @"\01-[A .cxx_destruct]"
|
252
|
68 // CHECK: [[SELFVAR:%.*]] = alloca ptr, align 4
|
|
69 // CHECK: [[SELF:%.*]] = load ptr, ptr [[SELFVAR]]
|
|
70 // CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i8, ptr [[SELF]], i32 8
|
|
71 // CHECK-NEXT: call void @llvm.objc.destroyWeak(ptr [[T1]])
|
|
72 // CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i8, ptr [[SELF]], i32 4
|
|
73 // CHECK-NEXT: call void @llvm.objc.storeStrong(ptr [[T1]], ptr null)
|
150
|
74 // CHECK-NEXT: ret void
|
|
75 @end
|
|
76
|
|
77 // Test case for corner case of ivar layout.
|
|
78 @interface B : A {
|
|
79 char _b_flag;
|
|
80 }
|
|
81 @end
|
|
82
|
|
83 @interface C : B {
|
|
84 char _c_flag;
|
|
85 __unsafe_unretained id c_unsafe[5];
|
|
86 id c_strong[4];
|
|
87 __weak id c_weak[3];
|
|
88 id c_strong2[7];
|
|
89 }
|
|
90 @end
|
|
91 @implementation C @end
|
|
92
|
|
93 // Note that these layouts implicitly start at the end of the previous
|
|
94 // class rounded up to pointer alignment.
|
|
95 // GLOBALS-LABEL: @OBJC_METACLASS_C
|
|
96 // Strong layout: skip five, scan four, skip three, scan seven
|
|
97 // 'T' == 0x54, '7' == 0x37
|
|
98 // GLOBALS: @OBJC_CLASS_NAME_{{.*}} = private unnamed_addr constant [3 x i8] c"T7\00"
|
|
99 // Weak layout: skip nine, scan three
|
|
100 // GLOBALS: @OBJC_CLASS_NAME_{{.*}} = private unnamed_addr constant [2 x i8] c"\93\00"
|
|
101
|
|
102 extern void useBlock(void (^block)(void));
|
|
103
|
|
104 // 256 == 0x100 == starts with 1 strong
|
|
105 // GLOBALS: @"__block_descriptor{{.*}} = linkonce_odr hidden {{.*}}, i32 256 }
|
|
106 void testBlockLayoutStrong(id x) {
|
|
107 useBlock(^{ (void) x; });
|
|
108 }
|
|
109
|
|
110 // 1 == 0x001 == starts with 1 weak
|
|
111 // GLOBALS: @"__block_descriptor{{.*}} = linkonce_odr hidden {{.*}}, i32 1 }
|
|
112 void testBlockLayoutWeak(__weak id x) {
|
|
113 useBlock(^{ (void) x; });
|
|
114 }
|
|
115
|
221
|
116 // CHECK-LABEL: define{{.*}} void @testCatch()
|
252
|
117 // CHECK: [[X:%.*]] = alloca ptr, align 4
|
|
118 // CHECK: [[Y:%.*]] = alloca ptr, align 4
|
150
|
119 // CHECK: call void @objc_exception_try_enter
|
|
120 // CHECK: br i1
|
236
|
121 // CHECK: call void @checkpoint(i32 noundef 0)
|
150
|
122 // CHECK: call void @objc_exception_try_exit
|
|
123 // CHECK: br label
|
236
|
124 // CHECK: call void @checkpoint(i32 noundef 3)
|
252
|
125 // CHECK: [[EXN:%.*]] = call ptr @objc_exception_extract
|
150
|
126 // CHECK: call i32 @objc_exception_match(
|
|
127 // CHECK: br i1
|
252
|
128 // CHECK: [[T2:%.*]] = call ptr @llvm.objc.retain(ptr [[EXN]])
|
|
129 // CHECK: store ptr [[T2]], ptr [[X]]
|
236
|
130 // CHECK: call void @checkpoint(i32 noundef 1)
|
252
|
131 // CHECK: call void @llvm.objc.storeStrong(ptr [[X]], ptr null)
|
150
|
132 // CHECK: br label
|
252
|
133 // CHECK: [[T0:%.*]] = call ptr @llvm.objc.retain(ptr [[EXN]])
|
|
134 // CHECK: store ptr [[T0]], ptr [[Y]]
|
236
|
135 // CHECK: call void @checkpoint(i32 noundef 2)
|
252
|
136 // CHECK: call void @llvm.objc.storeStrong(ptr [[Y]], ptr null)
|
150
|
137 extern void checkpoint(int n);
|
236
|
138 void testCatch(void) {
|
150
|
139 @try {
|
|
140 checkpoint(0);
|
|
141 } @catch (A *x) {
|
|
142 checkpoint(1);
|
|
143 } @catch (id y) {
|
|
144 checkpoint(2);
|
|
145 }
|
|
146 checkpoint(3);
|
|
147 }
|