xref: /freebsd/contrib/llvm-project/llvm/lib/Target/Mips/Mips16FrameLowering.cpp (revision 5ffd83dbcc34f10e07f6d3e968ae6365869615f4)
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"
65*5ffd83dbSDimitry Andric   unsigned CFIIndex =
66*5ffd83dbSDimitry 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 
750b57cec5SDimitry Andric     for (std::vector<CalleeSavedInfo>::const_iterator I = CSI.begin(),
760b57cec5SDimitry Andric          E = CSI.end(); I != E; ++I) {
770b57cec5SDimitry Andric       int64_t Offset = MFI.getObjectOffset(I->getFrameIdx());
780b57cec5SDimitry Andric       unsigned Reg = I->getReg();
790b57cec5SDimitry Andric       unsigned DReg = MRI->getDwarfRegNum(Reg, true);
800b57cec5SDimitry Andric       unsigned CFIIndex = MF.addFrameInst(
810b57cec5SDimitry Andric           MCCFIInstruction::createOffset(nullptr, DReg, Offset));
820b57cec5SDimitry Andric       BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION))
830b57cec5SDimitry Andric           .addCFIIndex(CFIIndex);
840b57cec5SDimitry Andric     }
850b57cec5SDimitry Andric   }
860b57cec5SDimitry Andric   if (hasFP(MF))
870b57cec5SDimitry Andric     BuildMI(MBB, MBBI, dl, TII.get(Mips::MoveR3216), Mips::S0)
880b57cec5SDimitry Andric       .addReg(Mips::SP).setMIFlag(MachineInstr::FrameSetup);
890b57cec5SDimitry Andric }
900b57cec5SDimitry Andric 
910b57cec5SDimitry Andric void Mips16FrameLowering::emitEpilogue(MachineFunction &MF,
920b57cec5SDimitry Andric                                  MachineBasicBlock &MBB) const {
930b57cec5SDimitry Andric   MachineBasicBlock::iterator MBBI = MBB.getFirstTerminator();
940b57cec5SDimitry Andric   MachineFrameInfo &MFI = MF.getFrameInfo();
950b57cec5SDimitry Andric   const Mips16InstrInfo &TII =
960b57cec5SDimitry Andric       *static_cast<const Mips16InstrInfo *>(STI.getInstrInfo());
970b57cec5SDimitry Andric   DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
980b57cec5SDimitry Andric   uint64_t StackSize = MFI.getStackSize();
990b57cec5SDimitry Andric 
1000b57cec5SDimitry Andric   if (!StackSize)
1010b57cec5SDimitry Andric     return;
1020b57cec5SDimitry Andric 
1030b57cec5SDimitry Andric   if (hasFP(MF))
1040b57cec5SDimitry Andric     BuildMI(MBB, MBBI, dl, TII.get(Mips::Move32R16), Mips::SP)
1050b57cec5SDimitry Andric       .addReg(Mips::S0);
1060b57cec5SDimitry Andric 
1070b57cec5SDimitry Andric   // Adjust stack.
1080b57cec5SDimitry Andric   // assumes stacksize multiple of 8
1090b57cec5SDimitry Andric   TII.restoreFrame(Mips::SP, StackSize, MBB, MBBI);
1100b57cec5SDimitry Andric }
1110b57cec5SDimitry Andric 
112*5ffd83dbSDimitry Andric bool Mips16FrameLowering::spillCalleeSavedRegisters(
113*5ffd83dbSDimitry Andric     MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
114*5ffd83dbSDimitry Andric     ArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const {
1150b57cec5SDimitry Andric   MachineFunction *MF = MBB.getParent();
1160b57cec5SDimitry Andric 
1170b57cec5SDimitry Andric   //
1180b57cec5SDimitry Andric   // Registers RA, S0,S1 are the callee saved registers and they
1190b57cec5SDimitry Andric   // will be saved with the "save" instruction
1200b57cec5SDimitry Andric   // during emitPrologue
1210b57cec5SDimitry Andric   //
1220b57cec5SDimitry Andric   for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
1230b57cec5SDimitry Andric     // Add the callee-saved register as live-in. Do not add if the register is
1240b57cec5SDimitry Andric     // RA and return address is taken, because it has already been added in
1250b57cec5SDimitry Andric     // method MipsTargetLowering::lowerRETURNADDR.
1260b57cec5SDimitry Andric     // It's killed at the spill, unless the register is RA and return address
1270b57cec5SDimitry Andric     // is taken.
1280b57cec5SDimitry Andric     unsigned Reg = CSI[i].getReg();
1290b57cec5SDimitry Andric     bool IsRAAndRetAddrIsTaken = (Reg == Mips::RA)
1300b57cec5SDimitry Andric       && MF->getFrameInfo().isReturnAddressTaken();
1310b57cec5SDimitry Andric     if (!IsRAAndRetAddrIsTaken)
1320b57cec5SDimitry Andric       MBB.addLiveIn(Reg);
1330b57cec5SDimitry Andric   }
1340b57cec5SDimitry Andric 
1350b57cec5SDimitry Andric   return true;
1360b57cec5SDimitry Andric }
1370b57cec5SDimitry Andric 
138*5ffd83dbSDimitry Andric bool Mips16FrameLowering::restoreCalleeSavedRegisters(
139*5ffd83dbSDimitry Andric     MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
140*5ffd83dbSDimitry Andric     MutableArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const {
1410b57cec5SDimitry Andric   //
1420b57cec5SDimitry Andric   // Registers RA,S0,S1 are the callee saved registers and they will be restored
1430b57cec5SDimitry Andric   // with the restore instruction during emitEpilogue.
1440b57cec5SDimitry Andric   // We need to override this virtual function, otherwise llvm will try and
1450b57cec5SDimitry Andric   // restore the registers on it's on from the stack.
1460b57cec5SDimitry Andric   //
1470b57cec5SDimitry Andric 
1480b57cec5SDimitry Andric   return true;
1490b57cec5SDimitry Andric }
1500b57cec5SDimitry Andric 
1510b57cec5SDimitry Andric bool
1520b57cec5SDimitry Andric Mips16FrameLowering::hasReservedCallFrame(const MachineFunction &MF) const {
1530b57cec5SDimitry Andric   const MachineFrameInfo &MFI = MF.getFrameInfo();
1540b57cec5SDimitry Andric   // Reserve call frame if the size of the maximum call frame fits into 15-bit
1550b57cec5SDimitry Andric   // immediate field and there are no variable sized objects on the stack.
1560b57cec5SDimitry Andric   return isInt<15>(MFI.getMaxCallFrameSize()) && !MFI.hasVarSizedObjects();
1570b57cec5SDimitry Andric }
1580b57cec5SDimitry Andric 
1590b57cec5SDimitry Andric void Mips16FrameLowering::determineCalleeSaves(MachineFunction &MF,
1600b57cec5SDimitry Andric                                                BitVector &SavedRegs,
1610b57cec5SDimitry Andric                                                RegScavenger *RS) const {
1620b57cec5SDimitry Andric   TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS);
1630b57cec5SDimitry Andric   const Mips16InstrInfo &TII =
1640b57cec5SDimitry Andric       *static_cast<const Mips16InstrInfo *>(STI.getInstrInfo());
1650b57cec5SDimitry Andric   const MipsRegisterInfo &RI = TII.getRegisterInfo();
1660b57cec5SDimitry Andric   const BitVector Reserved = RI.getReservedRegs(MF);
1670b57cec5SDimitry Andric   bool SaveS2 = Reserved[Mips::S2];
1680b57cec5SDimitry Andric   if (SaveS2)
1690b57cec5SDimitry Andric     SavedRegs.set(Mips::S2);
1700b57cec5SDimitry Andric   if (hasFP(MF))
1710b57cec5SDimitry Andric     SavedRegs.set(Mips::S0);
1720b57cec5SDimitry Andric }
1730b57cec5SDimitry Andric 
1740b57cec5SDimitry Andric const MipsFrameLowering *
1750b57cec5SDimitry Andric llvm::createMips16FrameLowering(const MipsSubtarget &ST) {
1760b57cec5SDimitry Andric   return new Mips16FrameLowering(ST);
1770b57cec5SDimitry Andric }
178