brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.5 KiB · 66dc051 Raw
181 lines · plain
1// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-runtime=macosx-fragile-10.5 -emit-llvm -fobjc-exceptions -mllvm -simplifycfg-sink-common=false -O2 -o - %s | FileCheck %s2//3// [irgen] [eh] Exception code built with clang (x86_64) crashes4 5// Just check that we don't emit any dead blocks.6@interface NSArray @end7void f0(void) {8  @try {9    @try {10      @throw @"a";11    } @catch(NSArray *e) {12    }13  } @catch (id e) {14  }15}16 17// CHECK-LABEL: define{{.*}} void @f1()18void f1(void) {19  extern void foo(void);20 21  while (1) {22    // CHECK:      call void @objc_exception_try_enter23    // CHECK-NEXT: call i32 @_setjmp(24    // CHECK-NEXT: icmp25    // CHECK-NEXT: br i126    @try {27    // CHECK:      call void asm sideeffect "", "=*m"28    // CHECK:      call void asm sideeffect "", "*m"29    // CHECK-NEXT: call void @foo()30      foo();31    // CHECK:      call void @objc_exception_try_exit32 33    } @finally {34      break;35    }36  }37}38 39// Test that modifications to local variables are respected under40// optimization.41 42// CHECK-LABEL: define{{.*}} i32 @f2()43int f2(void) {44  extern void foo(void);45 46  // CHECK:        [[X:%.*]] = alloca i3247  // CHECK:        store i32 5, ptr [[X]]48  int x = 0;49  x += 5;50 51  // CHECK:        [[SETJMP:%.*]] = call i32 @_setjmp52  // CHECK-NEXT:   [[CAUGHT:%.*]] = icmp eq i32 [[SETJMP]], 053  // CHECK-NEXT:   br i1 [[CAUGHT]]54  @try {55    // Landing pad.  Note that we elide the re-enter.56    // CHECK:      call void asm sideeffect "", "=*m,=*m"(ptr nonnull elementtype(i32) [[X]]57    // CHECK-NEXT: call ptr @objc_exception_extract58    // CHECK-NEXT: [[T1:%.*]] = load i32, ptr [[X]]59    // CHECK-NEXT: [[T2:%.*]] = add nsw i32 [[T1]], -160 61    // CHECK: store i32 6, ptr [[X]]62    x++;63    // CHECK-NEXT: call void asm sideeffect "", "*m,*m"(ptr nonnull elementtype(i32) [[X]]64    // CHECK-NEXT: call void @foo()65    // CHECK-NEXT: call void @objc_exception_try_exit66    // CHECK-NEXT: [[T:%.*]] = load i32, ptr [[X]]67    foo();68  } @catch (id) {69    x--;70  }71 72  return x;73}74 75// Test that the cleanup destination is saved when entering a finally76// block.77// CHECK-LABEL: define{{.*}} void @f3()78void f3(void) {79  extern void f3_helper(int, int*);80 81  // CHECK:      [[X:%.*]] = alloca i3282  // CHECK:      call void @llvm.lifetime.start.p0(ptr nonnull [[X]])83  // CHECK:      store i32 0, ptr [[X]]84  int x = 0;85 86  // CHECK:      call void @objc_exception_try_enter(87  // CHECK:      call i32 @_setjmp88  // CHECK-NEXT: [[DEST1:%.*]] = icmp eq89  // CHECK-NEXT: br i1 [[DEST1]]90 91  @try {92    // CHECK:    call void @f3_helper(i32 noundef 0, ptr noundef nonnull [[X]])93    // CHECK:    call void @objc_exception_try_exit(94    f3_helper(0, &x);95  } @finally {96    // CHECK:    call void @objc_exception_try_enter97    // CHECK:    call i32 @_setjmp98    // CHECK-NEXT: [[DEST2:%.*]] = icmp eq99    // CHECK-NEXT: br i1 [[DEST2]]100    @try {101      // CHECK:  call void @f3_helper(i32 noundef 1, ptr noundef nonnull [[X]])102      // CHECK:  call void @objc_exception_try_exit(103      f3_helper(1, &x);104    } @finally {105      // CHECK:  call void @f3_helper(i32 noundef 2, ptr noundef nonnull [[X]])106      f3_helper(2, &x);107 108      // This loop is large enough to dissuade the optimizer from just109      // duplicating the finally block.110      while (x) f3_helper(3, &x);111 112      // This is a switch or maybe some chained branches, but relying113      // on a specific result from the optimizer is really unstable.114      // CHECK:  [[DEST2]]115    }116 117      // This is a switch or maybe some chained branches, but relying118      // on a specific result from the optimizer is really unstable.119    // CHECK:    [[DEST1]]120  }121 122  // CHECK:      call void @f3_helper(i32 noundef 4, ptr noundef nonnull [[X]])123  // CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr nonnull [[X]])124  // CHECK-NEXT: ret void125  f3_helper(4, &x);126}127 128void f4(void) {129  extern void f4_help(int);130 131  // CHECK-LABEL: define{{.*}} void @f4()132  // CHECK:      [[EXNDATA:%.*]] = alloca [[EXNDATA_T:%.*]], align133  // CHECK:      call void @objc_exception_try_enter(ptr nonnull [[EXNDATA]])134  // CHECK:      call i32 @_setjmp135  @try {136  // CHECK:      call void @f4_help(i32 noundef 0)137    f4_help(0);138 139  // The finally cleanup has two threaded entrypoints after optimization:140 141  // finally.no-call-exit:  Predecessor is when the catch throws.142  // CHECK:      call ptr @objc_exception_extract(ptr nonnull [[EXNDATA]])143  // CHECK-NEXT: call void @f4_help(i32 noundef 2)144  // CHECK-NEXT: br label145  //   -> rethrow146 147  // finally.call-exit:  Predecessor is the no-match case in the catch mechanism148  // which rethrows.149  // CHECK:      call void @objc_exception_try_exit(ptr nonnull [[EXNDATA]])150  // CHECK-NEXT: call void @f4_help(i32 noundef 2)151  // CHECK-NEXT: br label152  //   -> rethrow153 154  // finally.end.critedge:  Predecessors are the @try and @catch fallthroughs.155  // CHECK:      call void @objc_exception_try_exit(ptr nonnull [[EXNDATA]])156  // CHECK-NEXT: call void @f4_help(i32 noundef 2)157  // CHECK-NEXT: ret void158 159  // Catch mechanism:160  // CHECK:      call ptr @objc_exception_extract(ptr nonnull [[EXNDATA]])161  // CHECK-NEXT: call void @objc_exception_try_enter(ptr nonnull [[EXNDATA]])162  // CHECK:      call i32 @_setjmp163  //   -> next, finally.no-call-exit164  // CHECK:      call i32 @objc_exception_match165  //   -> finally.call-exit, match166  } @catch (NSArray *a) {167  // match:168  // CHECK:      call void @f4_help(i32 noundef 1)169  // CHECK-NEXT: br label170  //   -> finally.call-exit171    f4_help(1);172  } @finally {173    f4_help(2);174  }175 176  // rethrow:177  // CHECK:      phi ptr178  // CHECK-NEXT: call void @objc_exception_throw(ptr179  // CHECK-NEXT: unreachable180}181