Пример #1
0
void SystemZFrameLowering::
processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
                                     RegScavenger *RS) const {
  MachineFrameInfo *MFFrame = MF.getFrameInfo();
  MachineRegisterInfo &MRI = MF.getRegInfo();
  const TargetRegisterInfo *TRI = MF.getTarget().getRegisterInfo();
  bool HasFP = hasFP(MF);
  SystemZMachineFunctionInfo *MFI = MF.getInfo<SystemZMachineFunctionInfo>();
  bool IsVarArg = MF.getFunction()->isVarArg();

  // va_start stores incoming FPR varargs in the normal way, but delegates
  // the saving of incoming GPR varargs to spillCalleeSavedRegisters().
  // Record these pending uses, which typically include the call-saved
  // argument register R6D.
  if (IsVarArg)
    for (unsigned I = MFI->getVarArgsFirstGPR(); I < SystemZ::NumArgGPRs; ++I)
      MRI.setPhysRegUsed(SystemZ::ArgGPRs[I]);

  // If the function requires a frame pointer, record that the hard
  // frame pointer will be clobbered.
  if (HasFP)
    MRI.setPhysRegUsed(SystemZ::R11D);

  // If the function calls other functions, record that the return
  // address register will be clobbered.
  if (MFFrame->hasCalls())
    MRI.setPhysRegUsed(SystemZ::R14D);

  // If we are saving GPRs other than the stack pointer, we might as well
  // save and restore the stack pointer at the same time, via STMG and LMG.
  // This allows the deallocation to be done by the LMG, rather than needing
  // a separate %r15 addition.
  const MCPhysReg *CSRegs = TRI->getCalleeSavedRegs(&MF);
  for (unsigned I = 0; CSRegs[I]; ++I) {
    unsigned Reg = CSRegs[I];
    if (SystemZ::GR64BitRegClass.contains(Reg) && MRI.isPhysRegUsed(Reg)) {
      MRI.setPhysRegUsed(SystemZ::R15D);
      break;
    }
  }
}
Пример #2
0
bool SystemZFrameLowering::
spillCalleeSavedRegisters(MachineBasicBlock &MBB,
                          MachineBasicBlock::iterator MBBI,
                          const std::vector<CalleeSavedInfo> &CSI,
                          const TargetRegisterInfo *TRI) const {
  if (CSI.empty())
    return false;

  MachineFunction &MF = *MBB.getParent();
  const TargetInstrInfo *TII = MF.getTarget().getInstrInfo();
  SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>();
  bool IsVarArg = MF.getFunction()->isVarArg();
  DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();

  // Scan the call-saved GPRs and find the bounds of the register spill area.
  unsigned LowGPR = 0;
  unsigned HighGPR = SystemZ::R15D;
  unsigned StartOffset = -1U;
  for (unsigned I = 0, E = CSI.size(); I != E; ++I) {
    unsigned Reg = CSI[I].getReg();
    if (SystemZ::GR64BitRegClass.contains(Reg)) {
      unsigned Offset = RegSpillOffsets[Reg];
      assert(Offset && "Unexpected GPR save");
      if (StartOffset > Offset) {
        LowGPR = Reg;
        StartOffset = Offset;
      }
    }
  }

  // Save the range of call-saved registers, for use by the epilogue inserter.
  ZFI->setLowSavedGPR(LowGPR);
  ZFI->setHighSavedGPR(HighGPR);

  // Include the GPR varargs, if any.  R6D is call-saved, so would
  // be included by the loop above, but we also need to handle the
  // call-clobbered argument registers.
  if (IsVarArg) {
    unsigned FirstGPR = ZFI->getVarArgsFirstGPR();
    if (FirstGPR < SystemZ::NumArgGPRs) {
      unsigned Reg = SystemZ::ArgGPRs[FirstGPR];
      unsigned Offset = RegSpillOffsets[Reg];
      if (StartOffset > Offset) {
        LowGPR = Reg; StartOffset = Offset;
      }
    }
  }

  // Save GPRs
  if (LowGPR) {
    assert(LowGPR != HighGPR && "Should be saving %r15 and something else");

    // Build an STMG instruction.
    MachineInstrBuilder MIB = BuildMI(MBB, MBBI, DL, TII->get(SystemZ::STMG));

    // Add the explicit register operands.
    addSavedGPR(MBB, MIB, LowGPR, false);
    addSavedGPR(MBB, MIB, HighGPR, false);

    // Add the address.
    MIB.addReg(SystemZ::R15D).addImm(StartOffset);

    // Make sure all call-saved GPRs are included as operands and are
    // marked as live on entry.
    for (unsigned I = 0, E = CSI.size(); I != E; ++I) {
      unsigned Reg = CSI[I].getReg();
      if (SystemZ::GR64BitRegClass.contains(Reg))
        addSavedGPR(MBB, MIB, Reg, true);
    }

    // ...likewise GPR varargs.
    if (IsVarArg)
      for (unsigned I = ZFI->getVarArgsFirstGPR(); I < SystemZ::NumArgGPRs; ++I)
        addSavedGPR(MBB, MIB, SystemZ::ArgGPRs[I], true);
  }

  // Save FPRs in the normal TargetInstrInfo way.
  for (unsigned I = 0, E = CSI.size(); I != E; ++I) {
    unsigned Reg = CSI[I].getReg();
    if (SystemZ::FP64BitRegClass.contains(Reg)) {
      MBB.addLiveIn(Reg);
      TII->storeRegToStackSlot(MBB, MBBI, Reg, true, CSI[I].getFrameIdx(),
                               &SystemZ::FP64BitRegClass, TRI);
    }
  }

  return true;
}