Skip to content

Commit fc7af32

Browse files
dylanmckaydylanmckay
dylanmckay
authored andcommitted
[AVR] Fix a bug where the frame pointer is clobbered
Because it was a callee-saved register, we automatically generated code to spill and unspill its original value so that it is restored after the function returns. The problem is that this code was being generated before the epilogue. The epilogue itself uses the Y register, which could be prematurely restored by the CSR restoration process. This removes R29R28 from the CSR list and changes the prologue/epilogue code to handle it explicitly. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@301887 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent b843dc3 commit fc7af32

File tree

1 file changed

+17
-7
lines changed

1 file changed

+17
-7
lines changed

lib/Target/AVR/AVRFrameLowering.cpp

+17-7
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ void AVRFrameLowering::emitPrologue(MachineFunction &MF,
5757
DebugLoc DL = (MBBI != MBB.end()) ? MBBI->getDebugLoc() : DebugLoc();
5858
const AVRSubtarget &STI = MF.getSubtarget<AVRSubtarget>();
5959
const AVRInstrInfo &TII = *STI.getInstrInfo();
60+
bool HasFP = hasFP(MF);
6061

6162
// Interrupt handlers re-enable interrupts in function entry.
6263
if (CallConv == CallingConv::AVR_INTR) {
@@ -69,9 +70,18 @@ void AVRFrameLowering::emitPrologue(MachineFunction &MF,
6970
// handlers before saving any other registers.
7071
if (CallConv == CallingConv::AVR_INTR ||
7172
CallConv == CallingConv::AVR_SIGNAL) {
73+
74+
// Save the frame pointer if we have one.
75+
if (HasFP) {
76+
BuildMI(MBB, MBBI, DL, TII.get(AVR::PUSHWRr))
77+
.addReg(AVR::R29R28, RegState::Kill)
78+
.setMIFlag(MachineInstr::FrameSetup);
79+
}
80+
7281
BuildMI(MBB, MBBI, DL, TII.get(AVR::PUSHWRr))
7382
.addReg(AVR::R1R0, RegState::Kill)
7483
.setMIFlag(MachineInstr::FrameSetup);
84+
7585
BuildMI(MBB, MBBI, DL, TII.get(AVR::INRdA), AVR::R0)
7686
.addImm(0x3f)
7787
.setMIFlag(MachineInstr::FrameSetup);
@@ -86,7 +96,7 @@ void AVRFrameLowering::emitPrologue(MachineFunction &MF,
8696
}
8797

8898
// Early exit if the frame pointer is not needed in this function.
89-
if (!hasFP(MF)) {
99+
if (!HasFP) {
90100
return;
91101
}
92102

@@ -163,6 +173,9 @@ void AVRFrameLowering::emitEpilogue(MachineFunction &MF,
163173
.addImm(0x3f)
164174
.addReg(AVR::R0, RegState::Kill);
165175
BuildMI(MBB, MBBI, DL, TII.get(AVR::POPWRd), AVR::R1R0);
176+
177+
if (hasFP(MF))
178+
BuildMI(MBB, MBBI, DL, TII.get(AVR::POPWRd), AVR::R29R28);
166179
}
167180

168181
// Early exit if there is no need to restore the frame pointer.
@@ -407,12 +420,9 @@ void AVRFrameLowering::determineCalleeSaves(MachineFunction &MF,
407420
RegScavenger *RS) const {
408421
TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS);
409422

410-
// Spill register Y when it is used as the frame pointer.
411-
if (hasFP(MF)) {
412-
SavedRegs.set(AVR::R29R28);
413-
SavedRegs.set(AVR::R29);
414-
SavedRegs.set(AVR::R28);
415-
}
423+
// If we have a frame pointer, the Y register needs to be saved as well.
424+
// We don't do that here however - the prologue and epilogue generation
425+
// code will handle it specially.
416426
}
417427
/// The frame analyzer pass.
418428
///

0 commit comments

Comments
 (0)