Skip to content

Commit

Permalink
[SystemZ] Support builtin_{frame,return}_address() with non-zero argu…
Browse files Browse the repository at this point in the history
…ment (#69405)

When the code is built with -mbackchain, it is possible to retrieve the
caller's frame and return addresses. GCC already can do this, add this
support to Clang as well. Use RISCVTargetLowering and GCC's
s390_return_addr_rtx() as inspiration. Add tests based on what GCC is
emitting.
  • Loading branch information
iii-i authored Oct 18, 2023
1 parent b69081e commit 8e810dc
Show file tree
Hide file tree
Showing 5 changed files with 128 additions and 4 deletions.
26 changes: 22 additions & 4 deletions llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3620,9 +3620,17 @@ SDValue SystemZTargetLowering::lowerFRAMEADDR(SDValue Op,
int BackChainIdx = TFL->getOrCreateFramePointerSaveIndex(MF);
SDValue BackChain = DAG.getFrameIndex(BackChainIdx, PtrVT);

// FIXME The frontend should detect this case.
if (Depth > 0) {
report_fatal_error("Unsupported stack frame traversal count");
// FIXME The frontend should detect this case.
if (!MF.getFunction().hasFnAttribute("backchain"))
report_fatal_error("Unsupported stack frame traversal count");

SDValue Offset = DAG.getConstant(TFL->getBackchainOffset(MF), DL, PtrVT);
while (Depth--) {
BackChain = DAG.getLoad(PtrVT, DL, DAG.getEntryNode(), BackChain,
MachinePointerInfo());
BackChain = DAG.getNode(ISD::ADD, DL, PtrVT, BackChain, Offset);
}
}

return BackChain;
Expand All @@ -3641,9 +3649,19 @@ SDValue SystemZTargetLowering::lowerRETURNADDR(SDValue Op,
unsigned Depth = cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue();
EVT PtrVT = getPointerTy(DAG.getDataLayout());

// FIXME The frontend should detect this case.
if (Depth > 0) {
report_fatal_error("Unsupported stack frame traversal count");
// FIXME The frontend should detect this case.
if (!MF.getFunction().hasFnAttribute("backchain"))
report_fatal_error("Unsupported stack frame traversal count");

SDValue FrameAddr = lowerFRAMEADDR(Op, DAG);
auto *TFL = Subtarget.getFrameLowering<SystemZELFFrameLowering>();
int Offset = (TFL->usePackedStack(MF) ? -2 : 14) *
getTargetMachine().getPointerSize(0);
SDValue Ptr = DAG.getNode(ISD::ADD, DL, PtrVT, FrameAddr,
DAG.getConstant(Offset, DL, PtrVT));
return DAG.getLoad(PtrVT, DL, DAG.getEntryNode(), Ptr,
MachinePointerInfo());
}

// Return R14D, which has the return address. Mark it an implicit live-in.
Expand Down
21 changes: 21 additions & 0 deletions llvm/test/CodeGen/SystemZ/frameaddr-01.ll
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,25 @@ entry:
ret ptr %1
}

; Check the caller's frame address.
define ptr @fpcaller() nounwind "backchain" {
entry:
; CHECK-LABEL: fpcaller:
; CHECK: lg %r2, 0(%r15)
; CHECK: br %r14
%0 = tail call ptr @llvm.frameaddress(i32 1)
ret ptr %0
}

; Check the caller's frame address.
define ptr @fpcallercaller() nounwind "backchain" {
entry:
; CHECK-LABEL: fpcallercaller:
; CHECK: lg %r1, 0(%r15)
; CHECK: lg %r2, 0(%r1)
; CHECK: br %r14
%0 = tail call ptr @llvm.frameaddress(i32 2)
ret ptr %0
}

declare ptr @llvm.frameaddress(i32) nounwind readnone
23 changes: 23 additions & 0 deletions llvm/test/CodeGen/SystemZ/frameaddr-02.ll
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,29 @@ entry:
ret ptr %1
}

; Check the caller's frame address.
define ptr @fpcaller() #0 {
entry:
; CHECK-LABEL: fpcaller:
; CHECK: lghi %r2, 152
; CHECK: ag %r2, 152(%r15)
; CHECK: br %r14
%0 = tail call ptr @llvm.frameaddress(i32 1)
ret ptr %0
}

; Check the caller's caller's frame address.
define ptr @fpcallercaller() #0 {
entry:
; CHECK-LABEL: fpcallercaller:
; CHECK: lg %r1, 152(%r15)
; CHECK: lghi %r2, 152
; CHECK: ag %r2, 152(%r1)
; CHECK: br %r14
%0 = tail call ptr @llvm.frameaddress(i32 2)
ret ptr %0
}

; Without back chain

attributes #1 = { nounwind "packed-stack" }
Expand Down
23 changes: 23 additions & 0 deletions llvm/test/CodeGen/SystemZ/ret-addr-01.ll
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,27 @@ entry:
ret ptr %0
}

; Check the caller's return address.
define ptr @rtcaller() nounwind "backchain" {
entry:
; CHECK-LABEL: rtcaller:
; CHECK: lg %r1, 0(%r15)
; CHECK lg %r2, 112(%r1)
; CHECK: br %r14
%0 = tail call ptr @llvm.returnaddress(i32 1)
ret ptr %0
}

; Check the caller's caller's return address.
define ptr @rtcallercaller() nounwind "backchain" {
entry:
; CHECK-LABEL: rtcallercaller:
; CHECK: lg %r1, 0(%r15)
; CHECK: lg %r1, 0(%r1)
; CHECK lg %r2, 112(%r1)
; CHECK: br %r14
%0 = tail call ptr @llvm.returnaddress(i32 2)
ret ptr %0
}

declare ptr @llvm.returnaddress(i32) nounwind readnone
39 changes: 39 additions & 0 deletions llvm/test/CodeGen/SystemZ/ret-addr-02.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
; Test support for the llvm.returnaddress intrinsic with packed-stack.

; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s

; The current function's return address is in the link register.
attributes #0 = { nounwind "packed-stack" "backchain" "use-soft-float"="true" }
define ptr @rt0() #0 {
entry:
; CHECK-LABEL: rt0:
; CHECK: lgr %r2, %r14
; CHECK: br %r14
%0 = tail call ptr @llvm.returnaddress(i32 0)
ret ptr %0
}

; Check the caller's return address.
define ptr @rtcaller() #0 {
entry:
; CHECK-LABEL: rtcaller:
; CHECK: lg %r1, 152(%r15)
; CHECK lg %r2, 136(%r1)
; CHECK: br %r14
%0 = tail call ptr @llvm.returnaddress(i32 1)
ret ptr %0
}

; Check the caller's caller's return address.
define ptr @rtcallercaller() #0 {
entry:
; CHECK-LABEL: rtcallercaller:
; CHECK: lg %r1, 152(%r15)
; CHECK: lg %r1, 152(%r1)
; CHECK lg %r2, 136(%r1)
; CHECK: br %r14
%0 = tail call ptr @llvm.returnaddress(i32 2)
ret ptr %0
}

declare ptr @llvm.returnaddress(i32) nounwind readnone

0 comments on commit 8e810dc

Please sign in to comment.