Chromium Code Reviews| Index: lib/Target/ARM/ARMFrameLowering.cpp |
| diff --git a/lib/Target/ARM/ARMFrameLowering.cpp b/lib/Target/ARM/ARMFrameLowering.cpp |
| index 8895dfa5c8e0b6ca1a503f5671c966ba5b4810b7..bb10fe21bf23779b1179afbfcd95bd064019e640 100644 |
| --- a/lib/Target/ARM/ARMFrameLowering.cpp |
| +++ b/lib/Target/ARM/ARMFrameLowering.cpp |
| @@ -966,6 +966,15 @@ void ARMFrameLowering::emitPushInst(MachineBasicBlock &MBB, |
| isKill = false; |
| } |
| + // @LOCALMOD-START |
| + // Functions which call EHReturn spill all CSRs plus R0/R1 |
| + if ((Reg == ARM::R0 || Reg == ARM::R1) && |
| + MF.getRegInfo().isLiveIn(Reg)) { |
| + assert(MF.getMMI().callsEHReturn()); |
| + isKill = false; |
| + } |
| + // @LOCALMOD-END |
| + |
| if (isKill) |
| MBB.addLiveIn(Reg); |
| @@ -1025,6 +1034,7 @@ void ARMFrameLowering::emitPopInst(MachineBasicBlock &MBB, |
| while (i != 0) { |
| unsigned LastReg = 0; |
| bool DeleteRet = false; |
| + unsigned SkippedPop = 0; // @LOCALMOD |
| for (; i != 0; --i) { |
| unsigned Reg = CSI[i-1].getReg(); |
| if (!(Func)(Reg, STI.isTargetDarwin())) continue; |
| @@ -1033,6 +1043,19 @@ void ARMFrameLowering::emitPopInst(MachineBasicBlock &MBB, |
| if (Reg >= ARM::D8 && Reg < ARM::D8 + NumAlignedDPRCS2Regs) |
| continue; |
| + // @LOCALMOD-START |
| + // Functions which call EHReturn spill all of their CSRs plus R0 and R1, |
| + // (the EHReturn return value registers). Epilogs which return via |
| + // EHreturn pop all of them, but epilogs which return via normal return |
| + // must not restore R0 and R1, as that would clobber the return value. |
| + if (MF.getMMI().callsEHReturn() && |
| + RetOpcode != ARM::ARMeh_return && |
| + (Reg == ARM::R0 || Reg == ARM::R1)) { |
| + SkippedPop++; |
| + continue; |
| + } |
| + // @LOCALMOD-END |
| + |
| if (Reg == ARM::LR && !isTailCall && !isVarArg && !isInterrupt && |
| STI.hasV5TOps() && |
| !STI.isTargetNaCl() /* @LOCALMOD */) { |
| @@ -1052,12 +1075,27 @@ void ARMFrameLowering::emitPopInst(MachineBasicBlock &MBB, |
| Regs.push_back(Reg); |
| } |
| + // @LOCALMOD-START |
| + if (SkippedPop) { |
| + // We need to increment the stack pointer to compensate for the skipped |
| + // pops. However we cannot directly increment it because the epilog |
| + // insertion code places the stack pointer restore before the CSR restores; |
|
jvoung (off chromium)
2015/06/03 17:19:38
80 col
Derek Schuff
2015/06/03 20:50:57
Done.
|
| + // it does this by finding the first instruction that's not a pop. |
| + // If we put an add here, the restore would go in between the restore of |
| + // the FP registers and the GPRs, instead of before the FP restore. So |
| + // use a pop into R12 to adjust SP. |
| + while(SkippedPop--) |
| + AddDefaultPred(BuildMI(MBB, MI, DL, TII.get(LdmOpc), ARM::SP) |
| + .addReg(ARM::SP)).addReg(ARM::R12); |
| + } |
| + // @LOCALMOD-END |
| + |
| if (Regs.empty()) |
| continue; |
| if (Regs.size() > 1 || LdrOpc == 0) { |
| MachineInstrBuilder MIB = |
| - AddDefaultPred(BuildMI(MBB, MI, DL, TII.get(LdmOpc), ARM::SP) |
| - .addReg(ARM::SP)); |
| + AddDefaultPred(BuildMI(MBB, MI, DL, TII.get(LdmOpc), ARM::SP) |
| + .addReg(ARM::SP)); |
|
jvoung (off chromium)
2015/06/03 17:19:38
revert whitespace change?
Derek Schuff
2015/06/03 20:50:57
Done.
|
| for (unsigned i = 0, e = Regs.size(); i < e; ++i) |
| MIB.addReg(Regs[i], getDefRegState(true)); |
| if (DeleteRet) { |