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 <cassert> 340b57cec5SDimitry Andric #include <cstdint> 350b57cec5SDimitry Andric #include <vector> 360b57cec5SDimitry Andric 370b57cec5SDimitry Andric using namespace llvm; 380b57cec5SDimitry Andric 390b57cec5SDimitry Andric Mips16FrameLowering::Mips16FrameLowering(const MipsSubtarget &STI) 400b57cec5SDimitry Andric : MipsFrameLowering(STI, STI.getStackAlignment()) {} 410b57cec5SDimitry Andric 420b57cec5SDimitry Andric void Mips16FrameLowering::emitPrologue(MachineFunction &MF, 430b57cec5SDimitry Andric MachineBasicBlock &MBB) const { 440b57cec5SDimitry Andric MachineFrameInfo &MFI = MF.getFrameInfo(); 450b57cec5SDimitry Andric const Mips16InstrInfo &TII = 460b57cec5SDimitry Andric *static_cast<const Mips16InstrInfo *>(STI.getInstrInfo()); 470b57cec5SDimitry Andric MachineBasicBlock::iterator MBBI = MBB.begin(); 480b57cec5SDimitry Andric 490b57cec5SDimitry Andric // Debug location must be unknown since the first debug location is used 500b57cec5SDimitry Andric // to determine the end of the prologue. 510b57cec5SDimitry Andric DebugLoc dl; 520b57cec5SDimitry Andric 530b57cec5SDimitry Andric uint64_t StackSize = MFI.getStackSize(); 540b57cec5SDimitry Andric 550b57cec5SDimitry Andric // No need to allocate space on the stack. 560b57cec5SDimitry Andric if (StackSize == 0 && !MFI.adjustsStack()) return; 570b57cec5SDimitry Andric 580b57cec5SDimitry Andric MachineModuleInfo &MMI = MF.getMMI(); 590b57cec5SDimitry Andric const MCRegisterInfo *MRI = MMI.getContext().getRegisterInfo(); 600b57cec5SDimitry Andric 610b57cec5SDimitry Andric // Adjust stack. 620b57cec5SDimitry Andric TII.makeFrame(Mips::SP, StackSize, MBB, MBBI); 630b57cec5SDimitry Andric 640b57cec5SDimitry Andric // emit ".cfi_def_cfa_offset StackSize" 655ffd83dbSDimitry Andric unsigned CFIIndex = 665ffd83dbSDimitry Andric MF.addFrameInst(MCCFIInstruction::cfiDefCfaOffset(nullptr, StackSize)); 670b57cec5SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) 680b57cec5SDimitry Andric .addCFIIndex(CFIIndex); 690b57cec5SDimitry Andric 700b57cec5SDimitry Andric const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo(); 710b57cec5SDimitry Andric 720b57cec5SDimitry Andric if (!CSI.empty()) { 730b57cec5SDimitry Andric const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo(); 740b57cec5SDimitry Andric 75*4824e7fdSDimitry Andric for (const CalleeSavedInfo &I : CSI) { 76*4824e7fdSDimitry Andric int64_t Offset = MFI.getObjectOffset(I.getFrameIdx()); 77*4824e7fdSDimitry Andric unsigned Reg = I.getReg(); 780b57cec5SDimitry Andric unsigned DReg = MRI->getDwarfRegNum(Reg, true); 790b57cec5SDimitry Andric unsigned CFIIndex = MF.addFrameInst( 800b57cec5SDimitry Andric MCCFIInstruction::createOffset(nullptr, DReg, Offset)); 810b57cec5SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) 820b57cec5SDimitry Andric .addCFIIndex(CFIIndex); 830b57cec5SDimitry Andric } 840b57cec5SDimitry Andric } 850b57cec5SDimitry Andric if (hasFP(MF)) 860b57cec5SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(Mips::MoveR3216), Mips::S0) 870b57cec5SDimitry Andric .addReg(Mips::SP).setMIFlag(MachineInstr::FrameSetup); 880b57cec5SDimitry Andric } 890b57cec5SDimitry Andric 900b57cec5SDimitry Andric void Mips16FrameLowering::emitEpilogue(MachineFunction &MF, 910b57cec5SDimitry Andric MachineBasicBlock &MBB) const { 920b57cec5SDimitry Andric MachineBasicBlock::iterator MBBI = MBB.getFirstTerminator(); 930b57cec5SDimitry Andric MachineFrameInfo &MFI = MF.getFrameInfo(); 940b57cec5SDimitry Andric const Mips16InstrInfo &TII = 950b57cec5SDimitry Andric *static_cast<const Mips16InstrInfo *>(STI.getInstrInfo()); 960b57cec5SDimitry Andric DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); 970b57cec5SDimitry Andric uint64_t StackSize = MFI.getStackSize(); 980b57cec5SDimitry Andric 990b57cec5SDimitry Andric if (!StackSize) 1000b57cec5SDimitry Andric return; 1010b57cec5SDimitry Andric 1020b57cec5SDimitry Andric if (hasFP(MF)) 1030b57cec5SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(Mips::Move32R16), Mips::SP) 1040b57cec5SDimitry Andric .addReg(Mips::S0); 1050b57cec5SDimitry Andric 1060b57cec5SDimitry Andric // Adjust stack. 1070b57cec5SDimitry Andric // assumes stacksize multiple of 8 1080b57cec5SDimitry Andric TII.restoreFrame(Mips::SP, StackSize, MBB, MBBI); 1090b57cec5SDimitry Andric } 1100b57cec5SDimitry Andric 1115ffd83dbSDimitry Andric bool Mips16FrameLowering::spillCalleeSavedRegisters( 1125ffd83dbSDimitry Andric MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, 1135ffd83dbSDimitry Andric ArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const { 1140b57cec5SDimitry Andric MachineFunction *MF = MBB.getParent(); 1150b57cec5SDimitry Andric 1160b57cec5SDimitry Andric // 1170b57cec5SDimitry Andric // Registers RA, S0,S1 are the callee saved registers and they 1180b57cec5SDimitry Andric // will be saved with the "save" instruction 1190b57cec5SDimitry Andric // during emitPrologue 1200b57cec5SDimitry Andric // 121*4824e7fdSDimitry Andric for (const CalleeSavedInfo &I : CSI) { 1220b57cec5SDimitry Andric // Add the callee-saved register as live-in. Do not add if the register is 1230b57cec5SDimitry Andric // RA and return address is taken, because it has already been added in 1240b57cec5SDimitry Andric // method MipsTargetLowering::lowerRETURNADDR. 1250b57cec5SDimitry Andric // It's killed at the spill, unless the register is RA and return address 1260b57cec5SDimitry Andric // is taken. 127*4824e7fdSDimitry Andric unsigned Reg = I.getReg(); 1280b57cec5SDimitry Andric bool IsRAAndRetAddrIsTaken = (Reg == Mips::RA) 1290b57cec5SDimitry Andric && MF->getFrameInfo().isReturnAddressTaken(); 1300b57cec5SDimitry Andric if (!IsRAAndRetAddrIsTaken) 1310b57cec5SDimitry Andric MBB.addLiveIn(Reg); 1320b57cec5SDimitry Andric } 1330b57cec5SDimitry Andric 1340b57cec5SDimitry Andric return true; 1350b57cec5SDimitry Andric } 1360b57cec5SDimitry Andric 1375ffd83dbSDimitry Andric bool Mips16FrameLowering::restoreCalleeSavedRegisters( 1385ffd83dbSDimitry Andric MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, 1395ffd83dbSDimitry Andric MutableArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const { 1400b57cec5SDimitry Andric // 1410b57cec5SDimitry Andric // Registers RA,S0,S1 are the callee saved registers and they will be restored 1420b57cec5SDimitry Andric // with the restore instruction during emitEpilogue. 1430b57cec5SDimitry Andric // We need to override this virtual function, otherwise llvm will try and 1440b57cec5SDimitry Andric // restore the registers on it's on from the stack. 1450b57cec5SDimitry Andric // 1460b57cec5SDimitry Andric 1470b57cec5SDimitry Andric return true; 1480b57cec5SDimitry Andric } 1490b57cec5SDimitry Andric 1500b57cec5SDimitry Andric bool 1510b57cec5SDimitry Andric Mips16FrameLowering::hasReservedCallFrame(const MachineFunction &MF) const { 1520b57cec5SDimitry Andric const MachineFrameInfo &MFI = MF.getFrameInfo(); 1530b57cec5SDimitry Andric // Reserve call frame if the size of the maximum call frame fits into 15-bit 1540b57cec5SDimitry Andric // immediate field and there are no variable sized objects on the stack. 1550b57cec5SDimitry Andric return isInt<15>(MFI.getMaxCallFrameSize()) && !MFI.hasVarSizedObjects(); 1560b57cec5SDimitry Andric } 1570b57cec5SDimitry Andric 1580b57cec5SDimitry Andric void Mips16FrameLowering::determineCalleeSaves(MachineFunction &MF, 1590b57cec5SDimitry Andric BitVector &SavedRegs, 1600b57cec5SDimitry Andric RegScavenger *RS) const { 1610b57cec5SDimitry Andric TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS); 1620b57cec5SDimitry Andric const Mips16InstrInfo &TII = 1630b57cec5SDimitry Andric *static_cast<const Mips16InstrInfo *>(STI.getInstrInfo()); 1640b57cec5SDimitry Andric const MipsRegisterInfo &RI = TII.getRegisterInfo(); 1650b57cec5SDimitry Andric const BitVector Reserved = RI.getReservedRegs(MF); 1660b57cec5SDimitry Andric bool SaveS2 = Reserved[Mips::S2]; 1670b57cec5SDimitry Andric if (SaveS2) 1680b57cec5SDimitry Andric SavedRegs.set(Mips::S2); 1690b57cec5SDimitry Andric if (hasFP(MF)) 1700b57cec5SDimitry Andric SavedRegs.set(Mips::S0); 1710b57cec5SDimitry Andric } 1720b57cec5SDimitry Andric 1730b57cec5SDimitry Andric const MipsFrameLowering * 1740b57cec5SDimitry Andric llvm::createMips16FrameLowering(const MipsSubtarget &ST) { 1750b57cec5SDimitry Andric return new Mips16FrameLowering(ST); 1760b57cec5SDimitry Andric } 177