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