[llvm] Fix https://github.com/llvm/llvm-project/issues/75998 (PR #82661)

Eleanor Bonnici via llvm-commits llvm-commits at lists.llvm.org
Thu Feb 22 09:43:55 PST 2024


https://github.com/eleanor-arm created https://github.com/llvm/llvm-project/pull/82661


When compiling for thumbv8.1m with +pacbti and making an indirect tail
call, the compiler was free to put the function pointer into R12.

This is incorrect because R12 is restored to contain authentication code
for the caller's return address.

This patch excludes R12 from the set of registers the compiler can put
the function pointer in.


>From e1a2e0dc0660f069819c42b58da83d345799cd2d Mon Sep 17 00:00:00 2001
From: Eleanor Bonnici <eleanor.bonnici at arm.com>
Date: Wed, 7 Feb 2024 12:53:34 +0000
Subject: [PATCH] Fix https://github.com/llvm/llvm-project/issues/75998

When compiling for thumbv8.1m with +pacbti and making an indirect tail
call, the compiler was free to put the function pointer into R12.

This is incorrect because R12 is restored to contain authentication code
for the caller's return address.

This patch excludes R12 from the set of registers the compiler can put
the function pointer in.
---
 llvm/lib/Target/ARM/ARMRegisterInfo.td        |  3 +-
 .../pacbti-m-indirect-tail-call-no-r12.ll     | 78 +++++++++++++++++++
 2 files changed, 80 insertions(+), 1 deletion(-)
 create mode 100644 llvm/test/CodeGen/Thumb2/pacbti-m-indirect-tail-call-no-r12.ll

diff --git a/llvm/lib/Target/ARM/ARMRegisterInfo.td b/llvm/lib/Target/ARM/ARMRegisterInfo.td
index 194d65cad8d170..025ca62d54376b 100644
--- a/llvm/lib/Target/ARM/ARMRegisterInfo.td
+++ b/llvm/lib/Target/ARM/ARMRegisterInfo.td
@@ -369,7 +369,8 @@ def hGPR : RegisterClass<"ARM", [i32], 32, (sub GPR, tGPR)> {
 def tcGPR : RegisterClass<"ARM", [i32], 32, (add R0, R1, R2, R3, R12)> {
   let AltOrders = [(and tcGPR, tGPR)];
   let AltOrderSelect = [{
-      return MF.getSubtarget<ARMSubtarget>().isThumb1Only();
+      return MF.getSubtarget<ARMSubtarget>().isThumb1Only() ||
+        MF.getInfo<ARMFunctionInfo>()->shouldSignReturnAddress(true);
   }];
 }
 
diff --git a/llvm/test/CodeGen/Thumb2/pacbti-m-indirect-tail-call-no-r12.ll b/llvm/test/CodeGen/Thumb2/pacbti-m-indirect-tail-call-no-r12.ll
new file mode 100644
index 00000000000000..844baa15500a3d
--- /dev/null
+++ b/llvm/test/CodeGen/Thumb2/pacbti-m-indirect-tail-call-no-r12.ll
@@ -0,0 +1,78 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4
+; RUN: llc %s -mtriple=thumbv8.1m.main -mattr=+pacbti -o - | 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"
+
+; Function Attrs: minsize nounwind optsize sspstrong
+define dso_local arm_aapcscc i32 @i3c_dev_do_priv_xfers_locked(ptr noundef %dev, ptr noundef %xfers, i32 noundef %nxfers) local_unnamed_addr #0 {
+; CHECK-LABEL: i3c_dev_do_priv_xfers_locked:
+; CHECK:       @ %bb.0: @ %entry
+; CHECK-NEXT:    pacbti r12, lr, sp
+; CHECK-NEXT:    push {r4, lr}
+; CHECK-NEXT:    str r12, [sp, #-4]!
+; CHECK-NEXT:    mov r3, r0
+; CHECK-NEXT:    mvn r0, #21
+; CHECK-NEXT:    cbz r1, .LBB0_5
+; CHECK-NEXT:  @ %bb.1: @ %entry
+; CHECK-NEXT:    ldr r4, [r3]
+; CHECK-NEXT:    cbz r4, .LBB0_5
+; CHECK-NEXT:  @ %bb.2: @ %if.end
+; CHECK-NEXT:    ldr r0, [r4]
+; CHECK-NEXT:    ldr r
+; CHECK-SAME-NOT      12
+; CHECK-SAME             , [r0]
+; CHECK-NEXT:    cbz r0, .LBB0_4
+; CHECK-NEXT:  @ %bb.3: @ %if.end5
+; CHECK-NEXT:    mov r4, r0
+; CHECK-NEXT:    mov r0, r3
+; CHECK-NEXT:    mov r3, r4
+; CHECK-NEXT:    ldr r12, [sp], #4
+; CHECK-NEXT:    pop.w {r4, lr}
+; CHECK-NEXT:    aut r12, lr, sp
+; CHECK-NEXT:    bx r
+; CHECK-SAME-NOT     12
+entry:
+  %0 = load ptr, ptr %dev, align 4, !tbaa !6
+  %tobool = icmp ne ptr %0, null
+  %tobool2 = icmp ne ptr %xfers, null
+  %or.cond = and i1 %tobool2, %tobool
+  br i1 %or.cond, label %if.end, label %cleanup
+
+if.end:                                           ; preds = %entry
+
+  %1 = load ptr, ptr %0, align 4, !tbaa !12
+  %2 = load ptr, ptr %1, align 4, !tbaa !14
+  %tobool3.not = icmp eq ptr %2, null
+  br i1 %tobool3.not, label %cleanup, label %if.end5
+
+if.end5:                                          ; preds = %if.end
+  %call = tail call arm_aapcscc i32 %2(ptr noundef nonnull %dev, ptr noundef nonnull %xfers, i32 noundef %nxfers) #1
+  br label %cleanup
+
+cleanup:                                          ; preds = %if.end, %entry, %if.end5
+  %retval.0 = phi i32 [ %call, %if.end5 ], [ -22, %entry ], [ -138, %if.end ]
+  ret i32 %retval.0
+}
+
+attributes #0 = { minsize sspstrong "target-features"="+armv8.1-m.main" }
+
+!llvm.module.flags = !{!0, !1, !2, !3, !4}
+!llvm.ident = !{!5}
+
+!0 = !{i32 1, !"wchar_size", i32 4}
+!1 = !{i32 1, !"min_enum_size", i32 1}
+!2 = !{i32 8, !"branch-target-enforcement", i32 1}
+!3 = !{i32 8, !"guarded-control-stack", i32 1}
+!4 = !{i32 8, !"sign-return-address", i32 1}
+!5 = !{!"clang version 18.0.0git (git at github.com:llvm/llvm-project.git 2db9244b6f66a4fd4c937de7b33a5b6dda4a06a8)"}
+!6 = !{!7, !9, i64 0}
+!7 = !{!"i3c_dev_desc", !8, i64 0}
+!8 = !{!"i3c_i2c_dev_desc", !9, i64 0}
+!9 = !{!"any pointer", !10, i64 0}
+!10 = !{!"omnipotent char", !11, i64 0}
+!11 = !{!"Simple C/C++ TBAA"}
+!12 = !{!13, !9, i64 0}
+!13 = !{!"i3c_master_controller", !9, i64 0}
+!14 = !{!15, !9, i64 0}
+!15 = !{!"i3c_master_controller_ops", !9, i64 0}



More information about the llvm-commits mailing list