1; RUN: llc -o - %s -verify-machineinstrs -mtriple=aarch64-windows | FileCheck %s
2
3; Windows runtime passes the establisher frame as the second argument to the
4; termination handler.  Check that we copy it into fp.
5
6; CHECK:      ?dtor$3@?0?main@4HA":
7; CHECK:      .seh_proc "?dtor$3@?0?main@4HA"
8; CHECK:      stp     x29, x30, [sp, #-16]!   // 16-byte Folded Spill
9; CHECK-NEXT: .seh_save_fplr_x 16
10; CHECK-NEXT: .seh_endprologue
11; CHECK-NEXT: mov     x29, x1
12
13target datalayout = "e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128"
14target triple = "aarch64-unknown-windows-msvc19.15.26732"
15
16; Function Attrs: noinline nounwind optnone uwtable
17define dso_local i32 @main() #0 personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*) {
18entry:
19  %retval = alloca i32, align 4
20  %Counter = alloca i32, align 4
21  %__exception_code = alloca i32, align 4
22  call void (...) @llvm.localescape(i32* %Counter)
23  store i32 0, i32* %retval, align 4
24  store i32 0, i32* %Counter, align 4
25  %call = invoke i32 bitcast (i32 (...)* @RaiseStatus to i32 (i32)*)(i32 -1073741675) #3
26          to label %invoke.cont unwind label %ehcleanup
27
28invoke.cont:                                      ; preds = %entry
29  %0 = call i8* @llvm.localaddress()
30  invoke void @"?fin$0@0@main@@"(i8 0, i8* %0) #3
31          to label %invoke.cont1 unwind label %catch.dispatch
32
33invoke.cont1:                                     ; preds = %invoke.cont
34  br label %__try.cont
35
36ehcleanup:                                        ; preds = %entry
37  %1 = cleanuppad within none []
38  %2 = call i8* @llvm.localaddress()
39  invoke void @"?fin$0@0@main@@"(i8 1, i8* %2) #3 [ "funclet"(token %1) ]
40          to label %invoke.cont2 unwind label %catch.dispatch
41
42invoke.cont2:                                     ; preds = %ehcleanup
43  cleanupret from %1 unwind label %catch.dispatch
44
45catch.dispatch:                                   ; preds = %invoke.cont2, %ehcleanup, %invoke.cont
46  %3 = catchswitch within none [label %__except] unwind to caller
47
48__except:                                         ; preds = %catch.dispatch
49  %4 = catchpad within %3 [i8* null]
50  catchret from %4 to label %__except3
51
52__except3:                                        ; preds = %__except
53  %5 = call i32 @llvm.eh.exceptioncode(token %4)
54  store i32 %5, i32* %__exception_code, align 4
55  %6 = load i32, i32* %Counter, align 4
56  %add = add nsw i32 %6, 5
57  store i32 %add, i32* %Counter, align 4
58  br label %__try.cont
59
60__try.cont:                                       ; preds = %__except3, %invoke.cont1
61  %7 = load i32, i32* %retval, align 4
62  ret i32 %7
63}
64
65define internal void @"?fin$0@0@main@@"(i8 %abnormal_termination, i8* %frame_pointer) {
66entry:
67  %frame_pointer.addr = alloca i8*, align 8
68  %abnormal_termination.addr = alloca i8, align 1
69  %0 = call i8* @llvm.localrecover(i8* bitcast (i32 ()* @main to i8*), i8* %frame_pointer, i32 0)
70  %Counter = bitcast i8* %0 to i32*
71  store i8* %frame_pointer, i8** %frame_pointer.addr, align 8
72  store i8 %abnormal_termination, i8* %abnormal_termination.addr, align 1
73  store i32 3, i32* %Counter, align 4
74  call void @"?fin$1@0@main@@"(i8 0, i8* %frame_pointer)
75  %1 = load i32, i32* %Counter, align 4
76  %add = add nsw i32 %1, 2
77  store i32 %add, i32* %Counter, align 4
78  %call = call i32 bitcast (i32 (...)* @RaiseStatus to i32 (i32)*)(i32 -1073741675)
79  ret void
80}
81
82; Function Attrs: nounwind readnone
83declare i8* @llvm.localrecover(i8*, i8*, i32) #1
84
85define internal void @"?fin$1@0@main@@"(i8 %abnormal_termination, i8* %frame_pointer) {
86entry:
87  %frame_pointer.addr = alloca i8*, align 8
88  %abnormal_termination.addr = alloca i8, align 1
89  %0 = call i8* @llvm.localrecover(i8* bitcast (i32 ()* @main to i8*), i8* %frame_pointer, i32 0)
90  %Counter = bitcast i8* %0 to i32*
91  store i8* %frame_pointer, i8** %frame_pointer.addr, align 8
92  store i8 %abnormal_termination, i8* %abnormal_termination.addr, align 1
93  %1 = load i32, i32* %Counter, align 4
94  %cmp = icmp eq i32 %1, 3
95  br i1 %cmp, label %if.then, label %if.end
96
97if.then:                                          ; preds = %entry
98  %2 = load i32, i32* %Counter, align 4
99  %add = add nsw i32 %2, 1
100  store i32 %add, i32* %Counter, align 4
101  br label %if.end
102
103if.end:                                           ; preds = %if.then, %entry
104  ret void
105}
106
107declare dso_local i32 @RaiseStatus(...)
108
109declare dso_local i32 @__C_specific_handler(...)
110
111; Function Attrs: nounwind readnone
112declare i8* @llvm.localaddress() #1
113
114; Function Attrs: nounwind readnone
115declare i32 @llvm.eh.exceptioncode(token) #1
116
117; Function Attrs: nounwind
118declare void @llvm.localescape(...) #2
119
120attributes #0 = { noinline nounwind optnone uwtable }
121attributes #1 = { nounwind readnone }
122attributes #2 = { nounwind }
123attributes #3 = { noinline }
124