308 lines
11 KiB
ArmAsm
308 lines
11 KiB
ArmAsm
// This test checks that we emit unwind info correctly for epilogs that:
|
|
// 1. mirror the prolog; or
|
|
// 2. are subsequence at the end of the prolog; or
|
|
// 3. neither of above two.
|
|
// in the same segment.
|
|
// RUN: llvm-mc -triple aarch64-pc-win32 -filetype=obj %s -o %t.o
|
|
// RUN: llvm-readobj -S -r -u %t.o | FileCheck %s
|
|
|
|
// CHECK: Section {
|
|
// CHECK: Number: 4
|
|
// CHECK-NEXT: Name: .xdata (2E 78 64 61 74 61 00 00)
|
|
// CHECK-NEXT: VirtualSize: 0x0
|
|
// CHECK-NEXT: VirtualAddress: 0x0
|
|
// CHECK-NEXT: RawDataSize: 80
|
|
// CHECK-NEXT: PointerToRawData: 0x1251AC
|
|
// CHECK-NEXT: PointerToRelocations: 0x0
|
|
// CHECK-NEXT: PointerToLineNumbers: 0x0
|
|
// CHECK-NEXT: RelocationCount: 0
|
|
// CHECK-NEXT: LineNumberCount: 0
|
|
// CHECK-NEXT: Characteristics [ (0x40300040)
|
|
// CHECK-NEXT: IMAGE_SCN_ALIGN_4BYTES (0x300000)
|
|
// CHECK-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA (0x40)
|
|
// CHECK-NEXT: IMAGE_SCN_MEM_READ (0x40000000)
|
|
// CHECK-NEXT: ]
|
|
// CHECK-NEXT: }
|
|
// CHECK-NEXT: Section {
|
|
// CHECK-NEXT: Number: 5
|
|
// CHECK-NEXT: Name: .pdata (2E 70 64 61 74 61 00 00)
|
|
// CHECK-NEXT: VirtualSize: 0x0
|
|
// CHECK-NEXT: VirtualAddress: 0x0
|
|
// CHECK-NEXT: RawDataSize: 16
|
|
// CHECK-NEXT: PointerToRawData: 0x1251FC
|
|
// CHECK-NEXT: PointerToRelocations: 0x12520C
|
|
// CHECK-NEXT: PointerToLineNumbers: 0x0
|
|
// CHECK-NEXT: RelocationCount: 4
|
|
// CHECK-NEXT: LineNumberCount: 0
|
|
// CHECK-NEXT: Characteristics [ (0x40300040)
|
|
// CHECK-NEXT: IMAGE_SCN_ALIGN_4BYTES (0x300000)
|
|
// CHECK-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA (0x40)
|
|
// CHECK-NEXT: IMAGE_SCN_MEM_READ (0x40000000)
|
|
// CHECK-NEXT: ]
|
|
// CHECK-NEXT: }
|
|
// CHECK-NEXT:]
|
|
// CHECK-LABEL:Relocations [
|
|
// CHECK-NEXT: Section (1) .text {
|
|
// CHECK-NEXT: 0x94 IMAGE_REL_ARM64_BRANCH26 foo (12)
|
|
// CHECK-NEXT: 0x125068 IMAGE_REL_ARM64_BRANCH26 foo (12)
|
|
// CHECK-NEXT: }
|
|
// CHECK-NEXT: Section (5) .pdata {
|
|
// CHECK-NEXT: 0x0 IMAGE_REL_ARM64_ADDR32NB .text (0)
|
|
// CHECK-NEXT: 0x4 IMAGE_REL_ARM64_ADDR32NB .xdata (7)
|
|
// CHECK-NEXT: 0x8 IMAGE_REL_ARM64_ADDR32NB .text (0)
|
|
// CHECK-NEXT: 0xC IMAGE_REL_ARM64_ADDR32NB .xdata (7)
|
|
// CHECK-NEXT: }
|
|
// CHECK-NEXT:]
|
|
// CHECK-LABEL:UnwindInformation [
|
|
// CHECK-NEXT: RuntimeFunction {
|
|
// CHECK-NEXT: Function: multi_epilog (0x0)
|
|
// CHECK-NEXT: ExceptionRecord: .xdata (0x0)
|
|
// CHECK-NEXT: ExceptionData {
|
|
// CHECK-NEXT: FunctionLength: 1048572
|
|
// CHECK-NEXT: Version: 0
|
|
// CHECK-NEXT: ExceptionData: No
|
|
// CHECK-NEXT: EpiloguePacked: No
|
|
// CHECK-NEXT: EpilogueScopes: 3
|
|
// CHECK-NEXT: ByteCodeLength: 24
|
|
// CHECK-NEXT: Prologue [
|
|
// CHECK-NEXT: 0xe1 ; mov fp, sp
|
|
// CHECK-NEXT: 0xca16 ; stp x27, x28, [sp, #176]
|
|
// CHECK-NEXT: 0xc998 ; stp x25, x26, [sp, #192]
|
|
// CHECK-NEXT: 0xc91a ; stp x23, x24, [sp, #208]
|
|
// CHECK-NEXT: 0xc89c ; stp x21, x22, [sp, #224]
|
|
// CHECK-NEXT: 0xc81e ; stp x19, x20, [sp, #240]
|
|
// CHECK-NEXT: 0x9f ; stp x29, x30, [sp, #-256]!
|
|
// CHECK-NEXT: 0xe4 ; end
|
|
// CHECK-NEXT: ]
|
|
// CHECK-NEXT: EpilogueScopes [
|
|
// CHECK-NEXT: EpilogueScope {
|
|
// CHECK-NEXT: StartOffset: 38
|
|
// CHECK-NEXT: EpilogueStartIndex: 0
|
|
// CHECK-NEXT: Opcodes [
|
|
// CHECK-NEXT: 0xe1 ; mov sp, fp
|
|
// CHECK-NEXT: 0xca16 ; ldp x27, x28, [sp, #176]
|
|
// CHECK-NEXT: 0xc998 ; ldp x25, x26, [sp, #192]
|
|
// CHECK-NEXT: 0xc91a ; ldp x23, x24, [sp, #208]
|
|
// CHECK-NEXT: 0xc89c ; ldp x21, x22, [sp, #224]
|
|
// CHECK-NEXT: 0xc81e ; ldp x19, x20, [sp, #240]
|
|
// CHECK-NEXT: 0x9f ; ldp x29, x30, [sp], #256
|
|
// CHECK-NEXT: 0xe4 ; end
|
|
// CHECK-NEXT: ]
|
|
// CHECK-NEXT: }
|
|
// CHECK-NEXT: EpilogueScope {
|
|
// CHECK-NEXT: StartOffset: 46
|
|
// CHECK-NEXT: EpilogueStartIndex: 3
|
|
// CHECK-NEXT: Opcodes [
|
|
// CHECK-NEXT: 0xc998 ; ldp x25, x26, [sp, #192]
|
|
// CHECK-NEXT: 0xc91a ; ldp x23, x24, [sp, #208]
|
|
// CHECK-NEXT: 0xc89c ; ldp x21, x22, [sp, #224]
|
|
// CHECK-NEXT: 0xc81e ; ldp x19, x20, [sp, #240]
|
|
// CHECK-NEXT: 0x9f ; ldp x29, x30, [sp], #256
|
|
// CHECK-NEXT: 0xe4 ; end
|
|
// CHECK-NEXT: ]
|
|
// CHECK-NEXT: }
|
|
// CHECK-NEXT: EpilogueScope {
|
|
// CHECK-NEXT: StartOffset: 52
|
|
// CHECK-NEXT: EpilogueStartIndex: 13
|
|
// CHECK-NEXT: Opcodes [
|
|
// CHECK-NEXT: 0xe1 ; mov sp, fp
|
|
// CHECK-NEXT: 0xc91a ; ldp x23, x24, [sp, #208]
|
|
// CHECK-NEXT: 0xc89c ; ldp x21, x22, [sp, #224]
|
|
// CHECK-NEXT: 0xc81e ; ldp x19, x20, [sp, #240]
|
|
// CHECK-NEXT: 0x9f ; ldp x29, x30, [sp], #256
|
|
// CHECK-NEXT: 0xe4 ; end
|
|
// CHECK-NEXT: ]
|
|
// CHECK-NEXT: }
|
|
// CHECK-NEXT: ]
|
|
// CHECK-NEXT: }
|
|
// CHECK-NEXT: }
|
|
// CHECK-NEXT: RuntimeFunction {
|
|
// CHECK-NEXT: Function: multi_epilog +0xFFFFC (0xFFFFC)
|
|
// CHECK-NEXT: ExceptionRecord: .xdata +0x28 (0x28)
|
|
// CHECK-NEXT: ExceptionData {
|
|
// CHECK-NEXT: FunctionLength: 151744
|
|
// CHECK-NEXT: Version: 0
|
|
// CHECK-NEXT: ExceptionData: No
|
|
// CHECK-NEXT: EpiloguePacked: No
|
|
// CHECK-NEXT: EpilogueScopes: 3
|
|
// CHECK-NEXT: ByteCodeLength: 24
|
|
// CHECK-NEXT: Prologue [
|
|
// CHECK-NEXT: 0xe5 ; end_c
|
|
// CHECK-NEXT: 0xe1 ; mov fp, sp
|
|
// CHECK-NEXT: 0xca16 ; stp x27, x28, [sp, #176]
|
|
// CHECK-NEXT: 0xc998 ; stp x25, x26, [sp, #192]
|
|
// CHECK-NEXT: 0xc91a ; stp x23, x24, [sp, #208]
|
|
// CHECK-NEXT: 0xc89c ; stp x21, x22, [sp, #224]
|
|
// CHECK-NEXT: 0xc81e ; stp x19, x20, [sp, #240]
|
|
// CHECK-NEXT: 0x9f ; stp x29, x30, [sp, #-256]!
|
|
// CHECK-NEXT: 0xe4 ; end
|
|
// CHECK-NEXT: ]
|
|
// CHECK-NEXT: EpilogueScopes [
|
|
// CHECK-NEXT: EpilogueScope {
|
|
// CHECK-NEXT: StartOffset: 37916
|
|
// CHECK-NEXT: EpilogueStartIndex: 1
|
|
// CHECK-NEXT: Opcodes [
|
|
// CHECK-NEXT: 0xe1 ; mov sp, fp
|
|
// CHECK-NEXT: 0xca16 ; ldp x27, x28, [sp, #176]
|
|
// CHECK-NEXT: 0xc998 ; ldp x25, x26, [sp, #192]
|
|
// CHECK-NEXT: 0xc91a ; ldp x23, x24, [sp, #208]
|
|
// CHECK-NEXT: 0xc89c ; ldp x21, x22, [sp, #224]
|
|
// CHECK-NEXT: 0xc81e ; ldp x19, x20, [sp, #240]
|
|
// CHECK-NEXT: 0x9f ; ldp x29, x30, [sp], #256
|
|
// CHECK-NEXT: 0xe4 ; end
|
|
// CHECK-NEXT: ]
|
|
// CHECK-NEXT: }
|
|
// CHECK-NEXT: EpilogueScope {
|
|
// CHECK-NEXT: StartOffset: 37924
|
|
// CHECK-NEXT: EpilogueStartIndex: 4
|
|
// CHECK-NEXT: Opcodes [
|
|
// CHECK-NEXT: 0xc998 ; ldp x25, x26, [sp, #192]
|
|
// CHECK-NEXT: 0xc91a ; ldp x23, x24, [sp, #208]
|
|
// CHECK-NEXT: 0xc89c ; ldp x21, x22, [sp, #224]
|
|
// CHECK-NEXT: 0xc81e ; ldp x19, x20, [sp, #240]
|
|
// CHECK-NEXT: 0x9f ; ldp x29, x30, [sp], #256
|
|
// CHECK-NEXT: 0xe4 ; end
|
|
// CHECK-NEXT: ]
|
|
// CHECK-NEXT: }
|
|
// CHECK-NEXT: EpilogueScope {
|
|
// CHECK-NEXT: StartOffset: 37930
|
|
// CHECK-NEXT: EpilogueStartIndex: 14
|
|
// CHECK-NEXT: Opcodes [
|
|
// CHECK-NEXT: 0xe1 ; mov sp, fp
|
|
// CHECK-NEXT: 0xc91a ; ldp x23, x24, [sp, #208]
|
|
// CHECK-NEXT: 0xc89c ; ldp x21, x22, [sp, #224]
|
|
// CHECK-NEXT: 0xc81e ; ldp x19, x20, [sp, #240]
|
|
// CHECK-NEXT: 0x9f ; ldp x29, x30, [sp], #256
|
|
// CHECK-NEXT: 0xe4 ; end
|
|
// CHECK-NEXT: ]
|
|
// CHECK-NEXT: }
|
|
// CHECK-NEXT: ]
|
|
// CHECK-NEXT: }
|
|
// CHECK-NEXT: }
|
|
// CHECK-NEXT:]
|
|
|
|
.text
|
|
.global multi_epilog
|
|
.p2align 2
|
|
.seh_proc multi_epilog
|
|
multi_epilog:
|
|
stp x29, lr, [sp, #-256]!
|
|
.seh_save_fplr_x 256
|
|
stp x19, x20, [sp, #240]
|
|
.seh_save_regp x19, 240
|
|
stp x21, x22, [sp, #224]
|
|
.seh_save_regp x21, 224
|
|
stp x23, x24, [sp, #208]
|
|
.seh_save_regp x23, 208
|
|
stp x25, x26, [sp, #192]
|
|
.seh_save_regp x25, 192
|
|
stp x27, x28, [sp, #176]
|
|
.seh_save_regp x27, 176
|
|
mov x29, fp
|
|
.seh_set_fp
|
|
.seh_endprologue
|
|
.rept 30
|
|
nop
|
|
.endr
|
|
bl foo
|
|
// Epilogs 1, 2 and 3 are in the same segment as prolog.
|
|
// epilog1 - mirroring prolog
|
|
.seh_startepilogue
|
|
mov sp, x29
|
|
.seh_set_fp
|
|
stp x27, x28, [sp, #176]
|
|
.seh_save_regp x27, 176
|
|
stp x25, x26, [sp, #192]
|
|
.seh_save_regp x25, 192
|
|
stp x23, x24, [sp, #208]
|
|
.seh_save_regp x23, 208
|
|
stp x21, x22, [sp, #224]
|
|
.seh_save_regp x21, 224
|
|
ldp x19, x20, [sp, #240]
|
|
.seh_save_regp x19, 240
|
|
ldp x29, lr, [sp], #256
|
|
.seh_save_fplr_x 256
|
|
.seh_endepilogue
|
|
ret
|
|
// epilog2 - a subsequence at the end of prolog, can use prolog's opcodes.
|
|
.seh_startepilogue
|
|
stp x25, x26, [sp, #192]
|
|
.seh_save_regp x25, 192
|
|
stp x23, x24, [sp, #208]
|
|
.seh_save_regp x23, 208
|
|
stp x21, x22, [sp, #224]
|
|
.seh_save_regp x21, 224
|
|
ldp x19, x20, [sp, #240]
|
|
.seh_save_regp x19, 240
|
|
ldp x29, lr, [sp], #256
|
|
.seh_save_fplr_x 256
|
|
.seh_endepilogue
|
|
ret
|
|
// epilog3 - cannot use prolog's opcode.
|
|
.seh_startepilogue
|
|
mov sp, x29
|
|
.seh_set_fp
|
|
stp x23, x24, [sp, #208]
|
|
.seh_save_regp x23, 208
|
|
stp x21, x22, [sp, #224]
|
|
.seh_save_regp x21, 224
|
|
ldp x19, x20, [sp, #240]
|
|
.seh_save_regp x19, 240
|
|
ldp x29, lr, [sp], #256
|
|
.seh_save_fplr_x 256
|
|
.seh_endepilogue
|
|
ret
|
|
.rept 300000
|
|
nop
|
|
.endr
|
|
bl foo
|
|
// Epilogs below are in a segment without prolog
|
|
// epilog4 - mirroring prolog, its start index should be 1, counting the end_c.
|
|
.seh_startepilogue
|
|
mov sp, x29
|
|
.seh_set_fp
|
|
stp x27, x28, [sp, #176]
|
|
.seh_save_regp x27, 176
|
|
stp x25, x26, [sp, #192]
|
|
.seh_save_regp x25, 192
|
|
stp x23, x24, [sp, #208]
|
|
.seh_save_regp x23, 208
|
|
stp x21, x22, [sp, #224]
|
|
.seh_save_regp x21, 224
|
|
ldp x19, x20, [sp, #240]
|
|
.seh_save_regp x19, 240
|
|
ldp x29, lr, [sp], #256
|
|
.seh_save_fplr_x 256
|
|
.seh_endepilogue
|
|
ret
|
|
// epilog5 - same as epilog2, its start index should be: 1 + epilog2's index.
|
|
.seh_startepilogue
|
|
stp x25, x26, [sp, #192]
|
|
.seh_save_regp x25, 192
|
|
stp x23, x24, [sp, #208]
|
|
.seh_save_regp x23, 208
|
|
stp x21, x22, [sp, #224]
|
|
.seh_save_regp x21, 224
|
|
ldp x19, x20, [sp, #240]
|
|
.seh_save_regp x19, 240
|
|
ldp x29, lr, [sp], #256
|
|
.seh_save_fplr_x 256
|
|
.seh_endepilogue
|
|
ret
|
|
// epilog6 - same as epilog3, cannot use prolog's opcode. Again its start index
|
|
// should be: 1 + epilog3's index.
|
|
.seh_startepilogue
|
|
mov sp, x29
|
|
.seh_set_fp
|
|
stp x23, x24, [sp, #208]
|
|
.seh_save_regp x23, 208
|
|
stp x21, x22, [sp, #224]
|
|
.seh_save_regp x21, 224
|
|
ldp x19, x20, [sp, #240]
|
|
.seh_save_regp x19, 240
|
|
ldp x29, lr, [sp], #256
|
|
.seh_save_fplr_x 256
|
|
.seh_endepilogue
|
|
ret
|
|
.seh_endfunclet
|
|
.seh_endproc
|