[llvm] [AArch64][BTI] Add BTI at EH entries: BTI j for Itanium EH, BTI c for… (PR #155308)

Shashi Shankar via llvm-commits llvm-commits at lists.llvm.org
Mon Aug 25 14:40:54 PDT 2025


https://github.com/shashforge created https://github.com/llvm/llvm-project/pull/155308

[AArch64][BTI] Add BTI at EH entries

Mark EH landing pads as indirect-branch targets so we emit `bti j` on Itanium EH; treat WinEH funclet entries as call-like to emit `bti c`.

Tests:
  * bti-ehpad.ll: asserts BTI j (or HINT #36) at the landing pad.
  * wineh-bti-funclet.ll: enables +bti and asserts BTI-c (or PAC) at entry;
    use POSIX whitespace classes in FileCheck for portability.

Fixes: #149267


>From ea8c72f931c3817367607b27b94d9c6ab44accc5 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   |  9 ++++-
 llvm/test/CodeGen/AArch64/bti-ehpad.ll        | 29 ++++++++++++++++
 .../test/CodeGen/AArch64/wineh-bti-funclet.ll | 34 +++++++++++++++++++
 3 files changed, 71 insertions(+), 1 deletion(-)
 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..42315ec7eb503 100644
--- a/llvm/lib/Target/AArch64/AArch64BranchTargets.cpp
+++ b/llvm/lib/Target/AArch64/AArch64BranchTargets.cpp
@@ -97,12 +97,19 @@ bool AArch64BranchTargets::runOnMachineFunction(MachineFunction &MF) {
          (F.hasAddressTaken() || !F.hasLocalLinkage())))
       CouldCall = true;
 
+
     // If the block itself is address-taken, it could be indirectly branched
     // to, but not called.
     if (MBB.isMachineBlockAddressTaken() || MBB.isIRBlockAddressTaken() ||
-        JumpTableTargets.count(&MBB))
+        JumpTableTargets.count(&MBB) || MBB.isEHPad())
       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;
diff --git a/llvm/test/CodeGen/AArch64/bti-ehpad.ll b/llvm/test/CodeGen/AArch64/bti-ehpad.ll
new file mode 100644
index 0000000000000..1845cca46e72e
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/bti-ehpad.ll
@@ -0,0 +1,29 @@
+; REQUIRES: aarch64-registered-target
+; RUN: llc -mtriple=aarch64-unknown-linux-gnu %s -o - | FileCheck %s
+
+target triple = "aarch64-unknown-linux-gnu"
+
+declare i32 @__gxx_personality_v0(...)
+declare void @may_throw()
+
+define void @test() #0 personality ptr @__gxx_personality_v0 {
+entry:
+  invoke void @may_throw()
+          to label %ret unwind label %lpad
+
+lpad:
+  landingpad { ptr, i32 } cleanup
+  ret void
+
+ret:
+  ret void
+}
+
+; Request BTI in codegen.
+attributes #0 = { "branch-target-enforcement"="true" "target-features"="+bti" }
+
+; CHECK-LABEL: test:
+; The assembler prints the label line like: ".LBB0_2: // %lpad"
+; Match the EH pad comment, then the very next line must be BTI j (or HINT #36).
+; CHECK:      {{//[[:space:]]*%lpad}}
+; CHECK-NEXT: {{(bti[[:space:]]+j|hint[[:space:]]+#36)}}
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..31e193b5425d4
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/wineh-bti-funclet.ll
@@ -0,0 +1,34 @@
+; REQUIRES: aarch64-registered-target
+; RUN: llc -mtriple=aarch64-windows -mattr=+bti -o - %s | FileCheck %s
+
+target triple = "aarch64-unknown-windows-msvc"
+
+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]
+  ; Put some code in the funclet so it materializes with text.
+  call void @may_throw() ["funclet"(token %cp)]
+  catchret from %cp to label %try.cont
+
+try.cont:
+  ret void
+}
+
+; Ask for BTI enforcement at the function level (the RUN line already enables +bti).
+attributes #0 = { "branch-target-enforcement"="true" }
+
+; Function entry should accept call-like entries:
+;  - Either 'hint #34' / 'bti c'
+;  - Or a PAC prologue (paciasp/pacibsp), which also satisfies BTI-c
+; CHECK-LABEL: "?w@@YAXXZ":
+; CHECK: {{(hint[[:space:]]+#34|bti[[:space:]]+c|paciasp|pacibsp)}}



More information about the llvm-commits mailing list