1*0b57cec5SDimitry Andric //===- Mips16FrameLowering.cpp - Mips16 Frame Information -----------------===// 2*0b57cec5SDimitry Andric // 3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0b57cec5SDimitry Andric // 7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8*0b57cec5SDimitry Andric // 9*0b57cec5SDimitry Andric // This file contains the Mips16 implementation of TargetFrameLowering class. 10*0b57cec5SDimitry Andric // 11*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 12*0b57cec5SDimitry Andric 13*0b57cec5SDimitry Andric #include "Mips16FrameLowering.h" 14*0b57cec5SDimitry Andric #include "MCTargetDesc/MipsBaseInfo.h" 15*0b57cec5SDimitry Andric #include "Mips16InstrInfo.h" 16*0b57cec5SDimitry Andric #include "MipsInstrInfo.h" 17*0b57cec5SDimitry Andric #include "MipsRegisterInfo.h" 18*0b57cec5SDimitry Andric #include "MipsSubtarget.h" 19*0b57cec5SDimitry Andric #include "llvm/ADT/BitVector.h" 20*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h" 21*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h" 22*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h" 23*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstr.h" 24*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h" 25*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineModuleInfo.h" 26*0b57cec5SDimitry Andric #include "llvm/IR/DebugLoc.h" 27*0b57cec5SDimitry Andric #include "llvm/MC/MCContext.h" 28*0b57cec5SDimitry Andric #include "llvm/MC/MCDwarf.h" 29*0b57cec5SDimitry Andric #include "llvm/MC/MCRegisterInfo.h" 30*0b57cec5SDimitry Andric #include "llvm/MC/MachineLocation.h" 31*0b57cec5SDimitry Andric #include "llvm/Support/MathExtras.h" 32*0b57cec5SDimitry Andric #include "llvm/CodeGen/TargetFrameLowering.h" 33*0b57cec5SDimitry Andric #include <cassert> 34*0b57cec5SDimitry Andric #include <cstdint> 35*0b57cec5SDimitry Andric #include <vector> 36*0b57cec5SDimitry Andric 37*0b57cec5SDimitry Andric using namespace llvm; 38*0b57cec5SDimitry Andric 39*0b57cec5SDimitry Andric Mips16FrameLowering::Mips16FrameLowering(const MipsSubtarget &STI) 40*0b57cec5SDimitry Andric : MipsFrameLowering(STI, STI.getStackAlignment()) {} 41*0b57cec5SDimitry Andric 42*0b57cec5SDimitry Andric void Mips16FrameLowering::emitPrologue(MachineFunction &MF, 43*0b57cec5SDimitry Andric MachineBasicBlock &MBB) const { 44*0b57cec5SDimitry Andric MachineFrameInfo &MFI = MF.getFrameInfo(); 45*0b57cec5SDimitry Andric const Mips16InstrInfo &TII = 46*0b57cec5SDimitry Andric *static_cast<const Mips16InstrInfo *>(STI.getInstrInfo()); 47*0b57cec5SDimitry Andric MachineBasicBlock::iterator MBBI = MBB.begin(); 48*0b57cec5SDimitry Andric 49*0b57cec5SDimitry Andric // Debug location must be unknown since the first debug location is used 50*0b57cec5SDimitry Andric // to determine the end of the prologue. 51*0b57cec5SDimitry Andric DebugLoc dl; 52*0b57cec5SDimitry Andric 53*0b57cec5SDimitry Andric uint64_t StackSize = MFI.getStackSize(); 54*0b57cec5SDimitry Andric 55*0b57cec5SDimitry Andric // No need to allocate space on the stack. 56*0b57cec5SDimitry Andric if (StackSize == 0 && !MFI.adjustsStack()) return; 57*0b57cec5SDimitry Andric 58*0b57cec5SDimitry Andric MachineModuleInfo &MMI = MF.getMMI(); 59*0b57cec5SDimitry Andric const MCRegisterInfo *MRI = MMI.getContext().getRegisterInfo(); 60*0b57cec5SDimitry Andric 61*0b57cec5SDimitry Andric // Adjust stack. 62*0b57cec5SDimitry Andric TII.makeFrame(Mips::SP, StackSize, MBB, MBBI); 63*0b57cec5SDimitry Andric 64*0b57cec5SDimitry Andric // emit ".cfi_def_cfa_offset StackSize" 65*0b57cec5SDimitry Andric unsigned CFIIndex = MF.addFrameInst( 66*0b57cec5SDimitry Andric MCCFIInstruction::createDefCfaOffset(nullptr, -StackSize)); 67*0b57cec5SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) 68*0b57cec5SDimitry Andric .addCFIIndex(CFIIndex); 69*0b57cec5SDimitry Andric 70*0b57cec5SDimitry Andric const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo(); 71*0b57cec5SDimitry Andric 72*0b57cec5SDimitry Andric if (!CSI.empty()) { 73*0b57cec5SDimitry Andric const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo(); 74*0b57cec5SDimitry Andric 75*0b57cec5SDimitry Andric for (std::vector<CalleeSavedInfo>::const_iterator I = CSI.begin(), 76*0b57cec5SDimitry Andric E = CSI.end(); I != E; ++I) { 77*0b57cec5SDimitry Andric int64_t Offset = MFI.getObjectOffset(I->getFrameIdx()); 78*0b57cec5SDimitry Andric unsigned Reg = I->getReg(); 79*0b57cec5SDimitry Andric unsigned DReg = MRI->getDwarfRegNum(Reg, true); 80*0b57cec5SDimitry Andric unsigned CFIIndex = MF.addFrameInst( 81*0b57cec5SDimitry Andric MCCFIInstruction::createOffset(nullptr, DReg, Offset)); 82*0b57cec5SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) 83*0b57cec5SDimitry Andric .addCFIIndex(CFIIndex); 84*0b57cec5SDimitry Andric } 85*0b57cec5SDimitry Andric } 86*0b57cec5SDimitry Andric if (hasFP(MF)) 87*0b57cec5SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(Mips::MoveR3216), Mips::S0) 88*0b57cec5SDimitry Andric .addReg(Mips::SP).setMIFlag(MachineInstr::FrameSetup); 89*0b57cec5SDimitry Andric } 90*0b57cec5SDimitry Andric 91*0b57cec5SDimitry Andric void Mips16FrameLowering::emitEpilogue(MachineFunction &MF, 92*0b57cec5SDimitry Andric MachineBasicBlock &MBB) const { 93*0b57cec5SDimitry Andric MachineBasicBlock::iterator MBBI = MBB.getFirstTerminator(); 94*0b57cec5SDimitry Andric MachineFrameInfo &MFI = MF.getFrameInfo(); 95*0b57cec5SDimitry Andric const Mips16InstrInfo &TII = 96*0b57cec5SDimitry Andric *static_cast<const Mips16InstrInfo *>(STI.getInstrInfo()); 97*0b57cec5SDimitry Andric DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); 98*0b57cec5SDimitry Andric uint64_t StackSize = MFI.getStackSize(); 99*0b57cec5SDimitry Andric 100*0b57cec5SDimitry Andric if (!StackSize) 101*0b57cec5SDimitry Andric return; 102*0b57cec5SDimitry Andric 103*0b57cec5SDimitry Andric if (hasFP(MF)) 104*0b57cec5SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(Mips::Move32R16), Mips::SP) 105*0b57cec5SDimitry Andric .addReg(Mips::S0); 106*0b57cec5SDimitry Andric 107*0b57cec5SDimitry Andric // Adjust stack. 108*0b57cec5SDimitry Andric // assumes stacksize multiple of 8 109*0b57cec5SDimitry Andric TII.restoreFrame(Mips::SP, StackSize, MBB, MBBI); 110*0b57cec5SDimitry Andric } 111*0b57cec5SDimitry Andric 112*0b57cec5SDimitry Andric bool Mips16FrameLowering:: 113*0b57cec5SDimitry Andric spillCalleeSavedRegisters(MachineBasicBlock &MBB, 114*0b57cec5SDimitry Andric MachineBasicBlock::iterator MI, 115*0b57cec5SDimitry Andric const std::vector<CalleeSavedInfo> &CSI, 116*0b57cec5SDimitry Andric const TargetRegisterInfo *TRI) const { 117*0b57cec5SDimitry Andric MachineFunction *MF = MBB.getParent(); 118*0b57cec5SDimitry Andric 119*0b57cec5SDimitry Andric // 120*0b57cec5SDimitry Andric // Registers RA, S0,S1 are the callee saved registers and they 121*0b57cec5SDimitry Andric // will be saved with the "save" instruction 122*0b57cec5SDimitry Andric // during emitPrologue 123*0b57cec5SDimitry Andric // 124*0b57cec5SDimitry Andric for (unsigned i = 0, e = CSI.size(); i != e; ++i) { 125*0b57cec5SDimitry Andric // Add the callee-saved register as live-in. Do not add if the register is 126*0b57cec5SDimitry Andric // RA and return address is taken, because it has already been added in 127*0b57cec5SDimitry Andric // method MipsTargetLowering::lowerRETURNADDR. 128*0b57cec5SDimitry Andric // It's killed at the spill, unless the register is RA and return address 129*0b57cec5SDimitry Andric // is taken. 130*0b57cec5SDimitry Andric unsigned Reg = CSI[i].getReg(); 131*0b57cec5SDimitry Andric bool IsRAAndRetAddrIsTaken = (Reg == Mips::RA) 132*0b57cec5SDimitry Andric && MF->getFrameInfo().isReturnAddressTaken(); 133*0b57cec5SDimitry Andric if (!IsRAAndRetAddrIsTaken) 134*0b57cec5SDimitry Andric MBB.addLiveIn(Reg); 135*0b57cec5SDimitry Andric } 136*0b57cec5SDimitry Andric 137*0b57cec5SDimitry Andric return true; 138*0b57cec5SDimitry Andric } 139*0b57cec5SDimitry Andric 140*0b57cec5SDimitry Andric bool Mips16FrameLowering::restoreCalleeSavedRegisters(MachineBasicBlock &MBB, 141*0b57cec5SDimitry Andric MachineBasicBlock::iterator MI, 142*0b57cec5SDimitry Andric std::vector<CalleeSavedInfo> &CSI, 143*0b57cec5SDimitry Andric const TargetRegisterInfo *TRI) const { 144*0b57cec5SDimitry Andric // 145*0b57cec5SDimitry Andric // Registers RA,S0,S1 are the callee saved registers and they will be restored 146*0b57cec5SDimitry Andric // with the restore instruction during emitEpilogue. 147*0b57cec5SDimitry Andric // We need to override this virtual function, otherwise llvm will try and 148*0b57cec5SDimitry Andric // restore the registers on it's on from the stack. 149*0b57cec5SDimitry Andric // 150*0b57cec5SDimitry Andric 151*0b57cec5SDimitry Andric return true; 152*0b57cec5SDimitry Andric } 153*0b57cec5SDimitry Andric 154*0b57cec5SDimitry Andric bool 155*0b57cec5SDimitry Andric Mips16FrameLowering::hasReservedCallFrame(const MachineFunction &MF) const { 156*0b57cec5SDimitry Andric const MachineFrameInfo &MFI = MF.getFrameInfo(); 157*0b57cec5SDimitry Andric // Reserve call frame if the size of the maximum call frame fits into 15-bit 158*0b57cec5SDimitry Andric // immediate field and there are no variable sized objects on the stack. 159*0b57cec5SDimitry Andric return isInt<15>(MFI.getMaxCallFrameSize()) && !MFI.hasVarSizedObjects(); 160*0b57cec5SDimitry Andric } 161*0b57cec5SDimitry Andric 162*0b57cec5SDimitry Andric void Mips16FrameLowering::determineCalleeSaves(MachineFunction &MF, 163*0b57cec5SDimitry Andric BitVector &SavedRegs, 164*0b57cec5SDimitry Andric RegScavenger *RS) const { 165*0b57cec5SDimitry Andric TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS); 166*0b57cec5SDimitry Andric const Mips16InstrInfo &TII = 167*0b57cec5SDimitry Andric *static_cast<const Mips16InstrInfo *>(STI.getInstrInfo()); 168*0b57cec5SDimitry Andric const MipsRegisterInfo &RI = TII.getRegisterInfo(); 169*0b57cec5SDimitry Andric const BitVector Reserved = RI.getReservedRegs(MF); 170*0b57cec5SDimitry Andric bool SaveS2 = Reserved[Mips::S2]; 171*0b57cec5SDimitry Andric if (SaveS2) 172*0b57cec5SDimitry Andric SavedRegs.set(Mips::S2); 173*0b57cec5SDimitry Andric if (hasFP(MF)) 174*0b57cec5SDimitry Andric SavedRegs.set(Mips::S0); 175*0b57cec5SDimitry Andric } 176*0b57cec5SDimitry Andric 177*0b57cec5SDimitry Andric const MipsFrameLowering * 178*0b57cec5SDimitry Andric llvm::createMips16FrameLowering(const MipsSubtarget &ST) { 179*0b57cec5SDimitry Andric return new Mips16FrameLowering(ST); 180*0b57cec5SDimitry Andric } 181