xref: /llvm-project/llvm/test/MC/ARM/seh.s (revision d4022ff3310635f682e9937c8ffa4aeb0d2e2854)
1// This test checks that the SEH directives emit the correct unwind data.
2
3// RUN: llvm-mc -triple thumbv7-pc-win32 -filetype=obj %s | llvm-readobj -S -r -u - | FileCheck %s
4
5// Check that the output assembler directives also can be parsed, and
6// that they produce equivalent output:
7
8// RUN: llvm-mc -triple thumbv7-pc-win32 -filetype=asm %s | llvm-mc -triple thumbv7-pc-win32 -filetype=obj - | llvm-readobj -S -r -u - | FileCheck %s
9
10// CHECK:      Sections [
11// CHECK:        Section {
12// CHECK:          Name: .text
13// CHECK:          RelocationCount: 1
14// CHECK:          Characteristics [
15// CHECK-NEXT:       ALIGN_4BYTES
16// CHECK-NEXT:       CNT_CODE
17// CHECK-NEXT:       MEM_16BIT
18// CHECK-NEXT:       MEM_EXECUTE
19// CHECK-NEXT:       MEM_PURGEABLE
20// CHECK-NEXT:       MEM_READ
21// CHECK-NEXT:     ]
22// CHECK-NEXT:   }
23// CHECK:        Section {
24// CHECK:          Name: .xdata
25// CHECK:          RawDataSize: 100
26// CHECK:          RelocationCount: 1
27// CHECK:          Characteristics [
28// CHECK-NEXT:       ALIGN_4BYTES
29// CHECK-NEXT:       CNT_INITIALIZED_DATA
30// CHECK-NEXT:       MEM_READ
31// CHECK-NEXT:     ]
32// CHECK-NEXT:   }
33// CHECK:        Section {
34// CHECK:          Name: .pdata
35// CHECK:          RelocationCount: 10
36// CHECK:          Characteristics [
37// CHECK-NEXT:       ALIGN_4BYTES
38// CHECK-NEXT:       CNT_INITIALIZED_DATA
39// CHECK-NEXT:       MEM_READ
40// CHECK-NEXT:     ]
41// CHECK-NEXT:   }
42// CHECK-NEXT: ]
43
44// CHECK-NEXT: Relocations [
45// CHECK-NEXT:   Section (1) .text {
46// CHECK-NEXT:     0x5C IMAGE_REL_ARM_BRANCH24T tailcall
47// CHECK-NEXT:   }
48// CHECK-NEXT:   Section (4) .xdata {
49// CHECK-NEXT:     0x34 IMAGE_REL_ARM_ADDR32NB __C_specific_handler
50// CHECK-NEXT:   }
51// CHECK-NEXT:   Section (5) .pdata {
52// CHECK-NEXT:     0x0 IMAGE_REL_ARM_ADDR32NB .text
53// CHECK-NEXT:     0x4 IMAGE_REL_ARM_ADDR32NB .xdata
54// CHECK-NEXT:     0x8 IMAGE_REL_ARM_ADDR32NB .text
55// CHECK-NEXT:     0xC IMAGE_REL_ARM_ADDR32NB .xdata
56// CHECK-NEXT:     0x10 IMAGE_REL_ARM_ADDR32NB .text
57// CHECK-NEXT:     0x14 IMAGE_REL_ARM_ADDR32NB .xdata
58// CHECK-NEXT:     0x18 IMAGE_REL_ARM_ADDR32NB .text
59// CHECK-NEXT:     0x1C IMAGE_REL_ARM_ADDR32NB .xdata
60// CHECK-NEXT:     0x20 IMAGE_REL_ARM_ADDR32NB .text
61// CHECK-NEXT:     0x24 IMAGE_REL_ARM_ADDR32NB .xdata
62// CHECK-NEXT:   }
63// CHECK-NEXT: ]
64
65// CHECK-NEXT: UnwindInformation [
66// CHECK-NEXT:   RuntimeFunction {
67// CHECK-NEXT:     Function: func
68// CHECK-NEXT:     ExceptionRecord: .xdata
69// CHECK-NEXT:     ExceptionData {
70// CHECK-NEXT:       FunctionLength: 86
71// CHECK:            EpiloguePacked: Yes
72// CHECK:            Fragment: No
73// CHECK:            EpilogueOffset: 31
74// CHECK:            Prologue [
75// CHECK-NEXT:         0xed 0xf8           ; push {r3-r7, lr}
76// CHECK-NEXT:         0xf6 0x27           ; vpush {d18-d23}
77// CHECK-NEXT:         0xf5 0x7e           ; vpush {d7-d14}
78// CHECK-NEXT:         0xfb                ; nop
79// CHECK-NEXT:         0xce                ; mov r14, sp
80// CHECK-NEXT:         0xe3                ; vpush {d8-d11}
81// CHECK-NEXT:         0xe6                ; vpush {d8-d14}
82// CHECK-NEXT:         0xed 0xf8           ; push {r3-r7, lr}
83// CHECK-NEXT:         0xbd 0x50           ; push.w {r4, r6, r8, r10-r12, lr}
84// CHECK-NEXT:         0xd7                ; push {r4-r7, lr}
85// CHECK-NEXT:         0xdd                ; push.w {r4-r9, lr}
86// CHECK-NEXT:         0xfa 0x01 0x00 0x00 ; sub.w sp, sp, #(65536 * 4)
87// CHECK-NEXT:         0xfc                ; nop.w
88// CHECK-NEXT:         0xfc                ; nop.w
89// CHECK-NEXT:         0xf9 0x04 0x00      ; sub.w sp, sp, #(1024 * 4)
90// CHECK-NEXT:         0xe8 0x80           ; sub.w sp, #(128 * 4)
91// CHECK-NEXT:         0xe8 0x80           ; sub.w sp, #(128 * 4)
92// CHECK-NEXT:         0x06                ; sub sp, #(6 * 4)
93// CHECK-NEXT:       ]
94// CHECK-NEXT:       Epilogue [
95// CHECK-NEXT:         0xfc                ; nop.w
96// CHECK-NEXT:         0xf7 0x00 0x80      ; add sp, sp, #(128 * 4)
97// CHECK-NEXT:         0xfc                ; nop.w
98// CHECK-NEXT:         0xfc                ; nop.w
99// CHECK-NEXT:         0xf8 0x01 0x00 0x00 ; add sp, sp, #(65536 * 4)
100// CHECK-NEXT:         0x06                ; add sp, #(6 * 4)
101// CHECK-NEXT:         0xef 0x04           ; ldr.w lr, [sp], #16
102// CHECK-NEXT:         0xfd                ; bx <reg>
103// CHECK-NEXT:       ]
104// CHECK-NEXT:       ExceptionHandler [
105// CHECK-NEXT:         Routine: __C_specific_handler
106// CHECK-NEXT:         Parameter: 0x0
107// CHECK-NEXT:       ]
108// CHECK-NEXT:     }
109// CHECK-NEXT:   }
110// CHECK-NEXT:   RuntimeFunction {
111// CHECK-NEXT:     Function: func2
112// CHECK:            Prologue [
113// CHECK-NEXT:         0xd3                ; push {r4-r7}
114// CHECK-NEXT:       ]
115// CHECK-NEXT:       Epilogue [
116// CHECK-NEXT:         0xd2                ; pop {r4-r6}
117// CHECK-NEXT:         0xfe                ; b.w <target>
118// CHECK-NEXT:       ]
119// CHECK-NEXT:     }
120// CHECK-NEXT:   }
121// CHECK-NEXT:   RuntimeFunction {
122// CHECK-NEXT:     Function: func3
123// CHECK:            FunctionLength: 8
124// CHECK:            EpilogueOffset: 2
125// CHECK:            Prologue [
126// CHECK-NEXT:         0xd5                ; push {r4-r5, lr}
127// CHECK-NEXT:       ]
128// CHECK-NEXT:       Epilogue [
129// CHECK-NEXT:         0xd6                ; pop {r4-r6, pc}
130// CHECK-NEXT:       ]
131// CHECK-NEXT:     }
132// CHECK-NEXT:   }
133// CHECK-NEXT:   RuntimeFunction {
134// CHECK-NEXT:     Function: fragment
135// CHECK:            FunctionLength: 6
136// CHECK:            Fragment: Yes
137// CHECK:            Prologue [
138// CHECK-NEXT:         0xcb                ; mov r11, sp
139// CHECK-NEXT:         0x10                ; sub sp, #(16 * 4)
140// CHECK-NEXT:         0xd5                ; push {r4-r5, lr}
141// CHECK-NEXT:       ]
142// CHECK-NEXT:       Epilogue [
143// CHECK-NEXT:         0x10                ; add sp, #(16 * 4)
144// CHECK-NEXT:         0xd5                ; pop {r4-r5, pc}
145// CHECK-NEXT:       ]
146// CHECK-NEXT:     }
147// CHECK-NEXT:   }
148// CHECK-NEXT:   RuntimeFunction {
149// CHECK-NEXT:     Function: condepilog
150// CHECK:            FunctionLength: 8
151// CHECK:            Prologue [
152// CHECK-NEXT:         0xd5                ; push {r4-r5, lr}
153// CHECK-NEXT:       ]
154// CHECK-NEXT:       EpilogueScopes [
155// CHECK-NEXT:         EpilogueScope {
156// CHECK-NEXT:           StartOffset: 3
157// CHECK-NEXT:           Condition: 10
158// CHECK-NEXT:           EpilogueStartIndex: 0
159// CHECK-NEXT:           Opcodes [
160// CHECK-NEXT:             0xd5                ; pop {r4-r5, pc}
161// CHECK-NEXT:           ]
162// CHECK-NEXT:         }
163// CHECK-NEXT:       ]
164// CHECK-NEXT:     }
165// CHECK-NEXT:   }
166// CHECK-NEXT: ]
167
168        .text
169        .syntax unified
170        .globl func
171        .def func
172        .scl 2
173        .type 32
174        .endef
175        .seh_proc func
176func:
177        sub sp, sp, #24
178        .seh_stackalloc 24
179        sub sp, sp, #512
180        .seh_stackalloc_w 512
181        sub sp, sp, #512
182        .seh_stackalloc_w 512
183        sub sp, sp, #4096
184        .seh_stackalloc_w 4096
185        movw r7, #0
186        .seh_nop_w
187        movt r7, #0x4 // 0x40000
188        .seh_nop_w
189        sub sp, sp, r7
190        .seh_stackalloc_w 0x40000
191        push {r4-r8,lr}
192        .seh_save_regs_w {r4-r9,lr}
193        push {r4-r7,lr}
194        .seh_save_regs {r4-r7,lr}
195        push {r4,r6,r8,r10,r11,r12,lr}
196        .seh_save_regs_w {r4,r6,r8,r10,r11,r12,lr}
197        push {r3-r7,lr}
198        .seh_save_regs {r3-r7,lr}
199        vpush {d8-d14}
200        .seh_save_fregs {d8-d14}
201        vpush {q4-q5}
202        .seh_save_fregs {q4-q5}
203        mov lr, sp
204        .seh_save_sp lr
205        nop
206        .seh_nop
207        vpush {d7-d14}
208        .seh_save_fregs {d7-d14}
209        vpush {d18-d23}
210        .seh_save_fregs {d18-d23}
211        push {r3-r7,lr}
212        .seh_custom 0xed, 0xf8
213        .seh_endprologue
214        nop
215        .seh_startepilogue
216        mov r7, #512
217        .seh_nop_w
218        add sp, sp, r7
219        .seh_stackalloc 512
220        movw r7, #0
221        .seh_nop_w
222        movt r7, #0x4 // 0x40000
223        .seh_nop_w
224        add sp, sp, r7
225        .seh_stackalloc 0x40000
226        add sp, sp, #24
227        .seh_stackalloc 24
228        ldr lr, [sp], #16
229        .seh_save_lr 16
230        bx lr
231        .seh_nop
232        .seh_endepilogue
233        .seh_handler __C_specific_handler, %except
234        .seh_handlerdata
235        .long 0
236        .text
237        .seh_endproc
238
239        .seh_proc func2
240func2:
241        push {r4-r7}
242        .seh_save_regs {r4-r7}
243        .seh_endprologue
244        nop
245        .seh_startepilogue
246        pop {r4-r6}
247        .seh_save_regs {r4-r6}
248        b.w tailcall
249        .seh_nop_w
250        .seh_endepilogue
251        .seh_endproc
252
253        .seh_proc func3
254func3:
255        push {r4-r5,lr}
256        .seh_save_regs {r4-r5,lr}
257        .seh_endprologue
258        nop
259        // The p2align causes the length of the function to be unknown.
260        .p2align 1
261        nop
262        .seh_startepilogue
263        pop {r4-r6,pc}
264        .seh_save_regs {r4-r6,pc}
265        .seh_endepilogue
266        .seh_endproc
267
268        .seh_proc fragment
269fragment:
270        // Prologue opcodes without matching instructions
271        .seh_save_regs {r4-r5,lr}
272        .seh_stackalloc 64
273        .seh_save_sp r11
274        .seh_endprologue_fragment
275        nop
276        .seh_startepilogue
277        add sp, sp, #64
278        .seh_stackalloc 64
279        pop {r4-r5,pc}
280        .seh_save_regs {r4-r5,pc}
281        .seh_endepilogue
282        .seh_endproc
283
284        .seh_proc condepilog
285condepilog:
286        push {r4-r5,lr}
287        .seh_save_regs {r4-r5,lr}
288        .seh_endprologue
289        nop
290        it ge
291        .seh_startepilogue_cond ge
292        popge {r4-r5,pc}
293        .seh_save_regs {r4-r5,pc}
294        .seh_endepilogue
295        .seh_endproc
296
297        // Function with no .seh directives; no pdata/xdata entries are
298        // generated.
299        .globl smallFunc
300        .def smallFunc
301        .scl 2
302        .type 32
303        .endef
304        .seh_proc smallFunc
305smallFunc:
306        bx lr
307        .seh_endproc
308
309        // Function with no .seh directives, but with .seh_handlerdata.
310        // No xdata/pdata entries are generated, but the custom handler data
311        // (the .long after .seh_handlerdata) is left orphaned in the xdata
312        // section.
313        .globl handlerFunc
314        .def handlerFunc
315        .scl 2
316        .type 32
317        .endef
318        .seh_proc handlerFunc
319handlerFunc:
320        bx lr
321        .seh_handler __C_specific_handler, %except
322        .seh_handlerdata
323        .long 0
324        .text
325        .seh_endproc
326