23#define AARCH64_POINTER_AUTH_NAME "AArch64 Pointer Authentication"
40 const unsigned BrkOperandBase = 0xc470;
41 return BrkOperandBase + KeyId;
55 Register AddrDisc,
unsigned IntDisc)
const;
69 return new AArch64PointerAuth();
72char AArch64PointerAuth::ID = 0;
94 if (MFnI.branchProtectionPAuthLR() && !Subtarget.hasPAuthLR())
102 bool EmitCFI = MFnI.needsDwarfUnwindInfo(MF);
117 if (MFnI.branchProtectionPAuthLR()) {
119 MFnI.setSigningInstrLabel(PACSym);
124 if (MFnI.branchProtectionPAuthLR() && Subtarget->hasPAuthLR()) {
126 TII->get(MFnI.shouldSignWithBKey() ? AArch64::PACIBSPPC
127 : AArch64::PACIASPPC))
133 TII->get(MFnI.shouldSignWithBKey() ? AArch64::PACIBSP
145 }
else if (NeedsWinCFI) {
151void AArch64PointerAuth::authenticateLR(
172 bool TerminatorIsCombinable =
173 TI !=
MBB.
end() && TI->getOpcode() == AArch64::RET;
176 if (Subtarget->hasPAuth() && TerminatorIsCombinable && !NeedsWinCFI &&
179 assert(PACSym &&
"No PAC instruction to refer to");
181 TII->get(UseBKey ? AArch64::RETABSPPCi : AArch64::RETAASPPCi))
187 BuildMI(
MBB, TI,
DL,
TII->get(UseBKey ? AArch64::RETAB : AArch64::RETAA))
194 assert(PACSym &&
"No PAC instruction to refer to");
196 TII->get(UseBKey ? AArch64::AUTIBSPPCi : AArch64::AUTIASPPCi))
202 TII->get(UseBKey ? AArch64::AUTIBSP : AArch64::AUTIASP))
226 auto MOVolatileLoad =
236 Register AuthenticatedReg,
Register TmpReg,
bool UseIKey,
unsigned BrkImm) {
248 case AuthCheckMethod::None:
250 case AuthCheckMethod::DummyLoad:
262 "Cannot insert the check at the very beginning of MBB");
278 case AuthCheckMethod::None:
279 case AuthCheckMethod::DummyLoad:
281 case AuthCheckMethod::HighBitsNoTBI:
282 BuildMI(CheckBlock,
DL,
TII->get(AArch64::EORXrs), TmpReg)
290 return *SuccessBlock;
291 case AuthCheckMethod::XPACHint:
292 assert(AuthenticatedReg == AArch64::LR &&
293 "XPACHint mode is only compatible with checking the LR register");
294 assert(UseIKey &&
"XPACHint mode is only compatible with I-keys");
295 BuildMI(CheckBlock,
DL,
TII->get(AArch64::ORRXrs), TmpReg)
300 BuildMI(CheckBlock,
DL,
TII->get(AArch64::SUBSXrs), AArch64::XZR)
307 return *SuccessBlock;
314 case AuthCheckMethod::None:
316 case AuthCheckMethod::DummyLoad:
318 case AuthCheckMethod::HighBitsNoTBI:
320 case AuthCheckMethod::XPACHint:
326bool AArch64PointerAuth::checkAuthenticatedLR(
334 if (Method == AuthCheckMethod::None)
339 assert(!TI->getMF()->hasWinCFI() &&
"WinCFI is not yet supported");
365 "Tail call is expected");
367 TI->readsRegister(AArch64::X16,
TRI) ? AArch64::X17 : AArch64::X16;
368 assert(!TI->readsRegister(TmpReg,
TRI) &&
369 "More than a single register is used by TCRETURN");
372 BrkOperandForKey(KeyId));
379 unsigned IntDisc)
const {
383 if (Result != AddrDisc)
395void AArch64PointerAuth::expandPAuthBlend(
399 unsigned IntDisc =
MBBI->getOperand(2).getImm();
400 emitBlend(
MBBI, ResultReg, AddrDisc, IntDisc);
407 TII = Subtarget->getInstrInfo();
408 TRI = Subtarget->getRegisterInfo();
414 bool HasAuthenticationInstrs =
false;
416 for (
auto &
MBB : MF) {
420 switch (
MI.getOpcode()) {
432 case AArch64::PAUTH_PROLOGUE:
433 case AArch64::PAUTH_EPILOGUE:
434 case AArch64::PAUTH_BLEND:
442 for (
auto It : PAuthPseudoInstrs) {
443 switch (It->getOpcode()) {
444 case AArch64::PAUTH_PROLOGUE:
447 case AArch64::PAUTH_EPILOGUE:
448 authenticateLR(MF, It);
449 HasAuthenticationInstrs =
true;
451 case AArch64::PAUTH_BLEND:
452 expandPAuthBlend(It);
457 It->eraseFromParent();
463 if (HasAuthenticationInstrs &&
465 for (
auto TailCall : TailCallInstrs) {
467 Modified |= checkAuthenticatedLR(TailCall);
#define AARCH64_POINTER_AUTH_NAME
static void BuildPACM(const AArch64Subtarget &Subtarget, MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, DebugLoc DL, MachineInstr::MIFlag Flags, MCSymbol *PACSym=nullptr)
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
const HexagonInstrInfo * TII
unsigned const TargetRegisterInfo * TRI
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
AArch64FunctionInfo - This class is derived from MachineFunctionInfo and contains private AArch64-spe...
bool needsShadowCallStackPrologueEpilogue(MachineFunction &MF) const
bool branchProtectionPAuthLR() const
bool needsAsyncDwarfUnwindInfo(const MachineFunction &MF) const
MCSymbol * getSigningInstrLabel() const
bool shouldSignWithBKey() const
static bool isTailCallReturnInst(const MachineInstr &MI)
Returns true if MI is one of the TCRETURN* instructions.
const AArch64InstrInfo * getInstrInfo() const override
const PseudoSourceValue * getAddressCheckPSV() const
AArch64PAuth::AuthCheckMethod getAuthenticatedLRCheckMethod() const
Choose a method of checking LR before performing a tail call.
FunctionPass class - This class is used to implement most global optimizations.
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
static MCCFIInstruction createNegateRAState(MCSymbol *L, SMLoc Loc={})
.cfi_negate_ra_state AArch64 negate RA state.
MCSymbol * createTempSymbol()
Create a temporary symbol with a unique name.
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
MachineBasicBlock * getFallThrough(bool JumpToFallThrough=true)
Return the fallthrough block if the block can implicitly transfer control to the block after it by fa...
const BasicBlock * getBasicBlock() const
Return the LLVM basic block that this instance corresponded to originally.
void splitSuccessor(MachineBasicBlock *Old, MachineBasicBlock *New, bool NormalizeSuccProbs=false)
Split the old successor into old plus new and updates the probability info.
MachineBasicBlock * splitAt(MachineInstr &SplitInst, bool UpdateLiveIns=true, LiveIntervals *LIS=nullptr)
Split a basic block into 2 pieces at SplitPoint.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
instr_iterator erase(instr_iterator I)
Remove an instruction from the instruction list and delete it.
instr_iterator getFirstInstrTerminator()
Same getFirstTerminator but it ignores bundles and return an instr_iterator instead.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
virtual bool runOnMachineFunction(MachineFunction &MF)=0
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
unsigned addFrameInst(const MCCFIInstruction &Inst)
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, LLT MemTy, Align base_alignment, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr, SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
void push_back(MachineBasicBlock *MBB)
Function & getFunction()
Return the LLVM function that this machine code represents.
MachineModuleInfo & getMMI() const
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineBasicBlock - Allocate a new MachineBasicBlock.
const MachineInstrBuilder & addCFIIndex(unsigned CFIIndex) const
const MachineInstrBuilder & setMIFlag(MachineInstr::MIFlag Flag) const
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addSym(MCSymbol *Sym, unsigned char TargetFlags=0) const
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
const MachineInstrBuilder & setMIFlags(unsigned Flags) const
const MachineInstrBuilder & copyImplicitOps(const MachineInstr &OtherMI) const
Copy all the implicit operands from OtherMI onto this one.
const MachineInstrBuilder & addMemOperand(MachineMemOperand *MMO) const
void setPreInstrSymbol(MachineFunction &MF, MCSymbol *Symbol)
Set a symbol that will be emitted just prior to the instruction itself.
A description of a memory reference used in the backend.
@ MOVolatile
The memory access is volatile.
@ MOLoad
The memory access reads data.
const MCContext & getContext() const
virtual StringRef getPassName() const
getPassName - Return a nice clean name for a pass.
Wrapper class representing virtual and physical registers.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
TargetInstrInfo - Interface to description of machine instruction set.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned getCheckerSizeInBytes(AuthCheckMethod Method)
Returns the number of bytes added by checkAuthenticatedRegister.
AuthCheckMethod
Variants of check performed on an authenticated pointer.
MachineBasicBlock & checkAuthenticatedRegister(MachineBasicBlock::iterator MBBI, AuthCheckMethod Method, Register AuthenticatedReg, Register TmpReg, bool UseIKey, unsigned BrkImm)
Explicitly checks that pointer authentication succeeded.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ Define
Register definition.
This is an optimization pass for GlobalISel generic memory operations.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
FunctionPass * createAArch64PointerAuthPass()
static unsigned getWRegFromXReg(unsigned Reg)
This struct is a compact representation of a valid (non-zero power of two) alignment.
This class contains a discriminated union of information about pointers in memory operands,...