[llvm] [Arm64] Make tail calls work properly for Arm64 Windows (PR #230429)
Saleem Abdulrasool via llvm-commits
llvm-commits at lists.llvm.org
Fri Oct 9 20:53:32 PDT 2026
================
@@ -0,0 +1,583 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc < %s -mtriple=aarch64-windows -verify-machineinstrs | FileCheck %s --check-prefix=HINT
+; RUN: llc < %s -mtriple=aarch64-windows -mattr=+pauth -verify-machineinstrs | FileCheck %s --check-prefix=PAUTH
+; RUN: llc < %s -mtriple=aarch64-windows -filetype=obj -o %t.obj
+; RUN: llvm-readobj --unwind %t.obj | FileCheck %s --check-prefix=UNWIND
+
+; When a tail call, or a return from a function with callee-popped stack
+; arguments, changes the stack argument size, the epilogue doesn't leave SP at
+; its value on entry. The Windows unwinder applies the pac_sign_lr unwind code
+; using whatever SP it has at that point, which wouldn't be the SP that the
+; return address was signed with, so the return address is authenticated before
+; the epilogue starts, where the prologue's unwind codes still apply, and the
+; authenticated return address stays in LR rather than being restored by
+; the epilogue. Its unwind codes then have no pac_sign_lr.
+
+declare swifttailcc void @callee12(i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64)
+declare swifttailcc void @callee1(i64)
+declare void @use(ptr)
+declare void @clobber()
+
+define swifttailcc void @pac_grow(i64 %a) "sign-return-address"="all" {
+;
+; HINT-LABEL: pac_grow:
+; HINT: .seh_proc pac_grow
+; HINT-NEXT: // %bb.0:
+; HINT-NEXT: hint #27
+; HINT-NEXT: .seh_pac_sign_lr
+; HINT-NEXT: str x30, [sp, #-48]! // 8-byte Folded Spill
+; HINT-NEXT: .seh_save_reg_x x30, 48
+; HINT-NEXT: .seh_endprologue
+; HINT-NEXT: mov x20, x0
+; HINT-NEXT: bl clobber
+; HINT-NEXT: ldr x17, [sp] // 8-byte Reload
+; HINT-NEXT: stp x20, x20, [sp, #32]
+; HINT-NEXT: mov x0, x20
+; HINT-NEXT: stp x20, x20, [sp, #16]
+; HINT-NEXT: mov x1, x20
+; HINT-NEXT: mov x2, x20
+; HINT-NEXT: mov x3, x20
+; HINT-NEXT: mov x4, x20
+; HINT-NEXT: mov x5, x20
+; HINT-NEXT: mov x6, x20
+; HINT-NEXT: mov x7, x20
+; HINT-NEXT: add x16, sp, #48
+; HINT-NEXT: hint #14
+; HINT-NEXT: mov x30, x17
+; HINT-NEXT: .seh_startepilogue
+; HINT-NEXT: add sp, sp, #16
+; HINT-NEXT: .seh_stackalloc 16
+; HINT-NEXT: .seh_endepilogue
+; HINT-NEXT: b callee12
+; HINT-NEXT: .seh_endfunclet
+; HINT-NEXT: .seh_endproc
+;
+; PAUTH-LABEL: pac_grow:
+; PAUTH: .seh_proc pac_grow
+; PAUTH-NEXT: // %bb.0:
+; PAUTH-NEXT: pacibsp
+; PAUTH-NEXT: .seh_pac_sign_lr
+; PAUTH-NEXT: str x30, [sp, #-48]! // 8-byte Folded Spill
+; PAUTH-NEXT: .seh_save_reg_x x30, 48
+; PAUTH-NEXT: .seh_endprologue
+; PAUTH-NEXT: mov x20, x0
+; PAUTH-NEXT: bl clobber
+; PAUTH-NEXT: ldr x30, [sp] // 8-byte Reload
+; PAUTH-NEXT: stp x20, x20, [sp, #32]
+; PAUTH-NEXT: mov x0, x20
+; PAUTH-NEXT: stp x20, x20, [sp, #16]
+; PAUTH-NEXT: mov x1, x20
+; PAUTH-NEXT: mov x2, x20
+; PAUTH-NEXT: mov x3, x20
+; PAUTH-NEXT: mov x4, x20
+; PAUTH-NEXT: mov x5, x20
+; PAUTH-NEXT: mov x6, x20
+; PAUTH-NEXT: mov x7, x20
+; PAUTH-NEXT: add x16, sp, #48
+; PAUTH-NEXT: autib x30, x16
+; PAUTH-NEXT: .seh_startepilogue
+; PAUTH-NEXT: add sp, sp, #16
+; PAUTH-NEXT: .seh_stackalloc 16
+; PAUTH-NEXT: .seh_endepilogue
+; PAUTH-NEXT: b callee12
+; PAUTH-NEXT: .seh_endfunclet
+; PAUTH-NEXT: .seh_endproc
----------------
compnerd wrote:
I'm not convinced that the full instruction matching helps understand the checked invariants. Simplifying the checks would help.
https://github.com/llvm/llvm-project/pull/230429
More information about the llvm-commits
mailing list