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);
103 bool EmitAsyncCFI = MFnI.needsAsyncDwarfUnwindInfo(MF);
118 if (MFnI.branchProtectionPAuthLR()) {
120 MFnI.setSigningInstrLabel(PACSym);
125 if (MFnI.branchProtectionPAuthLR() && Subtarget->hasPAuthLR()) {
127 TII->get(MFnI.shouldSignWithBKey() ? AArch64::PACIBSPPC
128 : AArch64::PACIASPPC))
134 TII->get(MFnI.shouldSignWithBKey() ? AArch64::PACIBSP
146 if (
I->getOpcode() == TargetOpcode::CFI_INSTRUCTION &&
158 }
else if (NeedsWinCFI) {
164void AArch64PointerAuth::authenticateLR(
185 bool TerminatorIsCombinable =
186 TI !=
MBB.
end() && TI->getOpcode() == AArch64::RET;
189 if (Subtarget->hasPAuth() && TerminatorIsCombinable && !NeedsWinCFI &&
192 assert(PACSym &&
"No PAC instruction to refer to");
194 TII->get(UseBKey ? AArch64::RETABSPPCi : AArch64::RETAASPPCi))
200 BuildMI(
MBB, TI,
DL,
TII->get(UseBKey ? AArch64::RETAB : AArch64::RETAA))
207 assert(PACSym &&
"No PAC instruction to refer to");
209 TII->get(UseBKey ? AArch64::AUTIBSPPCi : AArch64::AUTIASPPCi))
215 TII->get(UseBKey ? AArch64::AUTIBSP : AArch64::AUTIASP))
239 auto MOVolatileLoad =
249 Register AuthenticatedReg,
Register TmpReg,
bool UseIKey,
unsigned BrkImm) {
263 "MBBI should be the first terminator in MBB");
269 case AuthCheckMethod::None:
271 case AuthCheckMethod::DummyLoad:
290 case AuthCheckMethod::None:
291 case AuthCheckMethod::DummyLoad:
293 case AuthCheckMethod::HighBitsNoTBI:
303 case AuthCheckMethod::XPACHint:
304 assert(AuthenticatedReg == AArch64::LR &&
305 "XPACHint mode is only compatible with checking the LR register");
306 assert(UseIKey &&
"XPACHint mode is only compatible with I-keys");
326 case AuthCheckMethod::None:
328 case AuthCheckMethod::DummyLoad:
330 case AuthCheckMethod::HighBitsNoTBI:
332 case AuthCheckMethod::XPACHint:
338bool AArch64PointerAuth::checkAuthenticatedLR(
347 if (Method == AuthCheckMethod::None)
352 assert(!TI->getMF()->hasWinCFI() &&
"WinCFI is not yet supported");
378 "Tail call is expected");
380 TI->readsRegister(AArch64::X16,
TRI) ? AArch64::X17 : AArch64::X16;
381 assert(!TI->readsRegister(TmpReg,
TRI) &&
382 "More than a single register is used by TCRETURN");
385 BrkOperandForKey(KeyId));
392 unsigned IntDisc)
const {
396 if (Result != AddrDisc)
408void AArch64PointerAuth::expandPAuthBlend(
412 unsigned IntDisc =
MBBI->getOperand(2).getImm();
413 emitBlend(
MBBI, ResultReg, AddrDisc, IntDisc);
420 TII = Subtarget->getInstrInfo();
421 TRI = Subtarget->getRegisterInfo();
427 bool HasAuthenticationInstrs =
false;
429 for (
auto &
MBB : MF) {
433 switch (
MI.getOpcode()) {
445 case AArch64::PAUTH_PROLOGUE:
446 case AArch64::PAUTH_EPILOGUE:
447 case AArch64::PAUTH_BLEND:
455 for (
auto It : PAuthPseudoInstrs) {
456 switch (It->getOpcode()) {
457 case AArch64::PAUTH_PROLOGUE:
460 case AArch64::PAUTH_EPILOGUE:
461 authenticateLR(MF, It);
462 HasAuthenticationInstrs =
true;
464 case AArch64::PAUTH_BLEND:
465 expandPAuthBlend(It);
470 It->eraseFromParent();
476 if (HasAuthenticationInstrs &&
478 for (
auto TailCall : TailCallInstrs) {
480 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 MachineFunction &MF) 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 ...
const BasicBlock * getBasicBlock() const
Return the LLVM basic block that this instance corresponded to originally.
iterator getFirstTerminator()
Returns an iterator to the first terminator instruction of this basic block.
void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
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)
MCContext & getContext() const
Function & getFunction()
Return the LLVM function that this machine code represents.
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.
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.
void checkAuthenticatedRegister(MachineBasicBlock::iterator MBBI, AuthCheckMethod Method, Register AuthenticatedReg, Register TmpReg, bool UseIKey, unsigned BrkImm)
Explicitly checks that pointer authentication succeeded.
AuthCheckMethod
Variants of check performed on an authenticated pointer.
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,...