diff options
author | Artyom Skrobov <Artyom.Skrobov@arm.com> | 2014-02-14 17:19:07 +0000 |
---|---|---|
committer | Artyom Skrobov <Artyom.Skrobov@arm.com> | 2014-02-14 17:19:07 +0000 |
commit | e228078ca6de1c5316ec53a370568ea5d824f8e5 (patch) | |
tree | 7dfa79dfdd4dc4e51be2616dae57ac8876661dae /lib/Target/ARM/ARMFrameLowering.cpp | |
parent | 54136cad2ea9f322849ce49b299860454fc97368 (diff) | |
download | llvm-e228078ca6de1c5316ec53a370568ea5d824f8e5.tar.gz llvm-e228078ca6de1c5316ec53a370568ea5d824f8e5.tar.bz2 llvm-e228078ca6de1c5316ec53a370568ea5d824f8e5.tar.xz |
Generate the DWARF stack frame decode operations in the function prologue for ARM/Thumb functions.
Patch by Keith Walker!
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@201423 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Target/ARM/ARMFrameLowering.cpp')
-rw-r--r-- | lib/Target/ARM/ARMFrameLowering.cpp | 204 |
1 files changed, 181 insertions, 23 deletions
diff --git a/lib/Target/ARM/ARMFrameLowering.cpp b/lib/Target/ARM/ARMFrameLowering.cpp index 63f1577821..916417882b 100644 --- a/lib/Target/ARM/ARMFrameLowering.cpp +++ b/lib/Target/ARM/ARMFrameLowering.cpp @@ -19,10 +19,12 @@ #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/RegisterScavenging.h" #include "llvm/IR/CallingConv.h" #include "llvm/IR/Function.h" +#include "llvm/MC/MCContext.h" #include "llvm/Support/CommandLine.h" #include "llvm/Target/TargetOptions.h" @@ -129,11 +131,24 @@ static void emitSPUpdate(bool isARM, MachineBasicBlock &MBB, MIFlags, Pred, PredReg); } +static int sizeOfSPAdjustment(const MachineInstr *MI) { + assert(MI->getOpcode() == ARM::VSTMDDB_UPD); + int count = 0; + // ARM and Thumb2 push/pop insts have explicit "sp, sp" operands (+ + // pred) so the list starts at 4. + for (int i = MI->getNumOperands() - 1; i >= 4; --i) + count += 8; + return count; +} + void ARMFrameLowering::emitPrologue(MachineFunction &MF) const { MachineBasicBlock &MBB = MF.front(); MachineBasicBlock::iterator MBBI = MBB.begin(); MachineFrameInfo *MFI = MF.getFrameInfo(); ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>(); + MachineModuleInfo &MMI = MF.getMMI(); + MCContext &Context = MMI.getContext(); + const MCRegisterInfo *MRI = Context.getRegisterInfo(); const ARMBaseRegisterInfo *RegInfo = static_cast<const ARMBaseRegisterInfo*>(MF.getTarget().getRegisterInfo()); const ARMBaseInstrInfo &TII = @@ -147,6 +162,7 @@ void ARMFrameLowering::emitPrologue(MachineFunction &MF) const { const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo(); DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); unsigned FramePtr = RegInfo->getFrameRegister(MF); + int CFAOffset = 0; // Determine the sizes of each callee-save spill areas and record which frame // belongs to which callee-save spill areas. @@ -160,21 +176,46 @@ void ARMFrameLowering::emitPrologue(MachineFunction &MF) const { return; // Allocate the vararg register save area. This is not counted in NumBytes. - if (ArgRegsSaveSize) + if (ArgRegsSaveSize) { emitSPUpdate(isARM, MBB, MBBI, dl, TII, -ArgRegsSaveSize, MachineInstr::FrameSetup); + MCSymbol *SPLabel = Context.CreateTempSymbol(); + BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::PROLOG_LABEL)) + .addSym(SPLabel); + CFAOffset -= ArgRegsSaveSize; + MMI.addFrameInst( + MCCFIInstruction::createDefCfaOffset(SPLabel, CFAOffset)); + } if (!AFI->hasStackFrame()) { - if (NumBytes != 0) + if (NumBytes != 0) { emitSPUpdate(isARM, MBB, MBBI, dl, TII, -NumBytes, MachineInstr::FrameSetup); + MCSymbol *SPLabel = Context.CreateTempSymbol(); + BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::PROLOG_LABEL)) + .addSym(SPLabel); + CFAOffset -= NumBytes; + MMI.addFrameInst(MCCFIInstruction::createDefCfaOffset(SPLabel, + CFAOffset)); + } return; } + // Determine spill area sizes. for (unsigned i = 0, e = CSI.size(); i != e; ++i) { unsigned Reg = CSI[i].getReg(); int FI = CSI[i].getFrameIdx(); switch (Reg) { + case ARM::R8: + case ARM::R9: + case ARM::R10: + case ARM::R11: + case ARM::R12: + if (STI.isTargetMachO()) { + GPRCS2Size += 4; + break; + } + // fallthrough case ARM::R0: case ARM::R1: case ARM::R2: @@ -188,18 +229,6 @@ void ARMFrameLowering::emitPrologue(MachineFunction &MF) const { FramePtrSpillFI = FI; GPRCS1Size += 4; break; - case ARM::R8: - case ARM::R9: - case ARM::R10: - case ARM::R11: - case ARM::R12: - if (Reg == FramePtr) - FramePtrSpillFI = FI; - if (STI.isTargetMachO()) - GPRCS2Size += 4; - else - GPRCS1Size += 4; - break; default: // This is a DPR. Exclude the aligned DPRCS2 spills. if (Reg == ARM::D8) @@ -210,9 +239,10 @@ void ARMFrameLowering::emitPrologue(MachineFunction &MF) const { } // Move past area 1. - MachineBasicBlock::iterator LastPush = MBB.end(), FramePtrPush; + MachineBasicBlock::iterator LastPush = MBB.end(), GPRCS1Push, GPRCS2Push, + DPRCSPush; if (GPRCS1Size > 0) - FramePtrPush = LastPush = MBBI++; + GPRCS1Push = LastPush = MBBI++; // Determine starting offsets of spill areas. bool HasFP = hasFP(MF); @@ -230,13 +260,12 @@ void ARMFrameLowering::emitPrologue(MachineFunction &MF) const { AFI->setDPRCalleeSavedAreaOffset(DPRCSOffset); // Move past area 2. - if (GPRCS2Size > 0) { - LastPush = MBBI++; - } + if (GPRCS2Size > 0) + GPRCS2Push = LastPush = MBBI++; // Move past area 3. if (DPRCSSize > 0) { - LastPush = MBBI++; + DPRCSPush = MBBI; // Since vpush register list cannot have gaps, there may be multiple vpush // instructions in the prologue. while (MBBI->getOpcode() == ARM::VSTMDDB_UPD) @@ -254,11 +283,15 @@ void ARMFrameLowering::emitPrologue(MachineFunction &MF) const { } else NumBytes = DPRCSOffset; + unsigned adjustedGPRCS1Size = GPRCS1Size; if (NumBytes) { // Adjust SP after all the callee-save spills. if (tryFoldSPUpdateIntoPushPop(STI, MF, LastPush, NumBytes)) { - if (LastPush == FramePtrPush) + if (LastPush == GPRCS1Push) { FramePtrOffsetInPush += NumBytes; + adjustedGPRCS1Size += NumBytes; + NumBytes = 0; + } } else emitSPUpdate(isARM, MBB, MBBI, dl, TII, -NumBytes, MachineInstr::FrameSetup); @@ -275,17 +308,142 @@ void ARMFrameLowering::emitPrologue(MachineFunction &MF) const { AFI->setShouldRestoreSPFromFP(true); } + if (adjustedGPRCS1Size > 0) { + MCSymbol *SPLabel = Context.CreateTempSymbol(); + BuildMI(MBB, ++GPRCS1Push, dl, TII.get(TargetOpcode::PROLOG_LABEL)) + .addSym(SPLabel); + CFAOffset -= adjustedGPRCS1Size; + MMI.addFrameInst( + MCCFIInstruction::createDefCfaOffset(SPLabel, CFAOffset)); + for (std::vector<CalleeSavedInfo>::const_iterator I = CSI.begin(), + E = CSI.end(); I != E; ++I) { + unsigned Reg = I->getReg(); + int FI = I->getFrameIdx(); + switch (Reg) { + case ARM::R8: + case ARM::R9: + case ARM::R10: + case ARM::R11: + case ARM::R12: + if (STI.isTargetMachO()) + break; + // fallthrough + case ARM::R0: + case ARM::R1: + case ARM::R2: + case ARM::R3: + case ARM::R4: + case ARM::R5: + case ARM::R6: + case ARM::R7: + case ARM::LR: + MMI.addFrameInst(MCCFIInstruction::createOffset(SPLabel, + MRI->getDwarfRegNum(Reg, true), + MFI->getObjectOffset(FI) - ArgRegsSaveSize)); + break; + } + } + } + // Set FP to point to the stack slot that contains the previous FP. // For iOS, FP is R7, which has now been stored in spill area 1. // Otherwise, if this is not iOS, all the callee-saved registers go // into spill area 1, including the FP in R11. In either case, it // is in area one and the adjustment needs to take place just after // that push. - if (HasFP) - emitRegPlusImmediate(!AFI->isThumbFunction(), MBB, ++FramePtrPush, dl, TII, + if (HasFP) { + emitRegPlusImmediate(!AFI->isThumbFunction(), MBB, GPRCS1Push, dl, TII, FramePtr, ARM::SP, FramePtrOffsetInPush, MachineInstr::FrameSetup); + MCSymbol *SPLabel = Context.CreateTempSymbol(); + BuildMI(MBB, GPRCS1Push, dl, TII.get(TargetOpcode::PROLOG_LABEL)) + .addSym(SPLabel); + if (FramePtrOffsetInPush) { + CFAOffset += FramePtrOffsetInPush; + MMI.addFrameInst( + MCCFIInstruction::createDefCfa(SPLabel, + MRI->getDwarfRegNum(FramePtr, true), CFAOffset)); + } else + MMI.addFrameInst( + MCCFIInstruction::createDefCfaRegister(SPLabel, + MRI->getDwarfRegNum(FramePtr, true))); + } + if (GPRCS2Size > 0) { + MCSymbol *SPLabel = Context.CreateTempSymbol(); + BuildMI(MBB, ++GPRCS2Push, dl, TII.get(TargetOpcode::PROLOG_LABEL)) + .addSym(SPLabel); + if (!HasFP) { + CFAOffset -= GPRCS2Size; + MMI.addFrameInst( + MCCFIInstruction::createDefCfaOffset(SPLabel, CFAOffset)); + } + for (std::vector<CalleeSavedInfo>::const_iterator I = CSI.begin(), + E = CSI.end(); I != E; ++I) { + unsigned Reg = I->getReg(); + int FI = I->getFrameIdx(); + switch (Reg) { + case ARM::R8: + case ARM::R9: + case ARM::R10: + case ARM::R11: + case ARM::R12: + if (STI.isTargetMachO()) { + unsigned DwarfReg = MRI->getDwarfRegNum(Reg, true); + unsigned Offset = MFI->getObjectOffset(FI) - ArgRegsSaveSize; + MMI.addFrameInst( + MCCFIInstruction::createOffset(SPLabel, DwarfReg, Offset)); + } + break; + } + } + } + + if (DPRCSSize > 0) { + // Since vpush register list cannot have gaps, there may be multiple vpush + // instructions in the prologue. + MCSymbol *SPLabel = NULL; + do { + MachineBasicBlock::iterator Push = DPRCSPush++; + if (!HasFP) { + SPLabel = Context.CreateTempSymbol(); + BuildMI(MBB, DPRCSPush, dl, TII.get(TargetOpcode::PROLOG_LABEL)) + .addSym(SPLabel); + CFAOffset -= sizeOfSPAdjustment(Push);; + MMI.addFrameInst( + MCCFIInstruction::createDefCfaOffset(SPLabel, CFAOffset)); + } + } while (DPRCSPush->getOpcode() == ARM::VSTMDDB_UPD); + + if (!SPLabel) { + SPLabel = Context.CreateTempSymbol(); + BuildMI(MBB, DPRCSPush, dl, TII.get(TargetOpcode::PROLOG_LABEL)) + .addSym(SPLabel); + } + for (std::vector<CalleeSavedInfo>::const_iterator I = CSI.begin(), + E = CSI.end(); I != E; ++I) { + unsigned Reg = I->getReg(); + int FI = I->getFrameIdx(); + if ((Reg >= ARM::D0 && Reg <= ARM::D31) && + (Reg < ARM::D8 || Reg >= ARM::D8 + AFI->getNumAlignedDPRCS2Regs())) { + unsigned DwarfReg = MRI->getDwarfRegNum(Reg, true); + unsigned Offset = MFI->getObjectOffset(FI); + MMI.addFrameInst(MCCFIInstruction::createOffset(SPLabel, DwarfReg, + Offset)); + } + } + } + + if (NumBytes) { + if (!HasFP) { + MCSymbol *SPLabel = Context.CreateTempSymbol(); + BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::PROLOG_LABEL)) + .addSym(SPLabel); + CFAOffset -= NumBytes; + MMI.addFrameInst( + MCCFIInstruction::createDefCfaOffset(SPLabel, CFAOffset)); + } + } if (STI.isTargetELF() && hasFP(MF)) MFI->setOffsetAdjustment(MFI->getOffsetAdjustment() - |