10b57cec5SDimitry Andric //===- Mips16FrameLowering.cpp - Mips16 Frame Information -----------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This file contains the Mips16 implementation of TargetFrameLowering class. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #include "Mips16FrameLowering.h" 140b57cec5SDimitry Andric #include "MCTargetDesc/MipsBaseInfo.h" 150b57cec5SDimitry Andric #include "Mips16InstrInfo.h" 160b57cec5SDimitry Andric #include "MipsInstrInfo.h" 170b57cec5SDimitry Andric #include "MipsRegisterInfo.h" 180b57cec5SDimitry Andric #include "MipsSubtarget.h" 190b57cec5SDimitry Andric #include "llvm/ADT/BitVector.h" 200b57cec5SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h" 210b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h" 220b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h" 230b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstr.h" 240b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h" 250b57cec5SDimitry Andric #include "llvm/CodeGen/MachineModuleInfo.h" 260b57cec5SDimitry Andric #include "llvm/IR/DebugLoc.h" 270b57cec5SDimitry Andric #include "llvm/MC/MCContext.h" 280b57cec5SDimitry Andric #include "llvm/MC/MCDwarf.h" 290b57cec5SDimitry Andric #include "llvm/MC/MCRegisterInfo.h" 300b57cec5SDimitry Andric #include "llvm/MC/MachineLocation.h" 310b57cec5SDimitry Andric #include "llvm/Support/MathExtras.h" 320b57cec5SDimitry Andric #include "llvm/CodeGen/TargetFrameLowering.h" 330b57cec5SDimitry Andric #include <cstdint> 340b57cec5SDimitry Andric #include <vector> 350b57cec5SDimitry Andric 360b57cec5SDimitry Andric using namespace llvm; 370b57cec5SDimitry Andric 380b57cec5SDimitry Andric Mips16FrameLowering::Mips16FrameLowering(const MipsSubtarget &STI) 390b57cec5SDimitry Andric : MipsFrameLowering(STI, STI.getStackAlignment()) {} 400b57cec5SDimitry Andric 410b57cec5SDimitry Andric void Mips16FrameLowering::emitPrologue(MachineFunction &MF, 420b57cec5SDimitry Andric MachineBasicBlock &MBB) const { 430b57cec5SDimitry Andric MachineFrameInfo &MFI = MF.getFrameInfo(); 440b57cec5SDimitry Andric const Mips16InstrInfo &TII = 450b57cec5SDimitry Andric *static_cast<const Mips16InstrInfo *>(STI.getInstrInfo()); 460b57cec5SDimitry Andric MachineBasicBlock::iterator MBBI = MBB.begin(); 470b57cec5SDimitry Andric 480b57cec5SDimitry Andric // Debug location must be unknown since the first debug location is used 490b57cec5SDimitry Andric // to determine the end of the prologue. 500b57cec5SDimitry Andric DebugLoc dl; 510b57cec5SDimitry Andric 520b57cec5SDimitry Andric uint64_t StackSize = MFI.getStackSize(); 530b57cec5SDimitry Andric 540b57cec5SDimitry Andric // No need to allocate space on the stack. 550b57cec5SDimitry Andric if (StackSize == 0 && !MFI.adjustsStack()) return; 560b57cec5SDimitry Andric 57*0fca6ea1SDimitry Andric const MCRegisterInfo *MRI = MF.getContext().getRegisterInfo(); 580b57cec5SDimitry Andric 590b57cec5SDimitry Andric // Adjust stack. 600b57cec5SDimitry Andric TII.makeFrame(Mips::SP, StackSize, MBB, MBBI); 610b57cec5SDimitry Andric 620b57cec5SDimitry Andric // emit ".cfi_def_cfa_offset StackSize" 635ffd83dbSDimitry Andric unsigned CFIIndex = 645ffd83dbSDimitry Andric MF.addFrameInst(MCCFIInstruction::cfiDefCfaOffset(nullptr, StackSize)); 650b57cec5SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) 660b57cec5SDimitry Andric .addCFIIndex(CFIIndex); 670b57cec5SDimitry Andric 680b57cec5SDimitry Andric const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo(); 690b57cec5SDimitry Andric 700b57cec5SDimitry Andric if (!CSI.empty()) { 710b57cec5SDimitry Andric const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo(); 720b57cec5SDimitry Andric 734824e7fdSDimitry Andric for (const CalleeSavedInfo &I : CSI) { 744824e7fdSDimitry Andric int64_t Offset = MFI.getObjectOffset(I.getFrameIdx()); 7504eeddc0SDimitry Andric Register Reg = I.getReg(); 760b57cec5SDimitry Andric unsigned DReg = MRI->getDwarfRegNum(Reg, true); 770b57cec5SDimitry Andric unsigned CFIIndex = MF.addFrameInst( 780b57cec5SDimitry Andric MCCFIInstruction::createOffset(nullptr, DReg, Offset)); 790b57cec5SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) 800b57cec5SDimitry Andric .addCFIIndex(CFIIndex); 810b57cec5SDimitry Andric } 820b57cec5SDimitry Andric } 830b57cec5SDimitry Andric if (hasFP(MF)) 840b57cec5SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(Mips::MoveR3216), Mips::S0) 850b57cec5SDimitry Andric .addReg(Mips::SP).setMIFlag(MachineInstr::FrameSetup); 860b57cec5SDimitry Andric } 870b57cec5SDimitry Andric 880b57cec5SDimitry Andric void Mips16FrameLowering::emitEpilogue(MachineFunction &MF, 890b57cec5SDimitry Andric MachineBasicBlock &MBB) const { 900b57cec5SDimitry Andric MachineBasicBlock::iterator MBBI = MBB.getFirstTerminator(); 910b57cec5SDimitry Andric MachineFrameInfo &MFI = MF.getFrameInfo(); 920b57cec5SDimitry Andric const Mips16InstrInfo &TII = 930b57cec5SDimitry Andric *static_cast<const Mips16InstrInfo *>(STI.getInstrInfo()); 940b57cec5SDimitry Andric DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); 950b57cec5SDimitry Andric uint64_t StackSize = MFI.getStackSize(); 960b57cec5SDimitry Andric 970b57cec5SDimitry Andric if (!StackSize) 980b57cec5SDimitry Andric return; 990b57cec5SDimitry Andric 1000b57cec5SDimitry Andric if (hasFP(MF)) 1010b57cec5SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(Mips::Move32R16), Mips::SP) 1020b57cec5SDimitry Andric .addReg(Mips::S0); 1030b57cec5SDimitry Andric 1040b57cec5SDimitry Andric // Adjust stack. 1050b57cec5SDimitry Andric // assumes stacksize multiple of 8 1060b57cec5SDimitry Andric TII.restoreFrame(Mips::SP, StackSize, MBB, MBBI); 1070b57cec5SDimitry Andric } 1080b57cec5SDimitry Andric 1095ffd83dbSDimitry Andric bool Mips16FrameLowering::spillCalleeSavedRegisters( 1105ffd83dbSDimitry Andric MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, 1115ffd83dbSDimitry Andric ArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const { 1120b57cec5SDimitry Andric MachineFunction *MF = MBB.getParent(); 1130b57cec5SDimitry Andric 1140b57cec5SDimitry Andric // 1150b57cec5SDimitry Andric // Registers RA, S0,S1 are the callee saved registers and they 1160b57cec5SDimitry Andric // will be saved with the "save" instruction 1170b57cec5SDimitry Andric // during emitPrologue 1180b57cec5SDimitry Andric // 1194824e7fdSDimitry Andric for (const CalleeSavedInfo &I : CSI) { 1200b57cec5SDimitry Andric // Add the callee-saved register as live-in. Do not add if the register is 1210b57cec5SDimitry Andric // RA and return address is taken, because it has already been added in 1220b57cec5SDimitry Andric // method MipsTargetLowering::lowerRETURNADDR. 1230b57cec5SDimitry Andric // It's killed at the spill, unless the register is RA and return address 1240b57cec5SDimitry Andric // is taken. 12504eeddc0SDimitry Andric Register Reg = I.getReg(); 1260b57cec5SDimitry Andric bool IsRAAndRetAddrIsTaken = (Reg == Mips::RA) 1270b57cec5SDimitry Andric && MF->getFrameInfo().isReturnAddressTaken(); 1280b57cec5SDimitry Andric if (!IsRAAndRetAddrIsTaken) 1290b57cec5SDimitry Andric MBB.addLiveIn(Reg); 1300b57cec5SDimitry Andric } 1310b57cec5SDimitry Andric 1320b57cec5SDimitry Andric return true; 1330b57cec5SDimitry Andric } 1340b57cec5SDimitry Andric 1355ffd83dbSDimitry Andric bool Mips16FrameLowering::restoreCalleeSavedRegisters( 1365ffd83dbSDimitry Andric MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, 1375ffd83dbSDimitry Andric MutableArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const { 1380b57cec5SDimitry Andric // 1390b57cec5SDimitry Andric // Registers RA,S0,S1 are the callee saved registers and they will be restored 1400b57cec5SDimitry Andric // with the restore instruction during emitEpilogue. 1410b57cec5SDimitry Andric // We need to override this virtual function, otherwise llvm will try and 1420b57cec5SDimitry Andric // restore the registers on it's on from the stack. 1430b57cec5SDimitry Andric // 1440b57cec5SDimitry Andric 1450b57cec5SDimitry Andric return true; 1460b57cec5SDimitry Andric } 1470b57cec5SDimitry Andric 1480b57cec5SDimitry Andric bool 1490b57cec5SDimitry Andric Mips16FrameLowering::hasReservedCallFrame(const MachineFunction &MF) const { 1500b57cec5SDimitry Andric const MachineFrameInfo &MFI = MF.getFrameInfo(); 1510b57cec5SDimitry Andric // Reserve call frame if the size of the maximum call frame fits into 15-bit 1520b57cec5SDimitry Andric // immediate field and there are no variable sized objects on the stack. 1530b57cec5SDimitry Andric return isInt<15>(MFI.getMaxCallFrameSize()) && !MFI.hasVarSizedObjects(); 1540b57cec5SDimitry Andric } 1550b57cec5SDimitry Andric 1560b57cec5SDimitry Andric void Mips16FrameLowering::determineCalleeSaves(MachineFunction &MF, 1570b57cec5SDimitry Andric BitVector &SavedRegs, 1580b57cec5SDimitry Andric RegScavenger *RS) const { 1590b57cec5SDimitry Andric TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS); 1600b57cec5SDimitry Andric const Mips16InstrInfo &TII = 1610b57cec5SDimitry Andric *static_cast<const Mips16InstrInfo *>(STI.getInstrInfo()); 1620b57cec5SDimitry Andric const MipsRegisterInfo &RI = TII.getRegisterInfo(); 1630b57cec5SDimitry Andric const BitVector Reserved = RI.getReservedRegs(MF); 1640b57cec5SDimitry Andric bool SaveS2 = Reserved[Mips::S2]; 1650b57cec5SDimitry Andric if (SaveS2) 1660b57cec5SDimitry Andric SavedRegs.set(Mips::S2); 1670b57cec5SDimitry Andric if (hasFP(MF)) 1680b57cec5SDimitry Andric SavedRegs.set(Mips::S0); 1690b57cec5SDimitry Andric } 1700b57cec5SDimitry Andric 1710b57cec5SDimitry Andric const MipsFrameLowering * 1720b57cec5SDimitry Andric llvm::createMips16FrameLowering(const MipsSubtarget &ST) { 1730b57cec5SDimitry Andric return new Mips16FrameLowering(ST); 1740b57cec5SDimitry Andric } 175