[llvm-branch-commits] [llvm] [AArch64][PAC] Factor out printing real AUT/PAC/BLRA encodings (NFC) (PR #160901)
Anatoly Trosinenko via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Thu Dec 4 09:52:36 PST 2025
https://github.com/atrosinenko updated https://github.com/llvm/llvm-project/pull/160901
>From ce51a40dbff39fdca481ee9818ef34a9349b13de Mon Sep 17 00:00:00 2001
From: Anatoly Trosinenko <atrosinenko at accesssoftek.com>
Date: Thu, 25 Sep 2025 16:33:04 +0300
Subject: [PATCH 1/2] [AArch64][PAC] Factor out printing real AUT/PAC/BLRA
encodings (NFC)
Separate the low-level emission of the appropriate variants of `AUT*`,
`PAC*` and `B(L)RA*` instructions from the high-level logic of pseudo
instruction expansion.
Introduce `getBranchOpcodeForKey` helper function by analogy to
`get(AUT|PAC)OpcodeForKey`.
---
llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp | 176 +++++++-----------
llvm/lib/Target/AArch64/AArch64InstrInfo.h | 18 ++
2 files changed, 89 insertions(+), 105 deletions(-)
diff --git a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
index 7f1d331982bc2..eee35ba29dd86 100644
--- a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
+++ b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
@@ -331,6 +331,11 @@ class AArch64AsmPrinter : public AsmPrinter {
void emitMOVZ(Register Dest, uint64_t Imm, unsigned Shift);
void emitMOVK(Register Dest, uint64_t Imm, unsigned Shift);
+ void emitAUT(AArch64PACKey::ID Key, Register Pointer, Register Disc);
+ void emitPAC(AArch64PACKey::ID Key, Register Pointer, Register Disc);
+ void emitBLRA(bool IsCall, AArch64PACKey::ID Key, Register Target,
+ Register Disc);
+
/// Emit instruction to set float register to zero.
void emitFMov0(const MachineInstr &MI);
void emitFMov0AsFMov(const MachineInstr &MI, Register DestReg);
@@ -1852,6 +1857,55 @@ void AArch64AsmPrinter::emitMOVK(Register Dest, uint64_t Imm, unsigned Shift) {
.addImm(Shift));
}
+void AArch64AsmPrinter::emitAUT(AArch64PACKey::ID Key, Register Pointer,
+ Register Disc) {
+ bool IsZeroDisc = Disc == AArch64::XZR;
+ unsigned Opcode = getAUTOpcodeForKey(Key, IsZeroDisc);
+
+ // autiza x16 ; if IsZeroDisc
+ // autia x16, x17 ; if !IsZeroDisc
+ MCInst AUTInst;
+ AUTInst.setOpcode(Opcode);
+ AUTInst.addOperand(MCOperand::createReg(Pointer));
+ AUTInst.addOperand(MCOperand::createReg(Pointer));
+ if (!IsZeroDisc)
+ AUTInst.addOperand(MCOperand::createReg(Disc));
+
+ EmitToStreamer(AUTInst);
+}
+
+void AArch64AsmPrinter::emitPAC(AArch64PACKey::ID Key, Register Pointer,
+ Register Disc) {
+ bool IsZeroDisc = Disc == AArch64::XZR;
+ unsigned Opcode = getPACOpcodeForKey(Key, IsZeroDisc);
+
+ // paciza x16 ; if IsZeroDisc
+ // pacia x16, x17 ; if !IsZeroDisc
+ MCInst PACInst;
+ PACInst.setOpcode(Opcode);
+ PACInst.addOperand(MCOperand::createReg(Pointer));
+ PACInst.addOperand(MCOperand::createReg(Pointer));
+ if (!IsZeroDisc)
+ PACInst.addOperand(MCOperand::createReg(Disc));
+
+ EmitToStreamer(PACInst);
+}
+
+void AArch64AsmPrinter::emitBLRA(bool IsCall, AArch64PACKey::ID Key,
+ Register Target, Register Disc) {
+ bool IsZeroDisc = Disc == AArch64::XZR;
+ unsigned Opcode = getBranchOpcodeForKey(IsCall, Key, IsZeroDisc);
+
+ // blraaz x16 ; if IsZeroDisc
+ // blraa x16, x17 ; if !IsZeroDisc
+ MCInst Inst;
+ Inst.setOpcode(Opcode);
+ Inst.addOperand(MCOperand::createReg(Target));
+ if (!IsZeroDisc)
+ Inst.addOperand(MCOperand::createReg(Disc));
+ EmitToStreamer(Inst);
+}
+
void AArch64AsmPrinter::emitFMov0(const MachineInstr &MI) {
Register DestReg = MI.getOperand(0).getReg();
if (!STI->hasZeroCycleZeroingFPWorkaround() && STI->isNeonAvailable()) {
@@ -2200,20 +2254,9 @@ void AArch64AsmPrinter::emitPtrauthAuthResign(
// Compute aut discriminator
Register AUTDiscReg = emitPtrauthDiscriminator(
AUTDisc, AUTAddrDisc->getReg(), Scratch, AUTAddrDisc->isKill());
- bool AUTZero = AUTDiscReg == AArch64::XZR;
- unsigned AUTOpc = getAUTOpcodeForKey(AUTKey, AUTZero);
- if (!emitDeactivationSymbolRelocation(DS)) {
- // autiza x16 ; if AUTZero
- // autia x16, x17 ; if !AUTZero
- MCInst AUTInst;
- AUTInst.setOpcode(AUTOpc);
- AUTInst.addOperand(MCOperand::createReg(AUTVal));
- AUTInst.addOperand(MCOperand::createReg(AUTVal));
- if (!AUTZero)
- AUTInst.addOperand(MCOperand::createReg(AUTDiscReg));
- EmitToStreamer(*OutStreamer, AUTInst);
- }
+ if (!emitDeactivationSymbolRelocation(DS))
+ emitAUT(AUTKey, AUTVal, AUTDiscReg);
// Unchecked or checked-but-non-trapping AUT is just an "AUT": we're done.
if (!IsAUTPAC && (!ShouldCheck || !ShouldTrap))
@@ -2236,20 +2279,8 @@ void AArch64AsmPrinter::emitPtrauthAuthResign(
return;
// Compute pac discriminator
- Register PACDiscReg =
- emitPtrauthDiscriminator(PACDisc, PACAddrDisc, Scratch);
- bool PACZero = PACDiscReg == AArch64::XZR;
- unsigned PACOpc = getPACOpcodeForKey(*PACKey, PACZero);
-
- // pacizb x16 ; if PACZero
- // pacib x16, x17 ; if !PACZero
- MCInst PACInst;
- PACInst.setOpcode(PACOpc);
- PACInst.addOperand(MCOperand::createReg(AUTVal));
- PACInst.addOperand(MCOperand::createReg(AUTVal));
- if (!PACZero)
- PACInst.addOperand(MCOperand::createReg(PACDiscReg));
- EmitToStreamer(*OutStreamer, PACInst);
+ Register PACDiscReg = emitPtrauthDiscriminator(PACDisc, PACAddrDisc, Scratch);
+ emitPAC(*PACKey, AUTVal, PACDiscReg);
// Lend:
if (EndSym)
@@ -2272,21 +2303,11 @@ void AArch64AsmPrinter::emitPtrauthSign(const MachineInstr *MI) {
// Compute pac discriminator
Register DiscReg = emitPtrauthDiscriminator(
Disc, AddrDisc, ScratchReg, /*MayClobberAddrDisc=*/AddrDiscKilled);
- bool IsZeroDisc = DiscReg == AArch64::XZR;
- unsigned Opc = getPACOpcodeForKey(Key, IsZeroDisc);
if (emitDeactivationSymbolRelocation(MI->getDeactivationSymbol()))
return;
- // paciza x16 ; if IsZeroDisc
- // pacia x16, x17 ; if !IsZeroDisc
- MCInst PACInst;
- PACInst.setOpcode(Opc);
- PACInst.addOperand(MCOperand::createReg(Val));
- PACInst.addOperand(MCOperand::createReg(Val));
- if (!IsZeroDisc)
- PACInst.addOperand(MCOperand::createReg(DiscReg));
- EmitToStreamer(*OutStreamer, PACInst);
+ emitPAC(Key, Val, DiscReg);
}
void AArch64AsmPrinter::emitPtrauthBranch(const MachineInstr *MI) {
@@ -2294,9 +2315,6 @@ void AArch64AsmPrinter::emitPtrauthBranch(const MachineInstr *MI) {
unsigned BrTarget = MI->getOperand(0).getReg();
auto Key = (AArch64PACKey::ID)MI->getOperand(1).getImm();
- assert((Key == AArch64PACKey::IA || Key == AArch64PACKey::IB) &&
- "Invalid auth call key");
-
uint64_t Disc = MI->getOperand(2).getImm();
unsigned AddrDisc = MI->getOperand(3).getReg();
@@ -2326,27 +2344,7 @@ void AArch64AsmPrinter::emitPtrauthBranch(const MachineInstr *MI) {
IsCall && (AddrDisc == AArch64::X16 || AddrDisc == AArch64::X17);
Register DiscReg = emitPtrauthDiscriminator(Disc, AddrDisc, AArch64::X17,
AddrDiscIsImplicitDef);
- bool IsZeroDisc = DiscReg == AArch64::XZR;
-
- unsigned Opc;
- if (IsCall) {
- if (Key == AArch64PACKey::IA)
- Opc = IsZeroDisc ? AArch64::BLRAAZ : AArch64::BLRAA;
- else
- Opc = IsZeroDisc ? AArch64::BLRABZ : AArch64::BLRAB;
- } else {
- if (Key == AArch64PACKey::IA)
- Opc = IsZeroDisc ? AArch64::BRAAZ : AArch64::BRAA;
- else
- Opc = IsZeroDisc ? AArch64::BRABZ : AArch64::BRAB;
- }
-
- MCInst BRInst;
- BRInst.setOpcode(Opc);
- BRInst.addOperand(MCOperand::createReg(BrTarget));
- if (!IsZeroDisc)
- BRInst.addOperand(MCOperand::createReg(DiscReg));
- EmitToStreamer(*OutStreamer, BRInst);
+ emitBLRA(IsCall, Key, BrTarget, DiscReg);
}
static void emitAddress(MCStreamer &Streamer, MCRegister Reg,
@@ -2771,22 +2769,14 @@ void AArch64AsmPrinter::LowerMOVaddrPAC(const MachineInstr &MI) {
assert(GAOp.isGlobal());
assert(GAOp.getGlobal()->getValueType() != nullptr);
- unsigned AuthOpcode = GAOp.getGlobal()->getValueType()->isFunctionTy()
- ? AArch64::AUTIA
- : AArch64::AUTDA;
-
- EmitToStreamer(MCInstBuilder(AuthOpcode)
- .addReg(AArch64::X16)
- .addReg(AArch64::X16)
- .addReg(AArch64::X17));
- if (!STI->hasFPAC()) {
- auto AuthKey = (AuthOpcode == AArch64::AUTIA ? AArch64PACKey::IA
- : AArch64PACKey::DA);
+ bool IsFunctionTy = GAOp.getGlobal()->getValueType()->isFunctionTy();
+ auto AuthKey = IsFunctionTy ? AArch64PACKey::IA : AArch64PACKey::DA;
+ emitAUT(AuthKey, AArch64::X16, AArch64::X17);
+ if (!STI->hasFPAC())
emitPtrauthCheckAuthenticatedValue(AArch64::X16, AArch64::X17, AuthKey,
AArch64PAuth::AuthCheckMethod::XPAC);
- }
} else {
EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
.addReg(AArch64::X16)
@@ -2843,12 +2833,7 @@ void AArch64AsmPrinter::LowerMOVaddrPAC(const MachineInstr &MI) {
Register DiscReg = emitPtrauthDiscriminator(Disc, AddrDisc, AArch64::X17);
- auto MIB = MCInstBuilder(getPACOpcodeForKey(Key, DiscReg == AArch64::XZR))
- .addReg(AArch64::X16)
- .addReg(AArch64::X16);
- if (DiscReg != AArch64::XZR)
- MIB.addReg(DiscReg);
- EmitToStreamer(MIB);
+ emitPAC(Key, AArch64::X16, DiscReg);
}
void AArch64AsmPrinter::LowerLOADgotAUTH(const MachineInstr &MI) {
@@ -2902,21 +2887,15 @@ void AArch64AsmPrinter::LowerLOADgotAUTH(const MachineInstr &MI) {
}
assert(GAMO.getGlobal()->getValueType() != nullptr);
- unsigned AuthOpcode = GAMO.getGlobal()->getValueType()->isFunctionTy()
- ? AArch64::AUTIA
- : AArch64::AUTDA;
- EmitToStreamer(MCInstBuilder(AuthOpcode)
- .addReg(AuthResultReg)
- .addReg(AuthResultReg)
- .addReg(AArch64::X17));
+
+ bool IsFunctionTy = GAMO.getGlobal()->getValueType()->isFunctionTy();
+ auto AuthKey = IsFunctionTy ? AArch64PACKey::IA : AArch64PACKey::DA;
+ emitAUT(AuthKey, AuthResultReg, AArch64::X17);
if (GAMO.getGlobal()->hasExternalWeakLinkage())
OutStreamer->emitLabel(UndefWeakSym);
if (!STI->hasFPAC()) {
- auto AuthKey =
- (AuthOpcode == AArch64::AUTIA ? AArch64PACKey::IA : AArch64PACKey::DA);
-
emitPtrauthCheckAuthenticatedValue(AuthResultReg, AArch64::X17, AuthKey,
AArch64PAuth::AuthCheckMethod::XPAC);
@@ -3269,10 +3248,7 @@ void AArch64AsmPrinter::emitInstruction(const MachineInstr *MI) {
case AArch64::AUTH_TCRETURN:
case AArch64::AUTH_TCRETURN_BTI: {
Register Callee = MI->getOperand(0).getReg();
- const uint64_t Key = MI->getOperand(2).getImm();
- assert((Key == AArch64PACKey::IA || Key == AArch64PACKey::IB) &&
- "Invalid auth key for tail-call return");
-
+ const auto Key = (AArch64PACKey::ID)MI->getOperand(2).getImm();
const uint64_t Disc = MI->getOperand(3).getImm();
Register AddrDisc = MI->getOperand(4).getReg();
@@ -3293,17 +3269,7 @@ void AArch64AsmPrinter::emitInstruction(const MachineInstr *MI) {
AddrDisc == AArch64::X16 || AddrDisc == AArch64::X17;
Register DiscReg = emitPtrauthDiscriminator(Disc, AddrDisc, ScratchReg,
AddrDiscIsImplicitDef);
-
- const bool IsZero = DiscReg == AArch64::XZR;
- const unsigned Opcodes[2][2] = {{AArch64::BRAA, AArch64::BRAAZ},
- {AArch64::BRAB, AArch64::BRABZ}};
-
- MCInst TmpInst;
- TmpInst.setOpcode(Opcodes[Key][IsZero]);
- TmpInst.addOperand(MCOperand::createReg(Callee));
- if (!IsZero)
- TmpInst.addOperand(MCOperand::createReg(DiscReg));
- EmitToStreamer(*OutStreamer, TmpInst);
+ emitBLRA(/*IsCall*/ false, Key, Callee, DiscReg);
return;
}
diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.h b/llvm/lib/Target/AArch64/AArch64InstrInfo.h
index 2de2e0d73901f..8cdb778360a8b 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.h
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.h
@@ -806,6 +806,24 @@ static inline unsigned getPACOpcodeForKey(AArch64PACKey::ID K, bool Zero) {
llvm_unreachable("Unhandled AArch64PACKey::ID enum");
}
+static inline unsigned getBranchOpcodeForKey(bool IsCall, AArch64PACKey::ID K,
+ bool Zero) {
+ using namespace AArch64PACKey;
+ static const unsigned BranchOpcode[2][2] = {
+ {AArch64::BRAA, AArch64::BRAAZ},
+ {AArch64::BRAB, AArch64::BRABZ},
+ };
+ static const unsigned CallOpcode[2][2] = {
+ {AArch64::BLRAA, AArch64::BLRAAZ},
+ {AArch64::BLRAB, AArch64::BLRABZ},
+ };
+
+ assert((K == IA || K == IB) && "I-key expected");
+ if (IsCall)
+ return CallOpcode[K == IB][Zero];
+ return BranchOpcode[K == IB][Zero];
+}
+
// struct TSFlags {
#define TSFLAG_ELEMENT_SIZE_TYPE(X) (X) // 3-bits
#define TSFLAG_DESTRUCTIVE_INST_TYPE(X) ((X) << 3) // 4-bits
>From cb19909b3192efca76ea896d4b8420e46c26e573 Mon Sep 17 00:00:00 2001
From: Anatoly Trosinenko <atrosinenko at accesssoftek.com>
Date: Wed, 26 Nov 2025 22:03:00 +0300
Subject: [PATCH 2/2] Add a comment and update the assertion description
---
llvm/lib/Target/AArch64/AArch64InstrInfo.h | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.h b/llvm/lib/Target/AArch64/AArch64InstrInfo.h
index 8cdb778360a8b..387f49267a8d9 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.h
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.h
@@ -806,6 +806,9 @@ static inline unsigned getPACOpcodeForKey(AArch64PACKey::ID K, bool Zero) {
llvm_unreachable("Unhandled AArch64PACKey::ID enum");
}
+/// Return B(L)RA opcode to be used for an authenticated branch or call using
+/// the given key, or its B(L)RA*Z variant that doesn't take a discriminator
+/// operand, using zero instead.
static inline unsigned getBranchOpcodeForKey(bool IsCall, AArch64PACKey::ID K,
bool Zero) {
using namespace AArch64PACKey;
@@ -818,7 +821,7 @@ static inline unsigned getBranchOpcodeForKey(bool IsCall, AArch64PACKey::ID K,
{AArch64::BLRAB, AArch64::BLRABZ},
};
- assert((K == IA || K == IB) && "I-key expected");
+ assert((K == IA || K == IB) && "B(L)RA* instructions require IA or IB key");
if (IsCall)
return CallOpcode[K == IB][Zero];
return BranchOpcode[K == IB][Zero];
More information about the llvm-branch-commits
mailing list