xref: /llvm-project/llvm/test/MC/AArch64/seh-large-func-multi-epilog.s (revision 99e50e583867ac35ace36f5da50b3a3ff7c51d2e)
1// This test checks that we emit unwind info correctly for epilogs that:
2// 1. mirror the prolog; or
3// 2. are subsequence at the end of the prolog; or
4// 3. neither of above two.
5// in the same segment.
6// RUN: llvm-mc -triple aarch64-pc-win32 -filetype=obj %s -o %t.o
7// RUN: llvm-readobj -S -r -u %t.o | FileCheck %s
8
9// CHECK:       Section {
10// CHECK:         Number: 4
11// CHECK-NEXT:    Name: .xdata (2E 78 64 61 74 61 00 00)
12// CHECK-NEXT:    VirtualSize: 0x0
13// CHECK-NEXT:    VirtualAddress: 0x0
14// CHECK-NEXT:    RawDataSize: 80
15// CHECK-NEXT:    PointerToRawData: 0x1251AC
16// CHECK-NEXT:    PointerToRelocations: 0x0
17// CHECK-NEXT:    PointerToLineNumbers: 0x0
18// CHECK-NEXT:    RelocationCount: 0
19// CHECK-NEXT:    LineNumberCount: 0
20// CHECK-NEXT:    Characteristics [ (0x40300040)
21// CHECK-NEXT:      IMAGE_SCN_ALIGN_4BYTES (0x300000)
22// CHECK-NEXT:      IMAGE_SCN_CNT_INITIALIZED_DATA (0x40)
23// CHECK-NEXT:      IMAGE_SCN_MEM_READ (0x40000000)
24// CHECK-NEXT:    ]
25// CHECK-NEXT:  }
26// CHECK-NEXT:  Section {
27// CHECK-NEXT:    Number: 5
28// CHECK-NEXT:    Name: .pdata (2E 70 64 61 74 61 00 00)
29// CHECK-NEXT:    VirtualSize: 0x0
30// CHECK-NEXT:    VirtualAddress: 0x0
31// CHECK-NEXT:    RawDataSize: 16
32// CHECK-NEXT:    PointerToRawData: 0x1251FC
33// CHECK-NEXT:    PointerToRelocations: 0x12520C
34// CHECK-NEXT:    PointerToLineNumbers: 0x0
35// CHECK-NEXT:    RelocationCount: 4
36// CHECK-NEXT:    LineNumberCount: 0
37// CHECK-NEXT:    Characteristics [ (0x40300040)
38// CHECK-NEXT:      IMAGE_SCN_ALIGN_4BYTES (0x300000)
39// CHECK-NEXT:      IMAGE_SCN_CNT_INITIALIZED_DATA (0x40)
40// CHECK-NEXT:      IMAGE_SCN_MEM_READ (0x40000000)
41// CHECK-NEXT:    ]
42// CHECK-NEXT:  }
43// CHECK-NEXT:]
44// CHECK-LABEL:Relocations [
45// CHECK-NEXT:  Section (1) .text {
46// CHECK-NEXT:    0x94 IMAGE_REL_ARM64_BRANCH26 foo (12)
47// CHECK-NEXT:    0x125068 IMAGE_REL_ARM64_BRANCH26 foo (12)
48// CHECK-NEXT:  }
49// CHECK-NEXT:  Section (5) .pdata {
50// CHECK-NEXT:    0x0 IMAGE_REL_ARM64_ADDR32NB .text (0)
51// CHECK-NEXT:    0x4 IMAGE_REL_ARM64_ADDR32NB .xdata (7)
52// CHECK-NEXT:    0x8 IMAGE_REL_ARM64_ADDR32NB .text (0)
53// CHECK-NEXT:    0xC IMAGE_REL_ARM64_ADDR32NB .xdata (7)
54// CHECK-NEXT:  }
55// CHECK-NEXT:]
56// CHECK-LABEL:UnwindInformation [
57// CHECK-NEXT:  RuntimeFunction {
58// CHECK-NEXT:    Function: multi_epilog (0x0)
59// CHECK-NEXT:    ExceptionRecord: .xdata (0x0)
60// CHECK-NEXT:    ExceptionData {
61// CHECK-NEXT:      FunctionLength: 1048572
62// CHECK-NEXT:      Version: 0
63// CHECK-NEXT:      ExceptionData: No
64// CHECK-NEXT:      EpiloguePacked: No
65// CHECK-NEXT:      EpilogueScopes: 3
66// CHECK-NEXT:      ByteCodeLength: 24
67// CHECK-NEXT:      Prologue [
68// CHECK-NEXT:        0xe1                ; mov fp, sp
69// CHECK-NEXT:        0xca16              ; stp x27, x28, [sp, #176]
70// CHECK-NEXT:        0xc998              ; stp x25, x26, [sp, #192]
71// CHECK-NEXT:        0xc91a              ; stp x23, x24, [sp, #208]
72// CHECK-NEXT:        0xc89c              ; stp x21, x22, [sp, #224]
73// CHECK-NEXT:        0xc81e              ; stp x19, x20, [sp, #240]
74// CHECK-NEXT:        0x9f                ; stp x29, x30, [sp, #-256]!
75// CHECK-NEXT:        0xe4                ; end
76// CHECK-NEXT:      ]
77// CHECK-NEXT:      EpilogueScopes [
78// CHECK-NEXT:        EpilogueScope {
79// CHECK-NEXT:          StartOffset: 38
80// CHECK-NEXT:          EpilogueStartIndex: 0
81// CHECK-NEXT:          Opcodes [
82// CHECK-NEXT:            0xe1                ; mov sp, fp
83// CHECK-NEXT:            0xca16              ; ldp x27, x28, [sp, #176]
84// CHECK-NEXT:            0xc998              ; ldp x25, x26, [sp, #192]
85// CHECK-NEXT:            0xc91a              ; ldp x23, x24, [sp, #208]
86// CHECK-NEXT:            0xc89c              ; ldp x21, x22, [sp, #224]
87// CHECK-NEXT:            0xc81e              ; ldp x19, x20, [sp, #240]
88// CHECK-NEXT:            0x9f                ; ldp x29, x30, [sp], #256
89// CHECK-NEXT:            0xe4                ; end
90// CHECK-NEXT:          ]
91// CHECK-NEXT:        }
92// CHECK-NEXT:        EpilogueScope {
93// CHECK-NEXT:          StartOffset: 46
94// CHECK-NEXT:          EpilogueStartIndex: 3
95// CHECK-NEXT:          Opcodes [
96// CHECK-NEXT:            0xc998              ; ldp x25, x26, [sp, #192]
97// CHECK-NEXT:            0xc91a              ; ldp x23, x24, [sp, #208]
98// CHECK-NEXT:            0xc89c              ; ldp x21, x22, [sp, #224]
99// CHECK-NEXT:            0xc81e              ; ldp x19, x20, [sp, #240]
100// CHECK-NEXT:            0x9f                ; ldp x29, x30, [sp], #256
101// CHECK-NEXT:            0xe4                ; end
102// CHECK-NEXT:          ]
103// CHECK-NEXT:        }
104// CHECK-NEXT:        EpilogueScope {
105// CHECK-NEXT:          StartOffset: 52
106// CHECK-NEXT:          EpilogueStartIndex: 13
107// CHECK-NEXT:          Opcodes [
108// CHECK-NEXT:            0xe1                ; mov sp, fp
109// CHECK-NEXT:            0xc91a              ; ldp x23, x24, [sp, #208]
110// CHECK-NEXT:            0xc89c              ; ldp x21, x22, [sp, #224]
111// CHECK-NEXT:            0xc81e              ; ldp x19, x20, [sp, #240]
112// CHECK-NEXT:            0x9f                ; ldp x29, x30, [sp], #256
113// CHECK-NEXT:            0xe4                ; end
114// CHECK-NEXT:          ]
115// CHECK-NEXT:        }
116// CHECK-NEXT:      ]
117// CHECK-NEXT:    }
118// CHECK-NEXT:  }
119// CHECK-NEXT:  RuntimeFunction {
120// CHECK-NEXT:    Function: multi_epilog +0xFFFFC (0xFFFFC)
121// CHECK-NEXT:    ExceptionRecord: .xdata +0x28 (0x28)
122// CHECK-NEXT:    ExceptionData {
123// CHECK-NEXT:      FunctionLength: 151744
124// CHECK-NEXT:      Version: 0
125// CHECK-NEXT:      ExceptionData: No
126// CHECK-NEXT:      EpiloguePacked: No
127// CHECK-NEXT:      EpilogueScopes: 3
128// CHECK-NEXT:      ByteCodeLength: 24
129// CHECK-NEXT:      Prologue [
130// CHECK-NEXT:        0xe5                ; end_c
131// CHECK-NEXT:        0xe1                ; mov fp, sp
132// CHECK-NEXT:        0xca16              ; stp x27, x28, [sp, #176]
133// CHECK-NEXT:        0xc998              ; stp x25, x26, [sp, #192]
134// CHECK-NEXT:        0xc91a              ; stp x23, x24, [sp, #208]
135// CHECK-NEXT:        0xc89c              ; stp x21, x22, [sp, #224]
136// CHECK-NEXT:        0xc81e              ; stp x19, x20, [sp, #240]
137// CHECK-NEXT:        0x9f                ; stp x29, x30, [sp, #-256]!
138// CHECK-NEXT:        0xe4                ; end
139// CHECK-NEXT:      ]
140// CHECK-NEXT:      EpilogueScopes [
141// CHECK-NEXT:        EpilogueScope {
142// CHECK-NEXT:          StartOffset: 37916
143// CHECK-NEXT:          EpilogueStartIndex: 1
144// CHECK-NEXT:          Opcodes [
145// CHECK-NEXT:            0xe1                ; mov sp, fp
146// CHECK-NEXT:            0xca16              ; ldp x27, x28, [sp, #176]
147// CHECK-NEXT:            0xc998              ; ldp x25, x26, [sp, #192]
148// CHECK-NEXT:            0xc91a              ; ldp x23, x24, [sp, #208]
149// CHECK-NEXT:            0xc89c              ; ldp x21, x22, [sp, #224]
150// CHECK-NEXT:            0xc81e              ; ldp x19, x20, [sp, #240]
151// CHECK-NEXT:            0x9f                ; ldp x29, x30, [sp], #256
152// CHECK-NEXT:            0xe4                ; end
153// CHECK-NEXT:          ]
154// CHECK-NEXT:        }
155// CHECK-NEXT:        EpilogueScope {
156// CHECK-NEXT:          StartOffset: 37924
157// CHECK-NEXT:          EpilogueStartIndex: 4
158// CHECK-NEXT:          Opcodes [
159// CHECK-NEXT:            0xc998              ; ldp x25, x26, [sp, #192]
160// CHECK-NEXT:            0xc91a              ; ldp x23, x24, [sp, #208]
161// CHECK-NEXT:            0xc89c              ; ldp x21, x22, [sp, #224]
162// CHECK-NEXT:            0xc81e              ; ldp x19, x20, [sp, #240]
163// CHECK-NEXT:            0x9f                ; ldp x29, x30, [sp], #256
164// CHECK-NEXT:            0xe4                ; end
165// CHECK-NEXT:          ]
166// CHECK-NEXT:        }
167// CHECK-NEXT:        EpilogueScope {
168// CHECK-NEXT:          StartOffset: 37930
169// CHECK-NEXT:          EpilogueStartIndex: 14
170// CHECK-NEXT:          Opcodes [
171// CHECK-NEXT:            0xe1                ; mov sp, fp
172// CHECK-NEXT:            0xc91a              ; ldp x23, x24, [sp, #208]
173// CHECK-NEXT:            0xc89c              ; ldp x21, x22, [sp, #224]
174// CHECK-NEXT:            0xc81e              ; ldp x19, x20, [sp, #240]
175// CHECK-NEXT:            0x9f                ; ldp x29, x30, [sp], #256
176// CHECK-NEXT:            0xe4                ; end
177// CHECK-NEXT:          ]
178// CHECK-NEXT:        }
179// CHECK-NEXT:      ]
180// CHECK-NEXT:    }
181// CHECK-NEXT:  }
182// CHECK-NEXT:]
183
184	.text
185	.global	multi_epilog
186	.p2align	2
187	.seh_proc multi_epilog
188multi_epilog:
189	stp	x29, lr, [sp, #-256]!
190	.seh_save_fplr_x 256
191	stp	x19, x20, [sp, #240]
192	.seh_save_regp x19, 240
193	stp	x21, x22, [sp, #224]
194	.seh_save_regp x21, 224
195	stp	x23, x24, [sp, #208]
196	.seh_save_regp x23, 208
197	stp	x25, x26, [sp, #192]
198	.seh_save_regp x25, 192
199	stp	x27, x28, [sp, #176]
200	.seh_save_regp x27, 176
201	mov	x29, fp
202	.seh_set_fp
203	.seh_endprologue
204        .rept 30
205        nop
206        .endr
207	bl	foo
208// Epilogs 1, 2 and 3 are in the same segment as prolog.
209// epilog1 - mirroring prolog
210	.seh_startepilogue
211	mov	sp, x29
212	.seh_set_fp
213	stp	x27, x28, [sp, #176]
214	.seh_save_regp x27, 176
215	stp	x25, x26, [sp, #192]
216	.seh_save_regp x25, 192
217	stp	x23, x24, [sp, #208]
218	.seh_save_regp x23, 208
219	stp	x21, x22, [sp, #224]
220	.seh_save_regp x21, 224
221	ldp	x19, x20, [sp, #240]
222	.seh_save_regp x19, 240
223	ldp	x29, lr, [sp], #256
224	.seh_save_fplr_x 256
225	.seh_endepilogue
226	ret
227// epilog2 - a subsequence at the end of prolog, can use prolog's opcodes.
228	.seh_startepilogue
229	stp	x25, x26, [sp, #192]
230	.seh_save_regp x25, 192
231	stp	x23, x24, [sp, #208]
232	.seh_save_regp x23, 208
233	stp	x21, x22, [sp, #224]
234	.seh_save_regp x21, 224
235	ldp	x19, x20, [sp, #240]
236	.seh_save_regp x19, 240
237	ldp	x29, lr, [sp], #256
238	.seh_save_fplr_x 256
239	.seh_endepilogue
240	ret
241// epilog3 - cannot use prolog's opcode.
242	.seh_startepilogue
243	mov	sp, x29
244	.seh_set_fp
245	stp	x23, x24, [sp, #208]
246	.seh_save_regp x23, 208
247	stp	x21, x22, [sp, #224]
248	.seh_save_regp x21, 224
249	ldp	x19, x20, [sp, #240]
250	.seh_save_regp x19, 240
251	ldp	x29, lr, [sp], #256
252	.seh_save_fplr_x 256
253	.seh_endepilogue
254	ret
255        .rept 300000
256        nop
257        .endr
258	bl	foo
259// Epilogs below are in a segment without prolog
260// epilog4 - mirroring prolog, its start index should be 1, counting the end_c.
261	.seh_startepilogue
262	mov	sp, x29
263	.seh_set_fp
264	stp	x27, x28, [sp, #176]
265	.seh_save_regp x27, 176
266	stp	x25, x26, [sp, #192]
267	.seh_save_regp x25, 192
268	stp	x23, x24, [sp, #208]
269	.seh_save_regp x23, 208
270	stp	x21, x22, [sp, #224]
271	.seh_save_regp x21, 224
272	ldp	x19, x20, [sp, #240]
273	.seh_save_regp x19, 240
274	ldp	x29, lr, [sp], #256
275	.seh_save_fplr_x 256
276	.seh_endepilogue
277	ret
278// epilog5 - same as epilog2, its start index should be: 1 + epilog2's index.
279	.seh_startepilogue
280	stp	x25, x26, [sp, #192]
281	.seh_save_regp x25, 192
282	stp	x23, x24, [sp, #208]
283	.seh_save_regp x23, 208
284	stp	x21, x22, [sp, #224]
285	.seh_save_regp x21, 224
286	ldp	x19, x20, [sp, #240]
287	.seh_save_regp x19, 240
288	ldp	x29, lr, [sp], #256
289	.seh_save_fplr_x 256
290	.seh_endepilogue
291	ret
292// epilog6 - same as epilog3, cannot use prolog's opcode. Again its start index
293//           should be: 1 + epilog3's index.
294	.seh_startepilogue
295	mov	sp, x29
296	.seh_set_fp
297	stp	x23, x24, [sp, #208]
298	.seh_save_regp x23, 208
299	stp	x21, x22, [sp, #224]
300	.seh_save_regp x21, 224
301	ldp	x19, x20, [sp, #240]
302	.seh_save_regp x19, 240
303	ldp	x29, lr, [sp], #256
304	.seh_save_fplr_x 256
305	.seh_endepilogue
306	ret
307	.seh_endfunclet
308	.seh_endproc
309