xref: /llvm-project/llvm/test/MC/ARM/seh-epilog-packing.s (revision d4022ff3310635f682e9937c8ffa4aeb0d2e2854)
1// This test checks various cases around sharing opcodes between epilogue and prologue
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: Yes
13// CHECK-NEXT:      Fragment: No
14// CHECK-NEXT:      EpilogueOffset: 2
15// CHECK-NEXT:      ByteCodeLength:
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:        0xfe                ; b.w <target>
21// CHECK-NEXT:      ]
22// CHECK-NEXT:      Epilogue [
23// CHECK-NEXT:        0x05                ; add sp, #(5 * 4)
24// CHECK-NEXT:        0xa0 0xf0           ; pop.w {r4-r7, pc}
25// CHECK-NEXT:        0xfe                ; b.w <target>
26// CHECK-NEXT:      ]
27// CHECK-NEXT:    }
28// CHECK-NEXT:  }
29// CHECK-NEXT:  RuntimeFunction {
30// CHECK-NEXT:    Function: func2
31// CHECK-NEXT:    ExceptionRecord:
32// CHECK-NEXT:    ExceptionData {
33// CHECK-NEXT:      FunctionLength:
34// CHECK-NEXT:      Version:
35// CHECK-NEXT:      ExceptionData:
36// CHECK-NEXT:      EpiloguePacked: Yes
37// CHECK-NEXT:      Fragment: No
38// CHECK-NEXT:      EpilogueOffset: 0
39// CHECK-NEXT:      ByteCodeLength: 4
40// CHECK-NEXT:      Prologue [
41// CHECK-NEXT:        0xd2                ; push {r4-r6}
42// CHECK-NEXT:        0x04                ; sub sp, #(4 * 4)
43// CHECK-NEXT:        0xfd                ; bx <reg>
44// CHECK-NEXT:      ]
45// CHECK-NEXT:    }
46// CHECK-NEXT:  }
47// CHECK-NEXT:  RuntimeFunction {
48// CHECK-NEXT:    Function: func3
49// CHECK-NEXT:    ExceptionRecord:
50// CHECK-NEXT:    ExceptionData {
51// CHECK-NEXT:      FunctionLength:
52// CHECK-NEXT:      Version:
53// CHECK-NEXT:      ExceptionData:
54// CHECK-NEXT:      EpiloguePacked: Yes
55// CHECK-NEXT:      Fragment: No
56// CHECK-NEXT:      EpilogueOffset: 0
57// CHECK-NEXT:      ByteCodeLength: 4
58// CHECK-NEXT:      Prologue [
59// CHECK-NEXT:        0xe1                ; vpush {d8-d9}
60// CHECK-NEXT:        0xdf                ; push.w {r4-r11, lr}
61// CHECK-NEXT:      ]
62// CHECK-NEXT:    }
63// CHECK-NEXT:  }
64// CHECK-NEXT:  RuntimeFunction {
65// CHECK-NEXT:    Function: notshared1
66// CHECK-NEXT:    ExceptionRecord:
67// CHECK-NEXT:    ExceptionData {
68// CHECK-NEXT:      FunctionLength:
69// CHECK-NEXT:      Version:
70// CHECK-NEXT:      ExceptionData:
71// CHECK-NEXT:      EpiloguePacked: Yes
72// CHECK-NEXT:      Fragment:
73// CHECK-NEXT:      EpilogueOffset: 2
74// CHECK-NEXT:      ByteCodeLength: 4
75// CHECK-NEXT:      Prologue [
76// CHECK-NEXT:        0xdf                ; push.w {r4-r11, lr}
77// CHECK-NEXT:      ]
78// CHECK-NEXT:      Epilogue [
79// CHECK-NEXT:        0xdb                ; pop.w {r4-r11}
80// CHECK-NEXT:        0xfd                ; bx <reg>
81// CHECK-NEXT:      ]
82// CHECK:       RuntimeFunction {
83// CHECK-NEXT:    Function: notpacked2
84// CHECK-NEXT:    ExceptionRecord:
85// CHECK-NEXT:    ExceptionData {
86// CHECK-NEXT:      FunctionLength:
87// CHECK-NEXT:      Version:
88// CHECK-NEXT:      ExceptionData:
89// CHECK-NEXT:      EpiloguePacked: No
90// CHECK:       RuntimeFunction {
91// CHECK-NEXT:    Function: notpacked3
92// CHECK-NEXT:    ExceptionRecord:
93// CHECK-NEXT:    ExceptionData {
94// CHECK-NEXT:      FunctionLength:
95// CHECK-NEXT:      Version:
96// CHECK-NEXT:      ExceptionData:
97// CHECK-NEXT:      EpiloguePacked: No
98
99        .text
100        .syntax unified
101        .seh_proc func1
102func1:
103        push.w {r4-r7,lr}
104        .seh_save_regs_w {r4-r7,lr}
105        sub sp, sp, #20
106        .seh_stackalloc 20
107        vpush {d1-d5}
108        .seh_save_fregs {d1-d5}
109        .seh_endprologue
110        nop
111        .seh_startepilogue
112        add sp, sp, #20
113        .seh_stackalloc 20
114        // As we're popping into lr instead of directly into pc, this pop
115        // becomes a wide instruction. To match prologue vs epilogue, the
116        // push in the prologue has been made wide too.
117        pop.w {r4-r7,lr}
118        .seh_save_regs_w {r4-r7,lr}
119        b.w tailcall
120        .seh_nop_w
121        .seh_endepilogue
122        .seh_endproc
123
124        .seh_proc func2
125func2:
126        sub sp, sp, #16
127        .seh_stackalloc 16
128        push {r4-r6}
129        .seh_save_regs {r4-r6}
130        .seh_endprologue
131        nop
132        .seh_startepilogue
133        pop {r4-r6}
134        .seh_save_regs {r4-r6}
135        add sp, sp, #16
136        .seh_stackalloc 16
137        bx lr
138        .seh_nop
139        .seh_endepilogue
140        .seh_endproc
141
142        .seh_proc func3
143func3:
144        push {r4-r11,lr}
145        .seh_save_regs_w {r4-r11,lr}
146        vpush {d8-d9}
147        .seh_save_fregs {d8-d9}
148        .seh_endprologue
149        nop
150        .seh_startepilogue
151        vpop {d8-d9}
152        .seh_save_fregs {d8-d9}
153        pop {r4-r11,pc}
154        .seh_save_regs_w {r4-r11,pc}
155        .seh_endepilogue
156        .seh_endproc
157
158        .seh_proc notshared1
159notshared1:
160        push {r4-r11,lr}
161        .seh_save_regs_w {r4-r11,lr}
162        .seh_endprologue
163        nop
164        .seh_startepilogue
165        // Packed, but not shared as this opcode doesn't match the prolog
166        pop {r4-r11}
167        .seh_save_regs_w {r4-r11}
168        bx lr
169        .seh_nop
170        .seh_endepilogue
171        .seh_endproc
172
173        .seh_proc notpacked2
174notpacked2:
175        push {r4-r11}
176        .seh_save_regs_w {r4-r11}
177        vpush {d8-d9}
178        .seh_save_fregs {d8-d9}
179        .seh_endprologue
180        nop
181        .seh_startepilogue
182        vpop {d8-d9}
183        .seh_save_fregs {d8-d9}
184        pop {r4-r11}
185        .seh_save_regs_w {r4-r11}
186        bx lr
187        .seh_nop
188        .seh_endepilogue
189        // Not packed, as the epilog isn't at the end of the function
190        nop
191        .seh_endproc
192
193        .seh_proc notpacked3
194notpacked3:
195        push {r4-r11,lr}
196        .seh_save_regs_w {r4-r11,lr}
197        .seh_endprologue
198        nop
199        it ge
200        // Not packed, as the epilog is conditional
201        .seh_startepilogue_cond ge
202        popge {r4-r11,pc}
203        .seh_save_regs_w {r4-r11,pc}
204        .seh_endepilogue
205        .seh_endproc
206