[llvm] af0aa94 - [AArch64][PAC] Rework the expansion of AUT/AUTPAC pseudos (#169699)

via llvm-commits llvm-commits at lists.llvm.org
Sat Jul 18 05:18:49 PDT 2026


Author: Anatoly Trosinenko
Date: 2026-07-18T15:18:44+03:00
New Revision: af0aa9440f1121bd5041a3dd7abef0d78b0f91cd

URL: https://github.com/llvm/llvm-project/commit/af0aa9440f1121bd5041a3dd7abef0d78b0f91cd
DIFF: https://github.com/llvm/llvm-project/commit/af0aa9440f1121bd5041a3dd7abef0d78b0f91cd.diff

LOG: [AArch64][PAC] Rework the expansion of AUT/AUTPAC pseudos (#169699)

Refactor `AArch64AsmPrinter::emitPtrauthAuthResign` to improve
readability and tune the conditions when `emitPtrauthDiscriminator` is
allowed to clobber address discriminator operands.

When resigning, do not clobber address discriminator register used for
authentication if it is also used for signing. Such clobbering would
prevent passing raw, 64-bit value as the new discriminator. Clarify
other corner cases of clobbering address discriminator operands.

Reuse `enum PtrauthCheckMode` instead of separate `ShouldCheck` and
`ShouldTrap` flags and drop its `Default` enumerator.

Added: 
    

Modified: 
    llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
    llvm/lib/Target/AArch64/AArch64InstrInfo.td
    llvm/test/CodeGen/AArch64/ptrauth-intrinsic-auth-resign-with-blend.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
index 1f2da924db263..46eb6667d539d 100644
--- a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
+++ b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
@@ -82,14 +82,13 @@ STATISTIC(NumZCZeroingInstrsFPR,
           "Number of zero-cycle FPR zeroing instructions expanded from "
           "canonical pseudo instructions");
 
-enum PtrauthCheckMode { Default, Unchecked, Poison, Trap };
+enum PtrauthCheckMode { Unchecked, Poison, Trap };
 static cl::opt<PtrauthCheckMode> PtrauthAuthChecks(
     "aarch64-ptrauth-auth-checks", cl::Hidden,
     cl::values(clEnumValN(Unchecked, "none", "don't test for failure"),
                clEnumValN(Poison, "poison", "poison on failure"),
                clEnumValN(Trap, "trap", "trap on failure")),
-    cl::desc("Check pointer authentication auth/resign failures"),
-    cl::init(Default));
+    cl::desc("Check pointer authentication auth/resign failures"));
 
 namespace {
 
@@ -202,6 +201,10 @@ class AArch64AsmPrinter : public AsmPrinter {
     Register AddrDisc;
     bool AddrDiscIsKilled;
     Register PCDisc;
+
+    bool addrDiscIsKilledAndNoneOf(std::initializer_list<Register> Regs) {
+      return AddrDiscIsKilled && !llvm::is_contained(Regs, AddrDisc);
+    }
   };
 
   // Helper for emitting AUTRELLOADPAC: increment Pointer by Addend and then by
@@ -2358,52 +2361,65 @@ void AArch64AsmPrinter::emitPtrauthApplyIndirectAddend(Register Pointer,
                      .addImm(0));
 }
 
+static PtrauthCheckMode getCheckMode(const MachineFunction *MF) {
+  const AArch64Subtarget &STI = MF->getSubtarget<AArch64Subtarget>();
+
+  // If an override is passed via command line argument, just use that value.
+  if (PtrauthAuthChecks.getNumOccurrences())
+    return PtrauthAuthChecks;
+
+  // Otherwise, on an FPAC CPU, you get traps whether you want them or not:
+  // there's no point in emitting checks or traps.
+  if (STI.hasFPAC())
+    return PtrauthCheckMode::Unchecked;
+
+  bool ShouldTrap = MF->getFunction().hasFnAttribute("ptrauth-auth-traps");
+  return ShouldTrap ? PtrauthCheckMode::Trap : PtrauthCheckMode::Poison;
+}
+
+// We expand non-signing AUT* pseudo instructions into a sequence of the form
+//
+//      ; 1. Authenticate Pointer
+//
+// or
+//
+//      ; 1. Authenticate Pointer
+//      ; 2. Check that Pointer is valid, trap otherwise
+//
+// We expand AUT*PAC pseudo instructions into a sequence of the form
+// (with addend only applied if Addend argument is given):
+//
+//      ; 1. Authenticate Pointer
+//      ; 3. Apply addend and sign Pointer
+//
+// or
+//
+//      ; 1. Authenticate Pointer
+//      ; 2. Check that Pointer is valid, trap otherwise
+//      ; 3. Apply addend and sign Pointer
+//
+// or
+//
+//      ; 1. Authenticate Pointer
+//      ; 2. Check that Pointer is valid, jump to .Lon_failure otherwise
+//      ; 3. Apply addend and sign Pointer
+//    .Lon_failure:
+//
 void AArch64AsmPrinter::emitPtrauthAuthResign(
     Register Pointer, Register Scratch, PtrAuthSchema AuthSchema,
     std::optional<PtrAuthSchema> SignSchema, std::optional<int64_t> Addend,
     Value *DS) {
-  const bool IsResign = SignSchema.has_value();
-  const bool WithPC = AuthSchema.PCDisc != AArch64::NoRegister;
+  const PtrauthCheckMode CheckMode = getCheckMode(MF);
+  const bool IsAuthWithPC = AuthSchema.PCDisc != AArch64::NoRegister;
   assert(!SignSchema || SignSchema->PCDisc == AArch64::NoRegister);
 
-  // We expand AUT/AUTPAC (and their PC-blending variants) into:
-  //
-  //      ; authenticate Pointer
-  //      ; check Pointer
-  //    Lsuccess:
-  //      ; sign Pointer (if resign)
-  //    Lend:   ; if not trapping on failure
-  //
-  // with the checking sequence chosen depending on whether/how we should check
-  // the pointer and whether we should trap on failure.
-
-  // By default, auth/resign sequences check for auth failures.
-  bool ShouldCheck = true;
-  // In the checked sequence, we only trap if explicitly requested.
-  bool ShouldTrap = MF->getFunction().hasFnAttribute("ptrauth-auth-traps");
+  Register SignAddrDiscOrNone =
+      SignSchema ? SignSchema->AddrDisc : AArch64::NoRegister;
 
-  // On an FPAC CPU, you get traps whether you want them or not: there's
-  // no point in emitting checks or traps.
-  if (STI->hasFPAC())
-    ShouldCheck = ShouldTrap = false;
+  // 1. Authenticate Pointer - this is the only common step.
+  // It is more complex than signing because AUTI[AB]171615 may be used.
 
-  // However, command-line flags can override this, for experimentation.
-  switch (PtrauthAuthChecks) {
-  case PtrauthCheckMode::Default:
-    break;
-  case PtrauthCheckMode::Unchecked:
-    ShouldCheck = ShouldTrap = false;
-    break;
-  case PtrauthCheckMode::Poison:
-    ShouldCheck = true;
-    ShouldTrap = false;
-    break;
-  case PtrauthCheckMode::Trap:
-    ShouldCheck = ShouldTrap = true;
-    break;
-  }
-
-  if (WithPC) {
+  if (IsAuthWithPC) {
     assert(Pointer == AArch64::X17 && Scratch == AArch64::X16 &&
            "AUTPCPAC must use x17/x16 as Pointer/Scratch");
 
@@ -2426,46 +2442,63 @@ void AArch64AsmPrinter::emitPtrauthAuthResign(
       EmitToStreamer(MCInstBuilder(AutOpc));
     }
   } else {
-    // Standard AUT: discriminator computed into Scratch, then auti[ab].
-    Register AUTDiscReg =
-        emitPtrauthDiscriminator(AuthSchema.IntDisc, AuthSchema.AddrDisc,
-                                 Scratch, AuthSchema.AddrDiscIsKilled);
+    // emitPtrauthDiscriminator is allowed to clobber AuthSchema.AddrDisc as
+    // long as it is not used past this point neither externally (the register
+    // operand is "killed"), nor internally (it does not alias anything being
+    // used later by this pseudo instruction).
+    //
+    // Note that, while rather unlikely, it is technically possible to use the
+    // Pointer to compute its own discriminator.
+    Register AUTDiscReg = emitPtrauthDiscriminator(
+        AuthSchema.IntDisc, AuthSchema.AddrDisc, Scratch,
+        AuthSchema.addrDiscIsKilledAndNoneOf({Pointer, SignAddrDiscOrNone}));
     if (!emitDeactivationSymbolRelocation(DS))
       emitAUT(AuthSchema.Key, Pointer, AUTDiscReg);
   }
 
-  // Unchecked or checked-but-non-trapping AUT is just an "AUT": we're done.
-  if (!IsResign && (!ShouldCheck || !ShouldTrap))
-    return;
-
-  MCSymbol *EndSym = nullptr;
-
-  if (ShouldCheck) {
-    if (IsResign && !ShouldTrap)
-      EndSym = createTempSymbol("resign_end_");
-
+  // The other two steps are optional, define lambdas for them:
+  // 2. Check that Pointer is valid, on failure jump to label or trap.
+  auto EmitCheck = [&](MCSymbol *OnFailure = nullptr) {
     emitPtrauthCheckAuthenticatedValue(Pointer, Scratch, AuthSchema.Key,
                                        AArch64PAuth::AuthCheckMethod::XPAC,
-                                       EndSym);
-  }
-
-  // We already emitted unchecked and checked-but-non-trapping AUTs.
-  // That left us with trapping AUTs, and AUTPAC/AUTRELLOADPACs.
-  // Trapping AUTs don't need PAC: we're done.
-  if (!IsResign)
-    return;
+                                       OnFailure);
+  };
+  // 3. Apply addend and sign Pointer.
+  auto EmitResignOnSuccess = [&]() {
+    if (Addend.has_value())
+      emitPtrauthApplyIndirectAddend(Pointer, Scratch, *Addend);
+
+    assert(Pointer != SignSchema->AddrDisc && "Pointer is early-clobbered");
+    Register PACDiscReg =
+        emitPtrauthDiscriminator(SignSchema->IntDisc, SignSchema->AddrDisc,
+                                 Scratch, SignSchema->AddrDiscIsKilled);
+    emitPAC(SignSchema->Key, Pointer, PACDiscReg);
+  };
 
-  if (Addend.has_value())
-    emitPtrauthApplyIndirectAddend(Pointer, Scratch, *Addend);
+  // Emit checking and resigning as needed.
 
-  // Compute PAC discriminator into Scratch, then re-sign Pointer.
-  Register PACDiscReg = emitPtrauthDiscriminator(SignSchema->IntDisc,
-                                                 SignSchema->AddrDisc, Scratch);
-  emitPAC(SignSchema->Key, Pointer, PACDiscReg);
+  if (!SignSchema) {
+    if (CheckMode == PtrauthCheckMode::Trap)
+      EmitCheck();
+    // For authentication-only pseudos, Poison is demoted to Unchecked.
+    return;
+  }
 
-  //  Lend:
-  if (EndSym)
-    OutStreamer->emitLabel(EndSym);
+  switch (CheckMode) {
+  case Unchecked:
+    EmitResignOnSuccess();
+    break;
+  case Trap:
+    EmitCheck();
+    EmitResignOnSuccess();
+    break;
+  case Poison:
+    MCSymbol *OnFailure = createTempSymbol("resign_end_");
+    EmitCheck(OnFailure);
+    EmitResignOnSuccess();
+    OutStreamer->emitLabel(OnFailure);
+    break;
+  }
 }
 
 void AArch64AsmPrinter::emitPtrauthSign(const MachineInstr *MI) {

diff  --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
index 51fb2e1d1f9f0..c3ea54c1dd358 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
@@ -2267,6 +2267,8 @@ let Predicates = [HasPAuth] in {
                (ins i32imm:$AUTKey, i64imm:$AUTDisc, GPR64noip:$AUTAddrDisc,
                     i32imm:$PACKey, i64imm:$PACDisc, GPR64noip:$PACAddrDisc),
                []>, Sched<[WriteI, ReadI]> {
+    // Thanks to its register class, $PACAddrDisc never aliases X16 which is
+    // early-clobbered.
     let isCodeGenOnly = 1;
     let hasSideEffects = 1;
     let mayStore = 0;
@@ -2288,6 +2290,8 @@ let Predicates = [HasPAuth] in {
                (ins i32imm:$AUTKey,
                     i32imm:$PACKey, i64imm:$PACDisc, GPR64noip:$PACAddrDisc),
                []>, Sched<[WriteI, ReadI]> {
+    // Thanks to its register class, $PACAddrDisc never aliases X17 which is
+    // early-clobbered.
     let isCodeGenOnly = 1;
     let hasSideEffects = 1;
     let mayStore = 0;
@@ -2308,6 +2312,8 @@ let Predicates = [HasPAuth] in {
                    i64imm:$Addend),
                []>,
         Sched<[WriteI, ReadI]> {
+    // Thanks to its register class, $PACAddrDisc never aliases X16 which is
+    // early-clobbered.
     let isCodeGenOnly = 1;
     let hasSideEffects = 1;
     let mayStore = 0;

diff  --git a/llvm/test/CodeGen/AArch64/ptrauth-intrinsic-auth-resign-with-blend.ll b/llvm/test/CodeGen/AArch64/ptrauth-intrinsic-auth-resign-with-blend.ll
index a56921d008712..1dea85aba7fa7 100644
--- a/llvm/test/CodeGen/AArch64/ptrauth-intrinsic-auth-resign-with-blend.ll
+++ b/llvm/test/CodeGen/AArch64/ptrauth-intrinsic-auth-resign-with-blend.ll
@@ -1,4 +1,3 @@
-; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
 ; RUN: llc < %s -mtriple arm64e-apple-darwin -global-isel=0                    -verify-machineinstrs \
 ; RUN:   -aarch64-ptrauth-auth-checks=none | FileCheck %s -DL="L" --check-prefixes=UNCHECKED,UNCHECKED-DARWIN
 ; RUN: llc < %s -mtriple arm64e-apple-darwin -global-isel -global-isel-abort=1 -verify-machineinstrs \
@@ -89,12 +88,14 @@ define i64 @test_resign_blend(i64 %arg, i64 %arg1, i64 %arg2) {
 ; UNCHECKED-NEXT:    mov x16, x0
 ; UNCHECKED-ELF-NEXT:    movk x1, #12345, lsl #48
 ; UNCHECKED-ELF-NEXT:    autda x16, x1
+; UNCHECKED-ELF-NEXT:    movk x2, #56789, lsl #48
+; UNCHECKED-ELF-NEXT:    pacdb x16, x2
 ; UNCHECKED-DARWIN-NEXT: mov x17, x1
 ; UNCHECKED-DARWIN-NEXT: movk x17, #12345, lsl #48
 ; UNCHECKED-DARWIN-NEXT: autda x16, x17
-; UNCHECKED-NEXT:    mov x17, x2
-; UNCHECKED-NEXT:    movk x17, #56789, lsl #48
-; UNCHECKED-NEXT:    pacdb x16, x17
+; UNCHECKED-DARWIN-NEXT: mov x17, x2
+; UNCHECKED-DARWIN-NEXT: movk x17, #56789, lsl #48
+; UNCHECKED-DARWIN-NEXT: pacdb x16, x17
 ; UNCHECKED-NEXT:    mov x0, x16
 ; UNCHECKED-NEXT:    ret
 ;
@@ -113,9 +114,11 @@ define i64 @test_resign_blend(i64 %arg, i64 %arg1, i64 %arg2) {
 ; CHECKED-NEXT:    mov x16, x17
 ; CHECKED-NEXT:    b [[L]]resign_end_0
 ; CHECKED-NEXT:  Lauth_success_0:
-; CHECKED-NEXT:    mov x17, x2
-; CHECKED-NEXT:    movk x17, #56789, lsl #48
-; CHECKED-NEXT:    pacdb x16, x17
+; CHECKED-ELF-NEXT:    movk x2, #56789, lsl #48
+; CHECKED-ELF-NEXT:    pacdb x16, x2
+; CHECKED-DARWIN-NEXT: mov x17, x2
+; CHECKED-DARWIN-NEXT: movk x17, #56789, lsl #48
+; CHECKED-DARWIN-NEXT: pacdb x16, x17
 ; CHECKED-NEXT:  Lresign_end_0:
 ; CHECKED-NEXT:    mov x0, x16
 ; CHECKED-NEXT:    ret
@@ -134,9 +137,11 @@ define i64 @test_resign_blend(i64 %arg, i64 %arg1, i64 %arg2) {
 ; TRAP-NEXT:    b.eq [[L]]auth_success_1
 ; TRAP-NEXT:    brk #0xc472
 ; TRAP-NEXT:  Lauth_success_1:
-; TRAP-NEXT:    mov x17, x2
-; TRAP-NEXT:    movk x17, #56789, lsl #48
-; TRAP-NEXT:    pacdb x16, x17
+; TRAP-ELF-NEXT:    movk x2, #56789, lsl #48
+; TRAP-ELF-NEXT:    pacdb x16, x2
+; TRAP-DARWIN-NEXT: mov x17, x2
+; TRAP-DARWIN-NEXT: movk x17, #56789, lsl #48
+; TRAP-DARWIN-NEXT: pacdb x16, x17
 ; TRAP-NEXT:    mov x0, x16
 ; TRAP-NEXT:    ret
   %tmp0 = call i64 @llvm.ptrauth.blend(i64 %arg1, i64 12345)
@@ -326,6 +331,434 @@ some.other.bb:
   ret i64 %authed
 }
 
+define void @test_auth_live_addrdisc(i64 %p, i64 %arg, ptr %out) {
+; UNCHECKED-DARWIN-LABEL: test_auth_live_addrdisc:
+; UNCHECKED-DARWIN:       %bb.0:
+; UNCHECKED-DARWIN-NEXT:    mov     x16, x0
+; UNCHECKED-DARWIN-NEXT:    mov     x17, x1
+; UNCHECKED-DARWIN-NEXT:    movk    x17, #12345, lsl #48
+; UNCHECKED-DARWIN-NEXT:    autda   x16, x17
+; UNCHECKED-DARWIN-NEXT:    str     x16, [x2]
+; UNCHECKED-DARWIN-NEXT:    str     x1, [x2]
+; UNCHECKED-DARWIN-NEXT:    ret
+;
+; UNCHECKED-ELF-LABEL: test_auth_live_addrdisc:
+; UNCHECKED-ELF:       %bb.0:
+; UNCHECKED-ELF-NEXT:    mov     x8, x1
+; UNCHECKED-ELF-NEXT:    movk    x8, #12345, lsl #48
+; UNCHECKED-ELF-NEXT:    autda   x0, x8
+; UNCHECKED-ELF-NEXT:    str     x0, [x2]
+; UNCHECKED-ELF-NEXT:    str     x1, [x2]
+; UNCHECKED-ELF-NEXT:    ret
+;
+; CHECKED-DARWIN-LABEL: test_auth_live_addrdisc:
+; CHECKED-DARWIN:       %bb.0:
+; CHECKED-DARWIN-NEXT:    mov     x16, x0
+; CHECKED-DARWIN-NEXT:    mov     x17, x1
+; CHECKED-DARWIN-NEXT:    movk    x17, #12345, lsl #48
+; CHECKED-DARWIN-NEXT:    autda   x16, x17
+; CHECKED-DARWIN-NEXT:    str     x16, [x2]
+; CHECKED-DARWIN-NEXT:    str     x1, [x2]
+; CHECKED-DARWIN-NEXT:    ret
+;
+; CHECKED-ELF-LABEL: test_auth_live_addrdisc:
+; CHECKED-ELF:       %bb.0:
+; CHECKED-ELF-NEXT:    mov     x8, x1
+; CHECKED-ELF-NEXT:    movk    x8, #12345, lsl #48
+; CHECKED-ELF-NEXT:    autda   x0, x8
+; CHECKED-ELF-NEXT:    str     x0, [x2]
+; CHECKED-ELF-NEXT:    str     x1, [x2]
+; CHECKED-ELF-NEXT:    ret
+;
+; TRAP-DARWIN-LABEL: test_auth_live_addrdisc:
+; TRAP-DARWIN:       %bb.0:
+; TRAP-DARWIN-NEXT:    mov     x16, x0
+; TRAP-DARWIN-NEXT:    mov     x17, x1
+; TRAP-DARWIN-NEXT:    movk    x17, #12345, lsl #48
+; TRAP-DARWIN-NEXT:    autda   x16, x17
+; TRAP-DARWIN-NEXT:    mov     x17, x16
+; TRAP-DARWIN-NEXT:    xpacd   x17
+; TRAP-DARWIN-NEXT:    cmp     x16, x17
+; TRAP-DARWIN-NEXT:    b.eq    [[L]]auth_success_[[N:[0-9]+]]
+; TRAP-DARWIN-NEXT:    brk     #0xc472
+; TRAP-DARWIN-NEXT:  [[L]]auth_success_[[N]]:
+; TRAP-DARWIN-NEXT:    str     x16, [x2]
+; TRAP-DARWIN-NEXT:    str     x1, [x2]
+; TRAP-DARWIN-NEXT:    ret
+;
+; TRAP-ELF-LABEL: test_auth_live_addrdisc:
+; TRAP-ELF:       %bb.0:
+; TRAP-ELF-NEXT:    mov     x8, x1
+; TRAP-ELF-NEXT:    movk    x8, #12345, lsl #48
+; TRAP-ELF-NEXT:    autda   x0, x8
+; TRAP-ELF-NEXT:    mov     x8, x0
+; TRAP-ELF-NEXT:    xpacd   x8
+; TRAP-ELF-NEXT:    cmp     x0, x8
+; TRAP-ELF-NEXT:    b.eq    [[L]]auth_success_[[N:[0-9]+]]
+; TRAP-ELF-NEXT:    brk     #0xc472
+; TRAP-ELF-NEXT:  [[L]]auth_success_[[N]]:
+; TRAP-ELF-NEXT:    str     x0, [x2]
+; TRAP-ELF-NEXT:    str     x1, [x2]
+; TRAP-ELF-NEXT:    ret
+  %auth.disc = call i64 @llvm.ptrauth.blend(i64 %arg, i64 12345)
+  %authed = call i64 @llvm.ptrauth.auth(i64 %p, i32 2, i64 %auth.disc)
+  store volatile i64 %authed, ptr %out
+  store volatile i64 %arg, ptr %out
+  ret void
+}
+
+define void @test_resign_live_autaddrdisc(i64 %p, i64 %auth.arg, i64 %sign.arg, ptr %out) {
+; UNCHECKED-LABEL: test_resign_live_autaddrdisc:
+; UNCHECKED:       %bb.0:
+; UNCHECKED-NEXT:    mov     x16, x0
+; UNCHECKED-NEXT:    mov     x17, x1
+; UNCHECKED-NEXT:    movk    x17, #12345, lsl #48
+; UNCHECKED-NEXT:    autda   x16, x17
+; UNCHECKED-DARWIN-NEXT: mov     x17, x2
+; UNCHECKED-DARWIN-NEXT: movk    x17, #54321, lsl #48
+; UNCHECKED-DARWIN-NEXT: pacdb   x16, x17
+; UNCHECKED-ELF-NEXT:    movk    x2, #54321, lsl #48
+; UNCHECKED-ELF-NEXT:    pacdb   x16, x2
+; UNCHECKED-NEXT:    str     x16, [x3]
+; UNCHECKED-NEXT:    str     x1, [x3]
+; UNCHECKED-NEXT:    ret
+;
+; CHECKED-LABEL: test_resign_live_autaddrdisc:
+; CHECKED:       %bb.0:
+; CHECKED-NEXT:    mov     x16, x0
+; CHECKED-NEXT:    mov     x17, x1
+; CHECKED-NEXT:    movk    x17, #12345, lsl #48
+; CHECKED-NEXT:    autda   x16, x17
+; CHECKED-NEXT:    mov     x17, x16
+; CHECKED-NEXT:    xpacd   x17
+; CHECKED-NEXT:    cmp     x16, x17
+; CHECKED-NEXT:    b.eq    [[L]]auth_success_[[N:[0-9]+]]
+; CHECKED-NEXT:    mov     x16, x17
+; CHECKED-NEXT:    b       [[L]]resign_end_[[N]]
+; CHECKED-NEXT:  [[L]]auth_success_[[N]]:
+; CHECKED-DARWIN-NEXT: mov     x17, x2
+; CHECKED-DARWIN-NEXT: movk    x17, #54321, lsl #48
+; CHECKED-DARWIN-NEXT: pacdb   x16, x17
+; CHECKED-ELF-NEXT:    movk    x2, #54321, lsl #48
+; CHECKED-ELF-NEXT:    pacdb   x16, x2
+; CHECKED-NEXT:  [[L]]resign_end_[[N]]:
+; CHECKED-NEXT:    str     x16, [x3]
+; CHECKED-NEXT:    str     x1, [x3]
+; CHECKED-NEXT:    ret
+;
+; TRAP-LABEL: test_resign_live_autaddrdisc:
+; TRAP:       %bb.0:
+; TRAP-NEXT:    mov     x16, x0
+; TRAP-NEXT:    mov     x17, x1
+; TRAP-NEXT:    movk    x17, #12345, lsl #48
+; TRAP-NEXT:    autda   x16, x17
+; TRAP-NEXT:    mov     x17, x16
+; TRAP-NEXT:    xpacd   x17
+; TRAP-NEXT:    cmp     x16, x17
+; TRAP-NEXT:    b.eq    [[L]]auth_success_[[N:[0-9]+]]
+; TRAP-NEXT:    brk     #0xc472
+; TRAP-NEXT:  [[L]]auth_success_[[N]]:
+; TRAP-DARWIN-NEXT: mov     x17, x2
+; TRAP-DARWIN-NEXT: movk    x17, #54321, lsl #48
+; TRAP-DARWIN-NEXT: pacdb   x16, x17
+; TRAP-ELF-NEXT:    movk    x2, #54321, lsl #48
+; TRAP-ELF-NEXT:    pacdb   x16, x2
+; TRAP-NEXT:    str     x16, [x3]
+; TRAP-NEXT:    str     x1, [x3]
+; TRAP-NEXT:    ret
+  %auth.disc = call i64 @llvm.ptrauth.blend(i64 %auth.arg, i64 12345)
+  %sign.disc = call i64 @llvm.ptrauth.blend(i64 %sign.arg, i64 54321)
+  %resigned = call i64 @llvm.ptrauth.resign(i64 %p, i32 2, i64 %auth.disc, i32 3, i64 %sign.disc)
+  store volatile i64 %resigned, ptr %out
+  store volatile i64 %auth.arg, ptr %out
+  ret void
+}
+
+define void @test_resign_live_pacaddrdisc(i64 %p, i64 %auth.arg, i64 %sign.arg, ptr %out) {
+; UNCHECKED-LABEL: test_resign_live_pacaddrdisc:
+; UNCHECKED:       %bb.0:
+; UNCHECKED-NEXT:    mov     x16, x0
+; UNCHECKED-DARWIN-NEXT: mov     x17, x1
+; UNCHECKED-DARWIN-NEXT: movk    x17, #12345, lsl #48
+; UNCHECKED-DARWIN-NEXT: autda   x16, x17
+; UNCHECKED-ELF-NEXT:    movk    x1, #12345, lsl #48
+; UNCHECKED-ELF-NEXT:    autda   x16, x1
+; UNCHECKED-NEXT:    mov     x17, x2
+; UNCHECKED-NEXT:    movk    x17, #54321, lsl #48
+; UNCHECKED-NEXT:    pacdb   x16, x17
+; UNCHECKED-NEXT:    str     x16, [x3]
+; UNCHECKED-NEXT:    str     x2, [x3]
+; UNCHECKED-NEXT:    ret
+;
+; CHECKED-LABEL: test_resign_live_pacaddrdisc:
+; CHECKED:       %bb.0:
+; CHECKED-NEXT:    mov     x16, x0
+; CHECKED-DARWIN-NEXT: mov     x17, x1
+; CHECKED-DARWIN-NEXT: movk    x17, #12345, lsl #48
+; CHECKED-DARWIN-NEXT: autda   x16, x17
+; CHECKED-ELF-NEXT:    movk    x1, #12345, lsl #48
+; CHECKED-ELF-NEXT:    autda   x16, x1
+; CHECKED-NEXT:    mov     x17, x16
+; CHECKED-NEXT:    xpacd   x17
+; CHECKED-NEXT:    cmp     x16, x17
+; CHECKED-NEXT:    b.eq    [[L]]auth_success_[[N:[0-9]+]]
+; CHECKED-NEXT:    mov     x16, x17
+; CHECKED-NEXT:    b       [[L]]resign_end_[[N]]
+; CHECKED-NEXT:  [[L]]auth_success_[[N]]:
+; CHECKED-NEXT:    mov     x17, x2
+; CHECKED-NEXT:    movk    x17, #54321, lsl #48
+; CHECKED-NEXT:    pacdb   x16, x17
+; CHECKED-NEXT:  [[L]]resign_end_[[N]]:
+; CHECKED-NEXT:    str     x16, [x3]
+; CHECKED-NEXT:    str     x2, [x3]
+; CHECKED-NEXT:    ret
+;
+; TRAP-LABEL: test_resign_live_pacaddrdisc:
+; TRAP:       %bb.0:
+; TRAP-NEXT:    mov     x16, x0
+; TRAP-DARWIN-NEXT: mov     x17, x1
+; TRAP-DARWIN-NEXT: movk    x17, #12345, lsl #48
+; TRAP-DARWIN-NEXT: autda   x16, x17
+; TRAP-ELF-NEXT:    movk    x1, #12345, lsl #48
+; TRAP-ELF-NEXT:    autda   x16, x1
+; TRAP-NEXT:    mov     x17, x16
+; TRAP-NEXT:    xpacd   x17
+; TRAP-NEXT:    cmp     x16, x17
+; TRAP-NEXT:    b.eq    [[L]]auth_success_[[N:[0-9]+]]
+; TRAP-NEXT:    brk     #0xc472
+; TRAP-NEXT:  [[L]]auth_success_[[N]]:
+; TRAP-NEXT:    mov     x17, x2
+; TRAP-NEXT:    movk    x17, #54321, lsl #48
+; TRAP-NEXT:    pacdb   x16, x17
+; TRAP-NEXT:    str     x16, [x3]
+; TRAP-NEXT:    str     x2, [x3]
+; TRAP-NEXT:    ret
+  %auth.disc = call i64 @llvm.ptrauth.blend(i64 %auth.arg, i64 12345)
+  %sign.disc = call i64 @llvm.ptrauth.blend(i64 %sign.arg, i64 54321)
+  %resigned = call i64 @llvm.ptrauth.resign(i64 %p, i32 2, i64 %auth.disc, i32 3, i64 %sign.disc)
+  store volatile i64 %resigned, ptr %out
+  store volatile i64 %sign.arg, ptr %out
+  ret void
+}
+
+; As long as we support raw, non-blended 64-bit discriminators (which might be
+; useful for low-level code such as dynamic loaders), the "auth" part of resign
+; must not clobber %arg, if its upper bits are later used by the "sign" part.
+define i64 @test_resign_aliased_discs_raw_sign_disc(i64 %p, i64 %arg) {
+; UNCHECKED-LABEL: test_resign_aliased_discs_raw_sign_disc:
+; UNCHECKED:       %bb.0:
+; UNCHECKED-NEXT:    mov x16, x0
+; UNCHECKED-NEXT:    mov  x17, x1
+; UNCHECKED-NEXT:    movk x17, #12345, lsl #48
+; UNCHECKED-NEXT:    autda x16, x17
+; UNCHECKED-NEXT:    pacdb x16, x1
+; UNCHECKED-NEXT:    mov x0, x16
+; UNCHECKED-NEXT:    ret
+;
+; CHECKED-LABEL: test_resign_aliased_discs_raw_sign_disc:
+; CHECKED:       %bb.0:
+; CHECKED-NEXT:    mov x16, x0
+; CHECKED-NEXT:    mov  x17, x1
+; CHECKED-NEXT:    movk x17, #12345, lsl #48
+; CHECKED-NEXT:    autda x16, x17
+; CHECKED-NEXT:    mov x17, x16
+; CHECKED-NEXT:    xpacd x17
+; CHECKED-NEXT:    cmp x16, x17
+; CHECKED-NEXT:    b.eq [[L]]auth_success_[[N:[0-9]+]]
+; CHECKED-NEXT:    mov x16, x17
+; CHECKED-NEXT:    b [[L]]resign_end_[[N]]
+; CHECKED-NEXT:  Lauth_success_[[N]]:
+; CHECKED-NEXT:    pacdb x16, x1
+; CHECKED-NEXT:  Lresign_end_[[N]]:
+; CHECKED-NEXT:    mov x0, x16
+; CHECKED-NEXT:    ret
+;
+; TRAP-LABEL: test_resign_aliased_discs_raw_sign_disc:
+; TRAP:       %bb.0:
+; TRAP-NEXT:    mov x16, x0
+; TRAP-NEXT:    mov  x17, x1
+; TRAP-NEXT:    movk x17, #12345, lsl #48
+; TRAP-NEXT:    autda x16, x17
+; TRAP-NEXT:    mov x17, x16
+; TRAP-NEXT:    xpacd x17
+; TRAP-NEXT:    cmp x16, x17
+; TRAP-NEXT:    b.eq [[L]]auth_success_[[N:[0-9]+]]
+; TRAP-NEXT:    brk #0xc472
+; TRAP-NEXT:  Lauth_success_[[N]]:
+; TRAP-NEXT:    pacdb x16, x1
+; TRAP-NEXT:    mov x0, x16
+; TRAP-NEXT:    ret
+  %auth.disc = call i64 @llvm.ptrauth.blend(i64 %arg, i64 12345)
+  %res = call i64 @llvm.ptrauth.resign(i64 %p, i32 2, i64 %auth.disc, i32 3, i64 %arg)
+  ret i64 %res
+}
+
+; The following are rather obscure corner cases of computing the discriminator
+; by blending the pointer-in-question itself as the address modifier.
+; For the sake of brevity, just check which registers are used to compute the
+; discriminators.
+;
+; Note: common logic in AArch64AsmPrinter handles $AUTAddrDisc, but $PACAddrDisc
+; must be described appropriately in AArch64InstrInfo.td for each pseudo
+; instruction to prevent aliasing with the pointer.
+
+define i64 @test_auth_pointer_aliased_with_addrdisc(i64 %p) {
+; UNCHECKED-DARWIN-LABEL: test_auth_pointer_aliased_with_addrdisc:
+; UNCHECKED-DARWIN:       %bb.0:
+; UNCHECKED-DARWIN-NEXT:    mov  x16, x0
+; UNCHECKED-DARWIN-NEXT:    mov  x17, x0
+; UNCHECKED-DARWIN-NEXT:    movk x17, #12345, lsl #48
+; UNCHECKED-DARWIN-NEXT:    autda x16, x17
+; UNCHECKED-DARWIN-NEXT:    mov   x0, x16
+; UNCHECKED-DARWIN-NEXT:    ret
+;
+; UNCHECKED-ELF-LABEL: test_auth_pointer_aliased_with_addrdisc:
+; UNCHECKED-ELF:       %bb.0:
+; UNCHECKED-ELF-NEXT:    mov  x8, x0
+; UNCHECKED-ELF-NEXT:    movk x8, #12345, lsl #48
+; UNCHECKED-ELF-NEXT:    autda x0, x8
+; UNCHECKED-ELF-NEXT:    ret
+  %disc = call i64 @llvm.ptrauth.blend(i64 %p, i64 12345)
+  %res = call i64 @llvm.ptrauth.auth(i64 %p, i32 2, i64 %disc)
+  ret i64 %res
+}
+
+define i64 @test_resign_pointer_aliased_with_autaddrdisc(i64 %p, i64 %arg) {
+; UNCHECKED-DARWIN-LABEL: test_resign_pointer_aliased_with_autaddrdisc:
+; UNCHECKED-DARWIN:       %bb.0:
+; UNCHECKED-DARWIN-NEXT:    mov  x16, x0
+; UNCHECKED-DARWIN-NEXT:    mov  x17, x0
+; UNCHECKED-DARWIN-NEXT:    movk x17, #12345, lsl #48
+; UNCHECKED-DARWIN-NEXT:    autda x16, x17
+; UNCHECKED-DARWIN-NEXT:    mov  x17, x1
+; UNCHECKED-DARWIN-NEXT:    movk x17, #54321, lsl #48
+; UNCHECKED-DARWIN-NEXT:    pacdb x16, x17
+; UNCHECKED-DARWIN-NEXT:    mov x0, x16
+; UNCHECKED-DARWIN-NEXT:    ret
+;
+; UNCHECKED-ELF-LABEL: test_resign_pointer_aliased_with_autaddrdisc:
+; UNCHECKED-ELF:       %bb.0:
+; UNCHECKED-ELF-NEXT:    mov  x16, x0
+; UNCHECKED-ELF-NEXT:    movk x0, #12345, lsl #48
+; UNCHECKED-ELF-NEXT:    autda x16, x0
+; UNCHECKED-ELF-NEXT:    movk x1, #54321, lsl #48
+; UNCHECKED-ELF-NEXT:    pacdb x16, x1
+; UNCHECKED-ELF-NEXT:    mov x0, x16
+; UNCHECKED-ELF-NEXT:    ret
+  %auth.disc = call i64 @llvm.ptrauth.blend(i64 %p,   i64 12345)
+  %sign.disc = call i64 @llvm.ptrauth.blend(i64 %arg, i64 54321)
+  %res = call i64 @llvm.ptrauth.resign(i64 %p, i32 2, i64 %auth.disc, i32 3, i64 %sign.disc)
+  ret i64 %res
+}
+
+define i64 @test_resign_pointer_aliased_with_pacaddrdisc(i64 %p, i64 %arg) {
+; UNCHECKED-DARWIN-LABEL: test_resign_pointer_aliased_with_pacaddrdisc:
+; UNCHECKED-DARWIN:       %bb.0:
+; UNCHECKED-DARWIN-NEXT:    mov x16, x0
+; UNCHECKED-DARWIN-NEXT:    mov  x17, x1
+; UNCHECKED-DARWIN-NEXT:    movk x17, #12345, lsl #48
+; UNCHECKED-DARWIN-NEXT:    autda x16, x17
+; UNCHECKED-DARWIN-NEXT:    mov  x17, x0
+; UNCHECKED-DARWIN-NEXT:    movk x17, #54321, lsl #48
+; UNCHECKED-DARWIN-NEXT:    pacdb x16, x17
+; UNCHECKED-DARWIN-NEXT:    mov x0, x16
+; UNCHECKED-DARWIN-NEXT:    ret
+;
+
+; UNCHECKED-ELF-LABEL: test_resign_pointer_aliased_with_pacaddrdisc:
+; UNCHECKED-ELF:       %bb.0:
+; UNCHECKED-ELF-NEXT:    mov x16, x0
+; UNCHECKED-ELF-NEXT:    movk x1, #12345, lsl #48
+; UNCHECKED-ELF-NEXT:    autda x16, x1
+; UNCHECKED-ELF-NEXT:    movk x0, #54321, lsl #48
+; UNCHECKED-ELF-NEXT:    pacdb x16, x0
+; UNCHECKED-ELF-NEXT:    mov x0, x16
+; UNCHECKED-ELF-NEXT:    ret
+  %auth.disc = call i64 @llvm.ptrauth.blend(i64 %arg, i64 12345)
+  %sign.disc = call i64 @llvm.ptrauth.blend(i64 %p,   i64 54321)
+  %res = call i64 @llvm.ptrauth.resign(i64 %p, i32 2, i64 %auth.disc, i32 3, i64 %sign.disc)
+  ret i64 %res
+}
+
+define i64 @test_resign_pointer_aliased_with_both_addrdisc(i64 %p) {
+; UNCHECKED-LABEL: test_resign_pointer_aliased_with_both_addrdisc:
+; UNCHECKED:       %bb.0:
+; UNCHECKED-NEXT:    mov  x16, x0
+; UNCHECKED-NEXT:    mov  x17, x0
+; UNCHECKED-NEXT:    movk x17, #12345, lsl #48
+; UNCHECKED-NEXT:    autda x16, x17
+; UNCHECKED-NEXT:    mov  x17, x0
+; UNCHECKED-NEXT:    movk x17, #54321, lsl #48
+; UNCHECKED-NEXT:    pacdb x16, x17
+; UNCHECKED-NEXT:    mov x0, x16
+; UNCHECKED-NEXT:    ret
+  %auth.disc = call i64 @llvm.ptrauth.blend(i64 %p, i64 12345)
+  %sign.disc = call i64 @llvm.ptrauth.blend(i64 %p, i64 54321)
+  %res = call i64 @llvm.ptrauth.resign(i64 %p, i32 2, i64 %auth.disc, i32 3, i64 %sign.disc)
+  ret i64 %res
+}
+
+define i64 @test_autpcpac_pointer_aliased_with_pacaddrdisc(i64 %p, i64 %arg, i64 %auth.pc) {
+; UNCHECKED-DARWIN-LABEL: test_autpcpac_pointer_aliased_with_pacaddrdisc:
+; UNCHECKED-DARWIN:       %bb.0:
+; UNCHECKED-DARWIN-NEXT:    mov  x17, x0
+; UNCHECKED-DARWIN-NEXT:    mov  x16, x1
+; UNCHECKED-DARWIN-NEXT:    mov  x15, x2
+; UNCHECKED-DARWIN-NEXT:    autia171615
+; UNCHECKED-DARWIN-NEXT:    mov  x16, x0
+; UNCHECKED-DARWIN-NEXT:    movk x16, #54321, lsl #48
+; UNCHECKED-DARWIN-NEXT:    pacib x17, x16
+; UNCHECKED-DARWIN-NEXT:    mov x0, x17
+; UNCHECKED-DARWIN-NEXT:    ret
+;
+; UNCHECKED-ELF-LABEL: test_autpcpac_pointer_aliased_with_pacaddrdisc:
+; UNCHECKED-ELF:       %bb.0:
+; UNCHECKED-ELF-NEXT:    mov  x17, x0
+; UNCHECKED-ELF-NEXT:    mov  x16, x1
+; UNCHECKED-ELF-NEXT:    mov  x15, x2
+; UNCHECKED-ELF-NEXT:    autia171615
+; UNCHECKED-ELF-NEXT:    movk x0, #54321, lsl #48
+; UNCHECKED-ELF-NEXT:    pacib x17, x0
+; UNCHECKED-ELF-NEXT:    mov x0, x17
+; UNCHECKED-ELF-NEXT:    ret
+  %sign.disc = call i64 @llvm.ptrauth.blend(i64 %p, i64 54321)
+  %res = call i64 @llvm.ptrauth.auth.with.pc.and.resign(i64 %p, i32 0, i64 %arg, i64 %auth.pc, i32 1, i64 %sign.disc)
+  ret i64 %res
+}
+
+define i64 @test_autrelloadpac_pointer_aliased_with_pacaddrdisc(i64 %p, i64 %arg) {
+; UNCHECKED-DARWIN-LABEL: test_autrelloadpac_pointer_aliased_with_pacaddrdisc:
+; UNCHECKED-DARWIN:       %bb.0:
+; UNCHECKED-DARWIN-NEXT:    mov  x16, x0
+; UNCHECKED-DARWIN-NEXT:    mov  x17, x1
+; UNCHECKED-DARWIN-NEXT:    movk x17, #12345, lsl #48
+; UNCHECKED-DARWIN-NEXT:    autda x16, x17
+; UNCHECKED-DARWIN-NEXT:    ldrsw x17, [x16, #8]!
+; UNCHECKED-DARWIN-NEXT:    add   x16, x16, x17
+; UNCHECKED-DARWIN-NEXT:    mov  x17, x0
+; UNCHECKED-DARWIN-NEXT:    movk x17, #54321, lsl #48
+; UNCHECKED-DARWIN-NEXT:    pacdb x16, x17
+; UNCHECKED-DARWIN-NEXT:    mov x0, x16
+; UNCHECKED-DARWIN-NEXT:    ret
+;
+
+; UNCHECKED-ELF-LABEL: test_autrelloadpac_pointer_aliased_with_pacaddrdisc:
+; UNCHECKED-ELF:       %bb.0:
+; UNCHECKED-ELF-NEXT:    mov  x16, x0
+; UNCHECKED-ELF-NEXT:    movk x1, #12345, lsl #48
+; UNCHECKED-ELF-NEXT:    autda x16, x1
+; UNCHECKED-ELF-NEXT:    ldrsw x17, [x16, #8]!
+; UNCHECKED-ELF-NEXT:    add   x16, x16, x17
+; UNCHECKED-ELF-NEXT:    movk x0, #54321, lsl #48
+; UNCHECKED-ELF-NEXT:    pacdb x16, x0
+; UNCHECKED-ELF-NEXT:    mov x0, x16
+; UNCHECKED-ELF-NEXT:    ret
+  %auth.disc = call i64 @llvm.ptrauth.blend(i64 %arg, i64 12345)
+  %sign.disc = call i64 @llvm.ptrauth.blend(i64 %p,   i64 54321)
+  %res = call i64 @llvm.ptrauth.resign.load.relative(i64 %p, i32 2, i64 %auth.disc, i32 3, i64 %sign.disc, i64 8)
+  ret i64 %res
+}
+
 declare i64 @llvm.ptrauth.auth(i64, i32, i64)
 declare i64 @llvm.ptrauth.resign(i64, i32, i64, i32, i64)
 declare i64 @llvm.ptrauth.blend(i64, i64)


        


More information about the llvm-commits mailing list