Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / clang / test / CodeGenObjC / exceptions.m
blob1546ed2585db5b9f0b6ed2793c0e960858fac4f6
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 %s
2 //
3 // [irgen] [eh] Exception code built with clang (x86_64) crashes
5 // Just check that we don't emit any dead blocks.
6 @interface NSArray @end
7 void f0(void) {
8   @try {
9     @try {
10       @throw @"a";
11     } @catch(NSArray *e) {
12     }
13   } @catch (id e) {
14   }
17 // CHECK-LABEL: define{{.*}} void @f1()
18 void f1(void) {
19   extern void foo(void);
21   while (1) {
22     // CHECK:      call void @objc_exception_try_enter
23     // CHECK-NEXT: call i32 @_setjmp(
24     // CHECK-NEXT: icmp
25     // CHECK-NEXT: br i1
26     @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_exit
33     } @finally {
34       break;
35     }
36   }
39 // Test that modifications to local variables are respected under
40 // optimization.
42 // CHECK-LABEL: define{{.*}} i32 @f2()
43 int f2(void) {
44   extern void foo(void);
46   // CHECK:        [[X:%.*]] = alloca i32
47   // CHECK:        store i32 5, ptr [[X]]
48   int x = 0;
49   x += 5;
51   // CHECK:        [[SETJMP:%.*]] = call i32 @_setjmp
52   // CHECK-NEXT:   [[CAUGHT:%.*]] = icmp eq i32 [[SETJMP]], 0
53   // 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_extract
58     // CHECK-NEXT: [[T1:%.*]] = load i32, ptr [[X]]
59     // CHECK-NEXT: [[T2:%.*]] = add nsw i32 [[T1]], -1
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_exit
66     // CHECK-NEXT: [[T:%.*]] = load i32, ptr [[X]]
67     foo();
68   } @catch (id) {
69     x--;
70   }
72   return x;
75 // Test that the cleanup destination is saved when entering a finally
76 // block.
77 // CHECK-LABEL: define{{.*}} void @f3()
78 void f3(void) {
79   extern void f3_helper(int, int*);
81   // CHECK:      [[X:%.*]] = alloca i32
82   // CHECK:      call void @llvm.lifetime.start.p0(i64 4, ptr nonnull [[X]])
83   // CHECK:      store i32 0, ptr [[X]]
84   int x = 0;
86   // CHECK:      call void @objc_exception_try_enter(
87   // CHECK:      call i32 @_setjmp
88   // CHECK-NEXT: [[DEST1:%.*]] = icmp eq
89   // CHECK-NEXT: br i1 [[DEST1]]
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_enter
97     // CHECK:    call i32 @_setjmp
98     // CHECK-NEXT: [[DEST2:%.*]] = icmp eq
99     // 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);
108       // This loop is large enough to dissuade the optimizer from just
109       // duplicating the finally block.
110       while (x) f3_helper(3, &x);
112       // This is a switch or maybe some chained branches, but relying
113       // on a specific result from the optimizer is really unstable.
114       // CHECK:  [[DEST2]]
115     }
117       // This is a switch or maybe some chained branches, but relying
118       // on a specific result from the optimizer is really unstable.
119     // CHECK:    [[DEST1]]
120   }
122   // CHECK:      call void @f3_helper(i32 noundef 4, ptr noundef nonnull [[X]])
123   // CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 4, ptr nonnull [[X]])
124   // CHECK-NEXT: ret void
125   f3_helper(4, &x);
128 void f4(void) {
129   extern void f4_help(int);
131   // CHECK-LABEL: define{{.*}} void @f4()
132   // CHECK:      [[EXNDATA:%.*]] = alloca [[EXNDATA_T:%.*]], align
133   // CHECK:      call void @objc_exception_try_enter(ptr nonnull [[EXNDATA]])
134   // CHECK:      call i32 @_setjmp
135   @try {
136   // CHECK:      call void @f4_help(i32 noundef 0)
137     f4_help(0);
139   // The finally cleanup has two threaded entrypoints after optimization:
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 label
145   //   -> rethrow
147   // finally.call-exit:  Predecessors are the @try and @catch fallthroughs
148   // as well as the no-match case in the catch mechanism.  The i1 is whether
149   // to rethrow and should be true only in the last case.
150   // CHECK:      phi ptr
151   // CHECK-NEXT: phi i1
152   // CHECK-NEXT: call void @objc_exception_try_exit(ptr nonnull [[EXNDATA]])
153   // CHECK-NEXT: call void @f4_help(i32 noundef 2)
154   // CHECK-NEXT: br i1
155   //   -> ret, rethrow
157   // ret:
158   // CHECK:      ret void
160   // Catch mechanism:
161   // CHECK:      call ptr @objc_exception_extract(ptr nonnull [[EXNDATA]])
162   // CHECK-NEXT: call void @objc_exception_try_enter(ptr nonnull [[EXNDATA]])
163   // CHECK:      call i32 @_setjmp
164   //   -> next, finally.no-call-exit
165   // CHECK:      call i32 @objc_exception_match
166   //   -> finally.call-exit, match
167   } @catch (NSArray *a) {
168   // match:
169   // CHECK:      call void @f4_help(i32 noundef 1)
170   // CHECK-NEXT: br label
171   //   -> finally.call-exit
172     f4_help(1);
173   } @finally {
174     f4_help(2);
175   }
177   // rethrow:
178   // CHECK:      phi ptr
179   // CHECK-NEXT: call void @objc_exception_throw(ptr
180   // CHECK-NEXT: unreachable