aboutsummaryrefslogtreecommitdiff
path: root/lib/Target/ARM/ARMFrameLowering.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Target/ARM/ARMFrameLowering.cpp')
-rw-r--r--lib/Target/ARM/ARMFrameLowering.cpp84
1 files changed, 83 insertions, 1 deletions
diff --git a/lib/Target/ARM/ARMFrameLowering.cpp b/lib/Target/ARM/ARMFrameLowering.cpp
index 2629496cc5..72ec16bbe2 100644
--- a/lib/Target/ARM/ARMFrameLowering.cpp
+++ b/lib/Target/ARM/ARMFrameLowering.cpp
@@ -24,6 +24,9 @@
#include "llvm/CodeGen/RegisterScavenging.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Support/CommandLine.h"
+// @LOCALMOD-START
+#include "llvm/CodeGen/MachineModuleInfo.h"
+// @LOCALMOD-END
using namespace llvm;
@@ -151,6 +154,14 @@ void ARMFrameLowering::emitPrologue(MachineFunction &MF) const {
int FramePtrSpillFI = 0;
int D8SpillFI = 0;
+ // @LOCALMOD-START
+ MachineModuleInfo &MMI = MF.getMMI();
+ // This condition was gleaned from x86 / PowerPC / XCore
+ bool needsFrameMoves = MMI.hasDebugInfo() ||
+ !MF.getFunction()->doesNotThrow() ||
+ MF.getFunction()->needsUnwindTableEntry();
+ // @LOCALMOD-END
+
// Allocate the vararg register save area. This is not counted in NumBytes.
if (VARegSaveSize)
emitSPUpdate(isARM, MBB, MBBI, dl, TII, -VARegSaveSize,
@@ -205,6 +216,42 @@ void ARMFrameLowering::emitPrologue(MachineFunction &MF) const {
// Move past area 1.
if (GPRCS1Size > 0) MBBI++;
+ // @LOCALMOD-START
+ if (needsFrameMoves && GPRCS1Size > 0) {
+ // we just skipped the initial callee save reg instructions, e.g.
+ // push {r4, r5, r6, lr}
+ // NOTE: this likely is not the right thing to do for darwin as it does not
+ // treat all callee save regs uniformly
+ MCSymbol *AfterRegSave = MMI.getContext().CreateTempSymbol();
+ BuildMI(MBB, MBBI, dl, TII.get(ARM::PROLOG_LABEL)).addSym(AfterRegSave);
+ // record the fact that the stack has moved
+ MachineLocation dst(MachineLocation::VirtualFP);
+ MachineLocation src(MachineLocation::VirtualFP, -GPRCS1Size);
+ MMI.getFrameMoves().push_back(MachineMove(AfterRegSave, dst, src));
+ // for each callee saved register record where it has been saved
+ int offset = 0;
+ for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
+ unsigned Reg = CSI[i].getReg();
+ switch (Reg) {
+ case ARM::R4:
+ case ARM::R5:
+ case ARM::R6:
+ case ARM::R7:
+ case ARM::R8:
+ case ARM::R9:
+ case ARM::R10:
+ case ARM::R11:
+ case ARM::LR:
+ offset -= 4;
+ MachineLocation dst(MachineLocation::VirtualFP, offset);
+ MachineLocation src(Reg);
+ MMI.getFrameMoves().push_back(MachineMove(AfterRegSave, dst, src));
+ break;
+ }
+ }
+ }
+ // @LOCALMOD-END
+
// 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
@@ -218,8 +265,29 @@ void ARMFrameLowering::emitPrologue(MachineFunction &MF) const {
.addFrameIndex(FramePtrSpillFI).addImm(0)
.setMIFlag(MachineInstr::FrameSetup);
AddDefaultCC(AddDefaultPred(MIB));
+ // @LOCALMOD-START
+ if (needsFrameMoves) {
+ // we just emitted the fp pointer setup instruction, e.g.
+ // add r11, sp, #8
+ MCSymbol *AfterFramePointerInit = MMI.getContext().CreateTempSymbol();
+ BuildMI(MBB, MBBI, dl,
+ TII.get(ARM::PROLOG_LABEL)).addSym(AfterFramePointerInit);
+ // record the fact that the frame pointer is now tracking the "cfa"
+ // Note, gcc and llvm have a slightly different notion of where the
+ // frame pointer should be pointing. gcc points after the return address
+ // and llvm one word further down (two words = 8).
+ // This should be fine as long as we are consistent.
+ // NOTE: this is related to the offset computed for
+ // ISD::FRAME_TO_ARGS_OFFSET
+ MachineLocation dst(MachineLocation::VirtualFP);
+ MachineLocation src(FramePtr, 8);
+ MMI.getFrameMoves().push_back(MachineMove(AfterFramePointerInit, dst, src));
+ }
+ // @LOCALMOD-END
}
+
+
// Move past area 2.
if (GPRCS2Size > 0) MBBI++;
@@ -268,6 +336,19 @@ void ARMFrameLowering::emitPrologue(MachineFunction &MF) const {
// an inconsistent state (pointing to the middle of callee-saved area).
// The interrupt handler can end up clobbering the registers.
AFI->setShouldRestoreSPFromFP(true);
+
+ // @LOCALMOD-START
+ // we only track sp changes if do not have the fp to figure out where
+ // stack frame lives
+ if (needsFrameMoves && !HasFP) {
+ MCSymbol *AfterStackUpdate = MMI.getContext().CreateTempSymbol();
+ BuildMI(MBB, MBBI, dl,
+ TII.get(ARM::PROLOG_LABEL)).addSym(AfterStackUpdate);
+ MachineLocation dst(MachineLocation::VirtualFP);
+ MachineLocation src(MachineLocation::VirtualFP, - NumBytes - GPRCS1Size);
+ MMI.getFrameMoves().push_back(MachineMove(AfterStackUpdate, dst, src));
+ }
+ // @LOCALMOD-END
}
if (STI.isTargetELF() && hasFP(MF))
@@ -658,7 +739,8 @@ void ARMFrameLowering::emitPopInst(MachineBasicBlock &MBB,
if (Reg >= ARM::D8 && Reg < ARM::D8 + NumAlignedDPRCS2Regs)
continue;
- if (Reg == ARM::LR && !isTailCall && !isVarArg && STI.hasV5TOps()) {
+ if (Reg == ARM::LR && !isTailCall && !isVarArg && STI.hasV5TOps() &&
+ false /* @LOCALMOD */) {
Reg = ARM::PC;
LdmOpc = AFI->isThumbFunction() ? ARM::t2LDMIA_RET : ARM::LDMIA_RET;
// Fold the return instruction into the LDM.