1// This test checks that the epilogue is packed where possible.
2
3// RUN: llvm-mc -triple aarch64-pc-win32 -filetype=obj %s -o %t.o
4// RUN: llvm-readobj -u %t.o | FileCheck %s
5
6// CHECK:      UnwindInformation [
7// CHECK-NEXT:   RuntimeFunction {
8// CHECK-NEXT:     Function: func
9// CHECK-NEXT:     ExceptionRecord: .xdata
10// CHECK-NEXT:     ExceptionData {
11// CHECK-NEXT:       FunctionLength:
12// CHECK-NEXT:       Version:
13// CHECK-NEXT:       ExceptionData:
14// CHECK-NEXT:       EpiloguePacked: Yes
15// CHECK-NEXT:       EpilogueOffset: 2
16// CHECK-NEXT:       ByteCodeLength:
17// CHECK-NEXT:       Prologue [
18// CHECK-NEXT:         0xdc04              ; str d8, [sp, #32]
19// CHECK-NEXT:         0xe1                ; mov fp, sp
20// CHECK-NEXT:         0x42                ; stp x29, x30, [sp, #16]
21// CHECK-NEXT:         0x85                ; stp x29, x30, [sp, #-48]!
22// CHECK-NEXT:         0xe6                ; save next
23// CHECK-NEXT:         0x24                ; stp x19, x20, [sp, #-32]!
24// CHECK-NEXT:         0xc842              ; stp x20, x21, [sp, #16]
25// CHECK-NEXT:         0x03                ; sub sp, #48
26// CHECK-NEXT:         0xe4                ; end
27// CHECK-NEXT:       ]
28// CHECK-NEXT:       Epilogue [
29// CHECK-NEXT:         0xe1                ; mov sp, fp
30// CHECK-NEXT:         0x42                ; ldp x29, x30, [sp, #16]
31// CHECK-NEXT:         0x85                ; ldp x29, x30, [sp], #48
32// CHECK-NEXT:         0xe6                ; restore next
33// CHECK-NEXT:         0x24                ; ldp x19, x20, [sp], #32
34// CHECK-NEXT:         0xc842              ; ldp x20, x21, [sp, #16]
35// CHECK-NEXT:         0x03                ; add sp, #48
36// CHECK-NEXT:         0xe4                ; end
37// CHECK-NEXT:       ]
38// CHECK-NEXT:     }
39// CHECK-NEXT:   }
40// CHECK:        RuntimeFunction {
41// CHECK-NEXT:     Function: packed2
42// CHECK-NEXT:     ExceptionRecord:
43// CHECK-NEXT:     ExceptionData {
44// CHECK:            ExceptionData:
45// CHECK-NEXT:       EpiloguePacked: Yes
46// CHECK:        RuntimeFunction {
47// CHECK-NEXT:     Function: nonpacked1
48// CHECK-NEXT:     ExceptionRecord:
49// CHECK-NEXT:     ExceptionData {
50// CHECK:            ExceptionData:
51// CHECK-NEXT:       EpiloguePacked: No
52// CHECK:        RuntimeFunction {
53// CHECK-NEXT:     Function: nonpacked2
54// CHECK-NEXT:     ExceptionRecord:
55// CHECK-NEXT:     ExceptionData {
56// CHECK:            ExceptionData:
57// CHECK-NEXT:       EpiloguePacked: No
58// CHECK:        RuntimeFunction {
59// CHECK-NEXT:     Function: nonpacked3
60// CHECK-NEXT:     ExceptionRecord:
61// CHECK-NEXT:     ExceptionData {
62// CHECK:            ExceptionData:
63// CHECK-NEXT:       EpiloguePacked: No
64
65    .text
66    .globl func
67    .seh_proc func
68func:
69    sub sp, sp, #48
70    .seh_stackalloc 48
71    // Check that canonical opcode forms (r19r20_x, fplr, fplr_x, save_next,
72    // set_fp) are treated as a match even if one (in prologue or epilogue)
73    // was simplified from the more generic opcodes.
74    stp x20, x21, [sp, #16]
75    .seh_save_regp x20, 16
76    stp x19, x20, [sp, #-32]!
77    .seh_save_r19r20_x 32
78    stp x21, x22, [sp, #16]
79    .seh_save_regp x21, 16
80    stp x29, x30, [sp, #-48]!
81    .seh_save_regp_x x29, 48
82    stp x29, x30, [sp, #16]
83    .seh_save_regp x29, 16
84    add x29, sp, #0
85    .seh_add_fp 0
86    str d8, [sp, #32]
87    .seh_save_freg d8, 32
88    .seh_endprologue
89
90    nop
91
92    .seh_startepilogue
93    mov sp, x29
94    .seh_set_fp
95    ldp x29, x30, [sp, #16]
96    .seh_save_fplr 16
97    ldp x29, x30, [sp, #-48]!
98    .seh_save_fplr_x 48
99    ldp x21, x22, [sp, #16]
100    .seh_save_next
101    ldp x19, x20, [sp], #32
102    .seh_save_regp_x x19, 32
103    ldp x20, x21, [sp, #16]
104    .seh_save_regp x20, 16
105    add sp, sp, #48
106    .seh_stackalloc 48
107    .seh_endepilogue
108    ret
109    .seh_endproc
110
111
112    // Test a perfectly matching epilog with no offset.
113    .seh_proc packed2
114packed2:
115    sub sp, sp, #48
116    .seh_stackalloc 48
117    stp x29, lr, [sp, #-32]!
118    .seh_save_fplr_x 32
119    .seh_endprologue
120    nop
121    .seh_startepilogue
122    ldp x29, lr, [sp], #32
123    .seh_save_fplr_x 32
124    add sp, sp, #48
125    .seh_stackalloc 48
126    .seh_endepilogue
127    ret
128    .seh_endproc
129
130
131    .seh_proc nonpacked1
132nonpacked1:
133    sub sp, sp, #48
134    .seh_stackalloc 48
135    .seh_endprologue
136
137    nop
138    .seh_startepilogue
139    add sp, sp, #48
140    .seh_stackalloc 48
141    .seh_endepilogue
142    // This epilogue isn't packed with the prologue, as it doesn't align with
143    // the end of the function (one extra nop before the ret).
144    nop
145    ret
146    .seh_endproc
147
148
149    .seh_proc nonpacked2
150nonpacked2:
151    sub sp, sp, #48
152    .seh_stackalloc 48
153    sub sp, sp, #32
154    .seh_stackalloc 32
155    .seh_endprologue
156
157    nop
158    .seh_startepilogue
159    // Not packed; the epilogue mismatches at the second opcode.
160    add sp, sp, #16
161    .seh_stackalloc 16
162    add sp, sp, #48
163    .seh_stackalloc 48
164    .seh_endepilogue
165    ret
166    .seh_endproc
167
168    .seh_proc nonpacked3
169nonpacked3:
170    sub sp, sp, #48
171    .seh_stackalloc 48
172    sub sp, sp, #32
173    .seh_stackalloc 32
174    .seh_endprologue
175
176    nop
177    .seh_startepilogue
178    // Not packed; the epilogue is longer than the prologue.
179    mov sp, x29
180    .seh_set_fp
181    add sp, sp, #32
182    .seh_stackalloc 32
183    add sp, sp, #48
184    .seh_stackalloc 48
185    .seh_endepilogue
186    ret
187    .seh_endproc
188