Skip to content

Commit 199cbf4

Browse files
committed
[RISCV][CFI] add function epilogue cfi information
This patch adds information about cfa value and registers frame location in function's epilogue, that allows to obtain a valid backtrace at the end of functions. Also it fixes the stack pointer recovery from the frame pointer if the frame pointer is used. Before patch: %bb.0: addi sp, sp, -16 .cfi_def_cfa_offset 16 sw ra, 12(sp) # 4-byte Folded Spill sw s0, 8(sp) # 4-byte Folded Spill .cfi_offset ra, -4 .cfi_offset s0, -8 addi s0, sp, 16 .cfi_def_cfa s0, 0 lw ra, 12(sp) # 4-byte Folded Reload lw s0, 8(sp) # 4-byte Folded Reload addi sp, sp, 16 ret After patch: %bb.0: addi sp, sp, -16 .cfi_def_cfa_offset 16 sw ra, 12(sp) # 4-byte Folded Spill sw s0, 8(sp) # 4-byte Folded Spill .cfi_offset ra, -4 .cfi_offset s0, -8 addi s0, sp, 16 .cfi_def_cfa s0, 0 addi sp, s0, -16 .cfi_def_cfa sp, 16 lw ra, 12(sp) # 4-byte Folded Reload lw s0, 8(sp) # 4-byte Folded Reload .cfi_restore ra .cfi_restore s0 addi sp, sp, 16 .cfi_def_cfa_offset 0 ret
1 parent 6f1a8c2 commit 199cbf4

File tree

2 files changed

+146
-36
lines changed

2 files changed

+146
-36
lines changed

llvm/lib/Target/RISCV/RISCVFrameLowering.cpp

Lines changed: 138 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -755,11 +755,32 @@ void RISCVFrameLowering::emitPrologue(MachineFunction &MF,
755755
}
756756
}
757757

758+
void RISCVFrameLowering::deallocateStack(MachineFunction &MF,
759+
MachineBasicBlock &MBB,
760+
MachineBasicBlock::iterator MBBI,
761+
const DebugLoc &DL, uint64_t StackSize,
762+
int64_t CFAOffset) const {
763+
const RISCVRegisterInfo *RI = STI.getRegisterInfo();
764+
const RISCVInstrInfo *TII = STI.getInstrInfo();
765+
766+
Register SPReg = getSPReg(STI);
767+
768+
RI->adjustReg(MBB, MBBI, DL, SPReg, SPReg, StackOffset::getFixed(StackSize),
769+
MachineInstr::FrameDestroy, getStackAlign());
770+
771+
unsigned CFIIndex =
772+
MF.addFrameInst(MCCFIInstruction::cfiDefCfaOffset(nullptr, CFAOffset));
773+
BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION))
774+
.addCFIIndex(CFIIndex)
775+
.setMIFlag(MachineInstr::FrameDestroy);
776+
}
777+
758778
void RISCVFrameLowering::emitEpilogue(MachineFunction &MF,
759779
MachineBasicBlock &MBB) const {
760780
const RISCVRegisterInfo *RI = STI.getRegisterInfo();
761781
MachineFrameInfo &MFI = MF.getFrameInfo();
762782
auto *RVFI = MF.getInfo<RISCVMachineFunctionInfo>();
783+
const RISCVInstrInfo *TII = STI.getInstrInfo();
763784
Register FPReg = getFPReg(STI);
764785
Register SPReg = getSPReg(STI);
765786

@@ -786,20 +807,67 @@ void RISCVFrameLowering::emitEpilogue(MachineFunction &MF,
786807
--MBBI;
787808
}
788809

789-
const auto &CSI = getUnmanagedCSI(MF, MFI.getCalleeSavedInfo());
810+
const auto &CSI = MFI.getCalleeSavedInfo();
790811

791812
// Skip to before the restores of scalar callee-saved registers
792813
// FIXME: assumes exactly one instruction is used to restore each
793814
// callee-saved register.
794-
auto LastFrameDestroy = MBBI;
795-
if (!CSI.empty())
796-
LastFrameDestroy = std::prev(MBBI, CSI.size());
815+
auto LastFrameDestroy = std::prev(MBBI, getUnmanagedCSI(MF, CSI).size());
797816

798-
uint64_t RealStackSize = getStackSizeWithRVVPadding(MF);
799-
uint64_t StackSize = RealStackSize - RVFI->getReservedSpillsSize();
800-
uint64_t FPOffset = RealStackSize - RVFI->getVarArgsSaveSize();
817+
uint64_t FirstSPAdjustAmount = getFirstSPAdjustAmount(MF);
818+
uint64_t RealStackSize = FirstSPAdjustAmount ? FirstSPAdjustAmount
819+
: getStackSizeWithRVVPadding(MF);
820+
uint64_t StackSize = FirstSPAdjustAmount ? FirstSPAdjustAmount
821+
: getStackSizeWithRVVPadding(MF) -
822+
RVFI->getReservedSpillsSize();
823+
uint64_t FPOffset = FirstSPAdjustAmount ? FirstSPAdjustAmount
824+
: getStackSizeWithRVVPadding(MF) -
825+
RVFI->getVarArgsSaveSize();
801826
uint64_t RVVStackSize = RVFI->getRVVStackSize();
802827

828+
bool restoreFP = RI->hasStackRealignment(MF) || MFI.hasVarSizedObjects() ||
829+
!hasReservedCallFrame(MF);
830+
831+
if (RVVStackSize) {
832+
// If restoreFP the stack pointer will be restored using the frame pointer
833+
// value.
834+
if (!restoreFP) {
835+
adjustStackForRVV(MF, MBB, LastFrameDestroy, DL, RVVStackSize,
836+
MachineInstr::FrameDestroy);
837+
838+
unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::cfiDefCfa(
839+
nullptr, RI->getDwarfRegNum(SPReg, true), RealStackSize));
840+
BuildMI(MBB, LastFrameDestroy, DL,
841+
TII->get(TargetOpcode::CFI_INSTRUCTION))
842+
.addCFIIndex(CFIIndex)
843+
.setMIFlag(MachineInstr::FrameDestroy);
844+
}
845+
846+
emitCalleeSavedRVVEpilogCFI(MBB, LastFrameDestroy);
847+
}
848+
849+
if (FirstSPAdjustAmount) {
850+
uint64_t SecondSPAdjustAmount =
851+
getStackSizeWithRVVPadding(MF) - FirstSPAdjustAmount;
852+
assert(SecondSPAdjustAmount > 0 &&
853+
"SecondSPAdjustAmount should be greater than zero");
854+
855+
// If restoreFP the stack pointer will be restored using the frame pointer
856+
// value.
857+
if (!restoreFP) {
858+
RI->adjustReg(MBB, LastFrameDestroy, DL, SPReg, SPReg,
859+
StackOffset::getFixed(SecondSPAdjustAmount),
860+
MachineInstr::FrameDestroy, getStackAlign());
861+
862+
unsigned CFIIndex = MF.addFrameInst(
863+
MCCFIInstruction::cfiDefCfaOffset(nullptr, FirstSPAdjustAmount));
864+
BuildMI(MBB, LastFrameDestroy, DL,
865+
TII->get(TargetOpcode::CFI_INSTRUCTION))
866+
.addCFIIndex(CFIIndex)
867+
.setMIFlag(MachineInstr::FrameDestroy);
868+
}
869+
}
870+
803871
// Restore the stack pointer using the value of the frame pointer. Only
804872
// necessary if the stack pointer was modified, meaning the stack size is
805873
// unknown.
@@ -810,50 +878,58 @@ void RISCVFrameLowering::emitEpilogue(MachineFunction &MF,
810878
// normally it's just checking the variable sized object is present or not
811879
// is enough, but we also don't preserve that at prologue/epilogue when
812880
// have vector objects in stack.
813-
if (RI->hasStackRealignment(MF) || MFI.hasVarSizedObjects() ||
814-
!hasReservedCallFrame(MF)) {
815-
assert(hasFP(MF) && "frame pointer should not have been eliminated");
881+
if (restoreFP) {
816882
RI->adjustReg(MBB, LastFrameDestroy, DL, SPReg, FPReg,
817-
StackOffset::getFixed(-FPOffset),
818-
MachineInstr::FrameDestroy, getStackAlign());
819-
} else {
820-
if (RVVStackSize)
821-
adjustStackForRVV(MF, MBB, LastFrameDestroy, DL, RVVStackSize,
822-
MachineInstr::FrameDestroy);
823-
}
824-
825-
uint64_t FirstSPAdjustAmount = getFirstSPAdjustAmount(MF);
826-
if (FirstSPAdjustAmount) {
827-
uint64_t SecondSPAdjustAmount =
828-
getStackSizeWithRVVPadding(MF) - FirstSPAdjustAmount;
829-
assert(SecondSPAdjustAmount > 0 &&
830-
"SecondSPAdjustAmount should be greater than zero");
883+
StackOffset::getFixed(-FPOffset), MachineInstr::FrameDestroy,
884+
getStackAlign());
831885

832-
RI->adjustReg(MBB, LastFrameDestroy, DL, SPReg, SPReg,
833-
StackOffset::getFixed(SecondSPAdjustAmount),
834-
MachineInstr::FrameDestroy, getStackAlign());
886+
unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::cfiDefCfa(
887+
nullptr, RI->getDwarfRegNum(SPReg, true), RealStackSize));
888+
BuildMI(MBB, LastFrameDestroy, DL, TII->get(TargetOpcode::CFI_INSTRUCTION))
889+
.addCFIIndex(CFIIndex)
890+
.setMIFlag(MachineInstr::FrameDestroy);
835891
}
836892

837-
if (FirstSPAdjustAmount)
838-
StackSize = FirstSPAdjustAmount;
839-
840-
if (RVFI->isPushable(MF) && MBBI != MBB.end() &&
841-
MBBI->getOpcode() == RISCV::CM_POP) {
893+
bool ApplyPop = RVFI->isPushable(MF) && MBBI != MBB.end() &&
894+
MBBI->getOpcode() == RISCV::CM_POP;
895+
if (ApplyPop) {
842896
// Use available stack adjustment in pop instruction to deallocate stack
843897
// space. Align the stack size down to a multiple of 16. This is needed for
844898
// RVE.
845899
// FIXME: Can we increase the stack size to a multiple of 16 instead?
846900
uint64_t Spimm = std::min(alignDown(StackSize, 16), (uint64_t)48);
847901
MBBI->getOperand(1).setImm(Spimm);
848902
StackSize -= Spimm;
903+
904+
if (StackSize != 0)
905+
deallocateStack(MF, MBB, MBBI, DL, StackSize,
906+
/*stack_adj of cm.pop instr*/ RealStackSize - StackSize);
907+
908+
// Update CFA offset. After CM_POP SP should be equal to CFA, so CFA offset
909+
// is zero.
910+
MBBI = std::next(MBBI);
911+
unsigned CFIIndex =
912+
MF.addFrameInst(MCCFIInstruction::cfiDefCfaOffset(nullptr, 0));
913+
BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION))
914+
.addCFIIndex(CFIIndex)
915+
.setMIFlag(MachineInstr::FrameDestroy);
849916
}
850917

851-
// Deallocate stack
852-
if (StackSize != 0) {
853-
RI->adjustReg(MBB, MBBI, DL, SPReg, SPReg, StackOffset::getFixed(StackSize),
854-
MachineInstr::FrameDestroy, getStackAlign());
918+
// Recover callee-saved registers.
919+
for (const auto &Entry : CSI) {
920+
Register Reg = Entry.getReg();
921+
unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createRestore(
922+
nullptr, RI->getDwarfRegNum(Reg, true)));
923+
BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION))
924+
.addCFIIndex(CFIIndex)
925+
.setMIFlag(MachineInstr::FrameDestroy);
855926
}
856927

928+
// Deallocate stack if StackSize isn't a zero and if we didn't already do it
929+
// during cm.pop handling.
930+
if (StackSize != 0 && !ApplyPop)
931+
deallocateStack(MF, MBB, MBBI, DL, StackSize, 0);
932+
857933
// Emit epilogue for shadow call stack.
858934
emitSCSEpilogue(MF, MBB, MBBI, DL);
859935
}
@@ -1557,6 +1633,7 @@ void RISCVFrameLowering::emitCalleeSavedRVVPrologCFI(
15571633
int FI = CS.getFrameIdx();
15581634
if (FI >= 0 && MFI.getStackID(FI) == TargetStackID::ScalableVector) {
15591635
MCRegister BaseReg = TRI.getSubReg(CS.getReg(), RISCV::sub_vrm1_0);
1636+
15601637
// If it's not a grouped vector register, it doesn't have subregister, so
15611638
// the base register is just itself.
15621639
if (BaseReg == RISCV::NoRegister)
@@ -1576,6 +1653,31 @@ void RISCVFrameLowering::emitCalleeSavedRVVPrologCFI(
15761653
}
15771654
}
15781655

1656+
void RISCVFrameLowering::emitCalleeSavedRVVEpilogCFI(
1657+
MachineBasicBlock &MBB, MachineBasicBlock::iterator MI) const {
1658+
MachineFunction *MF = MBB.getParent();
1659+
const MachineFrameInfo &MFI = MF->getFrameInfo();
1660+
const RISCVRegisterInfo *RI = STI.getRegisterInfo();
1661+
const TargetInstrInfo &TII = *STI.getInstrInfo();
1662+
DebugLoc DL = MBB.findDebugLoc(MI);
1663+
1664+
const auto &RVVCSI = getRVVCalleeSavedInfo(*MF, MFI.getCalleeSavedInfo());
1665+
if (RVVCSI.empty())
1666+
return;
1667+
1668+
for (auto &CS : RVVCSI) {
1669+
int FI = CS.getFrameIdx();
1670+
if (FI >= 0 && MFI.getStackID(FI) == TargetStackID::ScalableVector) {
1671+
Register Reg = CS.getReg();
1672+
unsigned CFIIndex = MF->addFrameInst(MCCFIInstruction::createRestore(
1673+
nullptr, RI->getDwarfRegNum(Reg, true)));
1674+
BuildMI(MBB, MI, DL, TII.get(TargetOpcode::CFI_INSTRUCTION))
1675+
.addCFIIndex(CFIIndex)
1676+
.setMIFlag(MachineInstr::FrameDestroy);
1677+
}
1678+
}
1679+
}
1680+
15791681
bool RISCVFrameLowering::restoreCalleeSavedRegisters(
15801682
MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
15811683
MutableArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const {

llvm/lib/Target/RISCV/RISCVFrameLowering.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,9 +88,17 @@ class RISCVFrameLowering : public TargetFrameLowering {
8888
void adjustStackForRVV(MachineFunction &MF, MachineBasicBlock &MBB,
8989
MachineBasicBlock::iterator MBBI, const DebugLoc &DL,
9090
int64_t Amount, MachineInstr::MIFlag Flag) const;
91+
9192
void emitCalleeSavedRVVPrologCFI(MachineBasicBlock &MBB,
9293
MachineBasicBlock::iterator MI,
9394
bool HasFP) const;
95+
void emitCalleeSavedRVVEpilogCFI(MachineBasicBlock &MBB,
96+
MachineBasicBlock::iterator MI) const;
97+
98+
void deallocateStack(MachineFunction &MF, MachineBasicBlock &MBB,
99+
MachineBasicBlock::iterator MBBI, const DebugLoc &DL,
100+
uint64_t StackSize, int64_t CFAOffset) const;
101+
94102
std::pair<int64_t, Align>
95103
assignRVVStackObjectOffsets(MachineFunction &MF) const;
96104
};

0 commit comments

Comments
 (0)