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
Mips16FrameLowering(const MipsSubtarget & STI)380b57cec5SDimitry Andric Mips16FrameLowering::Mips16FrameLowering(const MipsSubtarget &STI)
390b57cec5SDimitry Andric : MipsFrameLowering(STI, STI.getStackAlignment()) {}
400b57cec5SDimitry Andric
emitPrologue(MachineFunction & MF,MachineBasicBlock & MBB) const410b57cec5SDimitry 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
emitEpilogue(MachineFunction & MF,MachineBasicBlock & MBB) const880b57cec5SDimitry 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
spillCalleeSavedRegisters(MachineBasicBlock & MBB,MachineBasicBlock::iterator MI,ArrayRef<CalleeSavedInfo> CSI,const TargetRegisterInfo * TRI) const1095ffd83dbSDimitry 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
restoreCalleeSavedRegisters(MachineBasicBlock & MBB,MachineBasicBlock::iterator MI,MutableArrayRef<CalleeSavedInfo> CSI,const TargetRegisterInfo * TRI) const1355ffd83dbSDimitry 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
hasReservedCallFrame(const MachineFunction & MF) const1490b57cec5SDimitry 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
determineCalleeSaves(MachineFunction & MF,BitVector & SavedRegs,RegScavenger * RS) const1560b57cec5SDimitry 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 *
createMips16FrameLowering(const MipsSubtarget & ST)1720b57cec5SDimitry Andric llvm::createMips16FrameLowering(const MipsSubtarget &ST) {
1730b57cec5SDimitry Andric return new Mips16FrameLowering(ST);
1740b57cec5SDimitry Andric }
175