1// This test checks that we emit unwind info correctly for epilogs that: 2// 1. mirror the prolog; or 3// 2. are subsequence at the end of the prolog; or 4// 3. neither of above two. 5// in the same segment. 6// RUN: llvm-mc -triple aarch64-pc-win32 -filetype=obj %s -o %t.o 7// RUN: llvm-readobj -S -r -u %t.o | FileCheck %s 8 9// CHECK: Section { 10// CHECK: Number: 4 11// CHECK-NEXT: Name: .xdata (2E 78 64 61 74 61 00 00) 12// CHECK-NEXT: VirtualSize: 0x0 13// CHECK-NEXT: VirtualAddress: 0x0 14// CHECK-NEXT: RawDataSize: 80 15// CHECK-NEXT: PointerToRawData: 0x1251AC 16// CHECK-NEXT: PointerToRelocations: 0x0 17// CHECK-NEXT: PointerToLineNumbers: 0x0 18// CHECK-NEXT: RelocationCount: 0 19// CHECK-NEXT: LineNumberCount: 0 20// CHECK-NEXT: Characteristics [ (0x40300040) 21// CHECK-NEXT: IMAGE_SCN_ALIGN_4BYTES (0x300000) 22// CHECK-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA (0x40) 23// CHECK-NEXT: IMAGE_SCN_MEM_READ (0x40000000) 24// CHECK-NEXT: ] 25// CHECK-NEXT: } 26// CHECK-NEXT: Section { 27// CHECK-NEXT: Number: 5 28// CHECK-NEXT: Name: .pdata (2E 70 64 61 74 61 00 00) 29// CHECK-NEXT: VirtualSize: 0x0 30// CHECK-NEXT: VirtualAddress: 0x0 31// CHECK-NEXT: RawDataSize: 16 32// CHECK-NEXT: PointerToRawData: 0x1251FC 33// CHECK-NEXT: PointerToRelocations: 0x12520C 34// CHECK-NEXT: PointerToLineNumbers: 0x0 35// CHECK-NEXT: RelocationCount: 4 36// CHECK-NEXT: LineNumberCount: 0 37// CHECK-NEXT: Characteristics [ (0x40300040) 38// CHECK-NEXT: IMAGE_SCN_ALIGN_4BYTES (0x300000) 39// CHECK-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA (0x40) 40// CHECK-NEXT: IMAGE_SCN_MEM_READ (0x40000000) 41// CHECK-NEXT: ] 42// CHECK-NEXT: } 43// CHECK-NEXT:] 44// CHECK-LABEL:Relocations [ 45// CHECK-NEXT: Section (1) .text { 46// CHECK-NEXT: 0x94 IMAGE_REL_ARM64_BRANCH26 foo (12) 47// CHECK-NEXT: 0x125068 IMAGE_REL_ARM64_BRANCH26 foo (12) 48// CHECK-NEXT: } 49// CHECK-NEXT: Section (5) .pdata { 50// CHECK-NEXT: 0x0 IMAGE_REL_ARM64_ADDR32NB .text (0) 51// CHECK-NEXT: 0x4 IMAGE_REL_ARM64_ADDR32NB .xdata (7) 52// CHECK-NEXT: 0x8 IMAGE_REL_ARM64_ADDR32NB .text (0) 53// CHECK-NEXT: 0xC IMAGE_REL_ARM64_ADDR32NB .xdata (7) 54// CHECK-NEXT: } 55// CHECK-NEXT:] 56// CHECK-LABEL:UnwindInformation [ 57// CHECK-NEXT: RuntimeFunction { 58// CHECK-NEXT: Function: multi_epilog (0x0) 59// CHECK-NEXT: ExceptionRecord: .xdata (0x0) 60// CHECK-NEXT: ExceptionData { 61// CHECK-NEXT: FunctionLength: 1048572 62// CHECK-NEXT: Version: 0 63// CHECK-NEXT: ExceptionData: No 64// CHECK-NEXT: EpiloguePacked: No 65// CHECK-NEXT: EpilogueScopes: 3 66// CHECK-NEXT: ByteCodeLength: 24 67// CHECK-NEXT: Prologue [ 68// CHECK-NEXT: 0xe1 ; mov fp, sp 69// CHECK-NEXT: 0xca16 ; stp x27, x28, [sp, #176] 70// CHECK-NEXT: 0xc998 ; stp x25, x26, [sp, #192] 71// CHECK-NEXT: 0xc91a ; stp x23, x24, [sp, #208] 72// CHECK-NEXT: 0xc89c ; stp x21, x22, [sp, #224] 73// CHECK-NEXT: 0xc81e ; stp x19, x20, [sp, #240] 74// CHECK-NEXT: 0x9f ; stp x29, x30, [sp, #-256]! 75// CHECK-NEXT: 0xe4 ; end 76// CHECK-NEXT: ] 77// CHECK-NEXT: EpilogueScopes [ 78// CHECK-NEXT: EpilogueScope { 79// CHECK-NEXT: StartOffset: 38 80// CHECK-NEXT: EpilogueStartIndex: 0 81// CHECK-NEXT: Opcodes [ 82// CHECK-NEXT: 0xe1 ; mov sp, fp 83// CHECK-NEXT: 0xca16 ; ldp x27, x28, [sp, #176] 84// CHECK-NEXT: 0xc998 ; ldp x25, x26, [sp, #192] 85// CHECK-NEXT: 0xc91a ; ldp x23, x24, [sp, #208] 86// CHECK-NEXT: 0xc89c ; ldp x21, x22, [sp, #224] 87// CHECK-NEXT: 0xc81e ; ldp x19, x20, [sp, #240] 88// CHECK-NEXT: 0x9f ; ldp x29, x30, [sp], #256 89// CHECK-NEXT: 0xe4 ; end 90// CHECK-NEXT: ] 91// CHECK-NEXT: } 92// CHECK-NEXT: EpilogueScope { 93// CHECK-NEXT: StartOffset: 46 94// CHECK-NEXT: EpilogueStartIndex: 3 95// CHECK-NEXT: Opcodes [ 96// CHECK-NEXT: 0xc998 ; ldp x25, x26, [sp, #192] 97// CHECK-NEXT: 0xc91a ; ldp x23, x24, [sp, #208] 98// CHECK-NEXT: 0xc89c ; ldp x21, x22, [sp, #224] 99// CHECK-NEXT: 0xc81e ; ldp x19, x20, [sp, #240] 100// CHECK-NEXT: 0x9f ; ldp x29, x30, [sp], #256 101// CHECK-NEXT: 0xe4 ; end 102// CHECK-NEXT: ] 103// CHECK-NEXT: } 104// CHECK-NEXT: EpilogueScope { 105// CHECK-NEXT: StartOffset: 52 106// CHECK-NEXT: EpilogueStartIndex: 13 107// CHECK-NEXT: Opcodes [ 108// CHECK-NEXT: 0xe1 ; mov sp, fp 109// CHECK-NEXT: 0xc91a ; ldp x23, x24, [sp, #208] 110// CHECK-NEXT: 0xc89c ; ldp x21, x22, [sp, #224] 111// CHECK-NEXT: 0xc81e ; ldp x19, x20, [sp, #240] 112// CHECK-NEXT: 0x9f ; ldp x29, x30, [sp], #256 113// CHECK-NEXT: 0xe4 ; end 114// CHECK-NEXT: ] 115// CHECK-NEXT: } 116// CHECK-NEXT: ] 117// CHECK-NEXT: } 118// CHECK-NEXT: } 119// CHECK-NEXT: RuntimeFunction { 120// CHECK-NEXT: Function: multi_epilog +0xFFFFC (0xFFFFC) 121// CHECK-NEXT: ExceptionRecord: .xdata +0x28 (0x28) 122// CHECK-NEXT: ExceptionData { 123// CHECK-NEXT: FunctionLength: 151744 124// CHECK-NEXT: Version: 0 125// CHECK-NEXT: ExceptionData: No 126// CHECK-NEXT: EpiloguePacked: No 127// CHECK-NEXT: EpilogueScopes: 3 128// CHECK-NEXT: ByteCodeLength: 24 129// CHECK-NEXT: Prologue [ 130// CHECK-NEXT: 0xe5 ; end_c 131// CHECK-NEXT: 0xe1 ; mov fp, sp 132// CHECK-NEXT: 0xca16 ; stp x27, x28, [sp, #176] 133// CHECK-NEXT: 0xc998 ; stp x25, x26, [sp, #192] 134// CHECK-NEXT: 0xc91a ; stp x23, x24, [sp, #208] 135// CHECK-NEXT: 0xc89c ; stp x21, x22, [sp, #224] 136// CHECK-NEXT: 0xc81e ; stp x19, x20, [sp, #240] 137// CHECK-NEXT: 0x9f ; stp x29, x30, [sp, #-256]! 138// CHECK-NEXT: 0xe4 ; end 139// CHECK-NEXT: ] 140// CHECK-NEXT: EpilogueScopes [ 141// CHECK-NEXT: EpilogueScope { 142// CHECK-NEXT: StartOffset: 37916 143// CHECK-NEXT: EpilogueStartIndex: 1 144// CHECK-NEXT: Opcodes [ 145// CHECK-NEXT: 0xe1 ; mov sp, fp 146// CHECK-NEXT: 0xca16 ; ldp x27, x28, [sp, #176] 147// CHECK-NEXT: 0xc998 ; ldp x25, x26, [sp, #192] 148// CHECK-NEXT: 0xc91a ; ldp x23, x24, [sp, #208] 149// CHECK-NEXT: 0xc89c ; ldp x21, x22, [sp, #224] 150// CHECK-NEXT: 0xc81e ; ldp x19, x20, [sp, #240] 151// CHECK-NEXT: 0x9f ; ldp x29, x30, [sp], #256 152// CHECK-NEXT: 0xe4 ; end 153// CHECK-NEXT: ] 154// CHECK-NEXT: } 155// CHECK-NEXT: EpilogueScope { 156// CHECK-NEXT: StartOffset: 37924 157// CHECK-NEXT: EpilogueStartIndex: 4 158// CHECK-NEXT: Opcodes [ 159// CHECK-NEXT: 0xc998 ; ldp x25, x26, [sp, #192] 160// CHECK-NEXT: 0xc91a ; ldp x23, x24, [sp, #208] 161// CHECK-NEXT: 0xc89c ; ldp x21, x22, [sp, #224] 162// CHECK-NEXT: 0xc81e ; ldp x19, x20, [sp, #240] 163// CHECK-NEXT: 0x9f ; ldp x29, x30, [sp], #256 164// CHECK-NEXT: 0xe4 ; end 165// CHECK-NEXT: ] 166// CHECK-NEXT: } 167// CHECK-NEXT: EpilogueScope { 168// CHECK-NEXT: StartOffset: 37930 169// CHECK-NEXT: EpilogueStartIndex: 14 170// CHECK-NEXT: Opcodes [ 171// CHECK-NEXT: 0xe1 ; mov sp, fp 172// CHECK-NEXT: 0xc91a ; ldp x23, x24, [sp, #208] 173// CHECK-NEXT: 0xc89c ; ldp x21, x22, [sp, #224] 174// CHECK-NEXT: 0xc81e ; ldp x19, x20, [sp, #240] 175// CHECK-NEXT: 0x9f ; ldp x29, x30, [sp], #256 176// CHECK-NEXT: 0xe4 ; end 177// CHECK-NEXT: ] 178// CHECK-NEXT: } 179// CHECK-NEXT: ] 180// CHECK-NEXT: } 181// CHECK-NEXT: } 182// CHECK-NEXT:] 183 184 .text 185 .global multi_epilog 186 .p2align 2 187 .seh_proc multi_epilog 188multi_epilog: 189 stp x29, lr, [sp, #-256]! 190 .seh_save_fplr_x 256 191 stp x19, x20, [sp, #240] 192 .seh_save_regp x19, 240 193 stp x21, x22, [sp, #224] 194 .seh_save_regp x21, 224 195 stp x23, x24, [sp, #208] 196 .seh_save_regp x23, 208 197 stp x25, x26, [sp, #192] 198 .seh_save_regp x25, 192 199 stp x27, x28, [sp, #176] 200 .seh_save_regp x27, 176 201 mov x29, fp 202 .seh_set_fp 203 .seh_endprologue 204 .rept 30 205 nop 206 .endr 207 bl foo 208// Epilogs 1, 2 and 3 are in the same segment as prolog. 209// epilog1 - mirroring prolog 210 .seh_startepilogue 211 mov sp, x29 212 .seh_set_fp 213 stp x27, x28, [sp, #176] 214 .seh_save_regp x27, 176 215 stp x25, x26, [sp, #192] 216 .seh_save_regp x25, 192 217 stp x23, x24, [sp, #208] 218 .seh_save_regp x23, 208 219 stp x21, x22, [sp, #224] 220 .seh_save_regp x21, 224 221 ldp x19, x20, [sp, #240] 222 .seh_save_regp x19, 240 223 ldp x29, lr, [sp], #256 224 .seh_save_fplr_x 256 225 .seh_endepilogue 226 ret 227// epilog2 - a subsequence at the end of prolog, can use prolog's opcodes. 228 .seh_startepilogue 229 stp x25, x26, [sp, #192] 230 .seh_save_regp x25, 192 231 stp x23, x24, [sp, #208] 232 .seh_save_regp x23, 208 233 stp x21, x22, [sp, #224] 234 .seh_save_regp x21, 224 235 ldp x19, x20, [sp, #240] 236 .seh_save_regp x19, 240 237 ldp x29, lr, [sp], #256 238 .seh_save_fplr_x 256 239 .seh_endepilogue 240 ret 241// epilog3 - cannot use prolog's opcode. 242 .seh_startepilogue 243 mov sp, x29 244 .seh_set_fp 245 stp x23, x24, [sp, #208] 246 .seh_save_regp x23, 208 247 stp x21, x22, [sp, #224] 248 .seh_save_regp x21, 224 249 ldp x19, x20, [sp, #240] 250 .seh_save_regp x19, 240 251 ldp x29, lr, [sp], #256 252 .seh_save_fplr_x 256 253 .seh_endepilogue 254 ret 255 .rept 300000 256 nop 257 .endr 258 bl foo 259// Epilogs below are in a segment without prolog 260// epilog4 - mirroring prolog, its start index should be 1, counting the end_c. 261 .seh_startepilogue 262 mov sp, x29 263 .seh_set_fp 264 stp x27, x28, [sp, #176] 265 .seh_save_regp x27, 176 266 stp x25, x26, [sp, #192] 267 .seh_save_regp x25, 192 268 stp x23, x24, [sp, #208] 269 .seh_save_regp x23, 208 270 stp x21, x22, [sp, #224] 271 .seh_save_regp x21, 224 272 ldp x19, x20, [sp, #240] 273 .seh_save_regp x19, 240 274 ldp x29, lr, [sp], #256 275 .seh_save_fplr_x 256 276 .seh_endepilogue 277 ret 278// epilog5 - same as epilog2, its start index should be: 1 + epilog2's index. 279 .seh_startepilogue 280 stp x25, x26, [sp, #192] 281 .seh_save_regp x25, 192 282 stp x23, x24, [sp, #208] 283 .seh_save_regp x23, 208 284 stp x21, x22, [sp, #224] 285 .seh_save_regp x21, 224 286 ldp x19, x20, [sp, #240] 287 .seh_save_regp x19, 240 288 ldp x29, lr, [sp], #256 289 .seh_save_fplr_x 256 290 .seh_endepilogue 291 ret 292// epilog6 - same as epilog3, cannot use prolog's opcode. Again its start index 293// should be: 1 + epilog3's index. 294 .seh_startepilogue 295 mov sp, x29 296 .seh_set_fp 297 stp x23, x24, [sp, #208] 298 .seh_save_regp x23, 208 299 stp x21, x22, [sp, #224] 300 .seh_save_regp x21, 224 301 ldp x19, x20, [sp, #240] 302 .seh_save_regp x19, 240 303 ldp x29, lr, [sp], #256 304 .seh_save_fplr_x 256 305 .seh_endepilogue 306 ret 307 .seh_endfunclet 308 .seh_endproc 309