Skip to content

Do not use R12 for indirect tail calls with PACBTI #82661

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions llvm/lib/Target/ARM/ARMBaseInstrInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -683,6 +683,7 @@ static inline bool isIndirectCall(const MachineInstr &MI) {
case ARM::BX_CALL:
case ARM::BMOVPCRX_CALL:
case ARM::TCRETURNri:
case ARM::TCRETURNrinotr12:
case ARM::TAILJMPr:
case ARM::TAILJMPr4:
case ARM::tBLXr:
Expand Down
6 changes: 4 additions & 2 deletions llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2197,7 +2197,8 @@ bool ARMExpandPseudo::ExpandMI(MachineBasicBlock &MBB,
}

case ARM::TCRETURNdi:
case ARM::TCRETURNri: {
case ARM::TCRETURNri:
case ARM::TCRETURNrinotr12: {
MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
if (MBBI->getOpcode() == ARM::SEH_EpilogEnd)
MBBI--;
Expand Down Expand Up @@ -2241,7 +2242,8 @@ bool ARMExpandPseudo::ExpandMI(MachineBasicBlock &MBB,
// Add the default predicate in Thumb mode.
if (STI->isThumb())
MIB.add(predOps(ARMCC::AL));
} else if (RetOpcode == ARM::TCRETURNri) {
} else if (RetOpcode == ARM::TCRETURNri ||
RetOpcode == ARM::TCRETURNrinotr12) {
unsigned Opcode =
STI->isThumb() ? ARM::tTAILJMPr
: (STI->hasV4TOps() ? ARM::TAILJMPr : ARM::TAILJMPr4);
Expand Down
8 changes: 6 additions & 2 deletions llvm/lib/Target/ARM/ARMFrameLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,8 @@ static int getArgumentStackToRestore(MachineFunction &MF,
if (MBB.end() != MBBI) {
unsigned RetOpcode = MBBI->getOpcode();
IsTailCallReturn = RetOpcode == ARM::TCRETURNdi ||
RetOpcode == ARM::TCRETURNri;
RetOpcode == ARM::TCRETURNri ||
RetOpcode == ARM::TCRETURNrinotr12;
}
ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();

Expand Down Expand Up @@ -486,6 +487,7 @@ static MachineBasicBlock::iterator insertSEH(MachineBasicBlock::iterator MBBI,

case ARM::tBX_RET:
case ARM::TCRETURNri:
case ARM::TCRETURNrinotr12:
MIB = BuildMI(MF, DL, TII.get(ARM::SEH_Nop_Ret))
.addImm(/*Wide=*/0)
.setMIFlags(Flags);
Expand Down Expand Up @@ -1615,7 +1617,9 @@ void ARMFrameLowering::emitPopInst(MachineBasicBlock &MBB,
if (MBB.end() != MI) {
DL = MI->getDebugLoc();
unsigned RetOpcode = MI->getOpcode();
isTailCall = (RetOpcode == ARM::TCRETURNdi || RetOpcode == ARM::TCRETURNri);
isTailCall =
(RetOpcode == ARM::TCRETURNdi || RetOpcode == ARM::TCRETURNri ||
RetOpcode == ARM::TCRETURNrinotr12);
isInterrupt =
RetOpcode == ARM::SUBS_PC_LR || RetOpcode == ARM::t2SUBS_PC_LR;
isTrap =
Expand Down
11 changes: 10 additions & 1 deletion llvm/lib/Target/ARM/ARMInstrInfo.td
Original file line number Diff line number Diff line change
Expand Up @@ -2677,6 +2677,9 @@ let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, Uses = [SP] in {
def TCRETURNri : PseudoInst<(outs), (ins tcGPR:$dst, i32imm:$SPDiff), IIC_Br, []>,
Sched<[WriteBr]>;

def TCRETURNrinotr12 : PseudoInst<(outs), (ins tcGPRnotr12:$dst, i32imm:$SPDiff), IIC_Br, []>,
Sched<[WriteBr]>;

def TAILJMPd : ARMPseudoExpand<(outs), (ins arm_br_target:$dst),
4, IIC_Br, [],
(Bcc arm_br_target:$dst, (ops 14, zero_reg))>,
Expand Down Expand Up @@ -6081,8 +6084,14 @@ def : ARMPat<(ARMWrapperJT tjumptable:$dst),
// TODO: add,sub,and, 3-instr forms?

// Tail calls. These patterns also apply to Thumb mode.
// Regular indirect tail call
def : Pat<(ARMtcret tcGPR:$dst, (i32 timm:$SPDiff)),
(TCRETURNri tcGPR:$dst, timm:$SPDiff)>;
(TCRETURNri tcGPR:$dst, timm:$SPDiff)>,
Requires<[NoSignRetAddr]>;
// Indirect tail call when PACBTI is enabled
def : Pat<(ARMtcret tcGPRnotr12:$dst, (i32 timm:$SPDiff)),
(TCRETURNrinotr12 tcGPRnotr12:$dst, timm:$SPDiff)>,
Requires<[SignRetAddr]>;
def : Pat<(ARMtcret (i32 tglobaladdr:$dst), (i32 timm:$SPDiff)),
(TCRETURNdi texternalsym:$dst, (i32 timm:$SPDiff))>;
def : Pat<(ARMtcret (i32 texternalsym:$dst), (i32 timm:$SPDiff)),
Expand Down
4 changes: 4 additions & 0 deletions llvm/lib/Target/ARM/ARMPredicates.td
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,10 @@ def DontGenExecuteOnly : Predicate<"!Subtarget->genExecuteOnly()">;
def GenT1ExecuteOnly : Predicate<"Subtarget->genExecuteOnly() && "
"Subtarget->isThumb1Only() && "
"!Subtarget->hasV8MBaselineOps()">;
let RecomputePerFunction = 1 in {
def SignRetAddr : Predicate<[{ MF->getInfo<ARMFunctionInfo>()->shouldSignReturnAddress(true) }]>;
def NoSignRetAddr : Predicate<[{ !MF->getInfo<ARMFunctionInfo>()->shouldSignReturnAddress(true) }]>;
}

// Armv8.5-A extensions
def HasSB : Predicate<"Subtarget->hasSB()">,
Expand Down
9 changes: 2 additions & 7 deletions llvm/lib/Target/ARM/ARMRegisterBankInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -156,11 +156,6 @@ ARMRegisterBankInfo::ARMRegisterBankInfo(const TargetRegisterInfo &TRI) {
"Subclass not added?");
assert(RBGPR.covers(*TRI.getRegClass(ARM::tcGPRRegClassID)) &&
"Subclass not added?");
assert(RBGPR.covers(*TRI.getRegClass(ARM::GPRnoip_and_tcGPRRegClassID)) &&
"Subclass not added?");
assert(RBGPR.covers(*TRI.getRegClass(
ARM::tGPREven_and_GPRnoip_and_tcGPRRegClassID)) &&
"Subclass not added?");
assert(RBGPR.covers(*TRI.getRegClass(ARM::tGPROdd_and_tcGPRRegClassID)) &&
"Subclass not added?");
assert(getMaximumSize(RBGPR.getID()) == 32 &&
Expand Down Expand Up @@ -188,16 +183,16 @@ ARMRegisterBankInfo::getRegBankFromRegClass(const TargetRegisterClass &RC,
case GPRnoip_and_GPRnopcRegClassID:
case rGPRRegClassID:
case GPRspRegClassID:
case GPRnoip_and_tcGPRRegClassID:
case tcGPRRegClassID:
case tcGPRnotr12RegClassID:
case tGPRRegClassID:
case tGPREvenRegClassID:
case tGPROddRegClassID:
case tGPR_and_tGPREvenRegClassID:
case tGPR_and_tGPROddRegClassID:
case tGPREven_and_tcGPRRegClassID:
case tGPREven_and_GPRnoip_and_tcGPRRegClassID:
case tGPROdd_and_tcGPRRegClassID:
case tGPREven_and_tcGPRnotr12RegClassID:
return getRegBank(ARM::GPRRegBankID);
case HPRRegClassID:
case SPR_8RegClassID:
Expand Down
10 changes: 10 additions & 0 deletions llvm/lib/Target/ARM/ARMRegisterInfo.td
Original file line number Diff line number Diff line change
Expand Up @@ -373,6 +373,16 @@ def tcGPR : RegisterClass<"ARM", [i32], 32, (add R0, R1, R2, R3, R12)> {
}];
}

// Some pointer authentication instructions require the use of R12. When return
// address signing is enabled, authentication of the caller's return address
// must be performed before a tail call is made. Therefore, indirect tail call
// jump cannot be from R12.
// FIXME: All PACBTI instruction currently implemented in the compiler
// implicitly use R12. When instructions that allow PAC to be placed in a
// specific register are implemented the restriction needs to be updated to
// make sure that PACBTI signature and indirect tail call both use a different register.
def tcGPRnotr12 : RegisterClass<"ARM", [i32], 32, (add R0, R1, R2, R3)>;

def tGPROdd : RegisterClass<"ARM", [i32], 32, (add R1, R3, R5, R7, R9, R11)> {
let AltOrders = [(and tGPROdd, tGPR)];
let AltOrderSelect = [{
Expand Down
6 changes: 3 additions & 3 deletions llvm/lib/Target/ARM/Thumb1FrameLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1049,9 +1049,9 @@ static void popRegsFromStack(MachineBasicBlock &MBB,
continue;

if (Reg == ARM::LR) {
if (!MBB.succ_empty() ||
MI->getOpcode() == ARM::TCRETURNdi ||
MI->getOpcode() == ARM::TCRETURNri)
if (!MBB.succ_empty() || MI->getOpcode() == ARM::TCRETURNdi ||
MI->getOpcode() == ARM::TCRETURNri ||
MI->getOpcode() == ARM::TCRETURNrinotr12)
// LR may only be popped into PC, as part of return sequence.
// If this isn't the return sequence, we'll need emitPopSpecialFixUp
// to restore LR the hard way.
Expand Down
37 changes: 37 additions & 0 deletions llvm/test/CodeGen/ARM/pacbti-indirect-tail-calls-function-flags.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
; RUN: llc -mtriple=thumbv8.1m.main-none-none-eabi -mattr=+pacbti< %s | FileCheck %s

target datalayout = "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"
target triple = "thumbv8.1m.main-m.main-unknown"

; When PACBTI is enabled, indirect tail-calls must not use R12 that is used
; to store authentication code.

define void @pacbti_disabled(ptr %p) "sign-return-address"="none" {
entry:
tail call void %p()
; CHECK: bx {{r0|r1|r2|r3|r12}}
ret void
}

define void @pacbti_enabled(ptr %p) "sign-return-address"="all" {
entry:
tail call void %p()
; CHECK: bx {{r0|r1|r2|r3}}
ret void
}

define void @pacbti_disabled_force_r12(ptr %p) "sign-return-address"="none" {
entry:
%p_r12 = tail call ptr asm "", "={r12},{r12},~{lr}"(ptr %p)
tail call void %p_r12()
; CHECK: bx r12
ret void
}

define void @pacbti_enabled_force_r12(ptr %p) "sign-return-address"="all" {
entry:
%p_r12 = tail call ptr asm "", "={r12},{r12},~{lr}"(ptr %p)
tail call void %p_r12()
; CHECK: bx {{r0|r1|r2|r3}}
ret void
}
17 changes: 17 additions & 0 deletions llvm/test/CodeGen/ARM/pacbti-indirect-tail-calls-module-flags1.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
; RUN: llc -mtriple=thumbv8.1m.main-none-none-eabi -mattr=+pacbti< %s | FileCheck %s

target datalayout = "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"
target triple = "thumbv8.1m.main-m.main-unknown"

define dso_local void @sgign_return_address(ptr noundef readonly %fptr_arg) local_unnamed_addr #0 {
entry:
%0 = tail call ptr asm "", "={r12},{r12},~{lr}"(ptr %fptr_arg)
tail call void %0()
; CHECK: bx {{r0|r1|r2|r3}}
ret void
}

!llvm.module.flags = !{!1}

!1 = !{i32 8, !"sign-return-address", i32 1}

18 changes: 18 additions & 0 deletions llvm/test/CodeGen/ARM/pacbti-indirect-tail-calls-module-flags2.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
; RUN: llc -mtriple=thumbv8.1m.main-none-none-eabi -mattr=+pacbti< %s | FileCheck %s

target datalayout = "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"
target triple = "thumbv8.1m.main-m.main-unknown"

define dso_local void @sgign_return_address_all(ptr noundef readonly %fptr_arg) local_unnamed_addr #0 {
entry:
%0 = tail call ptr asm "", "={r12},{r12},~{lr}"(ptr %fptr_arg)
tail call void %0()
; CHECK: bx {{r0|r1|r2|r3}}
ret void
}

!llvm.module.flags = !{!1}

!1 = !{i32 8, !"sign-return-address", i32 1}
!2 = !{i32 8, !"sign-return-address-all", i32 1}