Index: llvm/lib/Target/AArch64/AArch64BranchTargets.cpp =================================================================== --- llvm/lib/Target/AArch64/AArch64BranchTargets.cpp +++ llvm/lib/Target/AArch64/AArch64BranchTargets.cpp @@ -38,7 +38,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 @@ -91,16 +91,13 @@ 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() @@ -114,20 +111,45 @@ HintNum |= 2; if (CouldJump) HintNum |= 4; - assert(HintNum != 32 && "No target kinds!"); auto MBBI = MBB.begin(); - // Skip the meta instuctions, those will be removed anyway. + // Skip the meta instructions, those will be removed anyway. for (; MBBI != MBB.end() && MBBI->isMetaInstruction(); ++MBBI) ; + if (MBBI == MBB.end()) + return false; + // PACI[AB]SP are implicitly BTI JC, so no BTI instruction needed there. - if (MBBI != MBB.end() && (MBBI->getOpcode() == AArch64::PACIASP || - MBBI->getOpcode() == AArch64::PACIBSP)) - return; + if (MBBI->getOpcode() == AArch64::PACIASP || + MBBI->getOpcode() == AArch64::PACIBSP) { + // Only direct jump could reach this function, therefore the implicit + // landing could be removed. + if (HintNum == 32) { + const AArch64Subtarget &Subtarget = + MBB.getParent()->getSubtarget(); + + if (Subtarget.hasV8_3aOps()) { + // PACI[A|B] LR, SP performs the same operation but it is not a landing + // pad. + BuildMI(MBB, MBBI, MBB.findDebugLoc(MBB.begin()), + TII->get(MBBI->getOpcode() == AArch64::PACIASP + ? AArch64::PACIA + : AArch64::PACIB)) + .addReg(AArch64::LR) + .addReg(AArch64::SP); + MBB.erase(MBBI); + return true; + } + } + return false; + } + if(HintNum == 32) + return false; BuildMI(MBB, MBB.begin(), MBB.findDebugLoc(MBB.begin()), TII->get(AArch64::HINT)) .addImm(HintNum); + return true; } 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"="true" "sign-return-address"="all" "sign-return-address-key"="a_key" } \ No newline at end of file