Skip to content

Commit 97982a8

Browse files
authored
[RISCV][CFI] add function epilogue cfi information (#110810)
This patch adds CFI instructions in the function epilogue. Before patch: addi sp, s0, -32 ld ra, 24(sp) # 8-byte Folded Reload ld s0, 16(sp) # 8-byte Folded Reload ld s1, 8(sp) # 8-byte Folded Reload addi sp, sp, 32 ret After patch: addi sp, s0, -32 .cfi_def_cfa sp, 32 ld ra, 24(sp) # 8-byte Folded Reload ld s0, 16(sp) # 8-byte Folded Reload ld s1, 8(sp) # 8-byte Folded Reload .cfi_restore ra .cfi_restore s0 .cfi_restore s1 addi sp, sp, 32 .cfi_def_cfa_offset 0 ret This functionality is already present in `riscv-gcc`, but it’s not in `clang` and this slightly impairs the `lldb` debugging experience, e.g. backtrace.
1 parent 850d42f commit 97982a8

File tree

304 files changed

+5606
-102
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

304 files changed

+5606
-102
lines changed

llvm/lib/Target/RISCV/RISCVFrameLowering.cpp

Lines changed: 199 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -413,6 +413,25 @@ getRVVCalleeSavedInfo(const MachineFunction &MF,
413413
return RVVCSI;
414414
}
415415

416+
static SmallVector<CalleeSavedInfo, 8>
417+
getPushOrLibCallsSavedInfo(const MachineFunction &MF,
418+
const std::vector<CalleeSavedInfo> &CSI) {
419+
auto *RVFI = MF.getInfo<RISCVMachineFunctionInfo>();
420+
421+
SmallVector<CalleeSavedInfo, 8> PushPopOrLibCallsCSI;
422+
if (!RVFI->useSaveRestoreLibCalls(MF) && !RVFI->isPushable(MF))
423+
return PushPopOrLibCallsCSI;
424+
425+
for (auto &CS : CSI) {
426+
const auto *FII = llvm::find_if(
427+
FixedCSRFIMap, [&](auto P) { return P.first == CS.getReg(); });
428+
if (FII != std::end(FixedCSRFIMap))
429+
PushPopOrLibCallsCSI.push_back(CS);
430+
}
431+
432+
return PushPopOrLibCallsCSI;
433+
}
434+
416435
void RISCVFrameLowering::adjustStackForRVV(MachineFunction &MF,
417436
MachineBasicBlock &MBB,
418437
MachineBasicBlock::iterator MBBI,
@@ -557,6 +576,8 @@ void RISCVFrameLowering::emitPrologue(MachineFunction &MF,
557576
// Determine the correct frame layout
558577
determineFrameLayout(MF);
559578

579+
const auto &CSI = MFI.getCalleeSavedInfo();
580+
560581
// If libcalls are used to spill and restore callee-saved registers, the frame
561582
// has two sections; the opaque section managed by the libcalls, and the
562583
// section managed by MachineFrameInfo which can also hold callee saved
@@ -582,6 +603,23 @@ void RISCVFrameLowering::emitPrologue(MachineFunction &MF,
582603
unsigned LibCallFrameSize =
583604
alignTo((STI.getXLen() / 8) * LibCallRegs, getStackAlign());
584605
RVFI->setLibCallStackSize(LibCallFrameSize);
606+
607+
unsigned CFIIndex = MF.addFrameInst(
608+
MCCFIInstruction::cfiDefCfaOffset(nullptr, LibCallFrameSize));
609+
BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION))
610+
.addCFIIndex(CFIIndex)
611+
.setMIFlag(MachineInstr::FrameSetup);
612+
613+
for (const auto &Entry : getPushOrLibCallsSavedInfo(MF, CSI)) {
614+
int FrameIdx = Entry.getFrameIdx();
615+
int64_t Offset = MFI.getObjectOffset(FrameIdx);
616+
Register Reg = Entry.getReg();
617+
unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset(
618+
nullptr, RI->getDwarfRegNum(Reg, true), Offset));
619+
BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION))
620+
.addCFIIndex(CFIIndex)
621+
.setMIFlag(MachineInstr::FrameSetup);
622+
}
585623
}
586624

587625
// FIXME (note copied from Lanai): This appears to be overallocating. Needs
@@ -616,23 +654,38 @@ void RISCVFrameLowering::emitPrologue(MachineFunction &MF,
616654
uint64_t Spimm = std::min(alignDown(StackSize, 16), (uint64_t)48);
617655
FirstFrameSetup->getOperand(1).setImm(Spimm);
618656
StackSize -= Spimm;
657+
658+
unsigned CFIIndex = MF.addFrameInst(
659+
MCCFIInstruction::cfiDefCfaOffset(nullptr, RealStackSize - StackSize));
660+
BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION))
661+
.addCFIIndex(CFIIndex)
662+
.setMIFlag(MachineInstr::FrameSetup);
663+
664+
for (const auto &Entry : getPushOrLibCallsSavedInfo(MF, CSI)) {
665+
int FrameIdx = Entry.getFrameIdx();
666+
int64_t Offset = MFI.getObjectOffset(FrameIdx);
667+
Register Reg = Entry.getReg();
668+
unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset(
669+
nullptr, RI->getDwarfRegNum(Reg, true), Offset));
670+
BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION))
671+
.addCFIIndex(CFIIndex)
672+
.setMIFlag(MachineInstr::FrameSetup);
673+
}
619674
}
620675

621676
if (StackSize != 0) {
622677
// Allocate space on the stack if necessary.
623678
RI->adjustReg(MBB, MBBI, DL, SPReg, SPReg,
624679
StackOffset::getFixed(-StackSize), MachineInstr::FrameSetup,
625680
getStackAlign());
626-
}
627-
628-
// Emit ".cfi_def_cfa_offset RealStackSize"
629-
unsigned CFIIndex = MF.addFrameInst(
630-
MCCFIInstruction::cfiDefCfaOffset(nullptr, RealStackSize));
631-
BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION))
632-
.addCFIIndex(CFIIndex)
633-
.setMIFlag(MachineInstr::FrameSetup);
634681

635-
const auto &CSI = MFI.getCalleeSavedInfo();
682+
// Emit ".cfi_def_cfa_offset RealStackSize"
683+
unsigned CFIIndex = MF.addFrameInst(
684+
MCCFIInstruction::cfiDefCfaOffset(nullptr, RealStackSize));
685+
BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION))
686+
.addCFIIndex(CFIIndex)
687+
.setMIFlag(MachineInstr::FrameSetup);
688+
}
636689

637690
// The frame pointer is callee-saved, and code has been generated for us to
638691
// save it to the stack. We need to skip over the storing of callee-saved
@@ -644,7 +697,7 @@ void RISCVFrameLowering::emitPrologue(MachineFunction &MF,
644697

645698
// Iterate over list of callee-saved registers and emit .cfi_offset
646699
// directives.
647-
for (const auto &Entry : CSI) {
700+
for (const auto &Entry : getUnmanagedCSI(MF, CSI)) {
648701
int FrameIdx = Entry.getFrameIdx();
649702
if (FrameIdx >= 0 &&
650703
MFI.getStackID(FrameIdx) == TargetStackID::ScalableVector)
@@ -759,19 +812,29 @@ void RISCVFrameLowering::emitPrologue(MachineFunction &MF,
759812
void RISCVFrameLowering::deallocateStack(MachineFunction &MF,
760813
MachineBasicBlock &MBB,
761814
MachineBasicBlock::iterator MBBI,
762-
const DebugLoc &DL, uint64_t StackSize,
815+
const DebugLoc &DL,
816+
uint64_t &StackSize,
763817
int64_t CFAOffset) const {
764818
const RISCVRegisterInfo *RI = STI.getRegisterInfo();
819+
const RISCVInstrInfo *TII = STI.getInstrInfo();
765820

766821
RI->adjustReg(MBB, MBBI, DL, SPReg, SPReg, StackOffset::getFixed(StackSize),
767822
MachineInstr::FrameDestroy, getStackAlign());
823+
StackSize = 0;
824+
825+
unsigned CFIIndex =
826+
MF.addFrameInst(MCCFIInstruction::cfiDefCfaOffset(nullptr, CFAOffset));
827+
BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION))
828+
.addCFIIndex(CFIIndex)
829+
.setMIFlag(MachineInstr::FrameDestroy);
768830
}
769831

770832
void RISCVFrameLowering::emitEpilogue(MachineFunction &MF,
771833
MachineBasicBlock &MBB) const {
772834
const RISCVRegisterInfo *RI = STI.getRegisterInfo();
773835
MachineFrameInfo &MFI = MF.getFrameInfo();
774836
auto *RVFI = MF.getInfo<RISCVMachineFunctionInfo>();
837+
const RISCVInstrInfo *TII = STI.getInstrInfo();
775838

776839
// All calls are tail calls in GHC calling conv, and functions have no
777840
// prologue/epilogue.
@@ -814,15 +877,25 @@ void RISCVFrameLowering::emitEpilogue(MachineFunction &MF,
814877
RVFI->getVarArgsSaveSize();
815878
uint64_t RVVStackSize = RVFI->getRVVStackSize();
816879

817-
bool RestoreFP = RI->hasStackRealignment(MF) || MFI.hasVarSizedObjects() ||
818-
!hasReservedCallFrame(MF);
819-
880+
bool RestoreSPFromFP = RI->hasStackRealignment(MF) ||
881+
MFI.hasVarSizedObjects() || !hasReservedCallFrame(MF);
820882
if (RVVStackSize) {
821-
// If RestoreFP the stack pointer will be restored using the frame pointer
822-
// value.
823-
if (!RestoreFP)
883+
// If RestoreSPFromFP the stack pointer will be restored using the frame
884+
// pointer value.
885+
if (!RestoreSPFromFP)
824886
adjustStackForRVV(MF, MBB, LastFrameDestroy, DL, RVVStackSize,
825887
MachineInstr::FrameDestroy);
888+
889+
if (!hasFP(MF)) {
890+
unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::cfiDefCfa(
891+
nullptr, RI->getDwarfRegNum(SPReg, true), RealStackSize));
892+
BuildMI(MBB, LastFrameDestroy, DL,
893+
TII->get(TargetOpcode::CFI_INSTRUCTION))
894+
.addCFIIndex(CFIIndex)
895+
.setMIFlag(MachineInstr::FrameDestroy);
896+
}
897+
898+
emitCalleeSavedRVVEpilogCFI(MBB, LastFrameDestroy);
826899
}
827900

828901
if (FirstSPAdjustAmount) {
@@ -831,12 +904,21 @@ void RISCVFrameLowering::emitEpilogue(MachineFunction &MF,
831904
assert(SecondSPAdjustAmount > 0 &&
832905
"SecondSPAdjustAmount should be greater than zero");
833906

834-
// If RestoreFP the stack pointer will be restored using the frame pointer
835-
// value.
836-
if (!RestoreFP)
907+
// If RestoreSPFromFP the stack pointer will be restored using the frame
908+
// pointer value.
909+
if (!RestoreSPFromFP)
837910
RI->adjustReg(MBB, LastFrameDestroy, DL, SPReg, SPReg,
838911
StackOffset::getFixed(SecondSPAdjustAmount),
839912
MachineInstr::FrameDestroy, getStackAlign());
913+
914+
if (!hasFP(MF)) {
915+
unsigned CFIIndex = MF.addFrameInst(
916+
MCCFIInstruction::cfiDefCfaOffset(nullptr, FirstSPAdjustAmount));
917+
BuildMI(MBB, LastFrameDestroy, DL,
918+
TII->get(TargetOpcode::CFI_INSTRUCTION))
919+
.addCFIIndex(CFIIndex)
920+
.setMIFlag(MachineInstr::FrameDestroy);
921+
}
840922
}
841923

842924
// Restore the stack pointer using the value of the frame pointer. Only
@@ -849,14 +931,44 @@ void RISCVFrameLowering::emitEpilogue(MachineFunction &MF,
849931
// normally it's just checking the variable sized object is present or not
850932
// is enough, but we also don't preserve that at prologue/epilogue when
851933
// have vector objects in stack.
852-
if (RestoreFP) {
934+
if (RestoreSPFromFP) {
853935
assert(hasFP(MF) && "frame pointer should not have been eliminated");
854-
855936
RI->adjustReg(MBB, LastFrameDestroy, DL, SPReg, FPReg,
856937
StackOffset::getFixed(-FPOffset), MachineInstr::FrameDestroy,
857938
getStackAlign());
858939
}
859940

941+
if (hasFP(MF)) {
942+
unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::cfiDefCfa(
943+
nullptr, RI->getDwarfRegNum(SPReg, true), RealStackSize));
944+
BuildMI(MBB, LastFrameDestroy, DL, TII->get(TargetOpcode::CFI_INSTRUCTION))
945+
.addCFIIndex(CFIIndex)
946+
.setMIFlag(MachineInstr::FrameDestroy);
947+
}
948+
949+
if (getLibCallID(MF, CSI) != -1) {
950+
// tail __riscv_restore_[0-12] instruction is considered as a terminator,
951+
// therefor it is unnecessary to place any CFI instructions after it. Just
952+
// deallocate stack if needed and return.
953+
if (StackSize != 0)
954+
deallocateStack(MF, MBB, MBBI, DL, StackSize,
955+
RVFI->getLibCallStackSize());
956+
957+
// Emit epilogue for shadow call stack.
958+
emitSCSEpilogue(MF, MBB, MBBI, DL);
959+
return;
960+
}
961+
962+
// Recover callee-saved registers.
963+
for (const auto &Entry : getUnmanagedCSI(MF, CSI)) {
964+
Register Reg = Entry.getReg();
965+
unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createRestore(
966+
nullptr, RI->getDwarfRegNum(Reg, true)));
967+
BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION))
968+
.addCFIIndex(CFIIndex)
969+
.setMIFlag(MachineInstr::FrameDestroy);
970+
}
971+
860972
bool ApplyPop = RVFI->isPushable(MF) && MBBI != MBB.end() &&
861973
MBBI->getOpcode() == RISCV::CM_POP;
862974
if (ApplyPop) {
@@ -872,12 +984,31 @@ void RISCVFrameLowering::emitEpilogue(MachineFunction &MF,
872984
deallocateStack(MF, MBB, MBBI, DL, StackSize,
873985
/*stack_adj of cm.pop instr*/ RealStackSize - StackSize);
874986

875-
++MBBI;
987+
auto NextI = next_nodbg(MBBI, MBB.end());
988+
if (NextI == MBB.end() || NextI->getOpcode() != RISCV::PseudoRET) {
989+
++MBBI;
990+
991+
for (const auto &Entry : getPushOrLibCallsSavedInfo(MF, CSI)) {
992+
Register Reg = Entry.getReg();
993+
unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createRestore(
994+
nullptr, RI->getDwarfRegNum(Reg, true)));
995+
BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION))
996+
.addCFIIndex(CFIIndex)
997+
.setMIFlag(MachineInstr::FrameDestroy);
998+
}
999+
1000+
// Update CFA offset. After CM_POP SP should be equal to CFA, so CFA
1001+
// offset should be a zero.
1002+
unsigned CFIIndex =
1003+
MF.addFrameInst(MCCFIInstruction::cfiDefCfaOffset(nullptr, 0));
1004+
BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION))
1005+
.addCFIIndex(CFIIndex)
1006+
.setMIFlag(MachineInstr::FrameDestroy);
1007+
}
8761008
}
8771009

878-
// Deallocate stack if we didn't already do it during cm.pop handling and
879-
// StackSize isn't a zero
880-
if (StackSize != 0 && !ApplyPop)
1010+
// Deallocate stack if StackSize isn't a zero yet
1011+
if (StackSize != 0)
8811012
deallocateStack(MF, MBB, MBBI, DL, StackSize, 0);
8821013

8831014
// Emit epilogue for shadow call stack.
@@ -1564,6 +1695,23 @@ bool RISCVFrameLowering::spillCalleeSavedRegisters(
15641695
return true;
15651696
}
15661697

1698+
static unsigned getCaleeSavedRVVNumRegs(const Register &BaseReg) {
1699+
return RISCV::VRRegClass.contains(BaseReg) ? 1
1700+
: RISCV::VRM2RegClass.contains(BaseReg) ? 2
1701+
: RISCV::VRM4RegClass.contains(BaseReg) ? 4
1702+
: 8;
1703+
}
1704+
1705+
static MCRegister getRVVBaseRegister(const RISCVRegisterInfo &TRI,
1706+
const Register &Reg) {
1707+
MCRegister BaseReg = TRI.getSubReg(Reg, RISCV::sub_vrm1_0);
1708+
// If it's not a grouped vector register, it doesn't have subregister, so
1709+
// the base register is just itself.
1710+
if (BaseReg == RISCV::NoRegister)
1711+
BaseReg = Reg;
1712+
return BaseReg;
1713+
}
1714+
15671715
void RISCVFrameLowering::emitCalleeSavedRVVPrologCFI(
15681716
MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, bool HasFP) const {
15691717
MachineFunction *MF = MBB.getParent();
@@ -1590,15 +1738,8 @@ void RISCVFrameLowering::emitCalleeSavedRVVPrologCFI(
15901738
// Insert the spill to the stack frame.
15911739
int FI = CS.getFrameIdx();
15921740
if (FI >= 0 && MFI.getStackID(FI) == TargetStackID::ScalableVector) {
1593-
MCRegister BaseReg = TRI.getSubReg(CS.getReg(), RISCV::sub_vrm1_0);
1594-
// If it's not a grouped vector register, it doesn't have subregister, so
1595-
// the base register is just itself.
1596-
if (BaseReg == RISCV::NoRegister)
1597-
BaseReg = CS.getReg();
1598-
unsigned NumRegs = RISCV::VRRegClass.contains(CS.getReg()) ? 1
1599-
: RISCV::VRM2RegClass.contains(CS.getReg()) ? 2
1600-
: RISCV::VRM4RegClass.contains(CS.getReg()) ? 4
1601-
: 8;
1741+
MCRegister BaseReg = getRVVBaseRegister(TRI, CS.getReg());
1742+
unsigned NumRegs = getCaleeSavedRVVNumRegs(CS.getReg());
16021743
for (unsigned i = 0; i < NumRegs; ++i) {
16031744
unsigned CFIIndex = MF->addFrameInst(createDefCFAOffset(
16041745
TRI, BaseReg + i, -FixedSize, MFI.getObjectOffset(FI) / 8 + i));
@@ -1610,6 +1751,29 @@ void RISCVFrameLowering::emitCalleeSavedRVVPrologCFI(
16101751
}
16111752
}
16121753

1754+
void RISCVFrameLowering::emitCalleeSavedRVVEpilogCFI(
1755+
MachineBasicBlock &MBB, MachineBasicBlock::iterator MI) const {
1756+
MachineFunction *MF = MBB.getParent();
1757+
const MachineFrameInfo &MFI = MF->getFrameInfo();
1758+
const RISCVRegisterInfo *RI = STI.getRegisterInfo();
1759+
const TargetInstrInfo &TII = *STI.getInstrInfo();
1760+
const RISCVRegisterInfo &TRI = *STI.getRegisterInfo();
1761+
DebugLoc DL = MBB.findDebugLoc(MI);
1762+
1763+
const auto &RVVCSI = getRVVCalleeSavedInfo(*MF, MFI.getCalleeSavedInfo());
1764+
for (auto &CS : RVVCSI) {
1765+
MCRegister BaseReg = getRVVBaseRegister(TRI, CS.getReg());
1766+
unsigned NumRegs = getCaleeSavedRVVNumRegs(CS.getReg());
1767+
for (unsigned i = 0; i < NumRegs; ++i) {
1768+
unsigned CFIIndex = MF->addFrameInst(MCCFIInstruction::createRestore(
1769+
nullptr, RI->getDwarfRegNum(BaseReg + i, true)));
1770+
BuildMI(MBB, MI, DL, TII.get(TargetOpcode::CFI_INSTRUCTION))
1771+
.addCFIIndex(CFIIndex)
1772+
.setMIFlag(MachineInstr::FrameDestroy);
1773+
}
1774+
}
1775+
}
1776+
16131777
bool RISCVFrameLowering::restoreCalleeSavedRegisters(
16141778
MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
16151779
MutableArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const {

llvm/lib/Target/RISCV/RISCVFrameLowering.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,9 +91,11 @@ class RISCVFrameLowering : public TargetFrameLowering {
9191
void emitCalleeSavedRVVPrologCFI(MachineBasicBlock &MBB,
9292
MachineBasicBlock::iterator MI,
9393
bool HasFP) const;
94+
void emitCalleeSavedRVVEpilogCFI(MachineBasicBlock &MBB,
95+
MachineBasicBlock::iterator MI) const;
9496
void deallocateStack(MachineFunction &MF, MachineBasicBlock &MBB,
9597
MachineBasicBlock::iterator MBBI, const DebugLoc &DL,
96-
uint64_t StackSize, int64_t CFAOffset) const;
98+
uint64_t &StackSize, int64_t CFAOffset) const;
9799

98100
std::pair<int64_t, Align>
99101
assignRVVStackObjectOffsets(MachineFunction &MF) const;

llvm/lib/Target/RISCV/RISCVTargetMachine.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,8 @@ RISCVTargetMachine::RISCVTargetMachine(const Target &T, const Triple &TT,
172172

173173
if (TT.isOSFuchsia() && !TT.isArch64Bit())
174174
report_fatal_error("Fuchsia is only supported for 64-bit");
175+
176+
setCFIFixup(true);
175177
}
176178

177179
const RISCVSubtarget *

0 commit comments

Comments
 (0)