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