From 8893a3d159a674a6bddda145e2dd61ff0f101f3b Mon Sep 17 00:00:00 2001 From: Bill Schmidt Date: Fri, 16 Aug 2013 20:05:04 +0000 Subject: [PATCH] [PowerPC] Preparatory refactoring for making prologue and epilogue safe on PPC32 SVR4 ABI [Patch and following text by Mark Minich; committing on his behalf.] There are FIXME's in PowerPC/PPCFrameLowering.cpp, method PPCFrameLowering::emitPrologue() related to "negative offsets of R1" on PPC32 SVR4. They're true, but the real issue is that on PPC32 SVR4 (and any ABI without a Red Zone), no spills may be made until after the stackframe is claimed, which also includes the LR spill which is at a positive offset. The same problem exists in emitEpilogue(), though there's no FIXME for it. I intend to fix this issue, making LLVM-compiled code finally safe for use on SVR4/EABI/e500 32-bit platforms (including in particular, OS-free embedded systems & kernel code, where interrupts may share the same stack as user code). In preparation for making these changes, to make the diffs for the functional changes less cluttered, I am providing the non-functional refactorings in two stages: Stage 1 does some minor fluffy refactorings to pull multiple method calls up into a single bool, creating named bools for repeated uses of obscure logic, moving some code up earlier because either stage 2 or my final version will require it earlier, and rewording/adding some comments. My stage 1 changes can be characterized as primarily fluffy cleanup, the purpose of which may be unclear until the stage 2 or final changes are made. My stage 2 refactorings combine the separate PPC32 & PPC64 logic, which is currently performed by largely duplicate code, into a single flow, with the differences handled by a group of constants initialized early in the methods. This submission is for my stage 1 changes. There should be no functional changes whatsoever; this is a pure refactoring. llvm-svn: 188573 --- llvm/lib/Target/PowerPC/PPCFrameLowering.cpp | 187 +++++++++++++++------------ 1 file changed, 102 insertions(+), 85 deletions(-) diff --git a/llvm/lib/Target/PowerPC/PPCFrameLowering.cpp b/llvm/lib/Target/PowerPC/PPCFrameLowering.cpp index 24d3a0b..5161de8 100644 --- a/llvm/lib/Target/PowerPC/PPCFrameLowering.cpp +++ b/llvm/lib/Target/PowerPC/PPCFrameLowering.cpp @@ -204,10 +204,9 @@ unsigned PPCFrameLowering::determineFrameLayout(MachineFunction &MF, unsigned FrameSize = UseEstimate ? MFI->estimateStackSize(MF) : MFI->getStackSize(); - // Get the alignments provided by the target, and the maximum alignment - // (if any) of the fixed frame objects. - unsigned TargetAlign = getStackAlignment(); - unsigned MaxAlign = MFI->getMaxAlignment(); + // Get stack alignments. The frame must be aligned to the greatest of these: + unsigned TargetAlign = getStackAlignment(); // alignment required per the ABI + unsigned MaxAlign = MFI->getMaxAlignment(); // algmt required by data in frame unsigned AlignMask = std::max(MaxAlign, TargetAlign) - 1; const PPCRegisterInfo *RegInfo = @@ -346,12 +345,20 @@ void PPCFrameLowering::emitPrologue(MachineFunction &MF) const { bool needsFrameMoves = MMI.hasDebugInfo() || MF.getFunction()->needsUnwindTableEntry(); + // Get processor type. + bool isPPC64 = Subtarget.isPPC64(); + // Get the ABI. + bool isDarwinABI = Subtarget.isDarwinABI(); + bool isSVR4ABI = Subtarget.isSVR4ABI(); + assert((isDarwinABI || isSVR4ABI) && + "Currently only Darwin and SVR4 ABIs are supported for PowerPC."); + // Prepare for frame info. MCSymbol *FrameLabel = 0; // Scan the prolog, looking for an UPDATE_VRSAVE instruction. If we find it, // process it. - if (!Subtarget.isSVR4ABI()) + if (!isSVR4ABI) for (unsigned i = 0; MBBI != MBB.end(); ++i, ++MBBI) { if (MBBI->getOpcode() == PPC::UPDATE_VRSAVE) { HandleVRSaveUpdate(MBBI, TII); @@ -371,10 +378,6 @@ void PPCFrameLowering::emitPrologue(MachineFunction &MF) const { if (MFI->isFrameAddressTaken()) replaceFPWithRealFP(MF); - // Get processor type. - bool isPPC64 = Subtarget.isPPC64(); - // Get operating system - bool isDarwinABI = Subtarget.isDarwinABI(); // Check if the link register (LR) must be saved. PPCFunctionInfo *FI = MF.getInfo(); bool MustSaveLR = FI->mustSaveLR(); @@ -383,11 +386,18 @@ void PPCFrameLowering::emitPrologue(MachineFunction &MF) const { bool HasFP = hasFP(MF); bool HasBP = RegInfo->hasBasePointer(MF); + // Regarding this assert: Even though LR is saved in the caller's frame (i.e., + // LROffset is positive), that slot is callee-owned. Because PPC32 SVR4 has no + // Red Zone, an asynchronous event (a form of "callee") could claim a frame & + // overwrite it, so PPC32 SVR4 must claim at least a minimal frame to save LR. + assert((isPPC64 || !isSVR4ABI || !(!FrameSize && (MustSaveLR || HasFP))) && + "FrameSize must be >0 to save/restore the FP or LR for 32-bit SVR4."); + int LROffset = PPCFrameLowering::getReturnSaveOffset(isPPC64, isDarwinABI); int FPOffset = 0; if (HasFP) { - if (Subtarget.isSVR4ABI()) { + if (isSVR4ABI) { MachineFrameInfo *FFI = MF.getFrameInfo(); int FPIndex = FI->getFramePointerSaveIndex(); assert(FPIndex && "No Frame Pointer Save Slot!"); @@ -399,7 +409,7 @@ void PPCFrameLowering::emitPrologue(MachineFunction &MF) const { int BPOffset = 0; if (HasBP) { - if (Subtarget.isSVR4ABI()) { + if (isSVR4ABI) { MachineFrameInfo *FFI = MF.getFrameInfo(); int BPIndex = FI->getBasePointerSaveIndex(); assert(BPIndex && "No Base Pointer Save Slot!"); @@ -410,6 +420,16 @@ void PPCFrameLowering::emitPrologue(MachineFunction &MF) const { } } + // Get stack alignments. + unsigned MaxAlign = MFI->getMaxAlignment(); + if (HasBP && MaxAlign > 1) + assert(isPowerOf2_32(MaxAlign) && isInt<16>(MaxAlign) && + "Invalid alignment!"); + + // Frames of 32KB & larger require special handling because they cannot be + // indexed into with a simple STDU/STWU/STD/STW immediate offset operand. + bool isLargeFrame = !isInt<16>(NegFrameSize); + if (isPPC64) { if (MustSaveLR) BuildMI(MBB, MBBI, dl, TII.get(PPC::MFLR8), PPC::X0); @@ -444,21 +464,19 @@ void PPCFrameLowering::emitPrologue(MachineFunction &MF) const { .addReg(PPC::X12, getKillRegState(true)) .addImm(8) .addReg(PPC::X1); - } else { + } else { // PPC32... if (MustSaveLR) BuildMI(MBB, MBBI, dl, TII.get(PPC::MFLR), PPC::R0); if (HasFP) - // FIXME: On PPC32 SVR4, FPOffset is negative and access to negative - // offsets of R1 is not allowed. + // FIXME: On PPC32 SVR4, we must not spill before claiming the stackframe. BuildMI(MBB, MBBI, dl, TII.get(PPC::STW)) .addReg(PPC::R31) .addImm(FPOffset) .addReg(PPC::R1); if (HasBP) - // FIXME: On PPC32 SVR4, FPOffset is negative and access to negative - // offsets of R1 is not allowed. + // FIXME: On PPC32 SVR4, we must not spill before claiming the stackframe. BuildMI(MBB, MBBI, dl, TII.get(PPC::STW)) .addReg(PPC::R30) .addImm(BPOffset) @@ -468,23 +486,19 @@ void PPCFrameLowering::emitPrologue(MachineFunction &MF) const { "Prologue CR saving supported only in 64-bit mode"); if (MustSaveLR) + // FIXME: On PPC32 SVR4, we must not spill before claiming the stackframe. BuildMI(MBB, MBBI, dl, TII.get(PPC::STW)) .addReg(PPC::R0) .addImm(LROffset) .addReg(PPC::R1); } - // Skip if a leaf routine. + // Skip the rest if this is a leaf function & all spills fit in the Red Zone. if (!FrameSize) return; - // Get stack alignments. - unsigned MaxAlign = MFI->getMaxAlignment(); - // Adjust stack pointer: r1 += NegFrameSize. // If there is a preferred stack alignment, align R1 now - if (!isPPC64) { - // PPC32. - + if (!isPPC64) { // PPC32... if (HasBP) { // Save a copy of r1 as the base pointer. BuildMI(MBB, MBBI, dl, TII.get(PPC::OR), PPC::R30) @@ -493,15 +507,12 @@ void PPCFrameLowering::emitPrologue(MachineFunction &MF) const { } if (HasBP && MaxAlign > 1) { - assert(isPowerOf2_32(MaxAlign) && isInt<16>(MaxAlign) && - "Invalid alignment!"); - BuildMI(MBB, MBBI, dl, TII.get(PPC::RLWINM), PPC::R0) .addReg(PPC::R1) .addImm(0) .addImm(32 - Log2_32(MaxAlign)) .addImm(31); - if (isInt<16>(NegFrameSize)) { + if (!isLargeFrame) { BuildMI(MBB, MBBI, dl, TII.get(PPC::SUBFIC), PPC::R0) .addReg(PPC::R0, RegState::Kill) .addImm(NegFrameSize); @@ -519,11 +530,13 @@ void PPCFrameLowering::emitPrologue(MachineFunction &MF) const { .addReg(PPC::R1, RegState::Kill) .addReg(PPC::R1) .addReg(PPC::R0); - } else if (isInt<16>(NegFrameSize)) { + + } else if (!isLargeFrame) { BuildMI(MBB, MBBI, dl, TII.get(PPC::STWU), PPC::R1) .addReg(PPC::R1) .addImm(NegFrameSize) .addReg(PPC::R1); + } else { BuildMI(MBB, MBBI, dl, TII.get(PPC::LIS), PPC::R0) .addImm(NegFrameSize >> 16); @@ -535,7 +548,7 @@ void PPCFrameLowering::emitPrologue(MachineFunction &MF) const { .addReg(PPC::R1) .addReg(PPC::R0); } - } else { // PPC64. + } else { // PPC64... if (HasBP) { // Save a copy of r1 as the base pointer. BuildMI(MBB, MBBI, dl, TII.get(PPC::OR8), PPC::X30) @@ -544,14 +557,11 @@ void PPCFrameLowering::emitPrologue(MachineFunction &MF) const { } if (HasBP && MaxAlign > 1) { - assert(isPowerOf2_32(MaxAlign) && isInt<16>(MaxAlign) && - "Invalid alignment!"); - BuildMI(MBB, MBBI, dl, TII.get(PPC::RLDICL), PPC::X0) .addReg(PPC::X1) .addImm(0) .addImm(64 - Log2_32(MaxAlign)); - if (isInt<16>(NegFrameSize)) { + if (!isLargeFrame) { BuildMI(MBB, MBBI, dl, TII.get(PPC::SUBFIC8), PPC::X0) .addReg(PPC::X0, RegState::Kill) .addImm(NegFrameSize); @@ -569,11 +579,13 @@ void PPCFrameLowering::emitPrologue(MachineFunction &MF) const { .addReg(PPC::X1, RegState::Kill) .addReg(PPC::X1) .addReg(PPC::X0); - } else if (isInt<16>(NegFrameSize)) { + + } else if (!isLargeFrame) { BuildMI(MBB, MBBI, dl, TII.get(PPC::STDU), PPC::X1) .addReg(PPC::X1) .addImm(NegFrameSize) .addReg(PPC::X1); + } else { BuildMI(MBB, MBBI, dl, TII.get(PPC::LIS8), PPC::X0) .addImm(NegFrameSize >> 16); @@ -625,11 +637,11 @@ void PPCFrameLowering::emitPrologue(MachineFunction &MF) const { // If there is a frame pointer, copy R1 into R31 if (HasFP) { - if (!isPPC64) { + if (!isPPC64) { // PPC32... BuildMI(MBB, MBBI, dl, TII.get(PPC::OR), PPC::R31) .addReg(PPC::R1) .addReg(PPC::R1); - } else { + } else { // PPC64... BuildMI(MBB, MBBI, dl, TII.get(PPC::OR8), PPC::X31) .addReg(PPC::X1) .addReg(PPC::X1); @@ -641,8 +653,7 @@ void PPCFrameLowering::emitPrologue(MachineFunction &MF) const { // Mark effective beginning of when frame pointer is ready. BuildMI(MBB, MBBI, dl, TII.get(PPC::PROLOG_LABEL)).addSym(ReadyLabel); - unsigned Reg = HasFP ? (isPPC64 ? PPC::X31 : PPC::R31) - : (isPPC64 ? PPC::X1 : PPC::R1); + unsigned Reg = isPPC64 ? PPC::X31 : PPC::R31; Reg = MRI->getDwarfRegNum(Reg, true); MMI.addFrameInst(MCCFIInstruction::createDefCfaRegister(ReadyLabel, Reg)); } @@ -664,19 +675,16 @@ void PPCFrameLowering::emitPrologue(MachineFunction &MF) const { // For SVR4, don't emit a move for the CR spill slot if we haven't // spilled CRs. - if (Subtarget.isSVR4ABI() - && (PPC::CR2 <= Reg && Reg <= PPC::CR4) - && MustSaveCRs.empty()) - continue; + if (isSVR4ABI && (PPC::CR2 <= Reg && Reg <= PPC::CR4) + && MustSaveCRs.empty()) + continue; // For 64-bit SVR4 when we have spilled CRs, the spill location // is SP+8, not a frame-relative slot. - if (Subtarget.isSVR4ABI() - && Subtarget.isPPC64() - && (PPC::CR2 <= Reg && Reg <= PPC::CR4)) { + if (isSVR4ABI && isPPC64 && (PPC::CR2 <= Reg && Reg <= PPC::CR4)) { MMI.addFrameInst(MCCFIInstruction::createOffset( Label, MRI->getDwarfRegNum(PPC::CR2, true), 8)); - continue; + continue; } int Offset = MFI->getObjectOffset(CSI[I].getFrameIdx()); @@ -707,7 +715,7 @@ void PPCFrameLowering::emitEpilogue(MachineFunction &MF, RetOpcode == PPC::TCRETURNai8) && "Can only insert epilog into returning blocks"); - // Get alignment info so we know how to restore r1 + // Get alignment info so we know how to restore the SP. const MachineFrameInfo *MFI = MF.getFrameInfo(); // Get the number of bytes allocated from the FrameInfo. @@ -715,8 +723,10 @@ void PPCFrameLowering::emitEpilogue(MachineFunction &MF, // Get processor type. bool isPPC64 = Subtarget.isPPC64(); - // Get operating system + // Get the ABI. bool isDarwinABI = Subtarget.isDarwinABI(); + bool isSVR4ABI = Subtarget.isSVR4ABI(); + // Check if the link register (LR) has been saved. PPCFunctionInfo *FI = MF.getInfo(); bool MustSaveLR = FI->mustSaveLR(); @@ -729,7 +739,7 @@ void PPCFrameLowering::emitEpilogue(MachineFunction &MF, int FPOffset = 0; if (HasFP) { - if (Subtarget.isSVR4ABI()) { + if (isSVR4ABI) { MachineFrameInfo *FFI = MF.getFrameInfo(); int FPIndex = FI->getFramePointerSaveIndex(); assert(FPIndex && "No Frame Pointer Save Slot!"); @@ -741,7 +751,7 @@ void PPCFrameLowering::emitEpilogue(MachineFunction &MF, int BPOffset = 0; if (HasBP) { - if (Subtarget.isSVR4ABI()) { + if (isSVR4ABI) { MachineFrameInfo *FFI = MF.getFrameInfo(); int BPIndex = FI->getBasePointerSaveIndex(); assert(BPIndex && "No Base Pointer Save Slot!"); @@ -773,30 +783,35 @@ void PPCFrameLowering::emitEpilogue(MachineFunction &MF, FrameSize += StackAdj; } + // Frames of 32KB & larger require special handling because they cannot be + // indexed into with a simple LD/LWZ immediate offset operand. + bool isLargeFrame = !isInt<16>(FrameSize); + if (FrameSize) { - // The loaded (or persistent) stack pointer value is offset by the 'stwu' - // on entry to the function. Add this offset back now. + // In the prologue, the loaded (or persistent) stack pointer value is offset + // by the STDU/STDUX/STWU/STWUX instruction. Add this offset back now. if (!isPPC64) { // If this function contained a fastcc call and GuaranteedTailCallOpt is // enabled (=> hasFastCall()==true) the fastcc call might contain a tail // call which invalidates the stack pointer value in SP(0). So we use the // value of R31 in this case. - if (FI->hasFastCall() && isInt<16>(FrameSize)) { - assert(hasFP(MF) && "Expecting a valid the frame pointer."); - BuildMI(MBB, MBBI, dl, TII.get(PPC::ADDI), PPC::R1) - .addReg(PPC::R31).addImm(FrameSize); - } else if(FI->hasFastCall()) { - BuildMI(MBB, MBBI, dl, TII.get(PPC::LIS), PPC::R0) - .addImm(FrameSize >> 16); - BuildMI(MBB, MBBI, dl, TII.get(PPC::ORI), PPC::R0) - .addReg(PPC::R0, RegState::Kill) - .addImm(FrameSize & 0xFFFF); - BuildMI(MBB, MBBI, dl, TII.get(PPC::ADD4)) - .addReg(PPC::R1) - .addReg(PPC::R31) - .addReg(PPC::R0); - } else if (isInt<16>(FrameSize) && - !HasBP && + if (FI->hasFastCall()) { + assert(HasFP && "Expecting a valid frame pointer."); + if (!isLargeFrame) { + BuildMI(MBB, MBBI, dl, TII.get(PPC::ADDI), PPC::R1) + .addReg(PPC::R31).addImm(FrameSize); + } else { + BuildMI(MBB, MBBI, dl, TII.get(PPC::LIS), PPC::R0) + .addImm(FrameSize >> 16); + BuildMI(MBB, MBBI, dl, TII.get(PPC::ORI), PPC::R0) + .addReg(PPC::R0, RegState::Kill) + .addImm(FrameSize & 0xFFFF); + BuildMI(MBB, MBBI, dl, TII.get(PPC::ADD4)) + .addReg(PPC::R1) + .addReg(PPC::R31) + .addReg(PPC::R0); + } + } else if (!isLargeFrame && !HasBP && !MFI->hasVarSizedObjects()) { BuildMI(MBB, MBBI, dl, TII.get(PPC::ADDI), PPC::R1) .addReg(PPC::R1).addImm(FrameSize); @@ -804,22 +819,24 @@ void PPCFrameLowering::emitEpilogue(MachineFunction &MF, BuildMI(MBB, MBBI, dl, TII.get(PPC::LWZ),PPC::R1) .addImm(0).addReg(PPC::R1); } - } else { - if (FI->hasFastCall() && isInt<16>(FrameSize)) { - assert(hasFP(MF) && "Expecting a valid the frame pointer."); - BuildMI(MBB, MBBI, dl, TII.get(PPC::ADDI8), PPC::X1) - .addReg(PPC::X31).addImm(FrameSize); - } else if(FI->hasFastCall()) { - BuildMI(MBB, MBBI, dl, TII.get(PPC::LIS8), PPC::X0) - .addImm(FrameSize >> 16); - BuildMI(MBB, MBBI, dl, TII.get(PPC::ORI8), PPC::X0) - .addReg(PPC::X0, RegState::Kill) - .addImm(FrameSize & 0xFFFF); - BuildMI(MBB, MBBI, dl, TII.get(PPC::ADD8)) - .addReg(PPC::X1) - .addReg(PPC::X31) - .addReg(PPC::X0); - } else if (isInt<16>(FrameSize) && !HasBP && + } else { // PPC64... + if (FI->hasFastCall()) { + if (!isLargeFrame) { + assert(HasFP && "Expecting a valid frame pointer."); + BuildMI(MBB, MBBI, dl, TII.get(PPC::ADDI8), PPC::X1) + .addReg(PPC::X31).addImm(FrameSize); + } else { + BuildMI(MBB, MBBI, dl, TII.get(PPC::LIS8), PPC::X0) + .addImm(FrameSize >> 16); + BuildMI(MBB, MBBI, dl, TII.get(PPC::ORI8), PPC::X0) + .addReg(PPC::X0, RegState::Kill) + .addImm(FrameSize & 0xFFFF); + BuildMI(MBB, MBBI, dl, TII.get(PPC::ADD8)) + .addReg(PPC::X1) + .addReg(PPC::X31) + .addReg(PPC::X0); + } + } else if (!isLargeFrame && !HasBP && !MFI->hasVarSizedObjects()) { BuildMI(MBB, MBBI, dl, TII.get(PPC::ADDI8), PPC::X1) .addReg(PPC::X1).addImm(FrameSize); @@ -854,7 +871,7 @@ void PPCFrameLowering::emitEpilogue(MachineFunction &MF, if (MustSaveLR) BuildMI(MBB, MBBI, dl, TII.get(PPC::MTLR8)).addReg(PPC::X0); - } else { + } else { // PPC32... if (MustSaveLR) BuildMI(MBB, MBBI, dl, TII.get(PPC::LWZ), PPC::R0) .addImm(LROffset).addReg(PPC::R1); -- 2.7.4