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
|