diff --git a/llvm/lib/Target/AArch64/AArch64FrameLowering.h b/llvm/lib/Target/AArch64/AArch64FrameLowering.h --- a/llvm/lib/Target/AArch64/AArch64FrameLowering.h +++ b/llvm/lib/Target/AArch64/AArch64FrameLowering.h @@ -30,6 +30,14 @@ eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator I) const override; + static void signLR(MachineFunction &MF, MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI, bool UseBKey, + bool EmitCFI, bool NeedsWinCFI, bool *HasWinCFI); + + static void authenticateLR(MachineFunction &MF, MachineBasicBlock &MBB, + bool EmitCombined, bool UseBKey, bool NeedsWinCFI, + bool *HasWinCFI); + /// emitProlog/emitEpilog - These methods insert prolog and epilog code into /// the function. void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const override; diff --git a/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp b/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp --- a/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp +++ b/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp @@ -1385,6 +1385,41 @@ .setMIFlags(MachineInstr::FrameSetup); } +void AArch64FrameLowering::signLR(MachineFunction &MF, MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI, + bool UseBKey, bool EmitCFI, bool NeedsWinCFI, + bool *HasWinCFI) { + const AArch64Subtarget &Subtarget = MF.getSubtarget(); + const TargetInstrInfo *TII = Subtarget.getInstrInfo(); + + // Debug location must be unknown since the first debug location is used + // to determine the end of the prologue. + DebugLoc DL; + + if (UseBKey) { + BuildMI(MBB, MBBI, DL, TII->get(AArch64::EMITBKEY)) + .setMIFlag(MachineInstr::FrameSetup); + } + + // No SEH opcode for this one; it doesn't materialize into an + // instruction on Windows. + BuildMI(MBB, MBBI, DL, + TII->get(UseBKey ? AArch64::PACIBSP : AArch64::PACIASP)) + .setMIFlag(MachineInstr::FrameSetup); + + if (EmitCFI) { + unsigned CFIIndex = + MF.addFrameInst(MCCFIInstruction::createNegateRAState(nullptr)); + BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION)) + .addCFIIndex(CFIIndex) + .setMIFlags(MachineInstr::FrameSetup); + } else if (NeedsWinCFI) { + *HasWinCFI = true; + BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_PACSignLR)) + .setMIFlag(MachineInstr::FrameSetup); + } +} + void AArch64FrameLowering::emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const { MachineBasicBlock::iterator MBBI = MBB.begin(); @@ -1418,31 +1453,10 @@ emitShadowCallStackPrologue(*TII, MF, MBB, MBBI, DL, NeedsWinCFI, MFnI.needsDwarfUnwindInfo(MF)); - if (MFnI.shouldSignReturnAddress(MF)) { - if (MFnI.shouldSignWithBKey()) { - BuildMI(MBB, MBBI, DL, TII->get(AArch64::EMITBKEY)) - .setMIFlag(MachineInstr::FrameSetup); - } - - // No SEH opcode for this one; it doesn't materialize into an - // instruction on Windows. - BuildMI(MBB, MBBI, DL, - TII->get(MFnI.shouldSignWithBKey() ? AArch64::PACIBSP - : AArch64::PACIASP)) - .setMIFlag(MachineInstr::FrameSetup); + if (MFnI.shouldSignReturnAddress(MF)) + signLR(MF, MBB, MBBI, MFnI.shouldSignWithBKey(), EmitCFI, NeedsWinCFI, + &HasWinCFI); - if (EmitCFI) { - unsigned CFIIndex = - MF.addFrameInst(MCCFIInstruction::createNegateRAState(nullptr)); - BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION)) - .addCFIIndex(CFIIndex) - .setMIFlags(MachineInstr::FrameSetup); - } else if (NeedsWinCFI) { - HasWinCFI = true; - BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_PACSignLR)) - .setMIFlag(MachineInstr::FrameSetup); - } - } if (EmitCFI && MFnI.isMTETagged()) { BuildMI(MBB, MBBI, DL, TII->get(AArch64::EMITMTETAGGED)) .setMIFlag(MachineInstr::FrameSetup); @@ -1901,14 +1915,12 @@ } } -static void InsertReturnAddressAuth(MachineFunction &MF, MachineBasicBlock &MBB, - bool NeedsWinCFI, bool *HasWinCFI) { - const auto &MFI = *MF.getInfo(); - if (!MFI.shouldSignReturnAddress(MF)) - return; +void AArch64FrameLowering::authenticateLR(MachineFunction &MF, + MachineBasicBlock &MBB, + bool EmitCombined, bool UseBKey, + bool NeedsWinCFI, bool *HasWinCFI) { const AArch64Subtarget &Subtarget = MF.getSubtarget(); const TargetInstrInfo *TII = Subtarget.getInstrInfo(); - MachineBasicBlock::iterator MBBI = MBB.getFirstTerminator(); DebugLoc DL; if (MBBI != MBB.end()) @@ -1919,18 +1931,14 @@ // From v8.3a onwards there are optimised authenticate LR and return // instructions, namely RETA{A,B}, that can be used instead. In this case the // DW_CFA_AARCH64_negate_ra_state can't be emitted. - if (Subtarget.hasPAuth() && - !MF.getFunction().hasFnAttribute(Attribute::ShadowCallStack) && - MBBI != MBB.end() && MBBI->getOpcode() == AArch64::RET_ReallyLR && - !NeedsWinCFI) { - BuildMI(MBB, MBBI, DL, - TII->get(MFI.shouldSignWithBKey() ? AArch64::RETAB : AArch64::RETAA)) + if (EmitCombined) { + BuildMI(MBB, MBBI, DL, TII->get(UseBKey ? AArch64::RETAB : AArch64::RETAA)) .copyImplicitOps(*MBBI); MBB.erase(MBBI); + assert(!NeedsWinCFI && "Unexpected NeedsWinCFI with combined return"); } else { - BuildMI( - MBB, MBBI, DL, - TII->get(MFI.shouldSignWithBKey() ? AArch64::AUTIBSP : AArch64::AUTIASP)) + BuildMI(MBB, MBBI, DL, + TII->get(UseBKey ? AArch64::AUTIBSP : AArch64::AUTIASP)) .setMIFlag(MachineInstr::FrameDestroy); unsigned CFIIndex = @@ -1960,12 +1968,12 @@ MachineBasicBlock &MBB) const { MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr(); MachineFrameInfo &MFI = MF.getFrameInfo(); + AArch64FunctionInfo *AFI = MF.getInfo(); const AArch64Subtarget &Subtarget = MF.getSubtarget(); const TargetInstrInfo *TII = Subtarget.getInstrInfo(); DebugLoc DL; bool NeedsWinCFI = needsWinCFI(MF); - bool EmitCFI = - MF.getInfo()->needsAsyncDwarfUnwindInfo(MF); + bool EmitCFI = AFI->needsAsyncDwarfUnwindInfo(MF); bool HasWinCFI = false; bool IsFunclet = false; auto WinCFI = make_scope_exit([&]() { assert(HasWinCFI == MF.hasWinCFI()); }); @@ -1976,7 +1984,16 @@ } auto FinishingTouches = make_scope_exit([&]() { - InsertReturnAddressAuth(MF, MBB, NeedsWinCFI, &HasWinCFI); + if (AFI->shouldSignReturnAddress(MF)) { + MachineBasicBlock::iterator TI = MBB.getFirstTerminator(); + bool EmitCombined = + Subtarget.hasPAuth() && + !MF.getFunction().hasFnAttribute(Attribute::ShadowCallStack) && + TI != MBB.end() && TI->getOpcode() == AArch64::RET_ReallyLR && + !NeedsWinCFI; + authenticateLR(MF, MBB, EmitCombined, AFI->shouldSignWithBKey(), + NeedsWinCFI, &HasWinCFI); + } if (needsShadowCallStackPrologueEpilogue(MF)) emitShadowCallStackEpilogue(*TII, MF, MBB, MBB.getFirstTerminator(), DL); if (EmitCFI) @@ -1989,7 +2006,6 @@ int64_t NumBytes = IsFunclet ? getWinEHFuncletFrameSize(MF) : MFI.getStackSize(); - AArch64FunctionInfo *AFI = MF.getInfo(); // All calls are tail calls in GHC calling conv, and functions have no // prologue/epilogue. diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp --- a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp +++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp @@ -11,6 +11,7 @@ //===----------------------------------------------------------------------===// #include "AArch64InstrInfo.h" +#include "AArch64FrameLowering.h" #include "AArch64MachineFunctionInfo.h" #include "AArch64Subtarget.h" #include "MCTargetDesc/AArch64AddressingModes.h" @@ -7996,63 +7997,23 @@ static void signOutlinedFunction(MachineFunction &MF, MachineBasicBlock &MBB, bool ShouldSignReturnAddr, bool ShouldSignReturnAddrWithBKey) { - if (ShouldSignReturnAddr) { - MachineBasicBlock::iterator MBBPAC = MBB.begin(); - MachineBasicBlock::iterator MBBAUT = MBB.getFirstTerminator(); - const AArch64Subtarget &Subtarget = MF.getSubtarget(); - const TargetInstrInfo *TII = Subtarget.getInstrInfo(); - DebugLoc DL; - - if (MBBAUT != MBB.end()) - DL = MBBAUT->getDebugLoc(); - - // At the very beginning of the basic block we insert the following - // depending on the key type - // - // a_key: b_key: - // PACIASP EMITBKEY - // CFI_INSTRUCTION PACIBSP - // CFI_INSTRUCTION - if (ShouldSignReturnAddrWithBKey) { - BuildMI(MBB, MBBPAC, DebugLoc(), TII->get(AArch64::EMITBKEY)) - .setMIFlag(MachineInstr::FrameSetup); - } + if (!ShouldSignReturnAddr) + return; - BuildMI(MBB, MBBPAC, DebugLoc(), - TII->get(ShouldSignReturnAddrWithBKey ? AArch64::PACIBSP - : AArch64::PACIASP)) - .setMIFlag(MachineInstr::FrameSetup); + MachineBasicBlock::iterator MBBAUT = MBB.getFirstTerminator(); + const AArch64Subtarget &Subtarget = MF.getSubtarget(); - if (MF.getInfo()->needsDwarfUnwindInfo(MF)) { - unsigned CFIIndex = - MF.addFrameInst(MCCFIInstruction::createNegateRAState(nullptr)); - BuildMI(MBB, MBBPAC, DebugLoc(), TII->get(AArch64::CFI_INSTRUCTION)) - .addCFIIndex(CFIIndex) - .setMIFlags(MachineInstr::FrameSetup); - } + // FIXME Handle NeedsWinCFI + bool EmitCFI = MF.getInfo()->needsDwarfUnwindInfo(MF); + AArch64FrameLowering::signLR(MF, MBB, MBB.begin(), + ShouldSignReturnAddrWithBKey, EmitCFI, + /*NeedsWinCFI=*/false, /*HasWinCFI=*/nullptr); - // If v8.3a features are available we can replace a RET instruction by - // RETAA or RETAB and omit the AUT instructions. In this case the - // DW_CFA_AARCH64_negate_ra_state can't be emitted. - if (Subtarget.hasPAuth() && MBBAUT != MBB.end() && - MBBAUT->getOpcode() == AArch64::RET) { - BuildMI(MBB, MBBAUT, DL, - TII->get(ShouldSignReturnAddrWithBKey ? AArch64::RETAB - : AArch64::RETAA)) - .copyImplicitOps(*MBBAUT); - MBB.erase(MBBAUT); - } else { - BuildMI(MBB, MBBAUT, DL, - TII->get(ShouldSignReturnAddrWithBKey ? AArch64::AUTIBSP - : AArch64::AUTIASP)) - .setMIFlag(MachineInstr::FrameDestroy); - unsigned CFIIndexAuth = - MF.addFrameInst(MCCFIInstruction::createNegateRAState(nullptr)); - BuildMI(MBB, MBBAUT, DL, TII->get(TargetOpcode::CFI_INSTRUCTION)) - .addCFIIndex(CFIIndexAuth) - .setMIFlags(MachineInstr::FrameDestroy); - } - } + bool EmitCombined = Subtarget.hasPAuth() && MBBAUT != MBB.end() && + MBBAUT->getOpcode() == AArch64::RET; + AArch64FrameLowering::authenticateLR( + MF, MBB, EmitCombined, ShouldSignReturnAddrWithBKey, + /*NeedsWinCFI=*/false, /*HasWinCFI=*/nullptr); } void AArch64InstrInfo::buildOutlinedFrame(