xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/Mips/Mips16FrameLowering.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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