summaryrefslogtreecommitdiffstats
path: root/clang/test/CodeGen/exceptions-seh.c
diff options
context:
space:
mode:
authorReid Kleckner <reid@kleckner.net>2015-04-28 22:19:32 +0000
committerReid Kleckner <reid@kleckner.net>2015-04-28 22:19:32 +0000
commitddd40964f07769412be1916b4ce661027f14a3c6 (patch)
tree393414f1e30cd6a7c02d026c92c5f77a565e5c1f /clang/test/CodeGen/exceptions-seh.c
parentb49febeaee5dec219fae5d5f72fcdf4d3f24030f (diff)
downloadbcm5719-llvm-ddd40964f07769412be1916b4ce661027f14a3c6.tar.gz
bcm5719-llvm-ddd40964f07769412be1916b4ce661027f14a3c6.zip
[SEH] Add 32-bit lowering code for __try
This is just the clang-side of 32-bit SEH. LLVM still needs work, and it will determinstically fail to compile until it's feature complete. On x86, all outlined handlers have no parameters, but they do implicitly take the EBP value passed in and use it to address locals of the parent frame. We model this with llvm.frameaddress(1). This works (mostly), but __finally block inlining can break it. For now, we apply the 'noinline' attribute. If we really want to inline __finally blocks on 32-bit x86, we should teach the inliner how to untangle frameescape and framerecover. Promote the error diagnostic from codegen to sema. It now rejects SEH on non-Windows platforms. LLVM doesn't implement SEH on non-x86 Windows platforms, but there's nothing preventing it. llvm-svn: 236052
Diffstat (limited to 'clang/test/CodeGen/exceptions-seh.c')
-rw-r--r--clang/test/CodeGen/exceptions-seh.c59
1 files changed, 43 insertions, 16 deletions
diff --git a/clang/test/CodeGen/exceptions-seh.c b/clang/test/CodeGen/exceptions-seh.c
index d8135e805c6..40796bc075b 100644
--- a/clang/test/CodeGen/exceptions-seh.c
+++ b/clang/test/CodeGen/exceptions-seh.c
@@ -1,4 +1,7 @@
-// RUN: %clang_cc1 %s -triple x86_64-pc-win32 -fms-extensions -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 %s -triple x86_64-pc-win32 -fms-extensions -emit-llvm -o - \
+// RUN: | FileCheck %s --check-prefix=CHECK --check-prefix=X64
+// RUN: %clang_cc1 %s -triple i686-pc-win32 -fms-extensions -emit-llvm -o - \
+// RUN: | FileCheck %s --check-prefix=CHECK --check-prefix=X86
void try_body(int numerator, int denominator, int *myres) {
*myres = numerator / denominator;
@@ -24,7 +27,8 @@ int safe_div(int numerator, int denominator, int *res) {
// CHECK: to label %{{.*}} unwind label %[[lpad:[^ ]*]]
//
// CHECK: [[lpad]]
-// CHECK: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*)
+// X64: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*)
+// X86: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @_except_handler3 to i8*)
// CHECK-NEXT: catch i8* null
// CHECK-NOT: br i1
// CHECK: br label %[[except:[^ ]*]]
@@ -52,14 +56,19 @@ int filter_expr_capture(void) {
// CHECK: invoke void @j() #[[NOINLINE]]
//
// CHECK: landingpad
-// CHECK-NEXT: catch i8* bitcast (i32 (i8*, i8*)* @"\01?filt$0@0@filter_expr_capture@@" to i8*)
+// CHECK-NEXT: catch i8* bitcast (i32 ({{.*}})* @"\01?filt$0@0@filter_expr_capture@@" to i8*)
// CHECK: store i32 13, i32* %[[r]]
//
// CHECK: %[[rv:[^ ]*]] = load i32, i32* %[[r]]
// CHECK: ret i32 %[[rv]]
-// CHECK-LABEL: define internal i32 @"\01?filt$0@0@filter_expr_capture@@"(i8* %exception_pointers, i8* %frame_pointer)
-// CHECK: call i8* @llvm.framerecover(i8* bitcast (i32 ()* @filter_expr_capture to i8*), i8* %frame_pointer, i32 0)
+// X64-LABEL: define internal i32 @"\01?filt$0@0@filter_expr_capture@@"(i8* %exception_pointers, i8* %frame_pointer)
+// X64: call i8* @llvm.framerecover(i8* bitcast (i32 ()* @filter_expr_capture to i8*), i8* %frame_pointer, i32 0)
+//
+// X86-LABEL: define internal i32 @"\01?filt$0@0@filter_expr_capture@@"()
+// X86: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 1)
+// X86: call i8* @llvm.framerecover(i8* bitcast (i32 ()* @filter_expr_capture to i8*), i8* %[[fp]], i32 0)
+//
// CHECK: store i32 -1, i32* %{{.*}}
// CHECK: ret i32 -1
@@ -87,19 +96,20 @@ int nested_try(void) {
// CHECK: br label %[[inner_try_cont:[^ ]*]]
//
// CHECK: [[lpad]]
-// CHECK: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*)
-// CHECK: catch i8* bitcast (i32 (i8*, i8*)* @"\01?filt$1@0@nested_try@@" to i8*)
-// CHECK: catch i8* bitcast (i32 (i8*, i8*)* @"\01?filt$0@0@nested_try@@" to i8*)
+// X64: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*)
+// X86: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @_except_handler3 to i8*)
+// CHECK: catch i8* bitcast (i32 ({{.*}})* @"\01?filt$1@0@nested_try@@" to i8*)
+// CHECK: catch i8* bitcast (i32 ({{.*}})* @"\01?filt$0@0@nested_try@@" to i8*)
// CHECK: store i8* %{{.*}}, i8** %[[ehptr_slot:[^ ]*]]
// CHECK: store i32 %{{.*}}, i32* %[[sel_slot:[^ ]*]]
//
// CHECK: load i32, i32* %[[sel_slot]]
-// CHECK: call i32 @llvm.eh.typeid.for(i8* bitcast (i32 (i8*, i8*)* @"\01?filt$1@0@nested_try@@" to i8*))
+// CHECK: call i32 @llvm.eh.typeid.for(i8* bitcast (i32 ({{.*}})* @"\01?filt$1@0@nested_try@@" to i8*))
// CHECK: icmp eq i32
// CHECK: br i1
//
// CHECK: load i32, i32* %[[sel_slot]]
-// CHECK: call i32 @llvm.eh.typeid.for(i8* bitcast (i32 (i8*, i8*)* @"\01?filt$0@0@nested_try@@" to i8*))
+// CHECK: call i32 @llvm.eh.typeid.for(i8* bitcast (i32 ({{.*}})* @"\01?filt$0@0@nested_try@@" to i8*))
// CHECK: icmp eq i32
// CHECK: br i1
//
@@ -115,6 +125,20 @@ int nested_try(void) {
//
// CHECK: [[inner_try_cont]]
// CHECK: br label %[[outer_try_cont]]
+//
+// CHECK-LABEL: define internal i32 @"\01?filt$0@0@nested_try@@"({{.*}})
+// X86: call i8* @llvm.eh.exceptioninfo()
+// CHECK: load i32*, i32**
+// CHECK: load i32, i32*
+// CHECK: ptrtoint
+// CHECK: icmp eq i32 %{{.*}}, 456
+//
+// CHECK-LABEL: define internal i32 @"\01?filt$1@0@nested_try@@"({{.*}})
+// X86: call i8* @llvm.eh.exceptioninfo()
+// CHECK: load i32*, i32**
+// CHECK: load i32, i32*
+// CHECK: ptrtoint
+// CHECK: icmp eq i32 %{{.*}}, 123
static unsigned g = 0;
void basic_finally(void) {
@@ -134,18 +158,21 @@ void basic_finally(void) {
// CHECK: to label %[[cont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
//
// CHECK: [[cont]]
-// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
-// CHECK: call void @"\01?fin$0@0@basic_finally@@"(i8 0, i8* %[[fp]])
+// X64: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
+// X64: call void @"\01?fin$0@0@basic_finally@@"(i8 0, i8* %[[fp]])
+// X86: call void @"\01?fin$0@0@basic_finally@@"()
// CHECK: ret void
//
// CHECK: [[lpad]]
-// CHECK: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*)
+// X64: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*)
+// X86: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @_except_handler3 to i8*)
// CHECK-NEXT: cleanup
-// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
-// CHECK: call void @"\01?fin$0@0@basic_finally@@"(i8 1, i8* %[[fp]])
+// X64: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
+// X64: call void @"\01?fin$0@0@basic_finally@@"(i8 1, i8* %[[fp]])
+// X86: call void @"\01?fin$0@0@basic_finally@@"()
// CHECK: resume
-// CHECK: define internal void @"\01?fin$0@0@basic_finally@@"(i8 %abnormal_termination, i8* %frame_pointer)
+// CHECK: define internal void @"\01?fin$0@0@basic_finally@@"({{.*}})
// CHECK: load i32, i32* @g, align 4
// CHECK: add i32 %{{.*}}, -1
// CHECK: store i32 %{{.*}}, i32* @g, align 4
OpenPOWER on IntegriCloud