Index: llvm/lib/Target/AArch64/AArch64BranchTargets.cpp =================================================================== --- llvm/lib/Target/AArch64/AArch64BranchTargets.cpp +++ llvm/lib/Target/AArch64/AArch64BranchTargets.cpp @@ -86,7 +86,7 @@ StringRef getPassName() const override { return AARCH64_BRANCH_TARGETS_NAME; } private: - void addBTI(MachineBasicBlock &MBB, bool CouldCall, bool CouldJump); + bool addBTI(MachineBasicBlock &MBB, bool CouldCall, bool CouldJump); }; } // end anonymous namespace @@ -153,21 +153,19 @@ if (MBB.hasAddressTaken() || JumpTableTargets.count(&MBB)) CouldJump = true; - if (CouldCall || CouldJump) { - addBTI(MBB, CouldCall, CouldJump); - MadeChange = true; - } + MadeChange |= addBTI(MBB, CouldCall, CouldJump); } return MadeChange; } -void AArch64BranchTargets::addBTI(MachineBasicBlock &MBB, bool CouldCall, +bool AArch64BranchTargets::addBTI(MachineBasicBlock &MBB, bool CouldCall, bool CouldJump) { LLVM_DEBUG(dbgs() << "Adding BTI " << (CouldJump ? "j" : "") << (CouldCall ? "c" : "") << " to " << MBB.getName() << "\n"); - + const AArch64Subtarget &Subtarget = + MBB.getParent()->getSubtarget(); const AArch64InstrInfo *TII = static_cast( MBB.getParent()->getSubtarget().getInstrInfo()); @@ -176,7 +174,6 @@ HintNum |= 2; if (CouldJump) HintNum |= 4; - assert(HintNum != 32 && "No target kinds!"); auto MBBI = MBB.begin(); @@ -185,14 +182,37 @@ ++MBBI) ; + // No call or jump is expected to this block, but PACIASP would allow + // indirect calls. PACIASP and PACIA LR, SP are equivalent from PAC point of + // view while PACIA is not a BTI landing pad. BTI instruction could be + // inserted on <8.3A architectures but the PACIASP can't be removed + // therefore not worth it. + if (HintNum == 32) { + if (MBBI != MBB.end() && + (MBBI->getOpcode() == AArch64::PACIASP || + MBBI->getOpcode() == AArch64::PACIBSP) && + Subtarget.hasV8_3aOps()) { + BuildMI(MBB, MBBI, MBBI->getDebugLoc(), + TII->get(MBBI->getOpcode() == AArch64::PACIASP ? AArch64::PACIA + : AArch64::PACIB)) + .addReg(AArch64::LR, RegState::Define) + .addReg(AArch64::SP, RegState::InternalRead) + .setMIFlag(MachineInstr::FrameSetup); + MBB.erase(MBBI); + return true; + } + return false; + } + // SCTLR_EL1.BT[01] is set to 0 by default which means // PACI[AB]SP are implicitly BTI C so no BTI C instruction is needed there. - if (MBBI != MBB.end() && HintNum == 34 && + if (HintNum == 34 && MBBI != MBB.end() && (MBBI->getOpcode() == AArch64::PACIASP || MBBI->getOpcode() == AArch64::PACIBSP)) - return; + return false; BuildMI(MBB, MBB.begin(), MBB.findDebugLoc(MBB.begin()), TII->get(AArch64::HINT)) .addImm(HintNum); + return true; } Index: llvm/lib/Target/AArch64/AArch64InstrInfo.cpp =================================================================== --- llvm/lib/Target/AArch64/AArch64InstrInfo.cpp +++ llvm/lib/Target/AArch64/AArch64InstrInfo.cpp @@ -6316,6 +6316,13 @@ // Don't outline anything used for return address signing. The outlined // function will get signed later if needed switch (MI.getOpcode()) { + case AArch64::PACIA: + case AArch64::PACIB: + /* PACI[A|B] LR, SP is same as PACI[A|B]SP */ + if (MI.getNumOperands() == 2 && MI.getOperand(0).getReg() == AArch64::LR && + MI.getOperand(1).getReg() == AArch64::SP) + return outliner::InstrType::Illegal; + break; case AArch64::PACIASP: case AArch64::PACIBSP: case AArch64::AUTIASP: Index: llvm/test/CodeGen/AArch64/branch-target-enforcement-direct-calls.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/AArch64/branch-target-enforcement-direct-calls.ll @@ -0,0 +1,31 @@ +; RUN: llc -mtriple aarch64--none-eabi -mattr=+bti < %s | FileCheck %s --check-prefixes=CHECK,CHECK8_0 +; RUN: llc -mtriple aarch64--none-eabi -mattr=+bti -mattr=v8.3a < %s | FileCheck %s --check-prefixes=CHECK,CHECK8_3 + +target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128" +target triple = "aarch64-arm-none-eabi" + +; When BTI is enabled and Arm v8.3 is avaliable then in case of function that is called +; only with direct branch the landing pad should be replaced with an equivalent non landing +; instruction. + +define internal void @localfunc() #0 { +;CHECK: localfunc: +;CHECK8_0: hint #25 +;CHECK8_3: pacia x30, sp +entry: + %l1 = alloca i32, align 4 + ret void +} + +; Global function should have landing pad. Note hint #25 is paciasp. +;CHECK: bti_enabled: +;CHECK8_0: hint #25 +;CHECK8_3: paciasp +define void @bti_enabled() #0 { +entry: + %l1 = alloca i32, align 4 + tail call void @localfunc() + ret void +} + +attributes #0 = { noinline "branch-target-enforcement" "sign-return-address"="all" "sign-return-address-key"="a_key" }