From 3e5b86cec112f5f5639c71bd54e7ca7862cf58bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Fri, 28 Nov 2025 14:06:35 +0200 Subject: [PATCH 1/5] [AArch64] [test] Write the seh.s test output object to a file This is what is done in other tests; this makes it easier to inspect the output of this test manually. --- llvm/test/MC/AArch64/seh.s | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/llvm/test/MC/AArch64/seh.s b/llvm/test/MC/AArch64/seh.s index 5e194568f62dd..d1df900403f0a 100644 --- a/llvm/test/MC/AArch64/seh.s +++ b/llvm/test/MC/AArch64/seh.s @@ -1,6 +1,7 @@ // This test checks that the SEH directives emit the correct unwind data. -// RUN: llvm-mc -triple aarch64-pc-win32 -filetype=obj %s | llvm-readobj -S -r -u - | FileCheck %s +// RUN: llvm-mc -triple aarch64-pc-win32 -filetype=obj %s -o %t.o +// RUN: llvm-readobj -S -r -u %t.o | FileCheck %s // Check that the output assembler directives also can be parsed, and // that they produce equivalent output: From e50ac8a9b1bca90b5d3fea7a20b9985870a08df4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Fri, 28 Nov 2025 14:00:36 +0200 Subject: [PATCH 2/5] [AArch64] [test] Move tests for custom unwind opcodes to a separate function These custom opcodes disable the checker for having the prologue length actually match the opcodes (see checkARM64Instructions in MCWin64EH.cpp) - which led to the prologue mismatching the opcodes by one instruction, since 312d6b488ef9d7c0e4d649827820db7285e36406. Move the special opcodes to a separate test function. Remove the mismatched nop instruction at the end of the main function, as this prologue now is assembled with the strict length checking enabled. --- llvm/test/MC/AArch64/seh.s | 63 +++++++++++++++++++++++++------------- 1 file changed, 41 insertions(+), 22 deletions(-) diff --git a/llvm/test/MC/AArch64/seh.s b/llvm/test/MC/AArch64/seh.s index d1df900403f0a..ba2832cd6376f 100644 --- a/llvm/test/MC/AArch64/seh.s +++ b/llvm/test/MC/AArch64/seh.s @@ -21,7 +21,7 @@ // CHECK-NEXT: } // CHECK: Section { // CHECK: Name: .xdata -// CHECK: RawDataSize: 100 +// CHECK: RawDataSize: 108 // CHECK: RelocationCount: 1 // CHECK: Characteristics [ // CHECK-NEXT: ALIGN_4BYTES @@ -31,7 +31,7 @@ // CHECK-NEXT: } // CHECK: Section { // CHECK: Name: .pdata -// CHECK: RelocationCount: 2 +// CHECK: RelocationCount: 4 // CHECK: Characteristics [ // CHECK-NEXT: ALIGN_4BYTES // CHECK-NEXT: CNT_INITIALIZED_DATA @@ -42,11 +42,13 @@ // CHECK-NEXT: Relocations [ // CHECK-NEXT: Section (4) .xdata { -// CHECK-NEXT: 0x58 IMAGE_REL_ARM64_ADDR32NB __C_specific_handler +// CHECK-NEXT: 0x54 IMAGE_REL_ARM64_ADDR32NB __C_specific_handler // CHECK-NEXT: } // CHECK-NEXT: Section (5) .pdata { // CHECK-NEXT: 0x0 IMAGE_REL_ARM64_ADDR32NB .text // CHECK-NEXT: 0x4 IMAGE_REL_ARM64_ADDR32NB .xdata +// CHECK-NEXT: 0x8 IMAGE_REL_ARM64_ADDR32NB .text +// CHECK-NEXT: 0xC IMAGE_REL_ARM64_ADDR32NB .xdata // CHECK-NEXT: } // CHECK-NEXT: ] @@ -55,7 +57,7 @@ // CHECK-NEXT: Function: func // CHECK-NEXT: ExceptionRecord: .xdata // CHECK-NEXT: ExceptionData { -// CHECK-NEXT: FunctionLength: 172 +// CHECK-NEXT: FunctionLength: 148 // CHECK: Prologue [ // CHECK-NEXT: 0xe716c3 ; str p6, [sp, #3, mul vl] // CHECK-NEXT: 0xe703c5 ; str z11, [sp, #5, mul vl] @@ -73,11 +75,6 @@ // CHECK-NEXT: 0xe74104 ; stp x1, x2, [sp, #64] // CHECK-NEXT: 0xe70008 ; str x0, [sp, #64] // CHECK-NEXT: 0xfc ; pacibsp -// CHECK-NEXT: 0xec ; clear unwound to call -// CHECK-NEXT: 0xeb ; EC context -// CHECK-NEXT: 0xea ; context -// CHECK-NEXT: 0xe9 ; machine frame -// CHECK-NEXT: 0xe8 ; trap frame // CHECK-NEXT: 0xe3 ; nop // CHECK-NEXT: 0xe202 ; add fp, sp, #16 // CHECK-NEXT: 0xdd41 ; str d13, [sp, #8] @@ -100,8 +97,8 @@ // CHECK-NEXT: ] // CHECK-NEXT: EpilogueScopes [ // CHECK-NEXT: EpilogueScope { -// CHECK-NEXT: StartOffset: 41 -// CHECK-NEXT: EpilogueStartIndex: 77 +// CHECK-NEXT: StartOffset: 35 +// CHECK-NEXT: EpilogueStartIndex: 72 // CHECK-NEXT: Opcodes [ // CHECK-NEXT: 0x01 ; add sp, #16 // CHECK-NEXT: 0xe4 ; end @@ -114,6 +111,23 @@ // CHECK-NEXT: ] // CHECK-NEXT: } // CHECK-NEXT: } +// CHECK-NEXT: RuntimeFunction { +// CHECK-NEXT: Function: customfunc +// CHECK-NEXT: ExceptionRecord: .xdata +// CHECK-NEXT: ExceptionData { +// CHECK-NEXT: FunctionLength: 24 +// CHECK: Prologue [ +// CHECK-NEXT: 0xec ; clear unwound to call +// CHECK-NEXT: 0xeb ; EC context +// CHECK-NEXT: 0xea ; context +// CHECK-NEXT: 0xe9 ; machine frame +// CHECK-NEXT: 0xe8 ; trap frame +// CHECK-NEXT: 0xe4 ; end +// CHECK-NEXT: ] +// CHECK-NEXT: EpilogueScopes [ +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: } // CHECK-NEXT: ] @@ -161,16 +175,6 @@ func: .seh_add_fp 16 nop .seh_nop - nop - .seh_trap_frame - nop - .seh_pushframe - nop - .seh_context - nop - .seh_ec_context - nop - .seh_clear_unwound_to_call pacibsp .seh_pac_sign_lr nop @@ -203,7 +207,6 @@ func: .seh_save_zreg z11, 5 nop .seh_save_preg p6, 3 - nop .seh_endprologue nop .seh_startepilogue @@ -217,6 +220,22 @@ func: .text .seh_endproc + .seh_proc customfunc +customfunc: + nop + .seh_trap_frame + nop + .seh_pushframe + nop + .seh_context + nop + .seh_ec_context + nop + .seh_clear_unwound_to_call + .seh_endprologue + ret + .seh_endproc + // Function with no .seh directives; no pdata/xdata entries are // generated. .globl smallFunc From 9e27fefc180da46bed8731cb19f542f1bd6f2ff4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Fri, 28 Nov 2025 14:03:40 +0200 Subject: [PATCH 3/5] [AArch64] [test] Fix stack allocation instructions in the seh.s test The actual unwind opcodes only stores stack increments in units of 16 (which is what it is listed as in the unwind opcode dumping by llvm-readobj); actually write what we intend to encode. --- llvm/test/MC/AArch64/seh.s | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/llvm/test/MC/AArch64/seh.s b/llvm/test/MC/AArch64/seh.s index ba2832cd6376f..55ebf07ae28a3 100644 --- a/llvm/test/MC/AArch64/seh.s +++ b/llvm/test/MC/AArch64/seh.s @@ -139,8 +139,8 @@ .endef .seh_proc func func: - sub sp, sp, #24 - .seh_stackalloc 24 + sub sp, sp, #16 + .seh_stackalloc 16 mov x29, sp .seh_set_fp stp x29, x30, [sp, #-32]! @@ -210,8 +210,8 @@ func: .seh_endprologue nop .seh_startepilogue - add sp, sp, #24 - .seh_stackalloc 24 + add sp, sp, #16 + .seh_stackalloc 16 .seh_endepilogue ret .seh_handler __C_specific_handler, @except From 4a619a7d082473ca2373824ac9c7f2ea61011a73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Fri, 28 Nov 2025 14:04:44 +0200 Subject: [PATCH 4/5] [AArch64] [test] Spell out the matching instructions for SVE unwind opcodes The MS dumpbin.exe tool can dump the unwind opcodes with the "-unwindinfo" option; this mode also checks that the instructions actually match the expected ones here. (This mode doesn't seem to fully work for all instructions here, but spell out all the intended instructions here.) --- llvm/test/MC/AArch64/seh.s | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/llvm/test/MC/AArch64/seh.s b/llvm/test/MC/AArch64/seh.s index 55ebf07ae28a3..95411391710b4 100644 --- a/llvm/test/MC/AArch64/seh.s +++ b/llvm/test/MC/AArch64/seh.s @@ -131,6 +131,8 @@ // CHECK-NEXT: ] + .arch_extension sve + .text .globl func .def func @@ -177,35 +179,35 @@ func: .seh_nop pacibsp .seh_pac_sign_lr - nop + str x0, [sp, #64] .seh_save_any_reg x0, 64 - nop + stp x1, x2, [sp, #64] .seh_save_any_reg_p x1, 64 - nop + str d29, [sp, #64] .seh_save_any_reg d29, 64 - nop + stp d4, d5, [sp, #64] .seh_save_any_reg_p d4, 64 - nop + str q30, [sp, #64] .seh_save_any_reg q30, 64 - nop + stp q3, q4, [sp, #64] .seh_save_any_reg_p q3, 64 - nop + str x30, [sp, #-64]! .seh_save_any_reg_x lr, 64 - nop + stp x29, x30, [sp, #-64]! .seh_save_any_reg_px fp, 64 - nop + str d31, [sp, #-64]! .seh_save_any_reg_x d31, 64 - nop + stp d2, d3, [sp, #-64]! .seh_save_any_reg_px d2, 64 - nop + str q29, [sp, #-64]! .seh_save_any_reg_x q29, 64 - nop + stp q9, q10, [sp, #-64]! .seh_save_any_reg_px q9, 64 - nop + addvl sp, sp, #-5 .seh_allocz 5 - nop + str z11, [sp, #5, mul vl] .seh_save_zreg z11, 5 - nop + str p6, [sp, #3, mul vl] .seh_save_preg p6, 3 .seh_endprologue nop From 458035027c80e984bf5862140aed20d5e50dd22a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Fri, 28 Nov 2025 14:13:08 +0200 Subject: [PATCH 5/5] [AArch64] [test] Make unwind info tests actually use the right instructions This makes them match the expected decoding of the unwind info opcodes, avoiding mismatch indications from "dumpbin -unwindinfo". --- .../MC/AArch64/seh-large-func-multi-epilog.s | 38 +++++++++---------- llvm/test/MC/AArch64/seh-packed-epilog.s | 2 +- llvm/test/MC/AArch64/seh-packed-unwind.s | 4 +- 3 files changed, 22 insertions(+), 22 deletions(-) diff --git a/llvm/test/MC/AArch64/seh-large-func-multi-epilog.s b/llvm/test/MC/AArch64/seh-large-func-multi-epilog.s index c2d7f94f7b11f..8c6864fe9e196 100644 --- a/llvm/test/MC/AArch64/seh-large-func-multi-epilog.s +++ b/llvm/test/MC/AArch64/seh-large-func-multi-epilog.s @@ -198,7 +198,7 @@ multi_epilog: .seh_save_regp x25, 192 stp x27, x28, [sp, #176] .seh_save_regp x27, 176 - mov x29, fp + mov x29, sp .seh_set_fp .seh_endprologue .rept 30 @@ -210,13 +210,13 @@ multi_epilog: .seh_startepilogue mov sp, x29 .seh_set_fp - stp x27, x28, [sp, #176] + ldp x27, x28, [sp, #176] .seh_save_regp x27, 176 - stp x25, x26, [sp, #192] + ldp x25, x26, [sp, #192] .seh_save_regp x25, 192 - stp x23, x24, [sp, #208] + ldp x23, x24, [sp, #208] .seh_save_regp x23, 208 - stp x21, x22, [sp, #224] + ldp x21, x22, [sp, #224] .seh_save_regp x21, 224 ldp x19, x20, [sp, #240] .seh_save_regp x19, 240 @@ -226,11 +226,11 @@ multi_epilog: ret // epilog2 - a subsequence at the end of prolog, can use prolog's opcodes. .seh_startepilogue - stp x25, x26, [sp, #192] + ldp x25, x26, [sp, #192] .seh_save_regp x25, 192 - stp x23, x24, [sp, #208] + ldp x23, x24, [sp, #208] .seh_save_regp x23, 208 - stp x21, x22, [sp, #224] + ldp x21, x22, [sp, #224] .seh_save_regp x21, 224 ldp x19, x20, [sp, #240] .seh_save_regp x19, 240 @@ -242,9 +242,9 @@ multi_epilog: .seh_startepilogue mov sp, x29 .seh_set_fp - stp x23, x24, [sp, #208] + ldp x23, x24, [sp, #208] .seh_save_regp x23, 208 - stp x21, x22, [sp, #224] + ldp x21, x22, [sp, #224] .seh_save_regp x21, 224 ldp x19, x20, [sp, #240] .seh_save_regp x19, 240 @@ -261,13 +261,13 @@ multi_epilog: .seh_startepilogue mov sp, x29 .seh_set_fp - stp x27, x28, [sp, #176] + ldp x27, x28, [sp, #176] .seh_save_regp x27, 176 - stp x25, x26, [sp, #192] + ldp x25, x26, [sp, #192] .seh_save_regp x25, 192 - stp x23, x24, [sp, #208] + ldp x23, x24, [sp, #208] .seh_save_regp x23, 208 - stp x21, x22, [sp, #224] + ldp x21, x22, [sp, #224] .seh_save_regp x21, 224 ldp x19, x20, [sp, #240] .seh_save_regp x19, 240 @@ -277,11 +277,11 @@ multi_epilog: ret // epilog5 - same as epilog2, its start index should be: 1 + epilog2's index. .seh_startepilogue - stp x25, x26, [sp, #192] + ldp x25, x26, [sp, #192] .seh_save_regp x25, 192 - stp x23, x24, [sp, #208] + ldp x23, x24, [sp, #208] .seh_save_regp x23, 208 - stp x21, x22, [sp, #224] + ldp x21, x22, [sp, #224] .seh_save_regp x21, 224 ldp x19, x20, [sp, #240] .seh_save_regp x19, 240 @@ -294,9 +294,9 @@ multi_epilog: .seh_startepilogue mov sp, x29 .seh_set_fp - stp x23, x24, [sp, #208] + ldp x23, x24, [sp, #208] .seh_save_regp x23, 208 - stp x21, x22, [sp, #224] + ldp x21, x22, [sp, #224] .seh_save_regp x21, 224 ldp x19, x20, [sp, #240] .seh_save_regp x19, 240 diff --git a/llvm/test/MC/AArch64/seh-packed-epilog.s b/llvm/test/MC/AArch64/seh-packed-epilog.s index 85ac8e80dbdda..9fee71a10d445 100644 --- a/llvm/test/MC/AArch64/seh-packed-epilog.s +++ b/llvm/test/MC/AArch64/seh-packed-epilog.s @@ -126,7 +126,7 @@ func: .seh_set_fp ldp x29, x30, [sp, #16] .seh_save_fplr 16 - ldp x29, x30, [sp, #-48]! + ldp x29, x30, [sp], #48 .seh_save_fplr_x 48 ldp x21, x22, [sp, #16] .seh_save_next diff --git a/llvm/test/MC/AArch64/seh-packed-unwind.s b/llvm/test/MC/AArch64/seh-packed-unwind.s index 4c0f30b2536cd..cbb4762667633 100644 --- a/llvm/test/MC/AArch64/seh-packed-unwind.s +++ b/llvm/test/MC/AArch64/seh-packed-unwind.s @@ -892,7 +892,7 @@ nonpacked1: // Can't be packed; can't save integer registers after float registers. stp d8, d9, [sp, #-32]! .seh_save_fregp_x d8, 32 - stp x19, x20, [sp, #16]! + stp x19, x20, [sp, #16] .seh_save_regp x19, 16 .seh_endprologue nop @@ -1010,7 +1010,7 @@ nonpacked6: .seh_startepilogue mov sp, x29 .seh_set_fp - ldp x29, lr, [sp], #32 + ldp x29, lr, [sp], #16 .seh_save_fplr_x 16 ldr lr, [sp, #16] .seh_save_reg lr, 16