brintos

brintos / llvm-project-archived public Read only

0
0
Text · 12.7 KiB · 20f1e37 Raw
328 lines · plain
1// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fobjc-runtime-has-weak -fblocks -fobjc-arc -O2 -disable-llvm-passes -o - %s | FileCheck %s2 3struct NSFastEnumerationState;4@interface NSArray5- (unsigned long) countByEnumeratingWithState: (struct NSFastEnumerationState*) state6                  objects: (id*) buffer7                  count: (unsigned long) bufferSize;8@end;9NSArray *nsarray() { return 0; }10// CHECK: define{{.*}} ptr @_Z7nsarrayv()11 12void use(id);13 14// The analogous ObjC testcase test46 in arr.m.15void test0(__weak id *wp, __weak volatile id *wvp) {16  extern id test0_helper(void);17 18  // TODO: this is sub-optimal, we should retain at the actual call site.19  // TODO: in the non-volatile case, we do not need to be reloading.20 21  // CHECK:      [[T1:%.*]] = call noundef ptr @_Z12test0_helperv() [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]22  // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T1]])23  // CHECK-NEXT: [[T2:%.*]] = load ptr, ptr {{%.*}}, align 824  // CHECK-NEXT: [[T3:%.*]] = call ptr @llvm.objc.storeWeak(ptr [[T2]], ptr [[T1]])25  // CHECK-NEXT: [[T4:%.*]] = call ptr @llvm.objc.retain(ptr [[T3]])26  // CHECK-NEXT: store ptr [[T4]], ptr27  // CHECK-NEXT: call void @llvm.objc.release(ptr [[T1]])28  id x = *wp = test0_helper();29 30  // CHECK:      [[T1:%.*]] = call noundef ptr @_Z12test0_helperv() [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]31  // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T1]])32  // CHECK-NEXT: [[T2:%.*]] = load ptr, ptr {{%.*}}, align 833  // CHECK-NEXT: [[T3:%.*]] = call ptr @llvm.objc.storeWeak(ptr [[T2]], ptr [[T1]])34  // CHECK-NEXT: [[T4:%.*]] = call ptr @llvm.objc.loadWeakRetained(ptr [[T2]])35  // CHECK-NEXT: store ptr [[T4]], ptr36  // CHECK-NEXT: call void @llvm.objc.release(ptr [[T1]])37  id y = *wvp = test0_helper();38}39 40struct Test1_helper { Test1_helper(); };41@interface Test1 @end42@implementation Test1 { Test1_helper x; } @end43// CHECK: define internal noundef ptr @"\01-[Test1 .cxx_construct]"(44// CHECK:      call void @_ZN12Test1_helperC1Ev(45// CHECK-NEXT: load46// CHECK-NEXT: ret ptr47 48void test34(int cond) {49  __strong id strong;50  __weak id weak;51  extern void test34_sink(id *);52  test34_sink(cond ? &strong : 0);53  test34_sink(cond ? &weak : 0);54 55  // CHECK-LABEL:    define{{.*}} void @_Z6test34i(56  // CHECK:      [[COND:%.*]] = alloca i3257  // CHECK-NEXT: [[STRONG:%.*]] = alloca ptr58  // CHECK-NEXT: [[WEAK:%.*]] = alloca ptr59  // CHECK-NEXT: [[TEMP1:%.*]] = alloca ptr60  // CHECK-NEXT: [[TEMP2:%.*]] = alloca ptr61  // CHECK-NEXT: [[CONDCLEANUPSAVE:%.*]] = alloca ptr62  // CHECK-NEXT: [[CONDCLEANUP:%.*]] = alloca i163  // CHECK-NEXT: store i3264  // CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[STRONG]])65  // CHECK-NEXT: store ptr null, ptr [[STRONG]]66  // CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[WEAK]])67  // CHECK-NEXT: call ptr @llvm.objc.initWeak(ptr [[WEAK]], ptr null)68 69  // CHECK-NEXT: [[T0:%.*]] = load i32, ptr [[COND]]70  // CHECK-NEXT: [[T1:%.*]] = icmp ne i32 [[T0]], 071  // CHECK:      [[ARG:%.*]] = phi ptr72  // CHECK-NEXT: [[T0:%.*]] = icmp eq ptr [[ARG]], null73  // CHECK-NEXT: [[T1:%.*]] = select i1 [[T0]], ptr null, ptr [[TEMP1]]74  // CHECK-NEXT: br i1 [[T0]],75  // CHECK:      [[T0:%.*]] = load ptr, ptr [[ARG]]76  // CHECK-NEXT: store ptr [[T0]], ptr [[TEMP1]]77  // CHECK-NEXT: br label78  // CHECK:      [[W0:%.*]] = phi ptr [ [[T0]], {{%.*}} ], [ poison, {{%.*}} ]79  // CHECK:      call void @_Z11test34_sinkPU15__autoreleasingP11objc_object(ptr noundef [[T1]])80  // CHECK-NEXT: [[T0:%.*]] = icmp eq ptr [[ARG]], null81  // CHECK-NEXT: br i1 [[T0]],82  // CHECK:      [[T0:%.*]] = load ptr, ptr [[TEMP1]]83  // CHECK-NEXT: [[T1:%.*]] = call ptr @llvm.objc.retain(ptr [[T0]])84  // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.use(ptr [[W0]])85  // CHECK-NEXT: [[T2:%.*]] = load ptr, ptr [[ARG]]86  // CHECK-NEXT: store ptr [[T1]], ptr [[ARG]]87  // CHECK-NEXT: call void @llvm.objc.release(ptr [[T2]])88  // CHECK-NEXT: br label89 90  // CHECK:      [[T0:%.*]] = load i32, ptr [[COND]]91  // CHECK-NEXT: [[T1:%.*]] = icmp ne i32 [[T0]], 092  // CHECK:      [[ARG:%.*]] = phi ptr93  // CHECK-NEXT: [[T0:%.*]] = icmp eq ptr [[ARG]], null94  // CHECK-NEXT: [[T1:%.*]] = select i1 [[T0]], ptr null, ptr [[TEMP2]]95  // CHECK-NEXT: store i1 false, ptr [[CONDCLEANUP]]96  // CHECK-NEXT: br i1 [[T0]],97  // CHECK:      [[T0:%.*]] = call ptr @llvm.objc.loadWeakRetained(ptr [[ARG]])98  // CHECK-NEXT: store ptr [[T0]], ptr [[CONDCLEANUPSAVE]]99  // CHECK-NEXT: store i1 true, ptr [[CONDCLEANUP]]100  // CHECK-NEXT: store ptr [[T0]], ptr [[TEMP2]]101  // CHECK-NEXT: br label102  // CHECK:      call void @_Z11test34_sinkPU15__autoreleasingP11objc_object(ptr noundef [[T1]])103  // CHECK-NEXT: [[T0:%.*]] = icmp eq ptr [[ARG]], null104  // CHECK-NEXT: br i1 [[T0]],105  // CHECK:      [[T0:%.*]] = load ptr, ptr [[TEMP2]]106  // CHECK-NEXT: call ptr @llvm.objc.storeWeak(ptr [[ARG]], ptr [[T0]])107  // CHECK-NEXT: br label108 109  // CHECK:      call void @llvm.objc.destroyWeak(ptr [[WEAK]])110  // CHECK:      ret void111}112 113struct Test35_Helper {114  static id makeObject1() __attribute__((ns_returns_retained));115  id makeObject2() __attribute__((ns_returns_retained));116  static id makeObject3();117  id makeObject4();118};119 120// CHECK-LABEL: define{{.*}} void @_Z6test3513Test35_HelperPS_121void test35(Test35_Helper x0, Test35_Helper *x0p) {122  // CHECK: call void @llvm.lifetime.start123  // CHECK: call noundef ptr @_ZN13Test35_Helper11makeObject1Ev124  // CHECK-NOT: call ptr @llvm.objc.retain125  id obj1 = Test35_Helper::makeObject1();126  // CHECK: call void @llvm.lifetime.start127  // CHECK: call noundef ptr @_ZN13Test35_Helper11makeObject2Ev128  // CHECK-NOT: call ptr @llvm.objc.retain129  id obj2 = x0.makeObject2();130  // CHECK: call void @llvm.lifetime.start131  // CHECK: call noundef ptr @_ZN13Test35_Helper11makeObject2Ev132  // CHECK-NOT: call ptr @llvm.objc.retain133  id obj3 = x0p->makeObject2();134  id (Test35_Helper::*pmf)() __attribute__((ns_returns_retained))135    = &Test35_Helper::makeObject2;136  // CHECK: call void @llvm.lifetime.start137  // CHECK: call noundef ptr %138  // CHECK-NOT: call ptr @llvm.objc.retain139  id obj4 = (x0.*pmf)();140  // CHECK: call void @llvm.lifetime.start141  // CHECK: call noundef ptr %142  // CHECK-NOT: call ptr @llvm.objc.retain143  id obj5 = (x0p->*pmf)();144 145  // CHECK: call void @llvm.objc.release146  // CHECK: call void @llvm.lifetime.end147  // CHECK: call void @llvm.objc.release148  // CHECK: call void @llvm.lifetime.end149  // CHECK: call void @llvm.objc.release150  // CHECK: call void @llvm.lifetime.end151  // CHECK: call void @llvm.objc.release152  // CHECK: call void @llvm.lifetime.end153  // CHECK: call void @llvm.objc.release154  // CHECK: call void @llvm.lifetime.end155  // CHECK-NEXT: ret void156}157 158// CHECK-LABEL: define{{.*}} void @_Z7test35b13Test35_HelperPS_159void test35b(Test35_Helper x0, Test35_Helper *x0p) {160  // CHECK: call void @llvm.lifetime.start161  // CHECK: call noundef ptr @_ZN13Test35_Helper11makeObject3Ev{{.*}} [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]162  id obj1 = Test35_Helper::makeObject3();163  // CHECK: call void @llvm.lifetime.start164  // CHECK: call noundef ptr @_ZN13Test35_Helper11makeObject4Ev{{.*}} [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]165  id obj2 = x0.makeObject4();166  // CHECK: call void @llvm.lifetime.start167  // CHECK: call noundef ptr @_ZN13Test35_Helper11makeObject4Ev{{.*}} [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]168  id obj3 = x0p->makeObject4();169  id (Test35_Helper::*pmf)() = &Test35_Helper::makeObject4;170  // CHECK: call void @llvm.lifetime.start171  // CHECK: call noundef ptr %{{.*}} [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]172  id obj4 = (x0.*pmf)();173  // CHECK: call void @llvm.lifetime.start174  // CHECK: call noundef ptr %{{.*}} [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]175  id obj5 = (x0p->*pmf)();176 177  // CHECK: call void @llvm.objc.release178  // CHECK: call void @llvm.lifetime.end179  // CHECK: call void @llvm.objc.release180  // CHECK: call void @llvm.lifetime.end181  // CHECK: call void @llvm.lifetime.end182  // CHECK: call void @llvm.objc.release183  // CHECK: call void @llvm.lifetime.end184  // CHECK: call void @llvm.objc.release185  // CHECK: call void @llvm.lifetime.end186  // CHECK: call void @llvm.objc.release187  // CHECK: call void @llvm.lifetime.end188  // CHECK-NEXT: ret void189}190 191// CHECK-LABEL: define{{.*}} ptr @_Z6test36P11objc_object(192id test36(id z) {193  // CHECK: llvm.objc.retain194  // CHECK: llvm.objc.retain195  // CHECK: llvm.objc.release196  // CHECK: llvm.objc.autoreleaseReturnValue197  return z;198}199 200@interface Test37201+ alloc;202- init;203- (NSArray *) array;204@end205template <class T> void test37(T *a) {206  for (id x in a.array) {207    use(x);208  }209}210extern template void test37<Test37>(Test37 *a);211template void test37<Test37>(Test37 *a);212// CHECK-LABEL: define weak_odr void @_Z6test37I6Test37EvPT_(213// CHECK:      [[T2:%.*]] = call noundef ptr @objc_msgSend({{.*}} [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]214// CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use({{.*}} [[T2]])215 216// Make sure it's not immediately released before starting the iteration.217// CHECK-NEXT: load ptr, ptr @OBJC_SELECTOR_REFERENCES_218// CHECK-NEXT: @objc_msgSend219 220// This bitcast is for the mutation check.221// CHECK: @objc_enumerationMutation222 223// This bitcast is for the 'next' message send.224// CHECK: load ptr, ptr @OBJC_SELECTOR_REFERENCES_225// CHECK-NEXT: @objc_msgSend226 227// This bitcast is for the final release.228// CHECK: call void @llvm.objc.release(ptr [[T2]])229 230template<typename T>231void send_release() {232  [Test37 array];233}234 235// CHECK-LABEL: define weak_odr void @_Z12send_releaseIiEvv(236// CHECK: call noundef ptr @objc_msgSend{{.*}} [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]237// CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(238// CHECK-NEXT: call void @llvm.objc.release239// CHECK-NEXT: ret void240template void send_release<int>();241 242template<typename T>243Test37 *instantiate_init() {244  Test37 *result = [[Test37 alloc] init];245  return result;246}247 248// CHECK-LABEL: define weak_odr noundef ptr @_Z16instantiate_initIiEP6Test37v249// CHECK: call noundef ptr @objc_msgSend250// CHECK: call noundef ptr @objc_msgSend251// CHECK: call ptr @llvm.objc.retain252// CHECK: call void @llvm.objc.release253// CHECK: call ptr @llvm.objc.autoreleaseReturnValue254template Test37* instantiate_init<int>();255 256// Just make sure that the AST invariants hold properly here,257// i.e. that we don't crash.258// The block should get bound in the full-expression outside259// the statement-expression.260template <class T> class Test38 {261  void test(T x) {262    ^{ (void) x; }, ({ x; });263  }264};265// CHECK-LABEL: define weak_odr void @_ZN6Test38IiE4testEi(266template class Test38<int>;267 268class Test39_base1 {269  virtual void foo();270};271class Test39_base2 {272  virtual id bar();273};274class Test39 : Test39_base1, Test39_base2 { // base2 is at non-zero offset275  virtual id bar();276};277id Test39::bar() { return 0; }278// Note lack of autorelease.279// CHECK-LABEL:    define{{.*}} ptr @_ZThn8_N6Test393barEv(280// CHECK:      call noundef ptr @_ZN6Test393barEv(281// CHECK-NEXT: ret ptr282 283// Just a basic correctness check that IR-gen still works after instantiating284// a non-dependent message send that requires writeback.285@interface Test40286+ (void) foo:(id *)errorPtr;287@end288template <class T> void test40_helper() {289  id x;290  [Test40 foo: &x];291};292template void test40_helper<int>();293// CHECK-LABEL:    define weak_odr void @_Z13test40_helperIiEvv()294// CHECK:      [[X:%.*]] = alloca ptr295// CHECK-NEXT: [[TEMP:%.*]] = alloca ptr296// CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[X]])297// CHECK-NEXT: store ptr null, ptr [[X]]298// CHECK:      [[T0:%.*]] = load ptr, ptr [[X]]299// CHECK-NEXT: store ptr [[T0]], ptr [[TEMP]]300// CHECK:      @objc_msgSend301// CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[TEMP]]302// CHECK-NEXT: call ptr @llvm.objc.retain(ptr [[T0]])303 304// Check that moves out of __weak variables are compiled to use objc_moveWeak.305void test41(__weak id &&x) {306  __weak id y = static_cast<__weak id &&>(x);307}308// CHECK-LABEL: define{{.*}} void @_Z6test41OU6__weakP11objc_object309// CHECK:      [[X:%.*]] = alloca ptr310// CHECK:      [[Y:%.*]] = alloca ptr311// CHECK:      [[T0:%.*]] = load ptr, ptr [[X]]312// CHECK-NEXT: call void @llvm.objc.moveWeak(ptr [[Y]], ptr [[T0]])313// CHECK-NEXT: call void @llvm.objc.destroyWeak(ptr [[Y]])314 315void test42() {316  __attribute__((ns_returns_retained)) id test42_0();317  id test42_1(id);318  void test42_2(id &&);319  test42_2(test42_1(test42_0()));320}321 322// Check that the pointer returned by test42_0 is released after the full expression.323 324// CHECK-LABEL: define void @_Z6test42v()325// CHECK: %[[CALL:.*]] = call noundef ptr @_Z8test42_0v()326// CHECK: call void @_Z8test42_2OU15__autoreleasingP11objc_object(327// CHECK: call void @llvm.objc.release(ptr %[[CALL]])328