245 lines · plain
1// RUN: %clang_cc1 -emit-llvm -fobjc-arc -triple x86_64-apple-darwin10 %s -o - | FileCheck %s2 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 Root14- (int)getInt __attribute__((objc_direct));15@property(direct, readonly) int intProperty;16@property(direct, readonly) int intProperty2;17@property(direct, readonly) id objectProperty;18@end19 20@implementation Root21// 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 parameters29 // CHECK-LABEL: entry:30 // CHECK-NEXT: [[RETVAL:%.*]] = alloca31 // CHECK-NEXT: [[SELFADDR:%.*]] = alloca ptr,32 // CHECK-NEXT: store ptr %{{.*}}, ptr [[SELFADDR]],33 34 // self nil-check35 // CHECK-NEXT: [[SELF:%.*]] = load ptr, ptr [[SELFADDR]],36 // CHECK-NEXT: [[NILCHECK:%.*]] = icmp eq ptr [[SELF]], null37 // CHECK-NEXT: br i1 [[NILCHECK]],38 39 // setting return value to nil40 // CHECK-LABEL: objc_direct_method.self_is_nil:41 // CHECK-NEXT: call void @llvm.memset{{[^(]*}}({{[^,]*}}[[RETVAL]], i8 0,42 // CHECK-NEXT: br label43 44 // set value45 // CHECK-LABEL: objc_direct_method.cont:46 // CHECK: store{{.*}}[[RETVAL]],47 // CHECK-NEXT: br label48 49 // return50 // CHECK-LABEL: return:51 // CHECK: {{%.*}} = load{{.*}}[[RETVAL]],52 // CHECK-NEXT: ret53 return 42;54}55 56// CHECK-LABEL: define hidden i32 @"\01+[Root classGetInt]"(57+ (int)classGetInt __attribute__((objc_direct)) {58 // loading parameters59 // 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_msgSend67 // CHECK-NEXT: store ptr [[SELF0]], ptr [[SELFADDR]],68 69 // return70 // CHECK-NEXT: ret71 return 42;72}73 74// CHECK-LABEL: define hidden i64 @"\01-[Root getComplex]"(75- (struct my_complex_struct)getComplex __attribute__((objc_direct)) {76 // loading parameters77 // CHECK-LABEL: entry:78 // CHECK-NEXT: [[RETVAL:%.*]] = alloca79 // CHECK-NEXT: [[SELFADDR:%.*]] = alloca ptr,80 // CHECK-NEXT: store ptr %{{.*}}, ptr [[SELFADDR]],81 82 // self nil-check83 // CHECK-NEXT: [[SELF:%.*]] = load ptr, ptr [[SELFADDR]],84 // CHECK-NEXT: [[NILCHECK:%.*]] = icmp eq ptr [[SELF]], null85 // CHECK-NEXT: br i1 [[NILCHECK]],86 87 // setting return value to nil88 // CHECK-LABEL: objc_direct_method.self_is_nil:89 // CHECK-NEXT: call void @llvm.memset{{[^(]*}}({{[^,]*}}[[RETVAL]], i8 0,90 // CHECK-NEXT: br label91 92 // set value93 // CHECK-LABEL: objc_direct_method.cont:94 // CHECK-NEXT: call void @llvm.memcpy{{[^(]*}}({{[^,]*}}[[RETVAL]],95 // CHECK-NEXT: br label96 97 // return98 // CHECK-LABEL: return:99 // CHECK-NEXT: {{%.*}} = load{{.*}}[[RETVAL]],100 // CHECK-NEXT: ret101 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 i64110}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 parameters117 // CHECK-LABEL: entry:118 // CHECK-NEXT: [[SELFADDR:%.*]] = alloca ptr,119 // CHECK-NEXT: store ptr %{{.*}}, ptr [[SELFADDR]],120 121 // self nil-check122 // CHECK-NEXT: [[SELF:%.*]] = load ptr, ptr [[SELFADDR]],123 // CHECK-NEXT: [[NILCHECK:%.*]] = icmp eq ptr [[SELF]], null124 // CHECK-NEXT: br i1 [[NILCHECK]],125 126 // setting return value to nil127 // CHECK-LABEL: objc_direct_method.self_is_nil:128 // CHECK-NEXT: call void @llvm.memset{{[^(]*}}({{[^,]*}}[[RETVAL]], i8 0,129 // CHECK-NEXT: br label130 131 // set value132 // CHECK-LABEL: objc_direct_method.cont:133 // CHECK: br label134 135 // return136 // CHECK-LABEL: return:137 // CHECK: ret void138 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 void147}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 selector156 // 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@end163// CHECK-LABEL: define hidden i32 @"\01-[Root intProperty]"164 165// Check the synthesized objectProperty calls objc_getProperty(); this also166// 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: call ptr @objc_getProperty(ptr noundef [[SELFVAL]], ptr noundef poison, i64 noundef 8, {{.*}})171 172@interface Foo : Root {173 id __strong _cause_cxx_destruct;174}175@property(nonatomic, readonly, direct) int getDirect_setDynamic;176@property(nonatomic, readonly) int getDynamic_setDirect;177@end178 179@interface Foo ()180@property(nonatomic, readwrite) int getDirect_setDynamic;181@property(nonatomic, readwrite, direct) int getDynamic_setDirect;182- (int)directMethodInExtension __attribute__((objc_direct));183@end184 185@interface Foo (Cat)186- (int)directMethodInCategory __attribute__((objc_direct));187@end188 189__attribute__((objc_direct_members))190@implementation Foo191// CHECK-LABEL: define hidden i32 @"\01-[Foo directMethodInExtension]"(192- (int)directMethodInExtension {193 return 42;194}195// CHECK-LABEL: define hidden i32 @"\01-[Foo getDirect_setDynamic]"(196// CHECK-LABEL: define internal void @"\01-[Foo setGetDirect_setDynamic:]"(197// CHECK-LABEL: define internal i32 @"\01-[Foo getDynamic_setDirect]"(198// CHECK-LABEL: define hidden void @"\01-[Foo setGetDynamic_setDirect:]"(199// CHECK-LABEL: define internal void @"\01-[Foo .cxx_destruct]"(200@end201 202@implementation Foo (Cat)203// CHECK-LABEL: define hidden i32 @"\01-[Foo directMethodInCategory]"(204- (int)directMethodInCategory {205 return 42;206}207// CHECK-LABEL: define hidden i32 @"\01-[Foo directMethodInCategoryNoDecl]"(208- (int)directMethodInCategoryNoDecl __attribute__((objc_direct)) {209 return 42;210}211@end212 213int useRoot(Root *r) {214 // CHECK-LABEL: define{{.*}} i32 @useRoot215 // CHECK: %{{[^ ]*}} = call i32 @"\01-[Root getInt]"216 // CHECK: %{{[^ ]*}} = call i32 @"\01-[Root intProperty]"217 // CHECK: %{{[^ ]*}} = call i32 @"\01-[Root intProperty2]"218 return [r getInt] + [r intProperty] + [r intProperty2];219}220 221int useFoo(Foo *f) {222 // CHECK-LABEL: define{{.*}} i32 @useFoo223 // CHECK: call void @"\01-[Foo setGetDynamic_setDirect:]"224 // CHECK: %{{[^ ]*}} = call i32 @"\01-[Foo getDirect_setDynamic]"225 // CHECK: %{{[^ ]*}} = call i32 @"\01-[Foo directMethodInExtension]"226 // CHECK: %{{[^ ]*}} = call i32 @"\01-[Foo directMethodInCategory]"227 // CHECK: %{{[^ ]*}} = call i32 @"\01-[Foo directMethodInCategoryNoDecl]"228 [f setGetDynamic_setDirect:1];229 return [f getDirect_setDynamic] +230 [f directMethodInExtension] +231 [f directMethodInCategory] +232 [f directMethodInCategoryNoDecl];233}234 235__attribute__((objc_root_class))236@interface RootDeclOnly237@property(direct, readonly) int intProperty;238@end239 240int useRootDeclOnly(RootDeclOnly *r) {241 // CHECK-LABEL: define{{.*}} i32 @useRootDeclOnly242 // CHECK: %{{[^ ]*}} = call i32 @"\01-[RootDeclOnly intProperty]"243 return [r intProperty];244}245