1; RUN: llc -verify-machineinstrs -mtriple=i686-pc-windows-msvc < %s | FileCheck --check-prefix=X86 %s
2; RUN: llc -verify-machineinstrs -mtriple=x86_64-pc-windows-msvc < %s | FileCheck --check-prefix=X64 %s
3
4%rtti.TypeDescriptor2 = type { i8**, i8*, [3 x i8] }
5%eh.CatchableType = type { i32, i8*, i32, i32, i32, i32, i8* }
6%eh.CatchableTypeArray.1 = type { i32, [1 x %eh.CatchableType*] }
7%eh.ThrowInfo = type { i32, i8*, i8*, i8* }
8
9$"\01??_R0H@8" = comdat any
10
11@"\01??_7type_info@@6B@" = external constant i8*
12@"\01??_R0H@8" = linkonce_odr global %rtti.TypeDescriptor2 { i8** @"\01??_7type_info@@6B@", i8* null, [3 x i8] c".H\00" }, comdat
13
14declare i32 @getint()
15declare void @useints(...)
16declare void @f(i32 %p)
17declare i32 @__CxxFrameHandler3(...)
18
19define i32 @try_catch_catch() personality i32 (...)* @__CxxFrameHandler3 {
20entry:
21  %a = call i32 @getint()
22  %b = call i32 @getint()
23  %c = call i32 @getint()
24  %d = call i32 @getint()
25  call void (...) @useints(i32 %a, i32 %b, i32 %c, i32 %d)
26  invoke void @f(i32 1)
27          to label %try.cont unwind label %catch.dispatch
28
29try.cont:
30  ret i32 0
31
32catch.dispatch:
33  %cs = catchswitch within none [label %handler1] unwind to caller
34
35handler1:
36  %h1 = catchpad within %cs [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null]
37  call void @f(i32 2) [ "funclet"(token %h1) ]
38  catchret from %h1 to label %try.cont
39}
40
41; X86-LABEL: _try_catch_catch:
42; X86: pushl %ebp
43; X86: movl %esp, %ebp
44; X86: pushl %ebx
45; X86: pushl %edi
46; X86: pushl %esi
47; X86: subl ${{[0-9]+}}, %esp
48; X86: calll _getint
49; X86: calll _getint
50; X86: calll _getint
51; X86: calll _getint
52; X86: calll _useints
53; X86: movl $0, -{{[0-9]+}}(%ebp)
54; X86: pushl $1
55; X86: calll _f
56; X86: [[contbb:LBB0_[0-9]+]]: # %try.cont
57; X86: popl %esi
58; X86: popl %edi
59; X86: popl %ebx
60; X86: popl %ebp
61; X86: retl
62
63; X86: [[restorebb:LBB0_[0-9]+]]:
64; X86: addl $12, %ebp
65; X86: jmp [[contbb]]
66
67; X86: "?catch$[[catch1bb:[0-9]+]]@?0?try_catch_catch@4HA":
68; X86: LBB0_[[catch1bb]]: # %handler1{{$}}
69; X86: pushl %ebp
70; X86-NOT: pushl
71; X86: subl $16, %esp
72; X86: addl $12, %ebp
73; X86: movl $1, -{{[0-9]+}}(%ebp)
74; X86: pushl $2
75; X86: calll _f
76; X86: movl $[[restorebb]], %eax
77; X86-NEXT: addl $16, %esp
78; X86-NEXT: popl %ebp
79; X86-NEXT: retl
80
81; X86: L__ehtable$try_catch_catch:
82; X86: $handlerMap$0$try_catch_catch:
83; X86:   .long   0
84; X86:   .long   "??_R0H@8"
85; X86:   .long   0
86; X86:   .long   "?catch$[[catch1bb]]@?0?try_catch_catch@4HA"
87
88; X64-LABEL: try_catch_catch:
89; X64: pushq %rbp
90; X64: .seh_pushreg %rbp
91; X64: pushq %rsi
92; X64: .seh_pushreg %rsi
93; X64: pushq %rdi
94; X64: .seh_pushreg %rdi
95; X64: pushq %rbx
96; X64: .seh_pushreg %rbx
97; X64: subq $40, %rsp
98; X64: .seh_stackalloc 40
99; X64: leaq 32(%rsp), %rbp
100; X64: .seh_setframe %rbp, 32
101; X64: .seh_endprologue
102; X64: movq $-2, (%rbp)
103; X64: callq getint
104; X64: callq getint
105; X64: callq getint
106; X64: callq getint
107; X64: callq useints
108; X64: movl $1, %ecx
109; X64: callq f
110; X64: [[contbb:\.LBB0_[0-9]+]]: # Block address taken
111; X64-NEXT:                      # %try.cont
112; X64: addq $40, %rsp
113; X64: popq %rbp
114; X64: retq
115
116; X64: "?catch$[[catch1bb:[0-9]+]]@?0?try_catch_catch@4HA":
117; X64: LBB0_[[catch1bb]]: # %handler1{{$}}
118; X64: movq %rdx, 16(%rsp)
119; X64: pushq %rbp
120; X64: .seh_pushreg %rbp
121; X64: pushq %rsi
122; X64: .seh_pushreg %rsi
123; X64: pushq %rdi
124; X64: .seh_pushreg %rdi
125; X64: pushq %rbx
126; X64: .seh_pushreg %rbx
127; X64: subq $40, %rsp
128; X64: .seh_stackalloc 40
129; X64: leaq 32(%rdx), %rbp
130; X64: .seh_endprologue
131; X64: movl $2, %ecx
132; X64: callq f
133; X64: leaq [[contbb]](%rip), %rax
134; X64: addq $40, %rsp
135; X64: popq %rbx
136; X64: popq %rdi
137; X64: popq %rsi
138; X64: popq %rbp
139; X64: retq
140
141; X64: $handlerMap$0$try_catch_catch:
142; X64:   .long   0
143; X64:   .long   "??_R0H@8"@IMGREL
144; X64:   .long   0
145; X64:   .long   "?catch$[[catch1bb]]@?0?try_catch_catch@4HA"@IMGREL
146; X64:   .long   88
147
148define i32 @try_one_csr() personality i32 (...)* @__CxxFrameHandler3 {
149entry:
150  %a = call i32 @getint()
151  %b = call i32 @getint()
152  call void (...) @useints(i32 %a)
153  invoke void @f(i32 1)
154          to label %try.cont unwind label %catch.dispatch
155
156catch.dispatch:
157  %cs = catchswitch within none [label %handler1] unwind to caller
158
159handler1:
160  %0 = catchpad within %cs [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null]
161  catchret from %0 to label %try.cont
162
163try.cont:
164  ret i32 0
165}
166
167; X64-LABEL: try_one_csr:
168; X64: pushq %rbp
169; X64: .seh_pushreg %rbp
170; X64: pushq %rsi
171; X64: .seh_pushreg %rsi
172; X64-NOT: pushq
173; X64: subq $40, %rsp
174; X64: .seh_stackalloc 40
175; X64: leaq 32(%rsp), %rbp
176; X64: .seh_setframe %rbp, 32
177; X64: .seh_endprologue
178; X64: callq getint
179; X64: callq getint
180; X64: callq useints
181; X64: movl $1, %ecx
182; X64: callq f
183; X64: [[contbb:\.LBB1_[0-9]+]]: # Block address taken
184; X64-NEXT:                      # %try.cont
185; X64: addq $40, %rsp
186; X64-NOT: popq
187; X64: popq %rsi
188; X64: popq %rbp
189; X64: retq
190
191; X64: "?catch$[[catch1bb:[0-9]+]]@?0?try_one_csr@4HA":
192; X64: LBB1_[[catch1bb]]: # %handler1{{$}}
193; X64: movq %rdx, 16(%rsp)
194; X64: pushq %rbp
195; X64: .seh_pushreg %rbp
196; X64: pushq %rsi
197; X64: .seh_pushreg %rsi
198; X64: subq $40, %rsp
199; X64: .seh_stackalloc 40
200; X64: leaq 32(%rdx), %rbp
201; X64: .seh_endprologue
202; X64: leaq [[contbb]](%rip), %rax
203; X64: addq $40, %rsp
204; X64: popq %rsi
205; X64: popq %rbp
206; X64: retq
207
208; X64: $handlerMap$0$try_one_csr:
209; X64:   .long   0
210; X64:   .long   "??_R0H@8"@IMGREL
211; X64:   .long   0
212; X64:   .long   "?catch$[[catch1bb]]@?0?try_one_csr@4HA"@IMGREL
213; X64:   .long   72
214
215define i32 @try_no_csr() personality i32 (...)* @__CxxFrameHandler3 {
216entry:
217  invoke void @f(i32 1)
218          to label %try.cont unwind label %catch.dispatch
219
220catch.dispatch:
221  %cs = catchswitch within none [label %handler1] unwind to caller
222
223handler1:
224  %cp1 = catchpad within %cs [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null]
225  catchret from %cp1 to label %try.cont
226
227try.cont:
228  ret i32 0
229}
230
231; X64-LABEL: try_no_csr:
232; X64: pushq %rbp
233; X64: .seh_pushreg %rbp
234; X64-NOT: pushq
235; X64: subq $48, %rsp
236; X64: .seh_stackalloc 48
237; X64: leaq 48(%rsp), %rbp
238; X64: .seh_setframe %rbp, 48
239; X64: .seh_endprologue
240; X64: movl $1, %ecx
241; X64: callq f
242; X64: [[contbb:\.LBB2_[0-9]+]]: # Block address taken
243; X64-NEXT:                      # %try.cont
244; X64: addq $48, %rsp
245; X64-NOT: popq
246; X64: popq %rbp
247; X64: retq
248
249; X64: "?catch$[[catch1bb:[0-9]+]]@?0?try_no_csr@4HA":
250; X64: LBB2_[[catch1bb]]: # %handler1{{$}}
251; X64: movq %rdx, 16(%rsp)
252; X64: pushq %rbp
253; X64: .seh_pushreg %rbp
254; X64: subq $32, %rsp
255; X64: .seh_stackalloc 32
256; X64: leaq 48(%rdx), %rbp
257; X64: .seh_endprologue
258; X64: leaq [[contbb]](%rip), %rax
259; X64: addq $32, %rsp
260; X64: popq %rbp
261; X64: retq
262
263; X64: $handlerMap$0$try_no_csr:
264; X64:   .long   0
265; X64:   .long   "??_R0H@8"@IMGREL
266; X64:   .long   0
267; X64:   .long   "?catch$[[catch1bb]]@?0?try_no_csr@4HA"@IMGREL
268; X64:   .long   56
269