blob: b431e3712473b4e29d7029927040347f58de0468 [file] [log] [blame]
John McCallf1549f62010-07-06 01:34:17 +00001// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fexceptions -O2 -o - %s | FileCheck %s
Daniel Dunbarb76db232010-04-23 19:12:32 +00002//
3// <rdar://problem/7471679> [irgen] [eh] Exception code built with clang (x86_64) crashes
4
5// Just check that we don't emit any dead blocks.
Daniel Dunbarb76db232010-04-23 19:12:32 +00006@interface NSArray @end
7void f0() {
8 @try {
9 @try {
10 @throw @"a";
11 } @catch(NSArray *e) {
12 }
13 } @catch (id e) {
14 }
15}
John McCallf1549f62010-07-06 01:34:17 +000016
17// CHECK: define void @f1()
18void f1() {
19 extern void foo(void);
20
21 while (1) {
22 // CHECK: call void @objc_exception_try_enter
23 // CHECK-NEXT: getelementptr
24 // CHECK-NEXT: call i32 @_setjmp(
25 // CHECK-NEXT: icmp
26 // CHECK-NEXT: br i1
27 @try {
John McCall0b251722010-08-04 05:59:32 +000028 // CHECK: call void asm sideeffect "", "*m"
29 // CHECK-NEXT: call void @foo()
John McCallf1549f62010-07-06 01:34:17 +000030 foo();
John McCall0b251722010-08-04 05:59:32 +000031 // CHECK-NEXT: call void @objc_exception_try_exit
John McCallf1549f62010-07-06 01:34:17 +000032 // CHECK-NEXT: ret void
33
John McCall0b251722010-08-04 05:59:32 +000034 // CHECK: call void asm sideeffect "", "=*m"
John McCallf1549f62010-07-06 01:34:17 +000035 // CHECK-NEXT: ret void
36 } @finally {
37 break;
38 }
39 }
40}
John McCall87bb5822010-07-31 23:20:56 +000041
42// Test that modifications to local variables are respected under
43// optimization. rdar://problem/8160285
44
45// CHECK: define i32 @f2()
46int f2() {
47 extern void foo(void);
48
49 // CHECK: [[X:%.*]] = alloca i32
John McCall0b251722010-08-04 05:59:32 +000050 // CHECK: store i32 5, i32* [[X]]
John McCall87bb5822010-07-31 23:20:56 +000051 int x = 0;
John McCall0b251722010-08-04 05:59:32 +000052 x += 5;
John McCall87bb5822010-07-31 23:20:56 +000053
54 // CHECK: [[SETJMP:%.*]] = call i32 @_setjmp
55 // CHECK-NEXT: [[CAUGHT:%.*]] = icmp eq i32 [[SETJMP]], 0
56 // CHECK-NEXT: br i1 [[CAUGHT]]
57 @try {
John McCall0b251722010-08-04 05:59:32 +000058 // If the optimizers ever figure out how to make this store 6,
59 // that's okay.
John McCall87bb5822010-07-31 23:20:56 +000060 // CHECK: [[T1:%.*]] = load i32* [[X]]
61 // CHECK-NEXT: [[T2:%.*]] = add nsw i32 [[T1]], 1
62 // CHECK-NEXT: store i32 [[T2]], i32* [[X]]
63 x++;
John McCall0b251722010-08-04 05:59:32 +000064 // CHECK-NEXT: call void asm sideeffect "", "*m,*m"(i32* [[X]]
John McCall87bb5822010-07-31 23:20:56 +000065 // CHECK-NEXT: call void @foo()
John McCall0b251722010-08-04 05:59:32 +000066 // CHECK-NEXT: call void @objc_exception_try_exit
67 // CHECK-NEXT: [[T:%.*]] = load i32* [[X]]
68 // CHECK-NEXT: ret i32 [[T]]
John McCall87bb5822010-07-31 23:20:56 +000069 foo();
70 } @catch (id) {
John McCall0b251722010-08-04 05:59:32 +000071 // Landing pad. Note that we elide the re-enter.
72 // CHECK: call void asm sideeffect "", "=*m,=*m"(i32* [[X]]
John McCall87bb5822010-07-31 23:20:56 +000073 // CHECK-NEXT: call i8* @objc_exception_extract
John McCall0b251722010-08-04 05:59:32 +000074 // CHECK-NEXT: [[T1:%.*]] = load i32* [[X]]
John McCall87bb5822010-07-31 23:20:56 +000075 // CHECK-NEXT: [[T2:%.*]] = add nsw i32 [[T1]], -1
John McCall0b251722010-08-04 05:59:32 +000076
77 // This store is dead.
John McCall87bb5822010-07-31 23:20:56 +000078 // CHECK-NEXT: store i32 [[T2]], i32* [[X]]
John McCall0b251722010-08-04 05:59:32 +000079
80 // CHECK-NEXT: ret i32 [[T2]]
John McCall87bb5822010-07-31 23:20:56 +000081 x--;
82 }
John McCall87bb5822010-07-31 23:20:56 +000083 return x;
84}
John McCalld96a8e72010-08-11 00:16:14 +000085
86// Test that the cleanup destination is saved when entering a finally
87// block. rdar://problem/8293901
88// CHECK: define void @f3()
89void f3() {
90 extern void f3_helper(int, int*);
91
92 // CHECK: [[X:%.*]] = alloca i32
93 // CHECK: store i32 0, i32* [[X]]
94 int x = 0;
95
96 // CHECK: call void @objc_exception_try_enter(
97 // CHECK: call i32 @_setjmp
98 // CHECK-NEXT: icmp eq
99 // CHECK-NEXT: br i1
100
101 @try {
102 // CHECK: call void @f3_helper(i32 0, i32* [[X]])
103 // CHECK: call void @objc_exception_try_exit(
104 f3_helper(0, &x);
105 } @finally {
106 // CHECK: [[DEST1:%.*]] = phi i32 [ 0, {{%.*}} ], [ 3, {{%.*}} ]
107 // CHECK: call void @objc_exception_try_enter
108 // CHECK: call i32 @_setjmp
109 @try {
110 // CHECK: call void @f3_helper(i32 1, i32* [[X]])
111 // CHECK: call void @objc_exception_try_exit(
112 f3_helper(1, &x);
113 } @finally {
114 // CHECK: [[DEST2:%.*]] = phi i32 [ 0, {{%.*}} ], [ 5, {{%.*}} ]
115 // CHECK: call void @f3_helper(i32 2, i32* [[X]])
116 f3_helper(2, &x);
117
118 // This loop is large enough to dissuade the optimizer from just
119 // duplicating the finally block.
120 while (x) f3_helper(3, &x);
121
John McCall04348812010-08-11 02:06:44 +0000122 // This is a switch or maybe some chained branches, but relying
123 // on a specific result from the optimizer is really unstable.
124 // CHECK: [[DEST2]]
John McCalld96a8e72010-08-11 00:16:14 +0000125 }
126
John McCall04348812010-08-11 02:06:44 +0000127 // This is a switch or maybe some chained branches, but relying
128 // on a specific result from the optimizer is really unstable.
129 // CHECK: [[DEST1]]
John McCalld96a8e72010-08-11 00:16:14 +0000130 }
131
132 // CHECK: call void @f3_helper(i32 4, i32* [[X]])
133 // CHECK-NEXT: ret void
134 f3_helper(4, &x);
135}