[llvm] [ARM] Lower addressofreturnaddress on ARM (PR #195909)
via llvm-commits
llvm-commits at lists.llvm.org
Tue May 5 11:59:01 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-aarch64
Author: LumioseSil (LumioseSil)
<details>
<summary>Changes</summary>
Microsoft says it is available for ARM.
---
Full diff: https://github.com/llvm/llvm-project/pull/195909.diff
4 Files Affected:
- (modified) llvm/lib/Target/ARM/ARMISelLowering.cpp (+19)
- (modified) llvm/lib/Target/ARM/ARMISelLowering.h (+1)
- (modified) llvm/test/CodeGen/AArch64/addr-of-ret-addr.ll (+2-2)
- (added) llvm/test/CodeGen/ARM/addr-of-ret-addr.ll (+67)
``````````diff
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
+}
``````````
</details>
https://github.com/llvm/llvm-project/pull/195909
More information about the llvm-commits
mailing list