[CMake] More refactoring of symlink creation.
[oota-llvm.git] / test / CodeGen / WinEH / seh-simple.ll
index 26b3f837a7ad74641bdbd9fe430e5e5eec0d5f68..9974548ba33fd5ef5a8cfe870ed9878fccf9eefd 100644 (file)
@@ -1,7 +1,12 @@
-; RUN: opt -S -winehprepare -sehprepare -mtriple=x86_64-windows-msvc < %s | FileCheck %s
+; RUN: opt -S -winehprepare -mtriple=x86_64-windows-msvc < %s \
+; RUN:                 | FileCheck %s --check-prefix=CHECK --check-prefix=X64
+; RUN: opt -S -winehprepare -mtriple=x86_64-windows-coreclr < %s \
+; RUN:                 | FileCheck %s --check-prefix=CHECK --check-prefix=X64
 
-target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
-target triple = "x86_64-pc-windows-msvc"
+; This test should also pass in 32-bit using _except_handler3.
+; RUN: sed -e 's/__C_specific_handler/_except_handler3/' %s \
+; RUN:                 | opt -S -winehprepare -mtriple=i686-windows-msvc \
+; RUN:                 | FileCheck %s --check-prefix=CHECK --check-prefix=X86
 
 declare void @cleanup()
 declare i32 @filt()
@@ -9,7 +14,7 @@ declare void @might_crash()
 declare i32 @__C_specific_handler(...)
 declare i32 @llvm.eh.typeid.for(i8*)
 
-define i32 @simple_except_store() {
+define i32 @simple_except_store() personality i32 (...)* @__C_specific_handler {
 entry:
   %retval = alloca i32
   store i32 0, i32* %retval
@@ -17,7 +22,7 @@ entry:
           to label %return unwind label %lpad
 
 lpad:
-  %ehvals = landingpad { i8*, i32 } personality i32 (...)* @__C_specific_handler
+  %ehvals = landingpad { i8*, i32 }
           catch i32 ()* @filt
   %sel = extractvalue { i8*, i32 } %ehvals, 1
   %filt_sel = tail call i32 @llvm.eh.typeid.for(i8* bitcast (i32 ()* @filt to i8*))
@@ -39,10 +44,10 @@ eh.resume:
 ; CHECK-LABEL: define i32 @simple_except_store()
 ; CHECK: landingpad { i8*, i32 }
 ; CHECK-NEXT: catch i32 ()* @filt
-; CHECK-NEXT: call i8* (...)* @llvm.eh.actions(i32 1, i8* bitcast (i32 ()* @filt to i8*), i8* null, i8* blockaddress(@simple_except_store, %__except))
+; CHECK-NEXT: call i8* (...) @llvm.eh.actions(i32 1, i8* bitcast (i32 ()* @filt to i8*), i32 -1, i8* blockaddress(@simple_except_store, %__except))
 ; CHECK-NEXT: indirectbr {{.*}} [label %__except]
 
-define i32 @catch_all() {
+define i32 @catch_all() personality i32 (...)* @__C_specific_handler {
 entry:
   %retval = alloca i32
   store i32 0, i32* %retval
@@ -50,7 +55,7 @@ entry:
           to label %return unwind label %lpad
 
 lpad:
-  %ehvals = landingpad { i8*, i32 } personality i32 (...)* @__C_specific_handler
+  %ehvals = landingpad { i8*, i32 }
           catch i8* null
   store i32 1, i32* %retval
   br label %return
@@ -63,20 +68,20 @@ return:
 ; CHECK-LABEL: define i32 @catch_all()
 ; CHECK: landingpad { i8*, i32 }
 ; CHECK-NEXT: catch i8* null
-; CHECK-NEXT: call i8* (...)* @llvm.eh.actions(i32 1, i8* null, i8* null, i8* blockaddress(@catch_all, %catch.all))
-; CHECK-NEXT: indirectbr {{.*}} [label %catch.all]
+; CHECK-NEXT: call i8* (...) @llvm.eh.actions(i32 1, i8* null, i32 -1, i8* blockaddress(@catch_all, %lpad.split))
+; CHECK-NEXT: indirectbr {{.*}} [label %lpad.split]
 ;
-; CHECK: catch.all:
+; CHECK: lpad.split:
 ; CHECK: store i32 1, i32* %retval
 
 
-define i32 @except_phi() {
+define i32 @except_phi() personality i32 (...)* @__C_specific_handler {
 entry:
   invoke void @might_crash()
           to label %return unwind label %lpad
 
 lpad:
-  %ehvals = landingpad { i8*, i32 } personality i32 (...)* @__C_specific_handler
+  %ehvals = landingpad { i8*, i32 }
           catch i32 ()* @filt
   %sel = extractvalue { i8*, i32 } %ehvals, 1
   %filt_sel = tail call i32 @llvm.eh.typeid.for(i8* bitcast (i32 ()* @filt to i8*))
@@ -94,20 +99,101 @@ eh.resume:
 ; CHECK-LABEL: define i32 @except_phi()
 ; CHECK: landingpad { i8*, i32 }
 ; CHECK-NEXT: catch i32 ()* @filt
-; CHECK-NEXT: call i8* (...)* @llvm.eh.actions(i32 1, i8* bitcast (i32 ()* @filt to i8*), i8* null, i8* blockaddress(@except_phi, %return))
-; CHECK-NEXT: indirectbr {{.*}} [label %return]
+; CHECK-NEXT: call i8* (...) @llvm.eh.actions(i32 1, i8* bitcast (i32 ()* @filt to i8*), i32 -1, i8* blockaddress(@except_phi, %lpad.return_crit_edge))
+; CHECK-NEXT: indirectbr {{.*}} [label %lpad.return_crit_edge]
+;
+; CHECK: lpad.return_crit_edge:
+; CHECK: br label %return
+;
+; CHECK: return:
+; CHECK-NEXT: %r = phi i32 [ 0, %entry ], [ 1, %lpad.return_crit_edge ]
+; CHECK-NEXT: ret i32 %r
+
+define i32 @except_join() personality i32 (...)* @__C_specific_handler {
+entry:
+  invoke void @might_crash()
+          to label %return unwind label %lpad
+
+lpad:
+  %ehvals = landingpad { i8*, i32 }
+          catch i32 ()* @filt
+  %sel = extractvalue { i8*, i32 } %ehvals, 1
+  %filt_sel = tail call i32 @llvm.eh.typeid.for(i8* bitcast (i32 ()* @filt to i8*))
+  %matches = icmp eq i32 %sel, %filt_sel
+  br i1 %matches, label %return, label %eh.resume
+
+return:
+  ret i32 0
+
+eh.resume:
+  resume { i8*, i32 } %ehvals
+}
+
+; CHECK-LABEL: define i32 @except_join()
+; CHECK: landingpad { i8*, i32 }
+; CHECK-NEXT: catch i32 ()* @filt
+; CHECK-NEXT: call i8* (...) @llvm.eh.actions(i32 1, i8* bitcast (i32 ()* @filt to i8*), i32 -1, i8* blockaddress(@except_join, %lpad.return_crit_edge))
+; CHECK-NEXT: indirectbr {{.*}} [label %lpad.return_crit_edge]
+;
+; CHECK: lpad.return_crit_edge:
+; CHECK: br label %return
+;
+; CHECK: return:
+; CHECK-NEXT: ret i32 0
+
+define i32 @lpad_phi() personality i32 (...)* @__C_specific_handler {
+entry:
+  invoke void @might_crash()
+          to label %cont unwind label %lpad
+
+cont:
+  invoke void @might_crash()
+          to label %return unwind label %lpad
+
+lpad:
+  %ncalls.1 = phi i32 [ 0, %entry ], [ 1, %cont ]
+  %ehvals = landingpad { i8*, i32 }
+          catch i32 ()* @filt
+  %sel = extractvalue { i8*, i32 } %ehvals, 1
+  %filt_sel = tail call i32 @llvm.eh.typeid.for(i8* bitcast (i32 ()* @filt to i8*))
+  %matches = icmp eq i32 %sel, %filt_sel
+  br i1 %matches, label %return, label %eh.resume
+
+return:
+  %r = phi i32 [2, %cont], [%ncalls.1, %lpad]
+  ret i32 %r
+
+eh.resume:
+  resume { i8*, i32 } %ehvals
+}
+
+; CHECK-LABEL: define i32 @lpad_phi()
+; CHECK: alloca i32
+; CHECK: store i32 0, i32*
+; CHECK: invoke void @might_crash()
+; CHECK: store i32 1, i32*
+; CHECK: invoke void @might_crash()
+; CHECK: landingpad { i8*, i32 }
+; CHECK-NEXT: cleanup
+; CHECK-NEXT: catch i32 ()* @filt
+; CHECK-NEXT: call i8* (...) @llvm.eh.actions(i32 0, void ({{.*}})* @lpad_phi.cleanup, i32 1, i8* bitcast (i32 ()* @filt to i8*), i32 -1, i8* blockaddress(@lpad_phi, %lpad.return_crit_edge))
+; CHECK-NEXT: indirectbr {{.*}} [label %lpad.return_crit_edge]
+;
+; CHECK: lpad.return_crit_edge:
+; CHECK: load i32, i32*
+; CHECK: br label %return
 ;
 ; CHECK: return:
-; CHECK-NEXT: %r = phi i32 [ 0, %entry ], [ 1, %lpad1 ]
+; CHECK-NEXT: %r = phi i32 [ 2, %cont ], [ %{{.*}}, %lpad.return_crit_edge ]
 ; CHECK-NEXT: ret i32 %r
 
-define i32 @cleanup_and_except() {
+define i32 @cleanup_and_except() personality i32 (...)* @__C_specific_handler {
 entry:
   invoke void @might_crash()
           to label %return unwind label %lpad
 
 lpad:
-  %ehvals = landingpad { i8*, i32 } personality i32 (...)* @__C_specific_handler
+  %ehvals = landingpad { i8*, i32 }
           cleanup
           catch i32 ()* @filt
   call void @cleanup()
@@ -128,11 +214,22 @@ eh.resume:
 ; CHECK: landingpad { i8*, i32 }
 ; CHECK-NEXT: cleanup
 ; CHECK-NEXT: catch i32 ()* @filt
-; CHECK-NEXT: call i8* (...)* @llvm.eh.actions(
-; CHECK: i32 0, void (i8*, i8*)* @cleanup_and_except.cleanup,
-; CHECK: i32 1, i8* bitcast (i32 ()* @filt to i8*), i8* null, i8* blockaddress(@cleanup_and_except, %return))
-; CHECK-NEXT: indirectbr {{.*}} [label %return]
+; CHECK-NEXT: call i8* (...) @llvm.eh.actions(
+; CHECK: i32 0, void ({{.*}})* @cleanup_and_except.cleanup,
+; CHECK: i32 1, i8* bitcast (i32 ()* @filt to i8*), i32 -1, i8* blockaddress(@cleanup_and_except, %lpad.return_crit_edge))
+; CHECK-NEXT: indirectbr {{.*}} [label %lpad.return_crit_edge]
+;
+; CHECK: lpad.return_crit_edge:
+; CHECK: br label %return
 ;
 ; CHECK: return:
-; CHECK-NEXT: %r = phi i32 [ 0, %entry ], [ 1, %lpad1 ]
+; CHECK-NEXT: %r = phi i32 [ 0, %entry ], [ 1, %lpad.return_crit_edge ]
 ; CHECK-NEXT: ret i32 %r
+
+; FIXME: This cleanup is an artifact of bad demotion.
+; X64-LABEL: define internal void @lpad_phi.cleanup(i8*, i8*)
+; X86-LABEL: define internal void @lpad_phi.cleanup()
+; X86: call i8* @llvm.frameaddress(i32 1)
+; CHECK: call i8* @llvm.localrecover({{.*}})
+; CHECK: load i32
+; CHECK: store i32 %{{.*}}, i32*