1; RUN: opt -S -winehprepare -sehprepare -mtriple=x86_64-windows-msvc < %s | FileCheck %s
2
3target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
4target triple = "x86_64-pc-windows-msvc"
5
6declare void @cleanup()
7declare i32 @filt()
8declare void @might_crash()
9declare i32 @__C_specific_handler(...)
10declare i32 @llvm.eh.typeid.for(i8*)
11
12define i32 @simple_except_store() {
13entry:
14  %retval = alloca i32
15  store i32 0, i32* %retval
16  invoke void @might_crash()
17          to label %return unwind label %lpad
18
19lpad:
20  %ehvals = landingpad { i8*, i32 } personality i32 (...)* @__C_specific_handler
21          catch i32 ()* @filt
22  %sel = extractvalue { i8*, i32 } %ehvals, 1
23  %filt_sel = tail call i32 @llvm.eh.typeid.for(i8* bitcast (i32 ()* @filt to i8*))
24  %matches = icmp eq i32 %sel, %filt_sel
25  br i1 %matches, label %__except, label %eh.resume
26
27__except:
28  store i32 1, i32* %retval
29  br label %return
30
31return:
32  %r = load i32, i32* %retval
33  ret i32 %r
34
35eh.resume:
36  resume { i8*, i32 } %ehvals
37}
38
39; CHECK-LABEL: define i32 @simple_except_store()
40; CHECK: landingpad { i8*, i32 }
41; CHECK-NEXT: catch i32 ()* @filt
42; CHECK-NEXT: call i8* (...) @llvm.eh.actions(i32 1, i8* bitcast (i32 ()* @filt to i8*), i32 -1, i8* blockaddress(@simple_except_store, %__except))
43; CHECK-NEXT: indirectbr {{.*}} [label %__except]
44
45define i32 @catch_all() {
46entry:
47  %retval = alloca i32
48  store i32 0, i32* %retval
49  invoke void @might_crash()
50          to label %return unwind label %lpad
51
52lpad:
53  %ehvals = landingpad { i8*, i32 } personality i32 (...)* @__C_specific_handler
54          catch i8* null
55  store i32 1, i32* %retval
56  br label %return
57
58return:
59  %r = load i32, i32* %retval
60  ret i32 %r
61}
62
63; CHECK-LABEL: define i32 @catch_all()
64; CHECK: landingpad { i8*, i32 }
65; CHECK-NEXT: catch i8* null
66; CHECK-NEXT: call i8* (...) @llvm.eh.actions(i32 1, i8* null, i32 -1, i8* blockaddress(@catch_all, %catch.all))
67; CHECK-NEXT: indirectbr {{.*}} [label %catch.all]
68;
69; CHECK: catch.all:
70; CHECK: store i32 1, i32* %retval
71
72
73define i32 @except_phi() {
74entry:
75  invoke void @might_crash()
76          to label %return unwind label %lpad
77
78lpad:
79  %ehvals = landingpad { i8*, i32 } personality i32 (...)* @__C_specific_handler
80          catch i32 ()* @filt
81  %sel = extractvalue { i8*, i32 } %ehvals, 1
82  %filt_sel = tail call i32 @llvm.eh.typeid.for(i8* bitcast (i32 ()* @filt to i8*))
83  %matches = icmp eq i32 %sel, %filt_sel
84  br i1 %matches, label %return, label %eh.resume
85
86return:
87  %r = phi i32 [0, %entry], [1, %lpad]
88  ret i32 %r
89
90eh.resume:
91  resume { i8*, i32 } %ehvals
92}
93
94; CHECK-LABEL: define i32 @except_phi()
95; CHECK: landingpad { i8*, i32 }
96; CHECK-NEXT: catch i32 ()* @filt
97; CHECK-NEXT: call i8* (...) @llvm.eh.actions(i32 1, i8* bitcast (i32 ()* @filt to i8*), i32 -1, i8* blockaddress(@except_phi, %return))
98; CHECK-NEXT: indirectbr {{.*}} [label %return]
99;
100; CHECK: return:
101; CHECK-NEXT: %r = phi i32 [ 0, %entry ], [ 1, %lpad1 ]
102; CHECK-NEXT: ret i32 %r
103
104define i32 @cleanup_and_except() {
105entry:
106  invoke void @might_crash()
107          to label %return unwind label %lpad
108
109lpad:
110  %ehvals = landingpad { i8*, i32 } personality i32 (...)* @__C_specific_handler
111          cleanup
112          catch i32 ()* @filt
113  call void @cleanup()
114  %sel = extractvalue { i8*, i32 } %ehvals, 1
115  %filt_sel = tail call i32 @llvm.eh.typeid.for(i8* bitcast (i32 ()* @filt to i8*))
116  %matches = icmp eq i32 %sel, %filt_sel
117  br i1 %matches, label %return, label %eh.resume
118
119return:
120  %r = phi i32 [0, %entry], [1, %lpad]
121  ret i32 %r
122
123eh.resume:
124  resume { i8*, i32 } %ehvals
125}
126
127; CHECK-LABEL: define i32 @cleanup_and_except()
128; CHECK: landingpad { i8*, i32 }
129; CHECK-NEXT: cleanup
130; CHECK-NEXT: catch i32 ()* @filt
131; CHECK-NEXT: call i8* (...) @llvm.eh.actions(
132; CHECK: i32 0, void (i8*, i8*)* @cleanup_and_except.cleanup,
133; CHECK: i32 1, i8* bitcast (i32 ()* @filt to i8*), i32 -1, i8* blockaddress(@cleanup_and_except, %return))
134; CHECK-NEXT: indirectbr {{.*}} [label %return]
135;
136; CHECK: return:
137; CHECK-NEXT: %r = phi i32 [ 0, %entry ], [ 1, %lpad1 ]
138; CHECK-NEXT: ret i32 %r
139