MipsSEFrameLowering.cpp revision 239310
197403Sobrien//===-- MipsSEFrameLowering.cpp - Mips32/64 Frame Information -------------===//
297403Sobrien//
397403Sobrien//                     The LLVM Compiler Infrastructure
497403Sobrien//
597403Sobrien// This file is distributed under the University of Illinois Open Source
697403Sobrien// License. See LICENSE.TXT for details.
797403Sobrien//
897403Sobrien//===----------------------------------------------------------------------===//
997403Sobrien//
1097403Sobrien// This file contains the Mips32/64 implementation of TargetFrameLowering class.
1197403Sobrien//
1297403Sobrien//===----------------------------------------------------------------------===//
1397403Sobrien
1497403Sobrien#include "MipsSEFrameLowering.h"
1597403Sobrien#include "MipsAnalyzeImmediate.h"
1697403Sobrien#include "MipsSEInstrInfo.h"
1797403Sobrien#include "MipsMachineFunction.h"
1897403Sobrien#include "MCTargetDesc/MipsBaseInfo.h"
1997403Sobrien#include "llvm/Function.h"
2097403Sobrien#include "llvm/CodeGen/MachineFrameInfo.h"
2197403Sobrien#include "llvm/CodeGen/MachineFunction.h"
2297403Sobrien#include "llvm/CodeGen/MachineInstrBuilder.h"
2397403Sobrien#include "llvm/CodeGen/MachineModuleInfo.h"
2497403Sobrien#include "llvm/CodeGen/MachineRegisterInfo.h"
2597403Sobrien#include "llvm/Target/TargetData.h"
2697403Sobrien#include "llvm/Target/TargetOptions.h"
2797403Sobrien#include "llvm/Support/CommandLine.h"
2897403Sobrien
2997403Sobrienusing namespace llvm;
3097403Sobrien
3197403Sobrienvoid MipsSEFrameLowering::emitPrologue(MachineFunction &MF) const {
3297403Sobrien  MachineBasicBlock &MBB   = MF.front();
3397403Sobrien  MachineFrameInfo *MFI    = MF.getFrameInfo();
3497403Sobrien  const MipsRegisterInfo *RegInfo =
3597403Sobrien    static_cast<const MipsRegisterInfo*>(MF.getTarget().getRegisterInfo());
3697403Sobrien  const MipsSEInstrInfo &TII =
3797403Sobrien    *static_cast<const MipsSEInstrInfo*>(MF.getTarget().getInstrInfo());
3897403Sobrien  MachineBasicBlock::iterator MBBI = MBB.begin();
3997403Sobrien  DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
4097403Sobrien  unsigned SP = STI.isABI_N64() ? Mips::SP_64 : Mips::SP;
4197403Sobrien  unsigned FP = STI.isABI_N64() ? Mips::FP_64 : Mips::FP;
4297403Sobrien  unsigned ZERO = STI.isABI_N64() ? Mips::ZERO_64 : Mips::ZERO;
4397403Sobrien  unsigned ADDu = STI.isABI_N64() ? Mips::DADDu : Mips::ADDu;
4497403Sobrien
4597403Sobrien  // First, compute final stack size.
4697403Sobrien  uint64_t StackSize = MFI->getStackSize();
4797403Sobrien
4897403Sobrien  // No need to allocate space on the stack.
4997403Sobrien  if (StackSize == 0 && !MFI->adjustsStack()) return;
5097403Sobrien
5197403Sobrien  MachineModuleInfo &MMI = MF.getMMI();
5297403Sobrien  std::vector<MachineMove> &Moves = MMI.getFrameMoves();
5397403Sobrien  MachineLocation DstML, SrcML;
5497403Sobrien
5597403Sobrien  // Adjust stack.
5697403Sobrien  TII.adjustStackPtr(SP, -StackSize, MBB, MBBI);
5797403Sobrien
5897403Sobrien  // emit ".cfi_def_cfa_offset StackSize"
5997403Sobrien  MCSymbol *AdjustSPLabel = MMI.getContext().CreateTempSymbol();
6097403Sobrien  BuildMI(MBB, MBBI, dl,
6197403Sobrien          TII.get(TargetOpcode::PROLOG_LABEL)).addSym(AdjustSPLabel);
6297403Sobrien  DstML = MachineLocation(MachineLocation::VirtualFP);
6397403Sobrien  SrcML = MachineLocation(MachineLocation::VirtualFP, -StackSize);
6497403Sobrien  Moves.push_back(MachineMove(AdjustSPLabel, DstML, SrcML));
6597403Sobrien
6697403Sobrien  const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo();
6797403Sobrien
6897403Sobrien  if (CSI.size()) {
6997403Sobrien    // Find the instruction past the last instruction that saves a callee-saved
7097403Sobrien    // register to the stack.
7197403Sobrien    for (unsigned i = 0; i < CSI.size(); ++i)
7297403Sobrien      ++MBBI;
7397403Sobrien
7497403Sobrien    // Iterate over list of callee-saved registers and emit .cfi_offset
7597403Sobrien    // directives.
7697403Sobrien    MCSymbol *CSLabel = MMI.getContext().CreateTempSymbol();
7797403Sobrien    BuildMI(MBB, MBBI, dl,
7897403Sobrien            TII.get(TargetOpcode::PROLOG_LABEL)).addSym(CSLabel);
7997403Sobrien
8097403Sobrien    for (std::vector<CalleeSavedInfo>::const_iterator I = CSI.begin(),
8197403Sobrien           E = CSI.end(); I != E; ++I) {
8297403Sobrien      int64_t Offset = MFI->getObjectOffset(I->getFrameIdx());
8397403Sobrien      unsigned Reg = I->getReg();
8497403Sobrien
8597403Sobrien      // If Reg is a double precision register, emit two cfa_offsets,
8697403Sobrien      // one for each of the paired single precision registers.
8797403Sobrien      if (Mips::AFGR64RegClass.contains(Reg)) {
8897403Sobrien        MachineLocation DstML0(MachineLocation::VirtualFP, Offset);
8997403Sobrien        MachineLocation DstML1(MachineLocation::VirtualFP, Offset + 4);
9097403Sobrien        MachineLocation SrcML0(RegInfo->getSubReg(Reg, Mips::sub_fpeven));
9197403Sobrien        MachineLocation SrcML1(RegInfo->getSubReg(Reg, Mips::sub_fpodd));
9297403Sobrien
9397403Sobrien        if (!STI.isLittle())
9497403Sobrien          std::swap(SrcML0, SrcML1);
9597403Sobrien
9697403Sobrien        Moves.push_back(MachineMove(CSLabel, DstML0, SrcML0));
9797403Sobrien        Moves.push_back(MachineMove(CSLabel, DstML1, SrcML1));
9897403Sobrien      } else {
9997403Sobrien        // Reg is either in CPURegs or FGR32.
10097403Sobrien        DstML = MachineLocation(MachineLocation::VirtualFP, Offset);
10197403Sobrien        SrcML = MachineLocation(Reg);
10297403Sobrien        Moves.push_back(MachineMove(CSLabel, DstML, SrcML));
10397403Sobrien      }
10497403Sobrien    }
10597403Sobrien  }
10697403Sobrien
10797403Sobrien  // if framepointer enabled, set it to point to the stack pointer.
10897403Sobrien  if (hasFP(MF)) {
10997403Sobrien    // Insert instruction "move $fp, $sp" at this location.
11097403Sobrien    BuildMI(MBB, MBBI, dl, TII.get(ADDu), FP).addReg(SP).addReg(ZERO);
11197403Sobrien
11297403Sobrien    // emit ".cfi_def_cfa_register $fp"
11397403Sobrien    MCSymbol *SetFPLabel = MMI.getContext().CreateTempSymbol();
11497403Sobrien    BuildMI(MBB, MBBI, dl,
11597403Sobrien            TII.get(TargetOpcode::PROLOG_LABEL)).addSym(SetFPLabel);
11697403Sobrien    DstML = MachineLocation(FP);
11797403Sobrien    SrcML = MachineLocation(MachineLocation::VirtualFP);
11897403Sobrien    Moves.push_back(MachineMove(SetFPLabel, DstML, SrcML));
11997403Sobrien  }
12097403Sobrien}
12197403Sobrien
12297403Sobrienvoid MipsSEFrameLowering::emitEpilogue(MachineFunction &MF,
12397403Sobrien                                       MachineBasicBlock &MBB) const {
12497403Sobrien  MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
12597403Sobrien  MachineFrameInfo *MFI            = MF.getFrameInfo();
12697403Sobrien  const MipsSEInstrInfo &TII =
12797403Sobrien    *static_cast<const MipsSEInstrInfo*>(MF.getTarget().getInstrInfo());
12897403Sobrien  DebugLoc dl = MBBI->getDebugLoc();
12997403Sobrien  unsigned SP = STI.isABI_N64() ? Mips::SP_64 : Mips::SP;
13097403Sobrien  unsigned FP = STI.isABI_N64() ? Mips::FP_64 : Mips::FP;
13197403Sobrien  unsigned ZERO = STI.isABI_N64() ? Mips::ZERO_64 : Mips::ZERO;
13297403Sobrien  unsigned ADDu = STI.isABI_N64() ? Mips::DADDu : Mips::ADDu;
13397403Sobrien
13497403Sobrien  // if framepointer enabled, restore the stack pointer.
13597403Sobrien  if (hasFP(MF)) {
13697403Sobrien    // Find the first instruction that restores a callee-saved register.
13797403Sobrien    MachineBasicBlock::iterator I = MBBI;
13897403Sobrien
13997403Sobrien    for (unsigned i = 0; i < MFI->getCalleeSavedInfo().size(); ++i)
14097403Sobrien      --I;
14197403Sobrien
14297403Sobrien    // Insert instruction "move $sp, $fp" at this location.
14397403Sobrien    BuildMI(MBB, I, dl, TII.get(ADDu), SP).addReg(FP).addReg(ZERO);
14497403Sobrien  }
14597403Sobrien
14697403Sobrien  // Get the number of bytes from FrameInfo
14797403Sobrien  uint64_t StackSize = MFI->getStackSize();
14897403Sobrien
14997403Sobrien  if (!StackSize)
15097403Sobrien    return;
15197403Sobrien
15297403Sobrien  // Adjust stack.
15397403Sobrien  TII.adjustStackPtr(SP, StackSize, MBB, MBBI);
15497403Sobrien}
15597403Sobrien
15697403Sobrienbool MipsSEFrameLowering::
15797403SobrienspillCalleeSavedRegisters(MachineBasicBlock &MBB,
15897403Sobrien                          MachineBasicBlock::iterator MI,
15997403Sobrien                          const std::vector<CalleeSavedInfo> &CSI,
16097403Sobrien                          const TargetRegisterInfo *TRI) const {
16197403Sobrien  MachineFunction *MF = MBB.getParent();
16297403Sobrien  MachineBasicBlock *EntryBlock = MF->begin();
16397403Sobrien  const TargetInstrInfo &TII = *MF->getTarget().getInstrInfo();
16497403Sobrien
16597403Sobrien  for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
16697403Sobrien    // Add the callee-saved register as live-in. Do not add if the register is
16797403Sobrien    // RA and return address is taken, because it has already been added in
16897403Sobrien    // method MipsTargetLowering::LowerRETURNADDR.
16997403Sobrien    // It's killed at the spill, unless the register is RA and return address
17097403Sobrien    // is taken.
17197403Sobrien    unsigned Reg = CSI[i].getReg();
17297403Sobrien    bool IsRAAndRetAddrIsTaken = (Reg == Mips::RA || Reg == Mips::RA_64)
17397403Sobrien        && MF->getFrameInfo()->isReturnAddressTaken();
17497403Sobrien    if (!IsRAAndRetAddrIsTaken)
17597403Sobrien      EntryBlock->addLiveIn(Reg);
17697403Sobrien
17797403Sobrien    // Insert the spill to the stack frame.
17897403Sobrien    bool IsKill = !IsRAAndRetAddrIsTaken;
17997403Sobrien    const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg);
18097403Sobrien    TII.storeRegToStackSlot(*EntryBlock, MI, Reg, IsKill,
18197403Sobrien                            CSI[i].getFrameIdx(), RC, TRI);
18297403Sobrien  }
18397403Sobrien
18497403Sobrien  return true;
18597403Sobrien}
18697403Sobrien
18797403Sobrienbool
18897403SobrienMipsSEFrameLowering::hasReservedCallFrame(const MachineFunction &MF) const {
18997403Sobrien  const MachineFrameInfo *MFI = MF.getFrameInfo();
19097403Sobrien
19197403Sobrien  // Reserve call frame if the size of the maximum call frame fits into 16-bit
19297403Sobrien  // immediate field and there are no variable sized objects on the stack.
19397403Sobrien  return isInt<16>(MFI->getMaxCallFrameSize()) && !MFI->hasVarSizedObjects();
19497403Sobrien}
19597403Sobrien
19697403Sobrienvoid MipsSEFrameLowering::
19797403SobrienprocessFunctionBeforeCalleeSavedScan(MachineFunction &MF,
19897403Sobrien                                     RegScavenger *RS) const {
19997403Sobrien  MachineRegisterInfo &MRI = MF.getRegInfo();
20097403Sobrien  unsigned FP = STI.isABI_N64() ? Mips::FP_64 : Mips::FP;
20197403Sobrien
20297403Sobrien  // Mark $fp as used if function has dedicated frame pointer.
20397403Sobrien  if (hasFP(MF))
20497403Sobrien    MRI.setPhysRegUsed(FP);
20597403Sobrien}
20697403Sobrien
20797403Sobrienconst MipsFrameLowering *
20897403Sobrienllvm::createMipsSEFrameLowering(const MipsSubtarget &ST) {
20997403Sobrien  return new MipsSEFrameLowering(ST);
21097403Sobrien}
21197403Sobrien