[llvm] [ARM] Lower addressofreturnaddress on ARM (PR #195909)

via llvm-commits llvm-commits at lists.llvm.org
Tue May 5 11:58:15 PDT 2026


https://github.com/LumioseSil created https://github.com/llvm/llvm-project/pull/195909

Microsoft says it is available for ARM.

>From 4037d1b863113b2fa52dcac9c9a7da954bc74735 Mon Sep 17 00:00:00 2001
From: AZero13 <gfunni234 at gmail.com>
Date: Tue, 5 May 2026 14:55:40 -0400
Subject: [PATCH] [ARM] Lower addressofreturnaddress on ARM

Microsoft says it is available for ARM.
---
 llvm/lib/Target/ARM/ARMISelLowering.cpp       | 19 ++++++
 llvm/lib/Target/ARM/ARMISelLowering.h         |  1 +
 llvm/test/CodeGen/AArch64/addr-of-ret-addr.ll |  4 +-
 llvm/test/CodeGen/ARM/addr-of-ret-addr.ll     | 67 +++++++++++++++++++
 4 files changed, 89 insertions(+), 2 deletions(-)
 create mode 100644 llvm/test/CodeGen/ARM/addr-of-ret-addr.ll

diff --git a/llvm/lib/Target/ARM/ARMISelLowering.cpp b/llvm/lib/Target/ARM/ARMISelLowering.cpp
index cbff40f697b9b..86b877f55d730 100644
--- a/llvm/lib/Target/ARM/ARMISelLowering.cpp
+++ b/llvm/lib/Target/ARM/ARMISelLowering.cpp
@@ -5871,6 +5871,23 @@ SDValue ARMTargetLowering::LowerFCOPYSIGN(SDValue Op, SelectionDAG &DAG) const {
   return DAG.getNode(ARMISD::VMOVDRR, dl, MVT::f64, Lo, Hi);
 }
 
+SDValue ARMTargetLowering::LowerADDROFRETURNADDR(SDValue Op,
+                                                 SelectionDAG &DAG) const {
+  const ARMBaseRegisterInfo &ARI =
+      *static_cast<const ARMBaseRegisterInfo *>(RegInfo);
+  DAG.getMachineFunction().getFrameInfo().setFrameAddressIsTaken(true);
+
+  EVT VT = Op.getValueType();
+  SDLoc DL(Op);
+
+  MachineFunction &MF = DAG.getMachineFunction();
+  SDValue FrameAddr =
+      DAG.getCopyFromReg(DAG.getEntryNode(), DL, ARI.getFrameRegister(MF), VT);
+  SDValue Offset = DAG.getConstant(4, DL, getPointerTy(DAG.getDataLayout()));
+
+  return DAG.getNode(ISD::ADD, DL, VT, FrameAddr, Offset);
+}
+
 SDValue ARMTargetLowering::LowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const{
   MachineFunction &MF = DAG.getMachineFunction();
   MachineFrameInfo &MFI = MF.getFrameInfo();
@@ -10450,6 +10467,8 @@ SDValue ARMTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
   case ISD::FCOPYSIGN:     return LowerFCOPYSIGN(Op, DAG);
   case ISD::RETURNADDR:    return LowerRETURNADDR(Op, DAG);
   case ISD::FRAMEADDR:     return LowerFRAMEADDR(Op, DAG);
+  case ISD::ADDROFRETURNADDR:
+    return LowerADDROFRETURNADDR(Op, DAG);
   case ISD::EH_SJLJ_SETJMP: return LowerEH_SJLJ_SETJMP(Op, DAG);
   case ISD::EH_SJLJ_LONGJMP: return LowerEH_SJLJ_LONGJMP(Op, DAG);
   case ISD::EH_SJLJ_SETUP_DISPATCH: return LowerEH_SJLJ_SETUP_DISPATCH(Op, DAG);
diff --git a/llvm/lib/Target/ARM/ARMISelLowering.h b/llvm/lib/Target/ARM/ARMISelLowering.h
index 491beb5434555..a75688e2d6346 100644
--- a/llvm/lib/Target/ARM/ARMISelLowering.h
+++ b/llvm/lib/Target/ARM/ARMISelLowering.h
@@ -577,6 +577,7 @@ class VectorType;
     SDValue LowerFCOPYSIGN(SDValue Op, SelectionDAG &DAG) const;
     SDValue LowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const;
     SDValue LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const;
+    SDValue LowerADDROFRETURNADDR(SDValue Op, SelectionDAG &DAG) const;
     SDValue LowerShiftRightParts(SDValue Op, SelectionDAG &DAG) const;
     SDValue LowerShiftLeftParts(SDValue Op, SelectionDAG &DAG) const;
     SDValue LowerGET_ROUNDING(SDValue Op, SelectionDAG &DAG) const;
diff --git a/llvm/test/CodeGen/AArch64/addr-of-ret-addr.ll b/llvm/test/CodeGen/AArch64/addr-of-ret-addr.ll
index b6ec9eb569436..e1cfd478ed0b0 100644
--- a/llvm/test/CodeGen/AArch64/addr-of-ret-addr.ll
+++ b/llvm/test/CodeGen/AArch64/addr-of-ret-addr.ll
@@ -15,7 +15,7 @@
 declare void @llvm.va_start(ptr)
 declare ptr @llvm.addressofreturnaddress()
 
-define dso_local ptr @"foo"() {
+define dso_local ptr @foo() {
 ; CHECK-LABEL: foo:
 ; CHECK:       .seh_proc foo
 ; CHECK-NEXT:  // %bb.0: // %entry
@@ -37,7 +37,7 @@ entry:
   ret ptr %0
 }
 
-define dso_local i32 @"bar"(ptr %x, ...) {
+define dso_local i32 @bar(ptr %x, ...) {
 ; CHECK-LABEL: bar:
 ; CHECK:       .seh_proc bar
 ; CHECK-NEXT:  // %bb.0: // %entry
diff --git a/llvm/test/CodeGen/ARM/addr-of-ret-addr.ll b/llvm/test/CodeGen/ARM/addr-of-ret-addr.ll
new file mode 100644
index 0000000000000..8107081e25884
--- /dev/null
+++ b/llvm/test/CodeGen/ARM/addr-of-ret-addr.ll
@@ -0,0 +1,67 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 3
+; RUN: llc < %s -frame-pointer=all -mtriple=thumbv7-unknown-linux-gnueabihf | FileCheck %s
+
+; Test generated from C code:
+; #include <stdarg.h>
+; ptr foo() {
+;   return _AddressOfReturnAddress();
+; }
+; int bar(int x(va_list, ptr), ...) {
+;   va_list y;
+;   va_start(y, x);
+;   return x(y, _AddressOfReturnAddress()) + 1;
+; }
+
+declare void @llvm.va_start(ptr)
+declare ptr @llvm.addressofreturnaddress()
+
+define dso_local ptr @foo() {
+; CHECK-LABEL: foo:
+; CHECK:       @ %bb.0: @ %entry
+; CHECK-NEXT:    .save {r7, lr}
+; CHECK-NEXT:    push {r7, lr}
+; CHECK-NEXT:    .setfp r7, sp
+; CHECK-NEXT:    mov r7, sp
+; CHECK-NEXT:    adds r0, r7, #4
+; CHECK-NEXT:    pop {r7, pc}
+entry:
+  %0 = call ptr @llvm.addressofreturnaddress()
+  ret ptr %0
+}
+
+define dso_local i32 @bar(ptr %x, ...) {
+; CHECK-LABEL: bar:
+; CHECK:       @ %bb.0: @ %entry
+; CHECK-NEXT:    .pad #12
+; CHECK-NEXT:    sub sp, #12
+; CHECK-NEXT:    .save {r7, lr}
+; CHECK-NEXT:    push {r7, lr}
+; CHECK-NEXT:    .setfp r7, sp
+; CHECK-NEXT:    mov r7, sp
+; CHECK-NEXT:    .pad #12
+; CHECK-NEXT:    sub sp, #12
+; CHECK-NEXT:    add.w lr, r7, #8
+; CHECK-NEXT:    mov r12, r0
+; CHECK-NEXT:    add.w r0, r7, #8
+; CHECK-NEXT:    str r0, [sp]
+; CHECK-NEXT:    stm.w lr, {r1, r2, r3}
+; CHECK-NEXT:    adds r1, r7, #4
+; CHECK-NEXT:    str.w r12, [sp, #8]
+; CHECK-NEXT:    blx r12
+; CHECK-NEXT:    adds r0, #1
+; CHECK-NEXT:    add sp, #12
+; CHECK-NEXT:    pop.w {r7, lr}
+; CHECK-NEXT:    add sp, #12
+; CHECK-NEXT:    bx lr
+entry:
+  %x.addr = alloca ptr, align 8
+  %y = alloca ptr, align 8
+  store ptr %x, ptr %x.addr, align 8
+  call void @llvm.va_start(ptr %y)
+  %0 = load ptr, ptr %x.addr, align 8
+  %1 = call ptr @llvm.addressofreturnaddress()
+  %2 = load ptr, ptr %y, align 8
+  %call = call i32 %0(ptr %2, ptr %1)
+  %add = add nsw i32 %call, 1
+  ret i32 %add
+}



More information about the llvm-commits mailing list