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