[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