[llvm] [AArch64][BTI] Add BTI at EH entries. (PR #155308)
Shashi Shankar via llvm-commits
llvm-commits at lists.llvm.org
Tue Aug 26 05:55:09 PDT 2025
https://github.com/shashforge updated https://github.com/llvm/llvm-project/pull/155308
>From 1165f71e60fff13a84299b38e1aff59f766285e3 Mon Sep 17 00:00:00 2001
From: Shashi Shankar <shashishankar1687 at gmail.com>
Date: Mon, 25 Aug 2025 23:13:19 +0200
Subject: [PATCH] [AArch64][BTI] Add BTI at EH entries: BTI j for Itanium EH,
BTI c for WinEH
Signed-off-by: Shashi Shankar <shashishankar1687 at gmail.com>
---
.../Target/AArch64/AArch64BranchTargets.cpp | 27 ++++++++---
llvm/test/CodeGen/AArch64/bti-ehpad.ll | 45 +++++++++++++++++++
.../test/CodeGen/AArch64/wineh-bti-funclet.ll | 30 +++++++++++++
3 files changed, 97 insertions(+), 5 deletions(-)
create mode 100644 llvm/test/CodeGen/AArch64/bti-ehpad.ll
create mode 100644 llvm/test/CodeGen/AArch64/wineh-bti-funclet.ll
diff --git a/llvm/lib/Target/AArch64/AArch64BranchTargets.cpp b/llvm/lib/Target/AArch64/AArch64BranchTargets.cpp
index 3436dc9ef4521..83abdaac3fec1 100644
--- a/llvm/lib/Target/AArch64/AArch64BranchTargets.cpp
+++ b/llvm/lib/Target/AArch64/AArch64BranchTargets.cpp
@@ -62,9 +62,8 @@ bool AArch64BranchTargets::runOnMachineFunction(MachineFunction &MF) {
if (!MF.getInfo<AArch64FunctionInfo>()->branchTargetEnforcement())
return false;
- LLVM_DEBUG(
- dbgs() << "********** AArch64 Branch Targets **********\n"
- << "********** Function: " << MF.getName() << '\n');
+ LLVM_DEBUG(dbgs() << "********** AArch64 Branch Targets **********\n"
+ << "********** Function: " << MF.getName() << '\n');
const Function &F = MF.getFunction();
// LLVM does not consider basic blocks which are the targets of jump tables
@@ -103,6 +102,12 @@ bool AArch64BranchTargets::runOnMachineFunction(MachineFunction &MF) {
JumpTableTargets.count(&MBB))
CouldJump = true;
+ if (MBB.isEHPad()) {
+ if (HasWinCFI && (MBB.isEHFuncletEntry() || MBB.isCleanupFuncletEntry()))
+ CouldCall = true;
+ else
+ CouldJump = true;
+ }
if (CouldCall || CouldJump) {
addBTI(MBB, CouldCall, CouldJump, HasWinCFI);
MadeChange = true;
@@ -129,8 +134,15 @@ void AArch64BranchTargets::addBTI(MachineBasicBlock &MBB, bool CouldCall,
assert(HintNum != 32 && "No target kinds!");
auto MBBI = MBB.begin();
+ bool SawEHLabel = false;
- // Skip the meta instructions, those will be removed anyway.
+ // If the block starts with EH_LABEL(s), skip them first and remember we saw
+ // one.
+ while (MBBI != MBB.end() && MBBI->isEHLabel()) {
+ ++MBBI;
+ SawEHLabel = true;
+ }
+ /// Skip the meta instructions, those will be removed anyway.
for (; MBBI != MBB.end() &&
(MBBI->isMetaInstruction() || MBBI->getOpcode() == AArch64::EMITBKEY);
++MBBI)
@@ -147,7 +159,12 @@ void AArch64BranchTargets::addBTI(MachineBasicBlock &MBB, bool CouldCall,
BuildMI(MBB, MBB.begin(), MBB.findDebugLoc(MBB.begin()),
TII->get(AArch64::SEH_Nop));
}
- BuildMI(MBB, MBB.begin(), MBB.findDebugLoc(MBB.begin()),
+ // Insertion policy:
+ // If the block started with an EH_LABEL, insert BTI after the label and
+ // meta (at MBBI).Otherwise, keep legacy behavior: insert at block begin
+ // (before CFI/SEH NOP), to preserve existing codegen/test expectations.
+ MachineBasicBlock::iterator InsertHere = SawEHLabel ? MBBI : MBB.begin();
+ BuildMI(MBB, InsertHere, MBB.findDebugLoc(InsertHere),
TII->get(AArch64::HINT))
.addImm(HintNum);
}
diff --git a/llvm/test/CodeGen/AArch64/bti-ehpad.ll b/llvm/test/CodeGen/AArch64/bti-ehpad.ll
new file mode 100644
index 0000000000000..ecafbcdafbf05
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/bti-ehpad.ll
@@ -0,0 +1,45 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; RUN: llc -mtriple=aarch64-unknown-linux-gnu %s -o - | FileCheck %s
+
+declare i32 @__gxx_personality_v0(...)
+declare void @may_throw()
+
+define void @test() #0 personality ptr @__gxx_personality_v0 {
+; CHECK-LABEL: {{^test:.*$}}
+; CHECK: .Lfunc_begin0:
+; CHECK-NEXT: .cfi_startproc
+; CHECK-NEXT: .cfi_personality 156, DW.ref.__gxx_personality_v0
+; CHECK-NEXT: .cfi_lsda 28, .Lexception0
+; CHECK-NEXT: // %bb.0: // %entry
+; CHECK-NEXT: bti c
+; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill
+; CHECK-NEXT: .cfi_def_cfa_offset 16
+; CHECK-NEXT: .cfi_offset w30, -16
+; CHECK-NEXT: .Ltmp0: // EH_LABEL
+; CHECK-NEXT: bl may_throw
+; CHECK-NEXT: .Ltmp1: // EH_LABEL
+; CHECK-NEXT: // %bb.1: // %common.ret
+; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload
+; CHECK-NEXT: ret
+; CHECK-NEXT: .LBB0_2: // %lpad
+; CHECK-NEXT: .Ltmp2: // EH_LABEL
+; CHECK-NEXT: bti j
+; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload
+; CHECK-NEXT: ret
+entry:
+ invoke void @may_throw()
+ to label %ret unwind label %lpad
+
+lpad:
+ landingpad { ptr, i32 } cleanup
+ ret void
+
+ret:
+ ret void
+}
+
+; Enforce BTI at codegen.
+attributes #0 = { noinline "branch-target-enforcement"="true" "target-features"="+bti" }
+
+; (No extra BTI checks needed—the autogenerated CHECK block above already
+; asserts that the landing pad label is followed by EH_LABEL and `bti j`.)
diff --git a/llvm/test/CodeGen/AArch64/wineh-bti-funclet.ll b/llvm/test/CodeGen/AArch64/wineh-bti-funclet.ll
new file mode 100644
index 0000000000000..0272f270bccee
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/wineh-bti-funclet.ll
@@ -0,0 +1,30 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; RUN: llc -mtriple=aarch64-windows -mattr=+bti -o - %s | FileCheck %s
+
+declare i32 @__CxxFrameHandler3(...)
+declare void @may_throw()
+
+define dso_local void @"?w@@YAXXZ"() #0 personality ptr @__CxxFrameHandler3 {
+entry:
+ invoke void @may_throw()
+ to label %try.cont unwind label %catch.dispatch
+
+catch.dispatch:
+ %cs = catchswitch within none [label %catch] unwind to caller
+
+catch:
+ %cp = catchpad within %cs [ptr null, i32 0, ptr null]
+ call void @may_throw() ["funclet"(token %cp)]
+ catchret from %cp to label %try.cont
+
+try.cont:
+ ret void
+}
+
+attributes #0 = { "branch-target-enforcement"="true" }
+
+; CHECK-LABEL: "?w@@YAXXZ":
+; Either 'bti c' / 'hint #34' or a PAC prologue satisfies call-like entry.
+; CHECK: {{(hint +#34|bti +c|paciasp|pacibsp)}}
+;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
+; CHECK: {{.*}}
More information about the llvm-commits
mailing list