xref: /minix3/external/bsd/llvm/dist/clang/test/CodeGenObjC/exceptions.m (revision f4a2713ac843a11c696ec80c0a5e3e5d80b4d338)
1*f4a2713aSLionel Sambuc// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-runtime=macosx-fragile-10.5 -emit-llvm -fobjc-exceptions -O2 -o - %s | FileCheck %s
2*f4a2713aSLionel Sambuc//
3*f4a2713aSLionel Sambuc// <rdar://problem/7471679> [irgen] [eh] Exception code built with clang (x86_64) crashes
4*f4a2713aSLionel Sambuc
5*f4a2713aSLionel Sambuc// Just check that we don't emit any dead blocks.
6*f4a2713aSLionel Sambuc@interface NSArray @end
7*f4a2713aSLionel Sambucvoid f0() {
8*f4a2713aSLionel Sambuc  @try {
9*f4a2713aSLionel Sambuc    @try {
10*f4a2713aSLionel Sambuc      @throw @"a";
11*f4a2713aSLionel Sambuc    } @catch(NSArray *e) {
12*f4a2713aSLionel Sambuc    }
13*f4a2713aSLionel Sambuc  } @catch (id e) {
14*f4a2713aSLionel Sambuc  }
15*f4a2713aSLionel Sambuc}
16*f4a2713aSLionel Sambuc
17*f4a2713aSLionel Sambuc// CHECK-LABEL: define void @f1()
18*f4a2713aSLionel Sambucvoid f1() {
19*f4a2713aSLionel Sambuc  extern void foo(void);
20*f4a2713aSLionel Sambuc
21*f4a2713aSLionel Sambuc  while (1) {
22*f4a2713aSLionel Sambuc    // CHECK:      call void @objc_exception_try_enter
23*f4a2713aSLionel Sambuc    // CHECK-NEXT: getelementptr
24*f4a2713aSLionel Sambuc    // CHECK-NEXT: call i32 @_setjmp(
25*f4a2713aSLionel Sambuc    // CHECK-NEXT: icmp
26*f4a2713aSLionel Sambuc    // CHECK-NEXT: br i1
27*f4a2713aSLionel Sambuc    @try {
28*f4a2713aSLionel Sambuc    // CHECK:      call void asm sideeffect "", "*m"
29*f4a2713aSLionel Sambuc    // CHECK-NEXT: call void @foo()
30*f4a2713aSLionel Sambuc      foo();
31*f4a2713aSLionel Sambuc    // CHECK:      call void @objc_exception_try_exit
32*f4a2713aSLionel Sambuc
33*f4a2713aSLionel Sambuc    // CHECK:      call void asm sideeffect "", "=*m"
34*f4a2713aSLionel Sambuc    } @finally {
35*f4a2713aSLionel Sambuc      break;
36*f4a2713aSLionel Sambuc    }
37*f4a2713aSLionel Sambuc  }
38*f4a2713aSLionel Sambuc}
39*f4a2713aSLionel Sambuc
40*f4a2713aSLionel Sambuc// Test that modifications to local variables are respected under
41*f4a2713aSLionel Sambuc// optimization.  rdar://problem/8160285
42*f4a2713aSLionel Sambuc
43*f4a2713aSLionel Sambuc// CHECK-LABEL: define i32 @f2()
44*f4a2713aSLionel Sambucint f2() {
45*f4a2713aSLionel Sambuc  extern void foo(void);
46*f4a2713aSLionel Sambuc
47*f4a2713aSLionel Sambuc  // CHECK:        [[X:%.*]] = alloca i32
48*f4a2713aSLionel Sambuc  // CHECK:        store i32 5, i32* [[X]]
49*f4a2713aSLionel Sambuc  int x = 0;
50*f4a2713aSLionel Sambuc  x += 5;
51*f4a2713aSLionel Sambuc
52*f4a2713aSLionel Sambuc  // CHECK:        [[SETJMP:%.*]] = call i32 @_setjmp
53*f4a2713aSLionel Sambuc  // CHECK-NEXT:   [[CAUGHT:%.*]] = icmp eq i32 [[SETJMP]], 0
54*f4a2713aSLionel Sambuc  // CHECK-NEXT:   br i1 [[CAUGHT]]
55*f4a2713aSLionel Sambuc  @try {
56*f4a2713aSLionel Sambuc    // CHECK: store i32 6, i32* [[X]]
57*f4a2713aSLionel Sambuc    x++;
58*f4a2713aSLionel Sambuc    // CHECK-NEXT: call void asm sideeffect "", "*m,*m"(i32* [[X]]
59*f4a2713aSLionel Sambuc    // CHECK-NEXT: call void @foo()
60*f4a2713aSLionel Sambuc    // CHECK-NEXT: call void @objc_exception_try_exit
61*f4a2713aSLionel Sambuc    // CHECK-NEXT: [[T:%.*]] = load i32* [[X]]
62*f4a2713aSLionel Sambuc    foo();
63*f4a2713aSLionel Sambuc  } @catch (id) {
64*f4a2713aSLionel Sambuc    // Landing pad.  Note that we elide the re-enter.
65*f4a2713aSLionel Sambuc    // CHECK:      call void asm sideeffect "", "=*m,=*m"(i32* [[X]]
66*f4a2713aSLionel Sambuc    // CHECK-NEXT: call i8* @objc_exception_extract
67*f4a2713aSLionel Sambuc    // CHECK-NEXT: [[T1:%.*]] = load i32* [[X]]
68*f4a2713aSLionel Sambuc    // CHECK-NEXT: [[T2:%.*]] = add nsw i32 [[T1]], -1
69*f4a2713aSLionel Sambuc
70*f4a2713aSLionel Sambuc    // This store is dead.
71*f4a2713aSLionel Sambuc    // CHECK-NEXT: store i32 [[T2]], i32* [[X]]
72*f4a2713aSLionel Sambuc    x--;
73*f4a2713aSLionel Sambuc  }
74*f4a2713aSLionel Sambuc
75*f4a2713aSLionel Sambuc  return x;
76*f4a2713aSLionel Sambuc}
77*f4a2713aSLionel Sambuc
78*f4a2713aSLionel Sambuc// Test that the cleanup destination is saved when entering a finally
79*f4a2713aSLionel Sambuc// block.  rdar://problem/8293901
80*f4a2713aSLionel Sambuc// CHECK-LABEL: define void @f3()
81*f4a2713aSLionel Sambucvoid f3() {
82*f4a2713aSLionel Sambuc  extern void f3_helper(int, int*);
83*f4a2713aSLionel Sambuc
84*f4a2713aSLionel Sambuc  // CHECK:      [[X:%.*]] = alloca i32
85*f4a2713aSLionel Sambuc  // CHECK:      store i32 0, i32* [[X]]
86*f4a2713aSLionel Sambuc  int x = 0;
87*f4a2713aSLionel Sambuc
88*f4a2713aSLionel Sambuc  // CHECK:      call void @objc_exception_try_enter(
89*f4a2713aSLionel Sambuc  // CHECK:      call i32 @_setjmp
90*f4a2713aSLionel Sambuc  // CHECK-NEXT: icmp eq
91*f4a2713aSLionel Sambuc  // CHECK-NEXT: br i1
92*f4a2713aSLionel Sambuc
93*f4a2713aSLionel Sambuc  @try {
94*f4a2713aSLionel Sambuc    // CHECK:    call void @f3_helper(i32 0, i32* [[X]])
95*f4a2713aSLionel Sambuc    // CHECK:    call void @objc_exception_try_exit(
96*f4a2713aSLionel Sambuc    f3_helper(0, &x);
97*f4a2713aSLionel Sambuc  } @finally {
98*f4a2713aSLionel Sambuc    // CHECK:    [[DEST1:%.*]] = phi i32 [ 0, {{%.*}} ], [ 3, {{%.*}} ]
99*f4a2713aSLionel Sambuc    // CHECK:    call void @objc_exception_try_enter
100*f4a2713aSLionel Sambuc    // CHECK:    call i32 @_setjmp
101*f4a2713aSLionel Sambuc    @try {
102*f4a2713aSLionel Sambuc      // CHECK:  call void @f3_helper(i32 1, i32* [[X]])
103*f4a2713aSLionel Sambuc      // CHECK:  call void @objc_exception_try_exit(
104*f4a2713aSLionel Sambuc      f3_helper(1, &x);
105*f4a2713aSLionel Sambuc    } @finally {
106*f4a2713aSLionel Sambuc      // CHECK:  [[DEST2:%.*]] = phi i32 [ 0, {{%.*}} ], [ 5, {{%.*}} ]
107*f4a2713aSLionel Sambuc      // CHECK:  call void @f3_helper(i32 2, i32* [[X]])
108*f4a2713aSLionel Sambuc      f3_helper(2, &x);
109*f4a2713aSLionel Sambuc
110*f4a2713aSLionel Sambuc      // This loop is large enough to dissuade the optimizer from just
111*f4a2713aSLionel Sambuc      // duplicating the finally block.
112*f4a2713aSLionel Sambuc      while (x) f3_helper(3, &x);
113*f4a2713aSLionel Sambuc
114*f4a2713aSLionel Sambuc      // This is a switch or maybe some chained branches, but relying
115*f4a2713aSLionel Sambuc      // on a specific result from the optimizer is really unstable.
116*f4a2713aSLionel Sambuc      // CHECK:  [[DEST2]]
117*f4a2713aSLionel Sambuc    }
118*f4a2713aSLionel Sambuc
119*f4a2713aSLionel Sambuc      // This is a switch or maybe some chained branches, but relying
120*f4a2713aSLionel Sambuc      // on a specific result from the optimizer is really unstable.
121*f4a2713aSLionel Sambuc    // CHECK:    [[DEST1]]
122*f4a2713aSLionel Sambuc  }
123*f4a2713aSLionel Sambuc
124*f4a2713aSLionel Sambuc  // CHECK:      call void @f3_helper(i32 4, i32* [[X]])
125*f4a2713aSLionel Sambuc  // CHECK-NEXT: ret void
126*f4a2713aSLionel Sambuc  f3_helper(4, &x);
127*f4a2713aSLionel Sambuc}
128*f4a2713aSLionel Sambuc
129*f4a2713aSLionel Sambuc// rdar://problem/8440970
130*f4a2713aSLionel Sambucvoid f4() {
131*f4a2713aSLionel Sambuc  extern void f4_help(int);
132*f4a2713aSLionel Sambuc
133*f4a2713aSLionel Sambuc  // CHECK-LABEL: define void @f4()
134*f4a2713aSLionel Sambuc  // CHECK:      [[EXNDATA:%.*]] = alloca [[EXNDATA_T:%.*]], align
135*f4a2713aSLionel Sambuc  // CHECK:      call void @objc_exception_try_enter([[EXNDATA_T]]* [[EXNDATA]])
136*f4a2713aSLionel Sambuc  // CHECK:      call i32 @_setjmp
137*f4a2713aSLionel Sambuc  @try {
138*f4a2713aSLionel Sambuc  // CHECK:      call void @f4_help(i32 0)
139*f4a2713aSLionel Sambuc    f4_help(0);
140*f4a2713aSLionel Sambuc
141*f4a2713aSLionel Sambuc  // The finally cleanup has two threaded entrypoints after optimization:
142*f4a2713aSLionel Sambuc
143*f4a2713aSLionel Sambuc  // finally.no-call-exit:  Predecessor is when the catch throws.
144*f4a2713aSLionel Sambuc  // CHECK:      call i8* @objc_exception_extract([[EXNDATA_T]]* [[EXNDATA]])
145*f4a2713aSLionel Sambuc  // CHECK-NEXT: call void @f4_help(i32 2)
146*f4a2713aSLionel Sambuc  // CHECK-NEXT: br label
147*f4a2713aSLionel Sambuc  //   -> rethrow
148*f4a2713aSLionel Sambuc
149*f4a2713aSLionel Sambuc  // finally.call-exit:  Predecessors are the @try and @catch fallthroughs
150*f4a2713aSLionel Sambuc  // as well as the no-match case in the catch mechanism.  The i1 is whether
151*f4a2713aSLionel Sambuc  // to rethrow and should be true only in the last case.
152*f4a2713aSLionel Sambuc  // CHECK:      phi i8*
153*f4a2713aSLionel Sambuc  // CHECK-NEXT: phi i1
154*f4a2713aSLionel Sambuc  // CHECK-NEXT: call void @objc_exception_try_exit([[EXNDATA_T]]* [[EXNDATA]])
155*f4a2713aSLionel Sambuc  // CHECK-NEXT: call void @f4_help(i32 2)
156*f4a2713aSLionel Sambuc  // CHECK-NEXT: br i1
157*f4a2713aSLionel Sambuc  //   -> ret, rethrow
158*f4a2713aSLionel Sambuc
159*f4a2713aSLionel Sambuc  // ret:
160*f4a2713aSLionel Sambuc  // CHECK:      ret void
161*f4a2713aSLionel Sambuc
162*f4a2713aSLionel Sambuc  // Catch mechanism:
163*f4a2713aSLionel Sambuc  // CHECK:      call i8* @objc_exception_extract([[EXNDATA_T]]* [[EXNDATA]])
164*f4a2713aSLionel Sambuc  // CHECK-NEXT: call void @objc_exception_try_enter([[EXNDATA_T]]* [[EXNDATA]])
165*f4a2713aSLionel Sambuc  // CHECK:      call i32 @_setjmp
166*f4a2713aSLionel Sambuc  //   -> next, finally.no-call-exit
167*f4a2713aSLionel Sambuc  // CHECK:      call i32 @objc_exception_match
168*f4a2713aSLionel Sambuc  //   -> finally.call-exit, match
169*f4a2713aSLionel Sambuc  } @catch (NSArray *a) {
170*f4a2713aSLionel Sambuc  // match:
171*f4a2713aSLionel Sambuc  // CHECK:      call void @f4_help(i32 1)
172*f4a2713aSLionel Sambuc  // CHECK-NEXT: br label
173*f4a2713aSLionel Sambuc  //   -> finally.call-exit
174*f4a2713aSLionel Sambuc    f4_help(1);
175*f4a2713aSLionel Sambuc  } @finally {
176*f4a2713aSLionel Sambuc    f4_help(2);
177*f4a2713aSLionel Sambuc  }
178*f4a2713aSLionel Sambuc
179*f4a2713aSLionel Sambuc  // rethrow:
180*f4a2713aSLionel Sambuc  // CHECK:      phi i8*
181*f4a2713aSLionel Sambuc  // CHECK-NEXT: call void @objc_exception_throw(i8*
182*f4a2713aSLionel Sambuc  // CHECK-NEXT: unreachable
183*f4a2713aSLionel Sambuc}
184