188 lines
5.2 KiB
ArmAsm
188 lines
5.2 KiB
ArmAsm
|
// 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
|