1; RUN: opt -mtriple=i686-pc-windows-msvc -S -x86-winehstate  < %s | FileCheck %s
2
3target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32"
4target triple = "i686-pc-windows-msvc"
5
6%rtti.TypeDescriptor2 = type { i8**, i8*, [3 x i8] }
7%eh.CatchableType = type { i32, i8*, i32, i32, i32, i32, i8* }
8%eh.CatchableTypeArray.1 = type { i32, [1 x %eh.CatchableType*] }
9%eh.ThrowInfo = type { i32, i8*, i8*, i8* }
10
11$"\01??_R0H@8" = comdat any
12
13$"_CT??_R0H@84" = comdat any
14
15$_CTA1H = comdat any
16
17$_TI1H = comdat any
18
19@"\01??_7type_info@@6B@" = external constant i8*
20@"\01??_R0H@8" = linkonce_odr global %rtti.TypeDescriptor2 { i8** @"\01??_7type_info@@6B@", i8* null, [3 x i8] c".H\00" }, comdat
21@"_CT??_R0H@84" = linkonce_odr unnamed_addr constant %eh.CatchableType { i32 1, i8* bitcast (%rtti.TypeDescriptor2* @"\01??_R0H@8" to i8*), i32 0, i32 -1, i32 0, i32 4, i8* null }, section ".xdata", comdat
22@_CTA1H = linkonce_odr unnamed_addr constant %eh.CatchableTypeArray.1 { i32 1, [1 x %eh.CatchableType*] [%eh.CatchableType* @"_CT??_R0H@84"] }, section ".xdata", comdat
23@_TI1H = linkonce_odr unnamed_addr constant %eh.ThrowInfo { i32 0, i8* null, i8* null, i8* bitcast (%eh.CatchableTypeArray.1* @_CTA1H to i8*) }, section ".xdata", comdat
24
25define i32 @main() #0 personality i32 (...)* @__CxxFrameHandler3 {
26entry:
27  %tmp = alloca i32, align 4
28  ; CHECK: entry:
29  ; CHECK:   store i32 -1
30  ; CHECK:   call void @g(i32 3)
31  ; CHECK-NEXT:   call void @g(i32 4)
32  ; CHECK-NEXT:   call void @g(i32 5)
33  call void @g(i32 3)
34  call void @g(i32 4)
35  call void @g(i32 5)
36  store i32 0, i32* %tmp, align 4
37  %0 = bitcast i32* %tmp to i8*
38  ; CHECK:   store i32 0
39  ; CHECK:   invoke void @_CxxThrowException(
40  invoke void @_CxxThrowException(i8* %0, %eh.ThrowInfo* nonnull @_TI1H) #1
41          to label %unreachable.for.entry unwind label %catch.dispatch
42
43catch.dispatch:                                   ; preds = %entry
44  %cs1 = catchswitch within none [label %catch] unwind to caller
45
46catch:                                            ; preds = %catch.dispatch
47  %1 = catchpad within %cs1 [i8* null, i32 u0x40, i8* null]
48  ; CHECK: catch:
49  ; CHECK:   store i32 2
50  ; CHECK:   invoke void @_CxxThrowException(
51  invoke void @_CxxThrowException(i8* null, %eh.ThrowInfo* null) [ "funclet"(token %1) ]
52          to label %unreachable unwind label %catch.dispatch.1
53
54catch.dispatch.1:                                 ; preds = %catch
55  %cs2 = catchswitch within %1 [label %catch.3] unwind to caller
56catch.3:                                          ; preds = %catch.dispatch.1
57  %2 = catchpad within %cs2 [i8* null, i32 u0x40, i8* null]
58  ; CHECK: catch.3:
59  ; CHECK:   store i32 3
60  ; CHECK:   call void @g(i32 1)
61  ; CHECK-NEXT:   call void @g(i32 2)
62  ; CHECK-NEXT:   call void @g(i32 3)
63  call void @g(i32 1)
64  call void @g(i32 2)
65  call void @g(i32 3)
66  catchret from %2 to label %try.cont
67
68try.cont:                                         ; preds = %catch.3
69  ; CHECK: try.cont:
70  ; CHECK:   store i32 1
71  ; CHECK:   call void @g(i32 2)
72  ; CHECK-NEXT:   call void @g(i32 3)
73  ; CHECK-NEXT:   call void @g(i32 4)
74  call void @g(i32 2)
75  call void @g(i32 3)
76  call void @g(i32 4)
77  unreachable
78
79unreachable:                                      ; preds = %catch
80  unreachable
81
82unreachable.for.entry:                            ; preds = %entry
83  unreachable
84}
85
86define i32 @nopads() #0 personality i32 (...)* @__CxxFrameHandler3 {
87  ret i32 0
88}
89
90; CHECK-LABEL: define i32 @nopads()
91; CHECK-NEXT: ret i32 0
92; CHECK-NOT: __ehhandler$nopads
93
94; CHECK-LABEL: define void @PR25926()
95define void @PR25926() personality i32 (...)* @__CxxFrameHandler3 {
96entry:
97  ; CHECK: entry:
98  ; CHECK:   store i32 -1
99  ; CHECK:   store i32 0
100  ; CHECK:   invoke void @_CxxThrowException(
101  invoke void @_CxxThrowException(i8* null, %eh.ThrowInfo* null)
102          to label %unreachable unwind label %catch.dispatch
103
104catch.dispatch:                                   ; preds = %entry
105  %0 = catchswitch within none [label %catch] unwind to caller
106
107catch:                                            ; preds = %catch.dispatch
108  %1 = catchpad within %0 [i8* null, i32 64, i8* null]
109  ; CHECK: catch:
110  ; CHECK:   store i32 3
111  ; CHECK:   invoke void @_CxxThrowException(
112  invoke void @_CxxThrowException(i8* null, %eh.ThrowInfo* null) [ "funclet"(token %1) ]
113          to label %unreachable1 unwind label %catch.dispatch1
114
115catch.dispatch1:                                  ; preds = %catch
116  %2 = catchswitch within %1 [label %catch2] unwind label %ehcleanup
117
118catch2:                                           ; preds = %catch.dispatch1
119  %3 = catchpad within %2 [i8* null, i32 64, i8* null]
120  catchret from %3 to label %try.cont
121
122try.cont:                                         ; preds = %catch2
123  ; CHECK: try.cont:
124  ; CHECK:   store i32 1
125  ; CHECK:   call void @dtor()
126  ; CHECK-NEXT:   call void @dtor()
127  ; CHECK-NEXT:   call void @dtor()
128  call void @dtor() #3 [ "funclet"(token %1) ]
129  call void @dtor() #3 [ "funclet"(token %1) ]
130  call void @dtor() #3 [ "funclet"(token %1) ]
131  catchret from %1 to label %try.cont4
132
133try.cont4:                                        ; preds = %try.cont
134  ret void
135
136ehcleanup:                                        ; preds = %catch.dispatch1
137  %4 = cleanuppad within %1 []
138  ; CHECK: ehcleanup:
139  ; CHECK:   call void @dtor()
140  call void @dtor() #3 [ "funclet"(token %4) ]
141  cleanupret from %4 unwind to caller
142
143unreachable:                                      ; preds = %entry
144  unreachable
145
146unreachable1:                                     ; preds = %catch
147  unreachable
148}
149
150; CHECK-LABEL: define void @required_state_store(
151define void @required_state_store(i1 zeroext %cond) personality i32 (...)* @_except_handler3 {
152entry:
153  %__exception_code = alloca i32, align 4
154  call void (...) @llvm.localescape(i32* nonnull %__exception_code)
155; CHECK:   store i32 -1
156; CHECK:   call void @g(i32 0)
157  call void @g(i32 0)
158  br i1 %cond, label %if.then, label %if.end
159
160if.then:                                          ; preds = %entry
161; CHECK:        store i32 0
162; CHECK-NEXT:   invoke void @g(i32 1)
163  invoke void @g(i32 1)
164          to label %if.end unwind label %catch.dispatch
165
166catch.dispatch:                                   ; preds = %if.then
167  %0 = catchswitch within none [label %__except.ret] unwind to caller
168
169__except.ret:                                     ; preds = %catch.dispatch
170  %1 = catchpad within %0 [i8* bitcast (i32 ()* @"\01?filt$0@0@required_state_store@@" to i8*)]
171  catchret from %1 to label %if.end
172
173if.end:                                           ; preds = %if.then, %__except.ret, %entry
174; CHECK:        store i32 -1
175; CHECK-NEXT:   call void @dtor()
176  call void @dtor()
177  ret void
178}
179
180define internal i32 @"\01?filt$0@0@required_state_store@@"() {
181entry:
182  %0 = tail call i8* @llvm.frameaddress(i32 1)
183  %1 = tail call i8* @llvm.eh.recoverfp(i8* bitcast (void (i1)* @required_state_store to i8*), i8* %0)
184  %2 = tail call i8* @llvm.localrecover(i8* bitcast (void (i1)* @required_state_store to i8*), i8* %1, i32 0)
185  %__exception_code = bitcast i8* %2 to i32*
186  %3 = getelementptr inbounds i8, i8* %0, i32 -20
187  %4 = bitcast i8* %3 to { i32*, i8* }**
188  %5 = load { i32*, i8* }*, { i32*, i8* }** %4, align 4
189  %6 = getelementptr inbounds { i32*, i8* }, { i32*, i8* }* %5, i32 0, i32 0
190  %7 = load i32*, i32** %6, align 4
191  %8 = load i32, i32* %7, align 4
192  store i32 %8, i32* %__exception_code, align 4
193  ret i32 1
194}
195
196declare void @g(i32) #0
197
198declare void @dtor()
199
200declare x86_stdcallcc void @_CxxThrowException(i8*, %eh.ThrowInfo*)
201
202declare i32 @__CxxFrameHandler3(...)
203
204declare i8* @llvm.frameaddress(i32)
205
206declare i8* @llvm.eh.recoverfp(i8*, i8*)
207
208declare i8* @llvm.localrecover(i8*, i8*, i32)
209
210declare void @llvm.localescape(...)
211
212declare i32 @_except_handler3(...)
213
214attributes #0 = { "disable-tail-calls"="false" "less-precise-fpmad"="false" "frame-pointer"="none" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-realign-stack" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
215attributes #1 = { noreturn }
216
217!llvm.ident = !{!0}
218
219!0 = !{!"clang version 3.8.0 (trunk 245153) (llvm/trunk 245238)"}
220