diff options
| author | Reid Kleckner <reid@kleckner.net> | 2015-04-09 20:37:24 +0000 |
|---|---|---|
| committer | Reid Kleckner <reid@kleckner.net> | 2015-04-09 20:37:24 +0000 |
| commit | 0dbecf2b7816353329f58c91157670cd3e1e7b77 (patch) | |
| tree | 6ddd5da585e66e28a8f6726c7c02d09d47307269 /clang/test | |
| parent | 589015b1e3d220a0a0060ec115541a66c0d25fc7 (diff) | |
| download | bcm5719-llvm-0dbecf2b7816353329f58c91157670cd3e1e7b77.tar.gz bcm5719-llvm-0dbecf2b7816353329f58c91157670cd3e1e7b77.zip | |
[SEH] Outline finally blocks using the new variable capture support
WinEHPrepare was going to have to pattern match the control flow merge
and split that the old lowering used, and that wasn't really feasible.
Now we can teach WinEHPrepare to pattern match this, which is much
simpler:
%fp = call i8* @llvm.frameaddress(i32 0)
call void @func(iN [01], i8* %fp)
This prototype happens to match the prototype used by the Win64 SEH
personality function, so this is really simple.
llvm-svn: 234532
Diffstat (limited to 'clang/test')
| -rw-r--r-- | clang/test/CodeGen/exceptions-seh-finally.c | 229 | ||||
| -rw-r--r-- | clang/test/CodeGen/exceptions-seh-leave.c | 149 | ||||
| -rw-r--r-- | clang/test/CodeGen/exceptions-seh.c | 23 |
3 files changed, 165 insertions, 236 deletions
diff --git a/clang/test/CodeGen/exceptions-seh-finally.c b/clang/test/CodeGen/exceptions-seh-finally.c index eeadf0d5ec5..a315379d525 100644 --- a/clang/test/CodeGen/exceptions-seh-finally.c +++ b/clang/test/CodeGen/exceptions-seh-finally.c @@ -17,30 +17,20 @@ void basic_finally(void) { // CHECK: to label %[[invoke_cont:[^ ]*]] unwind label %[[lpad:[^ ]*]] // // CHECK: [[invoke_cont]] -// CHECK: store i8 0, i8* %[[abnormal:[^ ]*]] -// CHECK: br label %[[finally:[^ ]*]] -// -// CHECK: [[finally]] -// CHECK: call void @cleanup() -// CHECK: load i8, i8* %[[abnormal]] -// CHECK: icmp eq -// CHECK: br i1 %{{.*}}, label %[[finallycont:[^ ]*]], label %[[resumecont:[^ ]*]] -// -// CHECK: [[finallycont]] +// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) +// CHECK: call void @"\01?fin$0@0@basic_finally@@"(i1 zeroext false, i8* %[[fp]]) // CHECK-NEXT: ret void // // CHECK: [[lpad]] // CHECK-NEXT: landingpad // CHECK-NEXT: cleanup -// CHECK: store i8 1, i8* %[[abnormal]] -// CHECK: br label %[[finally]] -// -// CHECK: [[resumecont]] -// CHECK: br label %[[ehresume:[^ ]*]] -// -// CHECK: [[ehresume]] +// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) +// CHECK: call void @"\01?fin$0@0@basic_finally@@"(i1 zeroext true, i8* %[[fp]]) // CHECK: resume { i8*, i32 } +// CHECK: define internal void @"\01?fin$0@0@basic_finally@@"(i1 zeroext %abnormal_termination, i8* %frame_pointer) +// CHECK: call void @cleanup() + // Mostly check that we don't double emit 'r' which would crash. void decl_in_finally(void) { __try { @@ -67,10 +57,11 @@ l: // CHECK: to label %[[invoke_cont:[^ ]*]] unwind label %[[lpad:[^ ]*]] // // CHECK: [[invoke_cont]] -// CHECK: store i8 0, i8* %[[abnormal:[^ ]*]] -// CHECK: br label %[[finally:[^ ]*]] -// -// CHECK: [[finally]] +// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) +// CHECK: call void @"\01?fin$0@0@label_in_finally@@"(i1 zeroext false, i8* %[[fp]]) +// CHECK: ret void + +// CHECK: define internal void @"\01?fin$0@0@label_in_finally@@"(i1 zeroext %abnormal_termination, i8* %frame_pointer) // CHECK: br label %[[l:[^ ]*]] // // CHECK: [[l]] @@ -93,32 +84,22 @@ void use_abnormal_termination(void) { // CHECK: to label %[[invoke_cont:[^ ]*]] unwind label %[[lpad:[^ ]*]] // // CHECK: [[invoke_cont]] -// CHECK: store i8 0, i8* %[[abnormal:[^ ]*]] -// CHECK: br label %[[finally:[^ ]*]] -// -// CHECK: [[finally]] -// CHECK: load i8, i8* %[[abnormal]] -// CHECK: zext i8 %{{.*}} to i32 -// CHECK: store i32 %{{.*}}, i32* @crashed -// CHECK: load i8, i8* %[[abnormal]] -// CHECK: icmp eq -// CHECK: br i1 %{{.*}}, label %[[finallycont:[^ ]*]], label %[[resumecont:[^ ]*]] -// -// CHECK: [[finallycont]] -// CHECK-NEXT: ret void +// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) +// CHECK: call void @"\01?fin$0@0@use_abnormal_termination@@"(i1 zeroext false, i8* %[[fp]]) +// CHECK: ret void // // CHECK: [[lpad]] // CHECK-NEXT: landingpad // CHECK-NEXT: cleanup -// CHECK: store i8 1, i8* %[[abnormal]] -// CHECK: br label %[[finally]] -// -// CHECK: [[resumecont]] -// CHECK: br label %[[ehresume:[^ ]*]] -// -// CHECK: [[ehresume]] +// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) +// CHECK: call void @"\01?fin$0@0@use_abnormal_termination@@"(i1 zeroext true, i8* %[[fp]]) // CHECK: resume { i8*, i32 } +// CHECK: define internal void @"\01?fin$0@0@use_abnormal_termination@@"(i1 zeroext %abnormal_termination, i8* %frame_pointer) +// CHECK: %[[abnormal_zext:[^ ]*]] = zext i1 %abnormal_termination to i32 +// CHECK: store i32 %[[abnormal_zext]], i32* @crashed +// CHECK-NEXT: ret void + void noreturn_noop_finally() { __try { __noop(); @@ -128,12 +109,13 @@ void noreturn_noop_finally() { } // CHECK-LABEL: define void @noreturn_noop_finally() -// CHECK: store i8 0, i8* % -// CHECK: br label %[[finally:[^ ]*]] -// CHECK: [[finally]] +// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) +// CHECK: call void @"\01?fin$0@0@noreturn_noop_finally@@"(i1 zeroext false, i8* %[[fp]]) +// CHECK: ret void + +// CHECK: define internal void @"\01?fin$0@0@noreturn_noop_finally@@"(i1 zeroext %abnormal_termination, i8* %frame_pointer) // CHECK: call void @abort() -// CHECK-NEXT: unreachable -// CHECK-NOT: load +// CHECK: unreachable void noreturn_finally() { __try { @@ -148,18 +130,20 @@ void noreturn_finally() { // CHECK: to label %[[cont:[^ ]*]] unwind label %[[lpad:[^ ]*]] // // CHECK: [[cont]] -// CHECK: store i8 0, i8* % -// CHECK: br label %[[finally:[^ ]*]] -// -// CHECK: [[finally]] -// CHECK: call void @abort() -// CHECK-NEXT: unreachable +// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) +// CHECK: call void @"\01?fin$0@0@noreturn_finally@@"(i1 zeroext false, i8* %[[fp]]) +// CHECK: ret void // // CHECK: [[lpad]] // CHECK: landingpad // CHECK-NEXT: cleanup -// CHECK: store i8 1, i8* % -// CHECK: br label %[[finally]] +// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) +// CHECK: call void @"\01?fin$0@0@noreturn_finally@@"(i1 zeroext true, i8* %[[fp]]) +// CHECK: resume { i8*, i32 } + +// CHECK: define internal void @"\01?fin$0@0@noreturn_finally@@"(i1 zeroext %abnormal_termination, i8* %frame_pointer) +// CHECK: call void @abort() +// CHECK: unreachable int finally_with_return() { __try { @@ -168,15 +152,17 @@ int finally_with_return() { } } // CHECK-LABEL: define i32 @finally_with_return() -// CHECK: store i8 0, i8* % -// CHECK-NEXT: br label %[[finally:[^ ]*]] -// -// CHECK: [[finally]] -// CHECK-NEXT: br label %[[finallycont:[^ ]*]] -// -// CHECK: [[finallycont]] +// CHECK: alloca i32 +// CHECK-NEXT: store i32 +// CHECK-NEXT: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) +// CHECK-NEXT: call void @"\01?fin$0@0@finally_with_return@@"(i1 zeroext false, i8* %[[fp]]) // CHECK-NEXT: ret i32 42 +// CHECK: define internal void @"\01?fin$0@0@finally_with_return@@"(i1 zeroext %abnormal_termination, i8* %frame_pointer) +// CHECK-NOT: br i1 +// CHECK-NOT: br label +// CHECK: ret void + int nested___finally___finally() { __try { __try { @@ -188,38 +174,28 @@ int nested___finally___finally() { } return 0; } + // CHECK-LABEL: define i32 @nested___finally___finally -// CHECK: store i8 0, i8* % -// CHECK-NEXT: br label %[[finally:[^ ]*]] +// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) +// CHECK: invoke void @"\01?fin$1@0@nested___finally___finally@@"(i1 zeroext false, i8* %[[fp]]) +// CHECK: to label %[[outercont:[^ ]*]] unwind label %[[lpad:[^ ]*]] // -// CHECK: [[finally]] -// CHECK-NEXT: store i32 1, i32* % -// CHECK-NEXT: store i32 1, i32* % -// CHECK-NEXT: br label %[[cleanup:[^ ]*]] +// CHECK: [[outercont]] +// CHECK-NEXT: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) +// CHECK-NEXT: call void @"\01?fin$0@0@nested___finally___finally@@"(i1 zeroext false, i8* %[[fp]]) +// CHECK-NEXT: ret i32 0 // -// The finally's unreachable continuation block: -// CHECK: store i32 0, i32* % -// CHECK-NEXT: br label %[[cleanup]] -// -// CHECK: [[cleanup]] -// CHECK-NEXT: store i8 0, i8* % -// CHECK-NEXT: br label %[[outerfinally:[^ ]*]] -// -// CHECK: [[outerfinally]] -// CHECK-NEXT: br label %[[finallycont:[^ ]*]] -// -// CHECK: [[finallycont]] -// CHECK-NEXT: %[[dest:[^ ]*]] = load i32, i32* % -// CHECK-NEXT: switch i32 %[[dest]] -// CHECK-NEXT: i32 0, label %[[cleanupcont:[^ ]*]] -// -// CHECK: [[cleanupcont]] -// CHECK-NEXT: store i32 0, i32* % -// CHECK-NEXT: br label %[[return:[^ ]*]] -// -// CHECK: [[return]] -// CHECK-NEXT: %[[reg:[^ ]*]] = load i32, i32* % -// CHECK-NEXT: ret i32 %[[reg]] +// CHECK: [[lpad]] +// CHECK-NEXT: landingpad +// CHECK-NEXT: cleanup +// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) +// CHECK-NEXT: call void @"\01?fin$0@0@nested___finally___finally@@"(i1 zeroext true, i8* %[[fp]]) + +// CHECK-LABEL: define internal void @"\01?fin$0@0@nested___finally___finally@@"(i1 zeroext %abnormal_termination, i8* %frame_pointer) +// CHECK: ret void + +// CHECK-LABEL: define internal void @"\01?fin$1@0@nested___finally___finally@@"(i1 zeroext %abnormal_termination, i8* %frame_pointer) +// CHECK: unreachable int nested___finally___finally_with_eh_edge() { __try { @@ -234,58 +210,35 @@ int nested___finally___finally_with_eh_edge() { return 912; } // CHECK-LABEL: define i32 @nested___finally___finally_with_eh_edge -// CHECK: invoke void @might_crash() #3 -// CHECK-NEXT: to label %[[invokecont:[^ ]*]] unwind label %[[lpad:[^ ]*]] -// -// CHECK: [[invokecont]] -// CHECK-NEXT: store i8 0, i8* %[[abnormal:[^ ]*]] -// CHECK-NEXT: br label %[[finally:[^ ]*]] - -// CHECK: [[finally]] -// CHECK-NEXT: store i32 899, i32* % -// CHECK-NEXT: store i32 1, i32* % -// CHECK-NEXT: br label %[[cleanup:[^ ]*]] -// -// The inner finally's unreachable continuation block: -// CHECK: store i32 0, i32* % -// CHECK-NEXT: br label %[[cleanup]] -// -// CHECK: [[cleanup]] -// CHECK-NEXT: store i8 0, i8* % -// CHECK-NEXT: br label %[[outerfinally:[^ ]*]] -// -// CHECK: [[outerfinally]] -// CHECK-NEXT: %[[abnormallocal:[^ ]*]] = load i8, i8* %[[abnormal]] -// CHECK-NEXT: %[[reg:[^ ]*]] = icmp eq i8 %[[abnormallocal]], 0 -// CHECK-NEXT: br i1 %[[reg]], label %[[finallycont:[^ ]*]], label %[[finallyresume:[^ ]*]] -// -// CHECK: [[finallycont]] -// CHECK-NEXT: %[[dest:[^ ]*]] = load i32, i32* % -// CHECK-NEXT: switch i32 %[[dest]] -// CHECK-NEXT: i32 0, label %[[cleanupcont:[^ ]*]] +// CHECK: invoke void @might_crash() +// CHECK-NEXT: to label %[[invokecont:[^ ]*]] unwind label %[[lpad1:[^ ]*]] // -// CHECK: [[cleanupcont]] -// CHECK-NEXT: store i32 912, i32* % -// CHECK-NEXT: br label %[[return:[^ ]*]] +// [[invokecont]] +// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) +// CHECK: invoke void @"\01?fin$1@0@nested___finally___finally_with_eh_edge@@"(i1 zeroext false, i8* %[[fp]]) +// CHECK: to label %[[outercont:[^ ]*]] unwind label %[[lpad2:[^ ]*]] // +// CHECK: [[outercont]] +// CHECK-NEXT: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) +// CHECK-NEXT: call void @"\01?fin$0@0@nested___finally___finally_with_eh_edge@@"(i1 zeroext false, i8* %[[fp]]) +// CHECK-NEXT: ret i32 912 // -// CHECK: [[lpad]] +// CHECK: [[lpad1]] // CHECK-NEXT: landingpad // CHECK-NEXT: cleanup -// CHECK: store i8 1, i8* %[[abnormal]] -// CHECK: br label %[[finally]] -// -// The inner finally's unreachable resume block: -// CHECK: store i8 1, i8* %[[abnormal]] -// CHECK-NEXT: br label %[[outerfinally]] +// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) +// CHECK: invoke void @"\01?fin$1@0@nested___finally___finally_with_eh_edge@@"(i1 zeroext true, i8* %[[fp]]) +// CHECK: to label %[[outercont:[^ ]*]] unwind label %[[lpad2]] // -// CHECK: [[finallyresume]] -// CHECK-NEXT: br label %[[ehresume:[^ ]*]] -// -// CHECK: [[return]] -// CHECK-NEXT: %[[reg:[^ ]*]] = load i32, i32* % -// CHECK-NEXT: ret i32 %[[reg]] -// -// The ehresume block, not reachable either. -// CHECK: [[ehresume]] +// CHECK: [[lpad2]] +// CHECK-NEXT: landingpad +// CHECK-NEXT: cleanup +// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) +// CHECK: call void @"\01?fin$0@0@nested___finally___finally_with_eh_edge@@"(i1 zeroext true, i8* %[[fp]]) // CHECK: resume + +// CHECK-LABEL: define internal void @"\01?fin$0@0@nested___finally___finally_with_eh_edge@@"(i1 zeroext %abnormal_termination, i8* %frame_pointer) +// CHECK: ret void + +// CHECK-LABEL: define internal void @"\01?fin$1@0@nested___finally___finally_with_eh_edge@@"(i1 zeroext %abnormal_termination, i8* %frame_pointer) +// CHECK: unreachable diff --git a/clang/test/CodeGen/exceptions-seh-leave.c b/clang/test/CodeGen/exceptions-seh-leave.c index 0d38439c9b0..793501a9fe5 100644 --- a/clang/test/CodeGen/exceptions-seh-leave.c +++ b/clang/test/CodeGen/exceptions-seh-leave.c @@ -1,6 +1,6 @@ // RUN: %clang_cc1 %s -triple x86_64-pc-win32 -fms-extensions -emit-llvm -o - | FileCheck %s -void g(); +void g(void); ////////////////////////////////////////////////////////////////////////////// // __leave with __except @@ -38,7 +38,7 @@ int __leave_with___except() { return 1; } // CHECK-LABEL: define i32 @__leave_with___except() -// CHECK: invoke void bitcast (void (...)* @g to void ()*)() +// CHECK: invoke void @g() // CHECK-NEXT: to label %[[cont:.*]] unwind label %{{.*}} // For __excepts, instead of an explicit __try.__leave label, we could use // use invoke.cont as __leave jump target instead. However, not doing this @@ -74,8 +74,8 @@ int __leave_with___finally_simple() { // CHECK-NEXT: br label %[[tryleave:[^ ]*]] // CHECK-NOT: store i32 23 // CHECK: [[tryleave]] -// CHECK-NEXT: store i8 0, i8* % -// CHECK-NEXT: br label % +// CHECK-NEXT: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) +// CHECK-NEXT: call void @"\01?fin$0@0@__leave_with___finally_simple@@"(i1 zeroext false, i8* %[[fp]]) // __finally block doesn't return, __finally.cont doesn't exist. int __leave_with___finally_noreturn() { @@ -94,8 +94,8 @@ int __leave_with___finally_noreturn() { // CHECK-NEXT: br label %[[tryleave:[^ ]*]] // CHECK-NOT: store i32 23 // CHECK: [[tryleave]] -// CHECK-NEXT: store i8 0, i8* % -// CHECK-NEXT: br label % +// CHECK-NEXT: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) +// CHECK-NEXT: call void @"\01?fin$0@0@__leave_with___finally_noreturn@@"(i1 zeroext false, i8* %[[fp]]) // The "normal" case. int __leave_with___finally() { @@ -110,7 +110,7 @@ int __leave_with___finally() { return 1; } // CHECK-LABEL: define i32 @__leave_with___finally() -// CHECK: invoke void bitcast (void (...)* @g to void ()*)() +// CHECK: invoke void @g() // CHECK-NEXT: to label %[[cont:.*]] unwind label %{{.*}} // For __finally, there needs to be an explicit __try.__leave, because // abnormal.termination.slot needs to be set there. @@ -118,8 +118,8 @@ int __leave_with___finally() { // CHECK-NEXT: br label %[[tryleave:[^ ]*]] // CHECK-NOT: store i32 23 // CHECK: [[tryleave]] -// CHECK-NEXT: store i8 0, i8* % -// CHECK-NEXT: br label % +// CHECK-NEXT: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) +// CHECK-NEXT: call void @"\01?fin$0@0@__leave_with___finally@@"(i1 zeroext false, i8* %[[fp]]) ////////////////////////////////////////////////////////////////////////////// @@ -142,45 +142,37 @@ int nested___except___finally() { } return 1; } -// The order of basic blocks in the below doesn't matter. // CHECK-LABEL: define i32 @nested___except___finally() -// CHECK-LABEL: invoke void bitcast (void (...)* @g to void ()*)() -// CHECK-NEXT: to label %[[g1_cont:.*]] unwind label %[[g1_lpad:.*]] - -// CHECK: [[g1_cont]] -// CHECK-NEXT: store i8 0, i8* %[[abnormal:[^ ]*]] -// CHECK-NEXT: br label %[[finally:[^ ]*]] +// CHECK-LABEL: invoke void @g() +// CHECK-NEXT: to label %[[g1_cont1:.*]] unwind label %[[g1_lpad:.*]] -// CHECK: [[finally]] -// CHECK-NEXT: invoke void bitcast (void (...)* @g to void ()*)() -// CHECK-NEXT: to label %[[g2_cont:.*]] unwind label %[[g2_lpad:.*]] - -// CHECK: [[g2_cont]] -// CHECK-NEXT: br label %[[tryleave:[^ ]*]] -// CHECK-NOT: store i32 23 +// CHECK: [[g1_cont1]] +// CHECK-NEXT: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) +// CHECK-NEXT: invoke void @"\01?fin$0@0@nested___except___finally@@"(i1 zeroext false, i8* %[[fp]]) +// CHECK-NEXT: to label %[[fin_cont:.*]] unwind label %[[g2_lpad:.*]] -// Unused __finally continuation block +// CHECK: [[fin_cont]] // CHECK: store i32 51, i32* % -// CHECK-NEXT: br label %[[tryleave]] - -// CHECK: [[tryleave]] // CHECK-NEXT: br label %[[trycont:[^ ]*]] // CHECK: [[g1_lpad]] -// CHECK: store i8 1, i8* % -// CHECK-NEXT: br label %[[finally]] +// CHECK-NEXT: landingpad +// CHECK-NEXT: catch i8* null +// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) +// CHECK-NEXT: invoke void @"\01?fin$0@0@nested___except___finally@@"(i1 zeroext true, i8* %[[fp]]) +// CHECK-NEXT: to label %[[g1_resume:.*]] unwind label %[[g2_lpad]] // CHECK: [[g2_lpad]] -// CHECK-NOT: %[[abnormal]] -// CHECK: br label %[[except:[^ ]*]] - -// CHECK: [[except]] -// CHECK-NEXT: br label %[[trycont]] +// CHECK: br label %[[trycont]] // CHECK: [[trycont]] // CHECK-NEXT: ret i32 1 +// CHECK-LABEL: define internal void @"\01?fin$0@0@nested___except___finally@@"(i1 zeroext %abnormal_termination, i8* %frame_pointer) +// CHECK: call void @g() +// CHECK: unreachable + int nested___except___except() { int myres = 0; __try { @@ -202,7 +194,7 @@ int nested___except___except() { // The order of basic blocks in the below doesn't matter. // CHECK-LABEL: define i32 @nested___except___except() -// CHECK-LABEL: invoke void bitcast (void (...)* @g to void ()*)() +// CHECK-LABEL: invoke void @g() // CHECK-NEXT: to label %[[g1_cont:.*]] unwind label %[[g1_lpad:.*]] // CHECK: [[g1_cont]] @@ -213,7 +205,7 @@ int nested___except___except() { // CHECK: br label %[[except:[^ ]*]] // CHECK: [[except]] -// CHECK-NEXT: invoke void bitcast (void (...)* @g to void ()*)() #3 +// CHECK-NEXT: invoke void @g() // CHECK-NEXT: to label %[[g2_cont:.*]] unwind label %[[g2_lpad:.*]] // CHECK: [[g2_cont]] @@ -256,7 +248,7 @@ int nested___finally___except() { // The order of basic blocks in the below doesn't matter. // CHECK-LABEL: define i32 @nested___finally___except() -// CHECK-LABEL: invoke void bitcast (void (...)* @g to void ()*)() +// CHECK-LABEL: invoke void @g() // CHECK-NEXT: to label %[[g1_cont:.*]] unwind label %[[g1_lpad:.*]] // CHECK: [[g1_cont]] @@ -266,7 +258,7 @@ int nested___finally___except() { // CHECK: br label %[[except:[^ ]*]] // CHECK: [[except]] -// CHECK-NEXT: invoke void bitcast (void (...)* @g to void ()*)() +// CHECK-NEXT: invoke void @g() // CHECK-NEXT: to label %[[g2_cont:.*]] unwind label %[[g2_lpad:.*]] // CHECK: [[g2_cont]] @@ -274,31 +266,25 @@ int nested___finally___except() { // CHECK-NOT: 23 // CHECK: [[g2_lpad]] -// CHECK: store i8 1, i8* %[[abnormal:[^ ]*]] -// CHECK-NEXT: br label %[[finally:[^ ]*]] +// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) +// CHECK-NEXT: call void @"\01?fin$0@0@nested___finally___except@@"(i1 zeroext true, i8* %[[fp]]) +// CHECK-NEXT: br label %[[ehresume:[^ ]*]] // CHECK: [[trycont]] // CHECK: store i32 51, i32* % // CHECK-NEXT: br label %[[tryleave]] // CHECK: [[tryleave]] -// CHECK-NEXT: store i8 0, i8* %[[abnormal]] -// CHECK-NEXT: br label %[[finally:[^ ]*]] - -// CHECK: [[finally]] -// CHECK-NEXT: %[[abnormallocal:[^ ]*]] = load i8, i8* %[[abnormal]] -// CHECK-NEXT: %[[reg:[^ ]*]] = icmp eq i8 %[[abnormallocal]], 0 -// CHECK-NEXT: br i1 %[[reg]], label %[[finallycont:[^ ]*]], label %[[finallyresume:[^ ]*]] - -// CHECK: [[finallycont]] +// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) +// CHECK-NEXT: call void @"\01?fin$0@0@nested___finally___except@@"(i1 zeroext false, i8* %[[fp]]) // CHECK-NEXT: ret i32 1 -// CHECK: [[finallyresume]] -// CHECK-NEXT: br label %[[ehresume:[^ ]*]] - // CHECK: [[ehresume]] // CHECK: resume +// CHECK-LABEL: define internal void @"\01?fin$0@0@nested___finally___except@@"(i1 zeroext %abnormal_termination, i8* %frame_pointer) +// CHECK: ret void + int nested___finally___finally() { int myres = 0; __try { @@ -320,51 +306,44 @@ int nested___finally___finally() { // The order of basic blocks in the below doesn't matter. // CHECK-LABEL: define i32 @nested___finally___finally() -// CHECK-LABEL: invoke void bitcast (void (...)* @g to void ()*)() +// CHECK-LABEL: invoke void @g() // CHECK-NEXT: to label %[[g1_cont:.*]] unwind label %[[g1_lpad:.*]] // CHECK: [[g1_cont]] // CHECK: store i32 16, i32* %[[myres:[^ ]*]], -// CHECK: store i8 0, i8* %[[abnormal:[^ ]*]] -// CHECK-NEXT: br label %[[finally:[^ ]*]] - -// CHECK: [[finally]] -// CHECK-NEXT: invoke void bitcast (void (...)* @g to void ()*)() #3 -// CHECK-NEXT: to label %[[g2_cont:.*]] unwind label %[[g2_lpad:.*]] - -// CHECK: [[g2_cont]] -// CHECK-NEXT: br label %[[tryleave:[^ ]*]] -// CHECK-NOT: store i32 23 +// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) +// CHECK-NEXT: invoke void @"\01?fin$1@0@nested___finally___finally@@"(i1 zeroext false, i8* %[[fp]]) +// CHECK-NEXT: to label %[[finally_cont:.*]] unwind label %[[g2_lpad:.*]] -// There's an unreachable block for the skipped `myres = 51`. +// CHECK: [[finally_cont]] // CHECK: store i32 51, i32* %[[myres]] -// CHECK-NEXT: br label %[[tryleave]] - -// CHECK: [[tryleave]] -// CHECK-NEXT: store i8 0, i8* %[[abnormal]] -// CHECK-NEXT: br label %[[outerfinally:[^ ]*]] - -// CHECK: [[outerfinally]] -// CHECK-NEXT: %[[abnormallocal:[^ ]*]] = load i8, i8* %[[abnormal]] -// CHECK-NEXT: %[[reg:[^ ]*]] = icmp eq i8 %[[abnormallocal]], 0 -// CHECK-NEXT: br i1 %[[reg]], label %[[finallycont:[^ ]*]], label %[[finallyresume:[^ ]*]] - -// CHECK: [[finallycont]] +// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) +// CHECK-NEXT: call void @"\01?fin$0@0@nested___finally___finally@@"(i1 zeroext false, i8* %[[fp]]) // CHECK-NEXT: ret i32 1 // CHECK: [[g1_lpad]] -// CHECK: store i8 1, i8* %[[abnormal]] -// CHECK-NEXT: br label %[[finally:[^ ]*]] +// CHECK-NEXT: landingpad +// CHECK-NEXT: cleanup +// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) +// CHECK-NEXT: invoke void @"\01?fin$1@0@nested___finally___finally@@"(i1 zeroext true, i8* %[[fp]]) +// CHECK-NEXT: to label %[[finally_cont2:.*]] unwind label %[[g2_lpad]] // CHECK: [[g2_lpad]] -// CHECK: br label %[[ehcleanup:[^ ]*]] +// CHECK-NEXT: landingpad +// CHECK-NEXT: cleanup +// CHECK: br label %[[ehcleanup:.*]] + +// CHECK: [[finally_cont2]] +// CHECK: br label %[[ehcleanup]] // CHECK: [[ehcleanup]] -// CHECK-NEXT: store i8 1, i8* %[[abnormal]] -// CHECK-NEXT: br label %[[outerfinally]] +// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) +// CHECK-NEXT: call void @"\01?fin$0@0@nested___finally___finally@@"(i1 zeroext true, i8* %[[fp]]) +// CHECK: resume -// CHECK: [[finallyresume]] -// CHECK-NEXT: br label %[[ehresume:[^ ]*]] +// CHECK-LABEL: define internal void @"\01?fin$0@0@nested___finally___finally@@"(i1 zeroext %abnormal_termination, i8* %frame_pointer) +// CHECK: ret void -// CHECK: [[ehresume]] -// CHECK: resume +// CHECK-LABEL: define internal void @"\01?fin$1@0@nested___finally___finally@@"(i1 zeroext %abnormal_termination, i8* %frame_pointer) +// CHECK: call void @g() +// CHECK: unreachable diff --git a/clang/test/CodeGen/exceptions-seh.c b/clang/test/CodeGen/exceptions-seh.c index 2d9d4b1f018..9a273ced567 100644 --- a/clang/test/CodeGen/exceptions-seh.c +++ b/clang/test/CodeGen/exceptions-seh.c @@ -118,8 +118,6 @@ int nested_try(void) { // CHECK: [[inner_try_cont]] // CHECK: br label %[[outer_try_cont]] -// FIXME: This lowering of __finally can't actually work, it will have to -// change. static unsigned g = 0; void basic_finally(void) { ++g; @@ -138,24 +136,23 @@ void basic_finally(void) { // CHECK: to label %[[cont:[^ ]*]] unwind label %[[lpad:[^ ]*]] // // CHECK: [[cont]] -// CHECK: br label %[[finally:[^ ]*]] -// -// CHECK: [[finally]] -// CHECK: load i32, i32* @g -// CHECK: add i32 %{{.*}}, -1 -// CHECK: store i32 %{{.*}}, i32* @g -// CHECK: icmp eq -// CHECK: br i1 %{{.*}}, label -// +// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) +// CHECK: call void @"\01?fin$0@0@basic_finally@@"(i1 zeroext false, i8* %[[fp]]) // CHECK: ret void // // CHECK: [[lpad]] // CHECK: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*) // CHECK-NEXT: cleanup -// CHECK: br label %[[finally]] -// +// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) +// CHECK: call void @"\01?fin$0@0@basic_finally@@"(i1 zeroext true, i8* %[[fp]]) // CHECK: resume +// CHECK: define internal void @"\01?fin$0@0@basic_finally@@"(i1 zeroext %abnormal_termination, i8* %frame_pointer) +// CHECK: load i32, i32* @g, align 4 +// CHECK: add i32 %{{.*}}, -1 +// CHECK: store i32 %{{.*}}, i32* @g, align 4 +// CHECK: ret void + int returns_int(void); int except_return(void) { __try { |

