1// RUN: %clang_cc1 -emit-llvm -fobjc-arc -triple x86_64-apple-darwin10 %s -o - | FileCheck %s 2 3struct my_complex_struct { 4 int a, b; 5}; 6 7struct my_aggregate_struct { 8 int a, b; 9 char buf[128]; 10}; 11 12__attribute__((objc_root_class)) 13@interface Root 14- (int)getInt __attribute__((objc_direct)); 15@property(direct, readonly) int intProperty; 16@property(direct, readonly) int intProperty2; 17@end 18 19@implementation Root 20// CHECK-LABEL: define hidden i32 @"\01-[Root intProperty2]" 21- (int)intProperty2 { 22 return 42; 23} 24 25// CHECK-LABEL: define hidden i32 @"\01-[Root getInt]"( 26- (int)getInt __attribute__((objc_direct)) { 27 // loading parameters 28 // CHECK-LABEL: entry: 29 // CHECK-NEXT: [[RETVAL:%.*]] = alloca 30 // CHECK-NEXT: [[SELFADDR:%.*]] = alloca %0*, 31 // CHECK-NEXT: [[_CMDADDR:%.*]] = alloca i8*, 32 // CHECK-NEXT: store %0* %{{.*}}, %0** [[SELFADDR]], 33 // CHECK-NEXT: store i8* %{{.*}}, i8** [[_CMDADDR]], 34 35 // self nil-check 36 // CHECK-NEXT: [[SELF:%.*]] = load %0*, %0** [[SELFADDR]], 37 // CHECK-NEXT: [[NILCHECK:%.*]] = icmp eq %0* [[SELF]], null 38 // CHECK-NEXT: br i1 [[NILCHECK]], 39 40 // setting return value to nil 41 // CHECK-LABEL: objc_direct_method.self_is_nil: 42 // CHECK: [[RET0:%.*]] = bitcast{{.*}}[[RETVAL]] 43 // CHECK-NEXT: call void @llvm.memset{{[^(]*}}({{[^,]*}}[[RET0]], i8 0, 44 // CHECK-NEXT: br label 45 46 // set value 47 // CHECK-LABEL: objc_direct_method.cont: 48 // CHECK: store{{.*}}[[RETVAL]], 49 // CHECK-NEXT: br label 50 51 // return 52 // CHECK-LABEL: return: 53 // CHECK: {{%.*}} = load{{.*}}[[RETVAL]], 54 // CHECK-NEXT: ret 55 return 42; 56} 57 58// CHECK-LABEL: define hidden i32 @"\01+[Root classGetInt]"( 59+ (int)classGetInt __attribute__((objc_direct)) { 60 // loading parameters 61 // CHECK-LABEL: entry: 62 // CHECK-NEXT: [[SELFADDR:%.*]] = alloca i8*, 63 // CHECK-NEXT: [[_CMDADDR:%.*]] = alloca i8*, 64 // CHECK-NEXT: store i8* %{{.*}}, i8** [[SELFADDR]], 65 // CHECK-NEXT: store i8* %{{.*}}, i8** [[_CMDADDR]], 66 67 // [self self] 68 // CHECK-NEXT: [[SELF:%.*]] = load i8*, i8** [[SELFADDR]], 69 // CHECK-NEXT: [[SELFSEL:%.*]] = load i8*, i8** @OBJC_SELECTOR_REFERENCES_ 70 // CHECK-NEXT: [[SELF0:%.*]] = call {{.*}} @objc_msgSend 71 // CHECK-NEXT: store i8* [[SELF0]], i8** [[SELFADDR]], 72 73 // return 74 // CHECK-NEXT: ret 75 return 42; 76} 77 78// CHECK-LABEL: define hidden i64 @"\01-[Root getComplex]"( 79- (struct my_complex_struct)getComplex __attribute__((objc_direct)) { 80 // loading parameters 81 // CHECK-LABEL: entry: 82 // CHECK-NEXT: [[RETVAL:%.*]] = alloca 83 // CHECK-NEXT: [[SELFADDR:%.*]] = alloca %0*, 84 // CHECK-NEXT: [[_CMDADDR:%.*]] = alloca i8*, 85 // CHECK-NEXT: store %0* %{{.*}}, %0** [[SELFADDR]], 86 // CHECK-NEXT: store i8* %{{.*}}, i8** [[_CMDADDR]], 87 88 // self nil-check 89 // CHECK-NEXT: [[SELF:%.*]] = load %0*, %0** [[SELFADDR]], 90 // CHECK-NEXT: [[NILCHECK:%.*]] = icmp eq %0* [[SELF]], null 91 // CHECK-NEXT: br i1 [[NILCHECK]], 92 93 // setting return value to nil 94 // CHECK-LABEL: objc_direct_method.self_is_nil: 95 // CHECK: [[RET0:%.*]] = bitcast{{.*}}[[RETVAL]] 96 // CHECK-NEXT: call void @llvm.memset{{[^(]*}}({{[^,]*}}[[RET0]], i8 0, 97 // CHECK-NEXT: br label 98 99 // set value 100 // CHECK-LABEL: objc_direct_method.cont: 101 // CHECK: [[RET1:%.*]] = bitcast{{.*}}[[RETVAL]] 102 // CHECK-NEXT: call void @llvm.memcpy{{[^(]*}}({{[^,]*}}[[RET1]], 103 // CHECK-NEXT: br label 104 105 // return 106 // CHECK-LABEL: return: 107 // CHECK: [[RET2:%.*]] = bitcast{{.*}}[[RETVAL]] 108 // CHECK-NEXT: {{%.*}} = load{{.*}}[[RET2]], 109 // CHECK-NEXT: ret 110 struct my_complex_struct st = {.a = 42}; 111 return st; 112} 113 114// CHECK-LABEL: define hidden i64 @"\01+[Root classGetComplex]"( 115+ (struct my_complex_struct)classGetComplex __attribute__((objc_direct)) { 116 struct my_complex_struct st = {.a = 42}; 117 return st; 118 // CHECK: ret i64 119} 120 121// CHECK-LABEL: define hidden void @"\01-[Root getAggregate]"( 122- (struct my_aggregate_struct)getAggregate __attribute__((objc_direct)) { 123 // CHECK: %struct.my_aggregate_struct* noalias sret(%struct.my_aggregate_struct) align 4 [[RETVAL:%[^,]*]], 124 125 // loading parameters 126 // CHECK-LABEL: entry: 127 // CHECK-NEXT: [[SELFADDR:%.*]] = alloca %0*, 128 // CHECK-NEXT: [[_CMDADDR:%.*]] = alloca i8*, 129 // CHECK-NEXT: store %0* %{{.*}}, %0** [[SELFADDR]], 130 // CHECK-NEXT: store i8* %{{.*}}, i8** [[_CMDADDR]], 131 132 // self nil-check 133 // CHECK-NEXT: [[SELF:%.*]] = load %0*, %0** [[SELFADDR]], 134 // CHECK-NEXT: [[NILCHECK:%.*]] = icmp eq %0* [[SELF]], null 135 // CHECK-NEXT: br i1 [[NILCHECK]], 136 137 // setting return value to nil 138 // CHECK-LABEL: objc_direct_method.self_is_nil: 139 // CHECK: [[RET0:%.*]] = bitcast{{.*}}[[RETVAL]] 140 // CHECK-NEXT: call void @llvm.memset{{[^(]*}}({{[^,]*}}[[RET0]], i8 0, 141 // CHECK-NEXT: br label 142 143 // set value 144 // CHECK-LABEL: objc_direct_method.cont: 145 // CHECK: [[RET1:%.*]] = bitcast{{.*}}[[RETVAL]] 146 // CHECK: br label 147 148 // return 149 // CHECK-LABEL: return: 150 // CHECK: ret void 151 struct my_aggregate_struct st = {.a = 42}; 152 return st; 153} 154 155// CHECK-LABEL: define hidden void @"\01+[Root classGetAggregate]"( 156+ (struct my_aggregate_struct)classGetAggregate __attribute__((objc_direct)) { 157 struct my_aggregate_struct st = {.a = 42}; 158 return st; 159 // CHECK: ret void 160} 161 162@end 163// CHECK-LABEL: define hidden i32 @"\01-[Root intProperty]" 164 165@interface Foo : Root { 166 id __strong _cause_cxx_destruct; 167} 168@property(nonatomic, readonly, direct) int getDirect_setDynamic; 169@property(nonatomic, readonly) int getDynamic_setDirect; 170@end 171 172@interface Foo () 173@property(nonatomic, readwrite) int getDirect_setDynamic; 174@property(nonatomic, readwrite, direct) int getDynamic_setDirect; 175- (int)directMethodInExtension __attribute__((objc_direct)); 176@end 177 178@interface Foo (Cat) 179- (int)directMethodInCategory __attribute__((objc_direct)); 180@end 181 182__attribute__((objc_direct_members)) 183@implementation Foo 184// CHECK-LABEL: define hidden i32 @"\01-[Foo directMethodInExtension]"( 185- (int)directMethodInExtension { 186 return 42; 187} 188// CHECK-LABEL: define hidden i32 @"\01-[Foo getDirect_setDynamic]"( 189// CHECK-LABEL: define internal void @"\01-[Foo setGetDirect_setDynamic:]"( 190// CHECK-LABEL: define internal i32 @"\01-[Foo getDynamic_setDirect]"( 191// CHECK-LABEL: define hidden void @"\01-[Foo setGetDynamic_setDirect:]"( 192// CHECK-LABEL: define internal void @"\01-[Foo .cxx_destruct]"( 193@end 194 195@implementation Foo (Cat) 196// CHECK-LABEL: define hidden i32 @"\01-[Foo directMethodInCategory]"( 197- (int)directMethodInCategory { 198 return 42; 199} 200// CHECK-LABEL: define hidden i32 @"\01-[Foo directMethodInCategoryNoDecl]"( 201- (int)directMethodInCategoryNoDecl __attribute__((objc_direct)) { 202 return 42; 203} 204@end 205 206int useRoot(Root *r) { 207 // CHECK-LABEL: define{{.*}} i32 @useRoot 208 // CHECK: %{{[^ ]*}} = call i32 bitcast {{.*}} @"\01-[Root getInt]" 209 // CHECK: %{{[^ ]*}} = call i32 bitcast {{.*}} @"\01-[Root intProperty]" 210 // CHECK: %{{[^ ]*}} = call i32 bitcast {{.*}} @"\01-[Root intProperty2]" 211 return [r getInt] + [r intProperty] + [r intProperty2]; 212} 213 214int useFoo(Foo *f) { 215 // CHECK-LABEL: define{{.*}} i32 @useFoo 216 // CHECK: call void bitcast {{.*}} @"\01-[Foo setGetDynamic_setDirect:]" 217 // CHECK: %{{[^ ]*}} = call i32 bitcast {{.*}} @"\01-[Foo getDirect_setDynamic]" 218 // CHECK: %{{[^ ]*}} = call i32 bitcast {{.*}} @"\01-[Foo directMethodInExtension]" 219 // CHECK: %{{[^ ]*}} = call i32 bitcast {{.*}} @"\01-[Foo directMethodInCategory]" 220 // CHECK: %{{[^ ]*}} = call i32 bitcast {{.*}} @"\01-[Foo directMethodInCategoryNoDecl]" 221 [f setGetDynamic_setDirect:1]; 222 return [f getDirect_setDynamic] + 223 [f directMethodInExtension] + 224 [f directMethodInCategory] + 225 [f directMethodInCategoryNoDecl]; 226} 227 228__attribute__((objc_root_class)) 229@interface RootDeclOnly 230@property(direct, readonly) int intProperty; 231@end 232 233int useRootDeclOnly(RootDeclOnly *r) { 234 // CHECK-LABEL: define{{.*}} i32 @useRootDeclOnly 235 // CHECK: %{{[^ ]*}} = call i32 bitcast {{.*}} @"\01-[RootDeclOnly intProperty]" 236 return [r intProperty]; 237} 238