xref: /llvm-project/llvm/test/MC/ARM/seh-epilog-sharing.s (revision d4022ff3310635f682e9937c8ffa4aeb0d2e2854)
1// This test checks various cases around sharing opcodes between epilogue and prologue with more than one epilogue.
2
3// RUN: llvm-mc -triple thumbv7-pc-win32 -filetype=obj %s | llvm-readobj -u - | FileCheck %s
4
5// CHECK:       RuntimeFunction {
6// CHECK-NEXT:    Function: func1
7// CHECK-NEXT:    ExceptionRecord:
8// CHECK-NEXT:    ExceptionData {
9// CHECK-NEXT:      FunctionLength:
10// CHECK-NEXT:      Version:
11// CHECK-NEXT:      ExceptionData:
12// CHECK-NEXT:      EpiloguePacked: No
13// CHECK-NEXT:      Fragment:
14// CHECK-NEXT:      EpilogueScopes: 3
15// CHECK-NEXT:      ByteCodeLength: 12
16// CHECK-NEXT:      Prologue [
17// CHECK-NEXT:        0xf5 0x15           ; vpush {d1-d5}
18// CHECK-NEXT:        0x05                ; sub sp, #(5 * 4)
19// CHECK-NEXT:        0xa0 0xf0           ; push.w {r4-r7, lr}
20// CHECK-NEXT:      ]
21// CHECK-NEXT:      EpilogueScopes [
22// CHECK-NEXT:        EpilogueScope {
23// CHECK-NEXT:          StartOffset: 6
24// CHECK-NEXT:          Condition: 14
25// CHECK-NEXT:          EpilogueStartIndex: 6
26// CHECK-NEXT:          Opcodes [
27// CHECK-NEXT:            0x08                ; add sp, #(8 * 4)
28// CHECK-NEXT:            0xfd                ; bx <reg>
29// CHECK-NEXT:          ]
30// CHECK-NEXT:        }
31// CHECK-NEXT:        EpilogueScope {
32// CHECK-NEXT:          StartOffset: 9
33// CHECK-NEXT:          Condition: 14
34// CHECK-NEXT:          EpilogueStartIndex: 8
35// CHECK-NEXT:          Opcodes [
36// CHECK-NEXT:            0x10                ; add sp, #(16 * 4)
37// CHECK-NEXT:            0xfd                ; bx <reg>
38// CHECK-NEXT:          ]
39// CHECK-NEXT:        }
40// CHECK-NEXT:        EpilogueScope {
41// CHECK-NEXT:          StartOffset: 13
42// CHECK-NEXT:          Condition: 10
43// CHECK-NEXT:          EpilogueStartIndex: 6
44// CHECK-NEXT:          Opcodes [
45// CHECK-NEXT:            0x08                ; add sp, #(8 * 4)
46// CHECK-NEXT:            0xfd                ; bx <reg>
47// CHECK-NEXT:          ]
48// CHECK-NEXT:        }
49// CHECK-NEXT:      ]
50// CHECK-NEXT:    }
51// CHECK-NEXT:  }
52// CHECK-NEXT:  RuntimeFunction {
53// CHECK-NEXT:    Function: func2
54// CHECK-NEXT:    ExceptionRecord:
55// CHECK-NEXT:    ExceptionData {
56// CHECK-NEXT:      FunctionLength:
57// CHECK-NEXT:      Version:
58// CHECK-NEXT:      ExceptionData:
59// CHECK-NEXT:      EpiloguePacked: No
60// CHECK-NEXT:      Fragment:
61// CHECK-NEXT:      EpilogueScopes: 3
62// CHECK-NEXT:      ByteCodeLength: 12
63// CHECK-NEXT:      Prologue [
64// CHECK-NEXT:        0xf5 0x15           ; vpush {d1-d5}
65// CHECK-NEXT:        0x05                ; sub sp, #(5 * 4)
66// CHECK-NEXT:        0xa0 0xf0           ; push.w {r4-r7, lr}
67// CHECK-NEXT:        0xfe                ; b.w <target>
68// CHECK-NEXT:      ]
69// CHECK-NEXT:      EpilogueScopes [
70// CHECK-NEXT:        EpilogueScope {
71// CHECK-NEXT:          StartOffset: 6
72// CHECK-NEXT:          Condition: 14
73// CHECK-NEXT:          EpilogueStartIndex: 2
74// CHECK-NEXT:          Opcodes [
75// CHECK-NEXT:            0x05                ; add sp, #(5 * 4)
76// CHECK-NEXT:            0xa0 0xf0           ; pop.w {r4-r7, pc}
77// CHECK-NEXT:            0xfe                ; b.w <target>
78// CHECK-NEXT:          ]
79// CHECK-NEXT:        }
80// CHECK-NEXT:        EpilogueScope {
81// CHECK-NEXT:          StartOffset: 11
82// CHECK-NEXT:          Condition: 14
83// CHECK-NEXT:          EpilogueStartIndex: 3
84// CHECK-NEXT:          Opcodes [
85// CHECK-NEXT:            0xa0 0xf0           ; pop.w {r4-r7, pc}
86// CHECK-NEXT:            0xfe                ; b.w <target>
87// CHECK-NEXT:          ]
88// CHECK-NEXT:        }
89// CHECK-NEXT:        EpilogueScope {
90// CHECK-NEXT:          StartOffset: 15
91// CHECK-NEXT:          Condition: 14
92// CHECK-NEXT:          EpilogueStartIndex: 6
93// CHECK-NEXT:          Opcodes [
94// CHECK-NEXT:            0xa0 0xf0           ; pop.w {r4-r7, pc}
95// CHECK-NEXT:            0xfd                ; bx <reg>
96// CHECK-NEXT:          ]
97// CHECK-NEXT:        }
98// CHECK-NEXT:      ]
99// CHECK-NEXT:    }
100// CHECK-NEXT:  }
101
102        .text
103        .syntax unified
104
105        .seh_proc func1
106func1:
107        push.w {r4-r7,lr}
108        .seh_save_regs_w {r4-r7,lr}
109        sub sp, sp, #20
110        .seh_stackalloc 20
111        vpush {d1-d5}
112        .seh_save_fregs {d1-d5}
113        .seh_endprologue
114        nop
115
116        // Entirely different epilogue; can't be shared with the prologue.
117        .seh_startepilogue
118        add sp, sp, #32
119        .seh_stackalloc 32
120        bx lr
121        .seh_nop
122        .seh_endepilogue
123
124        nop
125
126        // Also a differing epilogue.
127        .seh_startepilogue
128        add sp, sp, #64
129        .seh_stackalloc 64
130        bx lr
131        .seh_nop
132        .seh_endepilogue
133
134        nop
135
136        // Epilogue matches the first one; will reuse that epilogue's opcodes,
137        // even if they differ in conditionality.
138        itt ge
139        .seh_startepilogue_cond ge
140        addge sp, sp, #32
141        .seh_stackalloc 32
142        bxge lr
143        .seh_nop
144        .seh_endepilogue
145        .seh_endproc
146
147        .seh_proc func2
148func2:
149        push.w {r4-r7,lr}
150        .seh_save_regs_w {r4-r7,lr}
151        sub sp, sp, #20
152        .seh_stackalloc 20
153        vpush {d1-d5}
154        .seh_save_fregs {d1-d5}
155        .seh_endprologue
156
157        nop
158
159        .seh_startepilogue
160        add sp, sp, #20
161        .seh_stackalloc 20
162        // As we're popping into lr instead of directly into pc, this pop
163        // becomes a wide instruction. To match prologue vs epilogue, the
164        // push in the prologue has been made wide too.
165        pop.w {r4-r7,lr}
166        .seh_save_regs_w {r4-r7,lr}
167        b.w tailcall
168        // Ending with a different end opcode, but can still be shared with
169        // the prolog.
170        .seh_nop_w
171        .seh_endepilogue
172
173        // Another epilogue, matching the end of the previous epilogue.
174        .seh_startepilogue
175        pop.w {r4-r7,lr}
176        .seh_save_regs_w {r4-r7,lr}
177        b.w tailcall
178        .seh_nop_w
179        .seh_endepilogue
180
181        // This epilogue differs in the end opcode, and can't be shared with
182        // the prologue.
183        .seh_startepilogue
184        pop.w {r4-r7,lr}
185        .seh_save_regs_w {r4-r7,lr}
186        bx lr
187        .seh_nop
188        .seh_endepilogue
189        .seh_endproc
190