Skip to content

Commit

Permalink
Add unwinding information when FP is changed.
Browse files Browse the repository at this point in the history
  • Loading branch information
weiguozhi committed May 6, 2024
1 parent c70ab81 commit 7017717
Show file tree
Hide file tree
Showing 5 changed files with 102 additions and 40 deletions.
29 changes: 23 additions & 6 deletions llvm/lib/CodeGen/CFIInstrInserter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,10 @@ void CFIInstrInserter::calculateOutgoingCFAInfo(MBBCFAInfo &MBBInfo) {
unsigned NumRegs = TRI.getNumSupportedRegs(*MF);
BitVector CSRSaved(NumRegs), CSRRestored(NumRegs);

#ifndef NDEBUG
int RememberState = 0;
#endif

// Determine cfa offset and register set by the block.
for (MachineInstr &MI : *MBBInfo.MBB) {
if (MI.isCFIInstruction()) {
Expand Down Expand Up @@ -228,17 +232,23 @@ void CFIInstrInserter::calculateOutgoingCFAInfo(MBBCFAInfo &MBBInfo) {
case MCCFIInstruction::OpRememberState:
// TODO: Add support for handling cfi_remember_state.
#ifndef NDEBUG
report_fatal_error(
"Support for cfi_remember_state not implemented! Value of CFA "
"may be incorrect!\n");
// Currently we need cfi_remember_state and cfi_restore_state to be in
// the same BB, so it will not impact outgoing CFA.
++RememberState;
if (RememberState != 1)
report_fatal_error(
"Support for cfi_remember_state not implemented! Value of CFA "
"may be incorrect!\n");
#endif
break;
case MCCFIInstruction::OpRestoreState:
// TODO: Add support for handling cfi_restore_state.
#ifndef NDEBUG
report_fatal_error(
"Support for cfi_restore_state not implemented! Value of CFA may "
"be incorrect!\n");
--RememberState;
if (RememberState != 0)
report_fatal_error(
"Support for cfi_restore_state not implemented! Value of CFA may "
"be incorrect!\n");
#endif
break;
// Other CFI directives do not affect CFA value.
Expand All @@ -263,6 +273,13 @@ void CFIInstrInserter::calculateOutgoingCFAInfo(MBBCFAInfo &MBBInfo) {
}
}

#ifndef NDEBUG
if (RememberState != 0)
report_fatal_error(
"Support for cfi_remember_state not implemented! Value of CFA "
"may be incorrect!\n");
#endif

MBBInfo.Processed = true;

// Update outgoing CFA info.
Expand Down
35 changes: 18 additions & 17 deletions llvm/lib/CodeGen/PrologEpilogInserter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,15 +77,15 @@ using MBBVector = SmallVector<MachineBasicBlock *, 4>;
STATISTIC(NumLeafFuncWithSpills, "Number of leaf functions with CSRs");
STATISTIC(NumFuncSeen, "Number of functions seen in PEI");

static cl::opt<bool> SpillClobberedFP(
"spill-clobbered-fp",
cl::desc("Spill clobbered fp register to stack."),
cl::init(false), cl::Hidden);
static cl::opt<bool>
SpillClobberedFP("spill-clobbered-fp",
cl::desc("Spill clobbered fp register to stack."),
cl::init(false), cl::Hidden);

static cl::opt<bool> SpillClobberedBP(
"spill-clobbered-bp",
cl::desc("Spill clobbered bp register to stack."),
cl::init(true), cl::Hidden);
static cl::opt<bool>
SpillClobberedBP("spill-clobbered-bp",
cl::desc("Spill clobbered bp register to stack."),
cl::init(true), cl::Hidden);

namespace {

Expand Down Expand Up @@ -1606,13 +1606,13 @@ static bool accessFrameBasePointer(const MachineInstr &MI, Register FP,
const TargetRegisterInfo *TRI) {
AccessFP = AccessBP = false;
if (FP) {
if (MI.findRegisterUseOperandIdx(FP, false, TRI) != -1 ||
MI.findRegisterDefOperandIdx(FP, false, true, TRI) != -1)
if (MI.findRegisterUseOperandIdx(FP, TRI, false) != -1 ||
MI.findRegisterDefOperandIdx(FP, TRI, false, true) != -1)
AccessFP = true;
}
if (BP) {
if (MI.findRegisterUseOperandIdx(BP, false, TRI) != -1 ||
MI.findRegisterDefOperandIdx(BP, false, true, TRI) != -1)
if (MI.findRegisterUseOperandIdx(BP, TRI, false) != -1 ||
MI.findRegisterDefOperandIdx(BP, TRI, false, true) != -1)
AccessBP = true;
}
return AccessFP || AccessBP;
Expand Down Expand Up @@ -1675,17 +1675,18 @@ void PEI::spillFrameBasePointer(MachineFunction &MF) {
SpillBP |= AccessBP;

// Maintain FPLive and BPLive.
if (FPLive && MI->findRegisterDefOperandIdx(FP, false, true, TRI) != -1)
if (FPLive && MI->findRegisterDefOperandIdx(FP, TRI, false, true) != -1)
FPLive = false;
if (FP && MI->findRegisterUseOperandIdx(FP, false, TRI) != -1)
if (FP && MI->findRegisterUseOperandIdx(FP, TRI, false) != -1)
FPLive = true;
if (BPLive && MI->findRegisterDefOperandIdx(BP, false, true, TRI) != -1)
if (BPLive && MI->findRegisterDefOperandIdx(BP, TRI, false, true) != -1)
BPLive = false;
if (BP && MI->findRegisterUseOperandIdx(BP, false, TRI) != -1)
if (BP && MI->findRegisterUseOperandIdx(BP, TRI, false) != -1)
BPLive = true;

Start = MI++;
} while ((MI != ME) && (FPLive || BPLive ||
} while ((MI != ME) &&
(FPLive || BPLive ||
accessFrameBasePointer(*MI, FP, BP, AccessFP, AccessBP, TRI)));

// If the bp is clobbered by a call, we should save and restore outside of
Expand Down
56 changes: 50 additions & 6 deletions llvm/lib/Target/X86/X86FrameLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4189,9 +4189,9 @@ static int computeSPAdjust4SpillFPBP(MachineFunction &MF,
return AlignedSize - AllocSize;
}

void X86FrameLowering::spillFPBPUsingSP(
MachineFunction &MF, MachineBasicBlock::iterator BeforeMI,
bool SpillFP, bool SpillBP) const {
void X86FrameLowering::spillFPBPUsingSP(MachineFunction &MF,
MachineBasicBlock::iterator BeforeMI,
bool SpillFP, bool SpillBP) const {
const TargetRegisterClass *RC;
unsigned RegNum = 0;
MachineBasicBlock *MBB = BeforeMI->getParent();
Expand Down Expand Up @@ -4227,11 +4227,46 @@ void X86FrameLowering::spillFPBPUsingSP(
int SPAdjust = computeSPAdjust4SpillFPBP(MF, RC, RegNum);
if (SPAdjust)
emitSPUpdate(*MBB, BeforeMI, DL, -SPAdjust, false);

// Emit unwinding information.
if (SpillFP && needsDwarfCFI(MF)) {
// Emit .cfi_remember_state to remember old frame.
unsigned CFIIndex =
MF.addFrameInst(MCCFIInstruction::createRememberState(nullptr));
BuildMI(*MBB, BeforeMI, DL, TII.get(TargetOpcode::CFI_INSTRUCTION))
.addCFIIndex(CFIIndex);

// Setup new CFA value with DW_CFA_def_cfa_expression:
// DW_OP_breg7+offset, DW_OP_deref, DW_OP_consts 16, DW_OP_plus
SmallString<64> CfaExpr;
uint8_t buffer[16];
int Offset = SPAdjust;
if (SpillBP)
Offset += TRI->getSpillSize(*RC);
Register StackPtr = TRI->getStackRegister();
if (STI.isTarget64BitILP32())
StackPtr = Register(getX86SubSuperRegister(StackPtr, 64));
unsigned DwarfStackPtr = TRI->getDwarfRegNum(StackPtr, true);
CfaExpr.push_back((uint8_t)(dwarf::DW_OP_breg0 + DwarfStackPtr));
CfaExpr.append(buffer, buffer + encodeSLEB128(Offset, buffer));
CfaExpr.push_back(dwarf::DW_OP_deref);
CfaExpr.push_back(dwarf::DW_OP_consts);
CfaExpr.append(buffer, buffer + encodeSLEB128(SlotSize * 2, buffer));
CfaExpr.push_back((uint8_t)dwarf::DW_OP_plus);

SmallString<64> DefCfaExpr;
DefCfaExpr.push_back(dwarf::DW_CFA_def_cfa_expression);
DefCfaExpr.append(buffer, buffer + encodeSLEB128(CfaExpr.size(), buffer));
DefCfaExpr.append(CfaExpr.str());
BuildCFI(*MBB, BeforeMI, DL,
MCCFIInstruction::createEscape(nullptr, DefCfaExpr.str()),
MachineInstr::FrameSetup);
}
}

void X86FrameLowering::restoreFPBPUsingSP(
MachineFunction &MF, MachineBasicBlock::iterator AfterMI,
bool SpillFP, bool SpillBP) const {
void X86FrameLowering::restoreFPBPUsingSP(MachineFunction &MF,
MachineBasicBlock::iterator AfterMI,
bool SpillFP, bool SpillBP) const {
Register FP, BP;
const TargetRegisterClass *RC;
unsigned RegNum = 0;
Expand Down Expand Up @@ -4268,6 +4303,15 @@ void X86FrameLowering::restoreFPBPUsingSP(
if (SpillFP) {
BuildMI(*MBB, Pos, DL,
TII.get(getPOPOpcode(MF.getSubtarget<X86Subtarget>())), FP);

// Emit unwinding information.
if (needsDwarfCFI(MF)) {
// Restore original frame with .cfi_restore_state.
unsigned CFIIndex =
MF.addFrameInst(MCCFIInstruction::createRestoreState(nullptr));
BuildMI(*MBB, Pos, DL, TII.get(TargetOpcode::CFI_INSTRUCTION))
.addCFIIndex(CFIIndex);
}
}
}

Expand Down
19 changes: 8 additions & 11 deletions llvm/lib/Target/X86/X86FrameLowering.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,19 +103,16 @@ class X86FrameLowering : public TargetFrameLowering {
MutableArrayRef<CalleeSavedInfo> CSI,
const TargetRegisterInfo *TRI) const override;

void
spillFPBPUsingSP(MachineFunction &MF,
const MachineBasicBlock::iterator BeforeMI,
bool SpillFP, bool SpillBP) const override;
void spillFPBPUsingSP(MachineFunction &MF,
const MachineBasicBlock::iterator BeforeMI,
bool SpillFP, bool SpillBP) const override;

void
restoreFPBPUsingSP(MachineFunction &MF,
const MachineBasicBlock::iterator AfterMI,
bool SpillFP, bool SpillBP) const override;
void restoreFPBPUsingSP(MachineFunction &MF,
const MachineBasicBlock::iterator AfterMI,
bool SpillFP, bool SpillBP) const override;

bool
skipSpillFPBP(MachineFunction &MF,
MachineBasicBlock::reverse_iterator &MI) const override;
bool skipSpillFPBP(MachineFunction &MF,
MachineBasicBlock::reverse_iterator &MI) const override;

bool hasFP(const MachineFunction &MF) const override;
bool hasReservedCallFrame(const MachineFunction &MF) const override;
Expand Down
3 changes: 3 additions & 0 deletions llvm/test/CodeGen/X86/clobber_frame_ptr.ll
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,14 @@ define i32 @foo(i32 %0, i32 %1) {
; CHECK-NEXT: # kill: def $edi killed $edi def $rdi
; CHECK-NEXT: pushq %rbp
; CHECK-NEXT: pushq %rax
; CHECK-NEXT: .cfi_remember_state
; CHECK-NEXT: .cfi_escape 0x0f, 0x06, 0x77, 0x08, 0x06, 0x11, 0x10, 0x22 #
; CHECK-NEXT: movl %esi, %ebp
; CHECK-NEXT: movq %rdi, %r13
; CHECK-NEXT: callq external@PLT
; CHECK-NEXT: addq $8, %rsp
; CHECK-NEXT: popq %rbp
; CHECK-NEXT: .cfi_restore_state
; CHECK-NEXT: leaq -40(%rbp), %rsp
; CHECK-NEXT: popq %rbx
; CHECK-NEXT: popq %r12
Expand Down

0 comments on commit 7017717

Please sign in to comment.