xref: /freebsd/contrib/llvm-project/llvm/lib/Target/Mips/Mips16FrameLowering.cpp (revision 04eeddc0aa8e0a417a16eaf9d7d095207f4a8623)
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 
754824e7fdSDimitry Andric     for (const CalleeSavedInfo &I : CSI) {
764824e7fdSDimitry Andric       int64_t Offset = MFI.getObjectOffset(I.getFrameIdx());
77*04eeddc0SDimitry Andric       Register 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   //
1214824e7fdSDimitry 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*04eeddc0SDimitry Andric     Register 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