llvm/llvm/test/MC/AArch64/seh-large-func.s

// This test checks that we emit unwind info correctly for functions
// larger than 1MB.
// 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: 52
// CHECK-NEXT:     PointerToRawData: 0x3D0A20
// 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: 40
// CHECK-NEXT:     PointerToRawData: 0x3D0A54
// CHECK-NEXT:     PointerToRelocations: 0x3D0A7C
// CHECK-NEXT:     PointerToLineNumbers: 0x0
// CHECK-NEXT:     RelocationCount: 10
// 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:     0x186A04 IMAGE_REL_ARM64_BRANCH26 foo (14)
// CHECK-NEXT:     0x3D091C IMAGE_REL_ARM64_BRANCH26 foo (14)
// CHECK-NEXT:   }
// CHECK-NEXT:   Section (5) .pdata {
// CHECK-NEXT:     0x0 IMAGE_REL_ARM64_ADDR32NB .text (0)
// CHECK-NEXT:     0x4 IMAGE_REL_ARM64_ADDR32NB .xdata (9)
// CHECK-NEXT:     0x8 IMAGE_REL_ARM64_ADDR32NB .text (0)
// CHECK-NEXT:     0xC IMAGE_REL_ARM64_ADDR32NB .xdata (9)
// CHECK-NEXT:     0x10 IMAGE_REL_ARM64_ADDR32NB $L.text_1 (2)
// CHECK-NEXT:     0x14 IMAGE_REL_ARM64_ADDR32NB .xdata (9)
// CHECK-NEXT:     0x18 IMAGE_REL_ARM64_ADDR32NB $L.text_2 (3)
// CHECK-NEXT:     0x1C IMAGE_REL_ARM64_ADDR32NB .xdata (9)
// CHECK-NEXT:     0x20 IMAGE_REL_ARM64_ADDR32NB $L.text_3 (4)
// CHECK-NEXT:     0x24 IMAGE_REL_ARM64_ADDR32NB .xdata (9)
// CHECK-NEXT:   }
// CHECK-NEXT: ]
// CHECK-LABEL: UnwindInformation [
// CHECK-NEXT:   RuntimeFunction {
// CHECK-NEXT:     Function: a (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: 0
// CHECK-NEXT:       ByteCodeLength: 4
// CHECK-NEXT:       Prologue [
// CHECK-NEXT:         0xd561              ; str x30, [sp, #-16]!
// CHECK-NEXT:         0xe4                ; end
// CHECK-NEXT:       ]
// CHECK-NEXT:       EpilogueScopes [
// CHECK-NEXT:       ]
// CHECK-NEXT:     }
// CHECK-NEXT:   }
// CHECK-NEXT:   RuntimeFunction {
// CHECK-NEXT:     Function: a +0xFFFFC (0xFFFFC)
// CHECK-NEXT:     ExceptionRecord: .xdata +0x8 (0x8)
// CHECK-NEXT:     ExceptionData {
// CHECK-NEXT:       FunctionLength: 551444
// CHECK-NEXT:       Version: 0
// CHECK-NEXT:       ExceptionData: No
// CHECK-NEXT:       EpiloguePacked: Yes
// CHECK-NEXT:       EpilogueOffset: 1
// CHECK-NEXT:       ByteCodeLength: 4
// CHECK-NEXT:       Prologue [
// CHECK-NEXT:         0xe5                ; end_c
// CHECK-NEXT:         0xd561              ; str x30, [sp, #-16]!
// CHECK-NEXT:         0xe4                ; end
// CHECK-NEXT:       ]
// CHECK-NEXT:       Epilogue [
// CHECK-NEXT:         0xd561              ; ldr x30, [sp], #16
// CHECK-NEXT:         0xe4                ; end
// CHECK-NEXT:       ]
// CHECK-NEXT:     }
// CHECK-NEXT:   }
// CHECK-NEXT:   RuntimeFunction {
// CHECK-NEXT:     Function: b (0x186A10)
// CHECK-NEXT:     ExceptionRecord: .xdata +0x10 (0x10)
// CHECK-NEXT:     ExceptionData {
// CHECK-NEXT:       FunctionLength: 1048572
// CHECK-NEXT:       Version: 0
// CHECK-NEXT:       ExceptionData: No
// CHECK-NEXT:       EpiloguePacked: No
// CHECK-NEXT:       EpilogueScopes: 0
// CHECK-NEXT:       ByteCodeLength: 8
// CHECK-NEXT:       Prologue [
// CHECK-NEXT:         0xe1                ; mov fp, sp
// 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:       ]
// CHECK-NEXT:     }
// CHECK-NEXT:   }
// CHECK-NEXT:   RuntimeFunction {
// CHECK-NEXT:     Function: $L.text_2 +0x86A0C (0x286A0C)
// CHECK-NEXT:     ExceptionRecord: .xdata +0x1C (0x1C)
// CHECK-NEXT:     ExceptionData {
// CHECK-NEXT:       FunctionLength: 1048572
// CHECK-NEXT:       Version: 0
// CHECK-NEXT:       ExceptionData: No
// CHECK-NEXT:       EpiloguePacked: Yes
// CHECK-NEXT:       EpilogueOffset: 0
// CHECK-NEXT:       ByteCodeLength: 8
// CHECK-NEXT:       Prologue [
// CHECK-NEXT:         0xe5                ; end_c
// CHECK-NEXT:         0xe1                ; mov fp, sp
// CHECK-NEXT:         0xc81e              ; stp x19, x20, [sp, #240]
// CHECK-NEXT:         0x9f                ; stp x29, x30, [sp, #-256]!
// CHECK-NEXT:         0xe4                ; end
// CHECK-NEXT:       ]
// CHECK-NEXT:     }
// CHECK-NEXT:   }
// CHECK-NEXT:   RuntimeFunction {
// CHECK-NEXT:     Function: $L.text_3 +0x86A08 (0x386A08)
// CHECK-NEXT:     ExceptionRecord: .xdata +0x28 (0x28)
// CHECK-NEXT:     ExceptionData {
// CHECK-NEXT:       FunctionLength: 302888
// CHECK-NEXT:       Version: 0
// CHECK-NEXT:       ExceptionData: No
// CHECK-NEXT:       EpiloguePacked: Yes
// CHECK-NEXT:       EpilogueOffset: 1
// CHECK-NEXT:       ByteCodeLength: 8
// CHECK-NEXT:       Prologue [
// CHECK-NEXT:         0xe5                ; end_c
// CHECK-NEXT:         0xe1                ; mov fp, sp
// CHECK-NEXT:         0xc81e              ; stp x19, x20, [sp, #240]
// CHECK-NEXT:         0x9f                ; stp x29, x30, [sp, #-256]!
// CHECK-NEXT:         0xe4                ; end
// CHECK-NEXT:       ]
// CHECK-NEXT:       Epilogue [
// CHECK-NEXT:         0xe1                ; mov sp, fp
// 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: ]

	.text
// A simple function with an single epilog mirroring the prolog.
	.global	a
	.p2align	2
	.seh_proc a
a:
	str	x30, [sp, #-16]!
	.seh_save_reg_x	x30, 16
	.seh_endprologue
        .rept 400000
        nop
        .endr
	bl	foo
	.seh_startepilogue
	ldr	x30, [sp], #16
	.seh_save_reg_x	x30, 16
	.seh_endepilogue
	ret
	.seh_endfunclet
	.seh_endproc

// Example 1 from https://docs.microsoft.com/en-us/cpp/build/arm64-exception-handling#function-fragments
	.global	b
	.p2align	2
	.seh_proc b
b:
	stp	x29, lr, [sp, #-256]!
	.seh_save_fplr_x 256
	stp	x19, x20, [sp, #240]
	.seh_save_regp x19, 240
	mov	x29, fp
	.seh_set_fp
	.seh_endprologue
        .rept 600000
        nop
        .endr
	bl	foo
	.seh_startepilogue
	mov	sp, x29
	.seh_set_fp
	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