Skip to content

Commit cce4dc7

Browse files
authored
[SystemZ][z/OS] Implement llvm.returnaddress for XPLINK (#89440)
The implementation follows the ELF implementation.
1 parent bddfbe7 commit cce4dc7

File tree

4 files changed

+82
-16
lines changed

4 files changed

+82
-16
lines changed

llvm/lib/Target/SystemZ/SystemZFrameLowering.cpp

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -56,14 +56,17 @@ static const TargetFrameLowering::SpillSlot XPLINKSpillOffsetTable[] = {
5656

5757
SystemZFrameLowering::SystemZFrameLowering(StackDirection D, Align StackAl,
5858
int LAO, Align TransAl,
59-
bool StackReal)
60-
: TargetFrameLowering(D, StackAl, LAO, TransAl, StackReal) {}
59+
bool StackReal, unsigned PointerSize)
60+
: TargetFrameLowering(D, StackAl, LAO, TransAl, StackReal),
61+
PointerSize(PointerSize) {}
6162

6263
std::unique_ptr<SystemZFrameLowering>
6364
SystemZFrameLowering::create(const SystemZSubtarget &STI) {
65+
unsigned PtrSz =
66+
STI.getTargetLowering()->getTargetMachine().getPointerSize(0);
6467
if (STI.isTargetXPLINK64())
65-
return std::make_unique<SystemZXPLINKFrameLowering>();
66-
return std::make_unique<SystemZELFFrameLowering>();
68+
return std::make_unique<SystemZXPLINKFrameLowering>(PtrSz);
69+
return std::make_unique<SystemZELFFrameLowering>(PtrSz);
6770
}
6871

6972
namespace {
@@ -272,9 +275,9 @@ void SystemZELFFrameLowering::determineCalleeSaves(MachineFunction &MF,
272275
}
273276
}
274277

275-
SystemZELFFrameLowering::SystemZELFFrameLowering()
278+
SystemZELFFrameLowering::SystemZELFFrameLowering(unsigned PointerSize)
276279
: SystemZFrameLowering(TargetFrameLowering::StackGrowsDown, Align(8), 0,
277-
Align(8), /* StackRealignable */ false),
280+
Align(8), /* StackRealignable */ false, PointerSize),
278281
RegSpillOffsets(0) {
279282

280283
// Due to the SystemZ ABI, the DWARF CFA (Canonical Frame Address) is not
@@ -884,9 +887,10 @@ bool SystemZELFFrameLowering::usePackedStack(MachineFunction &MF) const {
884887
return HasPackedStackAttr && CallConv;
885888
}
886889

887-
SystemZXPLINKFrameLowering::SystemZXPLINKFrameLowering()
890+
SystemZXPLINKFrameLowering::SystemZXPLINKFrameLowering(unsigned PointerSize)
888891
: SystemZFrameLowering(TargetFrameLowering::StackGrowsDown, Align(32), 0,
889-
Align(32), /* StackRealignable */ false),
892+
Align(32), /* StackRealignable */ false,
893+
PointerSize),
890894
RegSpillOffsets(-1) {
891895

892896
// Create a mapping from register number to save slot offset.

llvm/lib/Target/SystemZ/SystemZFrameLowering.h

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ class SystemZSubtarget;
2222
class SystemZFrameLowering : public TargetFrameLowering {
2323
public:
2424
SystemZFrameLowering(StackDirection D, Align StackAl, int LAO, Align TransAl,
25-
bool StackReal);
25+
bool StackReal, unsigned PointerSize);
2626

2727
static std::unique_ptr<SystemZFrameLowering>
2828
create(const SystemZSubtarget &STI);
@@ -45,15 +45,24 @@ class SystemZFrameLowering : public TargetFrameLowering {
4545
// Return the offset of the backchain.
4646
virtual unsigned getBackchainOffset(MachineFunction &MF) const = 0;
4747

48+
// Return the offset of the return address.
49+
virtual int getReturnAddressOffset(MachineFunction &MF) const = 0;
50+
4851
// Get or create the frame index of where the old frame pointer is stored.
4952
virtual int getOrCreateFramePointerSaveIndex(MachineFunction &MF) const = 0;
53+
54+
// Return the size of a pointer (in bytes).
55+
unsigned getPointerSize() const { return PointerSize; }
56+
57+
private:
58+
unsigned PointerSize;
5059
};
5160

5261
class SystemZELFFrameLowering : public SystemZFrameLowering {
5362
IndexedMap<unsigned> RegSpillOffsets;
5463

5564
public:
56-
SystemZELFFrameLowering();
65+
SystemZELFFrameLowering(unsigned PointerSize);
5766

5867
// Override TargetFrameLowering.
5968
bool
@@ -97,6 +106,11 @@ class SystemZELFFrameLowering : public SystemZFrameLowering {
97106
return usePackedStack(MF) ? SystemZMC::ELFCallFrameSize - 8 : 0;
98107
}
99108

109+
// Return the offset of the return address.
110+
int getReturnAddressOffset(MachineFunction &MF) const override {
111+
return (usePackedStack(MF) ? -2 : 14) * getPointerSize();
112+
}
113+
100114
// Get or create the frame index of where the old frame pointer is stored.
101115
int getOrCreateFramePointerSaveIndex(MachineFunction &MF) const override;
102116
};
@@ -105,7 +119,7 @@ class SystemZXPLINKFrameLowering : public SystemZFrameLowering {
105119
IndexedMap<unsigned> RegSpillOffsets;
106120

107121
public:
108-
SystemZXPLINKFrameLowering();
122+
SystemZXPLINKFrameLowering(unsigned PointerSize);
109123

110124
bool
111125
assignCalleeSavedSpillSlots(MachineFunction &MF,
@@ -146,6 +160,11 @@ class SystemZXPLINKFrameLowering : public SystemZFrameLowering {
146160
return 0;
147161
}
148162

163+
// Return the offset of the return address.
164+
int getReturnAddressOffset(MachineFunction &MF) const override {
165+
return 3 * getPointerSize();
166+
}
167+
149168
// Get or create the frame index of where the old frame pointer is stored.
150169
int getOrCreateFramePointerSaveIndex(MachineFunction &MF) const override;
151170
};

llvm/lib/Target/SystemZ/SystemZISelLowering.cpp

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3816,17 +3816,19 @@ SDValue SystemZTargetLowering::lowerRETURNADDR(SDValue Op,
38163816
report_fatal_error("Unsupported stack frame traversal count");
38173817

38183818
SDValue FrameAddr = lowerFRAMEADDR(Op, DAG);
3819-
auto *TFL = Subtarget.getFrameLowering<SystemZELFFrameLowering>();
3820-
int Offset = (TFL->usePackedStack(MF) ? -2 : 14) *
3821-
getTargetMachine().getPointerSize(0);
3819+
const auto *TFL = Subtarget.getFrameLowering<SystemZFrameLowering>();
3820+
int Offset = TFL->getReturnAddressOffset(MF);
38223821
SDValue Ptr = DAG.getNode(ISD::ADD, DL, PtrVT, FrameAddr,
38233822
DAG.getConstant(Offset, DL, PtrVT));
38243823
return DAG.getLoad(PtrVT, DL, DAG.getEntryNode(), Ptr,
38253824
MachinePointerInfo());
38263825
}
38273826

3828-
// Return R14D, which has the return address. Mark it an implicit live-in.
3829-
Register LinkReg = MF.addLiveIn(SystemZ::R14D, &SystemZ::GR64BitRegClass);
3827+
// Return R14D (Elf) / R7D (XPLINK), which has the return address. Mark it an
3828+
// implicit live-in.
3829+
SystemZCallingConventionRegisters *CCR = Subtarget.getSpecialRegisters();
3830+
Register LinkReg = MF.addLiveIn(CCR->getReturnFunctionAddressRegister(),
3831+
&SystemZ::GR64BitRegClass);
38303832
return DAG.getCopyFromReg(DAG.getEntryNode(), DL, LinkReg, PtrVT);
38313833
}
38323834

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4
2+
; RUN: llc < %s -mtriple=s390x-ibm-zos | FileCheck %s
3+
4+
; The current function's return address is in the link register.
5+
define ptr @rt0() norecurse nounwind readnone {
6+
; CHECK-LABEL: rt0:
7+
; CHECK: lgr 3, 7
8+
; CHECK-NEXT: b 2(7)
9+
entry:
10+
%0 = tail call ptr @llvm.returnaddress(i32 0)
11+
ret ptr %0
12+
}
13+
14+
; Check the caller's return address.
15+
define ptr @rtcaller() nounwind "backchain" {
16+
; CHECK-LABEL: rtcaller:
17+
; CHECK: stmg 4, 7, 2048(4)
18+
; CHECK-NEXT: lg 1, 2048(4)
19+
; CHECK-NEXT: lg 3, 24(1)
20+
; CHECK-NEXT: lmg 4, 7, 2048(4)
21+
; CHECK-NEXT: b 2(7)
22+
entry:
23+
%0 = tail call ptr @llvm.returnaddress(i32 1)
24+
ret ptr %0
25+
}
26+
27+
; Check the caller's caller's return address.
28+
define ptr @rtcallercaller() nounwind "backchain" {
29+
; CHECK-LABEL: rtcallercaller:
30+
; CHECK: stmg 4, 7, 2048(4)
31+
; CHECK-NEXT: lg 1, 2048(4)
32+
; CHECK-NEXT: lg 1, 0(1)
33+
; CHECK-NEXT: lg 3, 24(1)
34+
; CHECK-NEXT: lmg 4, 7, 2048(4)
35+
; CHECK-NEXT: b 2(7)
36+
entry:
37+
%0 = tail call ptr @llvm.returnaddress(i32 2)
38+
ret ptr %0
39+
}
40+
41+
declare ptr @llvm.returnaddress(i32) nounwind readnone

0 commit comments

Comments
 (0)