Files
clang-p2996/clang/test/CodeGenObjC/exceptions.m
John McCall 2dd7d44135 Some more correctness fixes and code-size optimizations for fragile-ABI
ObjC exceptions:
  - don't enter a try for the catch blocks unless there's a finally
  - put the setjmp buffer in the locals set for liveness reasons
  - dump the sync object into an alloca in the locals set for liveness reasons
Some of this can go away if the backend starts to properly calculate liveness
in the presence of setjmp (which would also be a *much* stabler solution).

llvm-svn: 110188
2010-08-04 05:59:32 +00:00

85 lines
2.3 KiB
Objective-C

// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fexceptions -O2 -o - %s | FileCheck %s
//
// <rdar://problem/7471679> [irgen] [eh] Exception code built with clang (x86_64) crashes
// Just check that we don't emit any dead blocks.
@interface NSArray @end
void f0() {
@try {
@try {
@throw @"a";
} @catch(NSArray *e) {
}
} @catch (id e) {
}
}
// CHECK: define void @f1()
void f1() {
extern void foo(void);
while (1) {
// CHECK: call void @objc_exception_try_enter
// CHECK-NEXT: getelementptr
// CHECK-NEXT: call i32 @_setjmp(
// CHECK-NEXT: icmp
// CHECK-NEXT: br i1
@try {
// CHECK: call void asm sideeffect "", "*m"
// CHECK-NEXT: call void @foo()
foo();
// CHECK-NEXT: call void @objc_exception_try_exit
// CHECK-NEXT: ret void
// CHECK: call void asm sideeffect "", "=*m"
// CHECK-NEXT: ret void
} @finally {
break;
}
}
}
// Test that modifications to local variables are respected under
// optimization. rdar://problem/8160285
// CHECK: define i32 @f2()
int f2() {
extern void foo(void);
// CHECK: [[X:%.*]] = alloca i32
// CHECK: store i32 5, i32* [[X]]
int x = 0;
x += 5;
// CHECK: [[SETJMP:%.*]] = call i32 @_setjmp
// CHECK-NEXT: [[CAUGHT:%.*]] = icmp eq i32 [[SETJMP]], 0
// CHECK-NEXT: br i1 [[CAUGHT]]
@try {
// If the optimizers ever figure out how to make this store 6,
// that's okay.
// CHECK: [[T1:%.*]] = load i32* [[X]]
// CHECK-NEXT: [[T2:%.*]] = add nsw i32 [[T1]], 1
// CHECK-NEXT: store i32 [[T2]], i32* [[X]]
x++;
// CHECK-NEXT: call void asm sideeffect "", "*m,*m"(i32* [[X]]
// CHECK-NEXT: call void @foo()
// CHECK-NEXT: call void @objc_exception_try_exit
// CHECK-NEXT: [[T:%.*]] = load i32* [[X]]
// CHECK-NEXT: ret i32 [[T]]
foo();
} @catch (id) {
// Landing pad. Note that we elide the re-enter.
// CHECK: call void asm sideeffect "", "=*m,=*m"(i32* [[X]]
// CHECK-NEXT: call i8* @objc_exception_extract
// CHECK-NEXT: [[T1:%.*]] = load i32* [[X]]
// CHECK-NEXT: [[T2:%.*]] = add nsw i32 [[T1]], -1
// This store is dead.
// CHECK-NEXT: store i32 [[T2]], i32* [[X]]
// CHECK-NEXT: ret i32 [[T2]]
x--;
}
return x;
}