diff options
Diffstat (limited to 'clang/test/CodeGenCXX/microsoft-abi-exceptions.cpp')
-rw-r--r-- | clang/test/CodeGenCXX/microsoft-abi-exceptions.cpp | 63 |
1 files changed, 38 insertions, 25 deletions
diff --git a/clang/test/CodeGenCXX/microsoft-abi-exceptions.cpp b/clang/test/CodeGenCXX/microsoft-abi-exceptions.cpp index 6731c0effb0..ecce71d6c5c 100644 --- a/clang/test/CodeGenCXX/microsoft-abi-exceptions.cpp +++ b/clang/test/CodeGenCXX/microsoft-abi-exceptions.cpp @@ -14,17 +14,21 @@ void HasEHCleanup() { } // With exceptions, we need to clean up at least one of these temporaries. -// WIN32: define void @"\01?HasEHCleanup@@YAXXZ"() {{.*}} { -// First one doesn't have any cleanups, no need for invoke. -// WIN32: call void @"\01?getA@@YA?AUA@@XZ"(%struct.A* sret %{{.*}}) +// WIN32-LABEL: define void @"\01?HasEHCleanup@@YAXXZ"() {{.*}} { +// WIN32: %[[base:.*]] = call i8* @llvm.stacksave() +// If this call throws, we have to restore the stack. +// WIN32: invoke void @"\01?getA@@YA?AUA@@XZ"(%struct.A* sret %{{.*}}) // If this call throws, we have to cleanup the first temporary. // WIN32: invoke void @"\01?getA@@YA?AUA@@XZ"(%struct.A* sret %{{.*}}) -// If this call throws, we already popped our cleanups -// WIN32: call i32 @"\01?TakesTwo@@YAHUA@@0@Z" +// If this call throws, we have to cleanup the stacksave. +// WIN32: invoke i32 @"\01?TakesTwo@@YAHUA@@0@Z" +// WIN32: call void @llvm.stackrestore(i8* %[[base]]) // WIN32: ret void // // There should be one dtor call for unwinding from the second getA. // WIN32: invoke x86_thiscallcc void @"\01??1A@@QAE@XZ" +// WIN32-NOT: @"\01??1A@@QAE@XZ" +// WIN32: call void @llvm.stackrestore // WIN32: } void TakeRef(const A &a); @@ -32,20 +36,28 @@ int HasDeactivatedCleanups() { return TakesTwo((TakeRef(A()), A()), (TakeRef(A()), A())); } -// WIN32: define i32 @"\01?HasDeactivatedCleanups@@YAHXZ"() {{.*}} { +// WIN32-LABEL: define i32 @"\01?HasDeactivatedCleanups@@YAHXZ"() {{.*}} { // WIN32: %[[isactive:.*]] = alloca i1 -// WIN32: call x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ" +// WIN32: call i8* @llvm.stacksave() +// WIN32: %[[argmem:.*]] = alloca [[argmem_ty:<{ %struct.A, %struct.A }>]], inalloca +// WIN32: %[[arg1:.*]] = getelementptr inbounds [[argmem_ty]]* %[[argmem]], i32 0, i32 1 +// WIN32: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ" // WIN32: invoke void @"\01?TakeRef@@YAXABUA@@@Z" -// WIN32: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"(%struct.A* %[[arg1:.*]]) +// +// WIN32: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"(%struct.A* %[[arg1]]) // WIN32: store i1 true, i1* %[[isactive]] +// +// WIN32: %[[arg0:.*]] = getelementptr inbounds [[argmem_ty]]* %[[argmem]], i32 0, i32 0 // WIN32: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ" // WIN32: invoke void @"\01?TakeRef@@YAXABUA@@@Z" // WIN32: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ" // WIN32: store i1 false, i1* %[[isactive]] -// WIN32: invoke i32 @"\01?TakesTwo@@YAHUA@@0@Z" +// +// WIN32: invoke i32 @"\01?TakesTwo@@YAHUA@@0@Z"([[argmem_ty]]* inalloca %[[argmem]]) +// WIN32: call void @llvm.stackrestore // Destroy the two const ref temporaries. // WIN32: invoke x86_thiscallcc void @"\01??1A@@QAE@XZ" -// WIN32: call x86_thiscallcc void @"\01??1A@@QAE@XZ" +// WIN32: invoke x86_thiscallcc void @"\01??1A@@QAE@XZ" // WIN32: ret i32 // // Conditionally destroy arg1. @@ -60,20 +72,22 @@ int HasConditionalCleanup(bool cond) { return (cond ? TakesTwo(A(), A()) : CouldThrow()); } -// WIN32: define i32 @"\01?HasConditionalCleanup@@YAH_N@Z"(i1 zeroext %{{.*}}) {{.*}} { +// WIN32-LABEL: define i32 @"\01?HasConditionalCleanup@@YAH_N@Z"(i1 zeroext %{{.*}}) {{.*}} { // WIN32: store i1 false // WIN32: br i1 -// No cleanups, so we call and then activate a cleanup if it succeeds. -// WIN32: call x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"(%struct.A* %[[arg1:.*]]) +// WIN32: call i8* @llvm.stacksave() +// WIN32: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"(%struct.A* %{{.*}}) // WIN32: store i1 true -// Now we have a cleanup for the first aggregate, so we invoke. // WIN32: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"(%struct.A* %{{.*}}) -// Now we have no cleanups because TakeTwo will destruct both args. -// WIN32: call i32 @"\01?TakesTwo@@YAHUA@@0@Z" -// Still no cleanups, so call. +// WIN32: invoke i32 @"\01?TakesTwo@@YAHUA@@0@Z" +// WIN32: call void @llvm.stackrestore +// // WIN32: call i32 @"\01?CouldThrow@@YAHXZ"() -// Somewhere in the landing pad for our single invoke, call the dtor. -// WIN32: invoke x86_thiscallcc void @"\01??1A@@QAE@XZ"(%struct.A* %[[arg1]]) +// +// Only one dtor in the invoke for arg1 +// WIN32: invoke x86_thiscallcc void @"\01??1A@@QAE@XZ"({{.*}}) +// WIN32-NOT: invoke x86_thiscallcc void @"\01??1A@@QAE@XZ" +// WIN32: call void @llvm.stackrestore // WIN32: } // Now test both. @@ -81,8 +95,7 @@ int HasConditionalDeactivatedCleanups(bool cond) { return (cond ? TakesTwo((TakeRef(A()), A()), (TakeRef(A()), A())) : CouldThrow()); } -// WIN32: define i32 @"\01?HasConditionalDeactivatedCleanups@@YAH_N@Z"{{.*}} { -// WIN32: %[[arg1:.*]] = alloca %struct.A, align 4 +// WIN32-LABEL: define i32 @"\01?HasConditionalDeactivatedCleanups@@YAH_N@Z"{{.*}} { // WIN32: alloca i1 // WIN32: %[[arg1_cond:.*]] = alloca i1 // Start all four cleanups as deactivated. @@ -92,10 +105,10 @@ int HasConditionalDeactivatedCleanups(bool cond) { // WIN32: store i1 false // WIN32: br i1 // True condition. -// WIN32: call x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ" +// WIN32: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ" // WIN32: store i1 true // WIN32: invoke void @"\01?TakeRef@@YAXABUA@@@Z" -// WIN32: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"(%struct.A* %[[arg1]]) +// WIN32: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ" // WIN32: store i1 true, i1* %[[arg1_cond]] // WIN32: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ" // WIN32: store i1 true @@ -108,13 +121,13 @@ int HasConditionalDeactivatedCleanups(bool cond) { // WIN32: invoke i32 @"\01?CouldThrow@@YAHXZ"() // Two normal cleanups for TakeRef args. // WIN32: invoke x86_thiscallcc void @"\01??1A@@QAE@XZ" -// WIN32: call x86_thiscallcc void @"\01??1A@@QAE@XZ" +// WIN32: invoke x86_thiscallcc void @"\01??1A@@QAE@XZ" // WIN32: ret i32 // // Somewhere in the landing pad soup, we conditionally destroy arg1. // WIN32: %[[isactive:.*]] = load i1* %[[arg1_cond]] // WIN32: br i1 %[[isactive]] -// WIN32: invoke x86_thiscallcc void @"\01??1A@@QAE@XZ"(%struct.A* %[[arg1]]) +// WIN32: invoke x86_thiscallcc void @"\01??1A@@QAE@XZ" // WIN32: } namespace crash_on_partial_destroy { |