xref: /freebsd/contrib/llvm-project/llvm/lib/Target/Mips/Mips16FrameLowering.cpp (revision 0b57cec536236d46e3dba9bd041533462f33dbb7)
1*0b57cec5SDimitry Andric //===- Mips16FrameLowering.cpp - Mips16 Frame Information -----------------===//
2*0b57cec5SDimitry Andric //
3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*0b57cec5SDimitry Andric //
7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
8*0b57cec5SDimitry Andric //
9*0b57cec5SDimitry Andric // This file contains the Mips16 implementation of TargetFrameLowering class.
10*0b57cec5SDimitry Andric //
11*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
12*0b57cec5SDimitry Andric 
13*0b57cec5SDimitry Andric #include "Mips16FrameLowering.h"
14*0b57cec5SDimitry Andric #include "MCTargetDesc/MipsBaseInfo.h"
15*0b57cec5SDimitry Andric #include "Mips16InstrInfo.h"
16*0b57cec5SDimitry Andric #include "MipsInstrInfo.h"
17*0b57cec5SDimitry Andric #include "MipsRegisterInfo.h"
18*0b57cec5SDimitry Andric #include "MipsSubtarget.h"
19*0b57cec5SDimitry Andric #include "llvm/ADT/BitVector.h"
20*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h"
21*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h"
22*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
23*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstr.h"
24*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h"
25*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineModuleInfo.h"
26*0b57cec5SDimitry Andric #include "llvm/IR/DebugLoc.h"
27*0b57cec5SDimitry Andric #include "llvm/MC/MCContext.h"
28*0b57cec5SDimitry Andric #include "llvm/MC/MCDwarf.h"
29*0b57cec5SDimitry Andric #include "llvm/MC/MCRegisterInfo.h"
30*0b57cec5SDimitry Andric #include "llvm/MC/MachineLocation.h"
31*0b57cec5SDimitry Andric #include "llvm/Support/MathExtras.h"
32*0b57cec5SDimitry Andric #include "llvm/CodeGen/TargetFrameLowering.h"
33*0b57cec5SDimitry Andric #include <cassert>
34*0b57cec5SDimitry Andric #include <cstdint>
35*0b57cec5SDimitry Andric #include <vector>
36*0b57cec5SDimitry Andric 
37*0b57cec5SDimitry Andric using namespace llvm;
38*0b57cec5SDimitry Andric 
39*0b57cec5SDimitry Andric Mips16FrameLowering::Mips16FrameLowering(const MipsSubtarget &STI)
40*0b57cec5SDimitry Andric     : MipsFrameLowering(STI, STI.getStackAlignment()) {}
41*0b57cec5SDimitry Andric 
42*0b57cec5SDimitry Andric void Mips16FrameLowering::emitPrologue(MachineFunction &MF,
43*0b57cec5SDimitry Andric                                        MachineBasicBlock &MBB) const {
44*0b57cec5SDimitry Andric   MachineFrameInfo &MFI = MF.getFrameInfo();
45*0b57cec5SDimitry Andric   const Mips16InstrInfo &TII =
46*0b57cec5SDimitry Andric       *static_cast<const Mips16InstrInfo *>(STI.getInstrInfo());
47*0b57cec5SDimitry Andric   MachineBasicBlock::iterator MBBI = MBB.begin();
48*0b57cec5SDimitry Andric 
49*0b57cec5SDimitry Andric   // Debug location must be unknown since the first debug location is used
50*0b57cec5SDimitry Andric   // to determine the end of the prologue.
51*0b57cec5SDimitry Andric   DebugLoc dl;
52*0b57cec5SDimitry Andric 
53*0b57cec5SDimitry Andric   uint64_t StackSize = MFI.getStackSize();
54*0b57cec5SDimitry Andric 
55*0b57cec5SDimitry Andric   // No need to allocate space on the stack.
56*0b57cec5SDimitry Andric   if (StackSize == 0 && !MFI.adjustsStack()) return;
57*0b57cec5SDimitry Andric 
58*0b57cec5SDimitry Andric   MachineModuleInfo &MMI = MF.getMMI();
59*0b57cec5SDimitry Andric   const MCRegisterInfo *MRI = MMI.getContext().getRegisterInfo();
60*0b57cec5SDimitry Andric 
61*0b57cec5SDimitry Andric   // Adjust stack.
62*0b57cec5SDimitry Andric   TII.makeFrame(Mips::SP, StackSize, MBB, MBBI);
63*0b57cec5SDimitry Andric 
64*0b57cec5SDimitry Andric   // emit ".cfi_def_cfa_offset StackSize"
65*0b57cec5SDimitry Andric   unsigned CFIIndex = MF.addFrameInst(
66*0b57cec5SDimitry Andric       MCCFIInstruction::createDefCfaOffset(nullptr, -StackSize));
67*0b57cec5SDimitry Andric   BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION))
68*0b57cec5SDimitry Andric       .addCFIIndex(CFIIndex);
69*0b57cec5SDimitry Andric 
70*0b57cec5SDimitry Andric   const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
71*0b57cec5SDimitry Andric 
72*0b57cec5SDimitry Andric   if (!CSI.empty()) {
73*0b57cec5SDimitry Andric     const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
74*0b57cec5SDimitry Andric 
75*0b57cec5SDimitry Andric     for (std::vector<CalleeSavedInfo>::const_iterator I = CSI.begin(),
76*0b57cec5SDimitry Andric          E = CSI.end(); I != E; ++I) {
77*0b57cec5SDimitry Andric       int64_t Offset = MFI.getObjectOffset(I->getFrameIdx());
78*0b57cec5SDimitry Andric       unsigned Reg = I->getReg();
79*0b57cec5SDimitry Andric       unsigned DReg = MRI->getDwarfRegNum(Reg, true);
80*0b57cec5SDimitry Andric       unsigned CFIIndex = MF.addFrameInst(
81*0b57cec5SDimitry Andric           MCCFIInstruction::createOffset(nullptr, DReg, Offset));
82*0b57cec5SDimitry Andric       BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION))
83*0b57cec5SDimitry Andric           .addCFIIndex(CFIIndex);
84*0b57cec5SDimitry Andric     }
85*0b57cec5SDimitry Andric   }
86*0b57cec5SDimitry Andric   if (hasFP(MF))
87*0b57cec5SDimitry Andric     BuildMI(MBB, MBBI, dl, TII.get(Mips::MoveR3216), Mips::S0)
88*0b57cec5SDimitry Andric       .addReg(Mips::SP).setMIFlag(MachineInstr::FrameSetup);
89*0b57cec5SDimitry Andric }
90*0b57cec5SDimitry Andric 
91*0b57cec5SDimitry Andric void Mips16FrameLowering::emitEpilogue(MachineFunction &MF,
92*0b57cec5SDimitry Andric                                  MachineBasicBlock &MBB) const {
93*0b57cec5SDimitry Andric   MachineBasicBlock::iterator MBBI = MBB.getFirstTerminator();
94*0b57cec5SDimitry Andric   MachineFrameInfo &MFI = MF.getFrameInfo();
95*0b57cec5SDimitry Andric   const Mips16InstrInfo &TII =
96*0b57cec5SDimitry Andric       *static_cast<const Mips16InstrInfo *>(STI.getInstrInfo());
97*0b57cec5SDimitry Andric   DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
98*0b57cec5SDimitry Andric   uint64_t StackSize = MFI.getStackSize();
99*0b57cec5SDimitry Andric 
100*0b57cec5SDimitry Andric   if (!StackSize)
101*0b57cec5SDimitry Andric     return;
102*0b57cec5SDimitry Andric 
103*0b57cec5SDimitry Andric   if (hasFP(MF))
104*0b57cec5SDimitry Andric     BuildMI(MBB, MBBI, dl, TII.get(Mips::Move32R16), Mips::SP)
105*0b57cec5SDimitry Andric       .addReg(Mips::S0);
106*0b57cec5SDimitry Andric 
107*0b57cec5SDimitry Andric   // Adjust stack.
108*0b57cec5SDimitry Andric   // assumes stacksize multiple of 8
109*0b57cec5SDimitry Andric   TII.restoreFrame(Mips::SP, StackSize, MBB, MBBI);
110*0b57cec5SDimitry Andric }
111*0b57cec5SDimitry Andric 
112*0b57cec5SDimitry Andric bool Mips16FrameLowering::
113*0b57cec5SDimitry Andric spillCalleeSavedRegisters(MachineBasicBlock &MBB,
114*0b57cec5SDimitry Andric                           MachineBasicBlock::iterator MI,
115*0b57cec5SDimitry Andric                           const std::vector<CalleeSavedInfo> &CSI,
116*0b57cec5SDimitry Andric                           const TargetRegisterInfo *TRI) const {
117*0b57cec5SDimitry Andric   MachineFunction *MF = MBB.getParent();
118*0b57cec5SDimitry Andric 
119*0b57cec5SDimitry Andric   //
120*0b57cec5SDimitry Andric   // Registers RA, S0,S1 are the callee saved registers and they
121*0b57cec5SDimitry Andric   // will be saved with the "save" instruction
122*0b57cec5SDimitry Andric   // during emitPrologue
123*0b57cec5SDimitry Andric   //
124*0b57cec5SDimitry Andric   for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
125*0b57cec5SDimitry Andric     // Add the callee-saved register as live-in. Do not add if the register is
126*0b57cec5SDimitry Andric     // RA and return address is taken, because it has already been added in
127*0b57cec5SDimitry Andric     // method MipsTargetLowering::lowerRETURNADDR.
128*0b57cec5SDimitry Andric     // It's killed at the spill, unless the register is RA and return address
129*0b57cec5SDimitry Andric     // is taken.
130*0b57cec5SDimitry Andric     unsigned Reg = CSI[i].getReg();
131*0b57cec5SDimitry Andric     bool IsRAAndRetAddrIsTaken = (Reg == Mips::RA)
132*0b57cec5SDimitry Andric       && MF->getFrameInfo().isReturnAddressTaken();
133*0b57cec5SDimitry Andric     if (!IsRAAndRetAddrIsTaken)
134*0b57cec5SDimitry Andric       MBB.addLiveIn(Reg);
135*0b57cec5SDimitry Andric   }
136*0b57cec5SDimitry Andric 
137*0b57cec5SDimitry Andric   return true;
138*0b57cec5SDimitry Andric }
139*0b57cec5SDimitry Andric 
140*0b57cec5SDimitry Andric bool Mips16FrameLowering::restoreCalleeSavedRegisters(MachineBasicBlock &MBB,
141*0b57cec5SDimitry Andric                                           MachineBasicBlock::iterator MI,
142*0b57cec5SDimitry Andric                                        std::vector<CalleeSavedInfo> &CSI,
143*0b57cec5SDimitry Andric                                        const TargetRegisterInfo *TRI) const {
144*0b57cec5SDimitry Andric   //
145*0b57cec5SDimitry Andric   // Registers RA,S0,S1 are the callee saved registers and they will be restored
146*0b57cec5SDimitry Andric   // with the restore instruction during emitEpilogue.
147*0b57cec5SDimitry Andric   // We need to override this virtual function, otherwise llvm will try and
148*0b57cec5SDimitry Andric   // restore the registers on it's on from the stack.
149*0b57cec5SDimitry Andric   //
150*0b57cec5SDimitry Andric 
151*0b57cec5SDimitry Andric   return true;
152*0b57cec5SDimitry Andric }
153*0b57cec5SDimitry Andric 
154*0b57cec5SDimitry Andric bool
155*0b57cec5SDimitry Andric Mips16FrameLowering::hasReservedCallFrame(const MachineFunction &MF) const {
156*0b57cec5SDimitry Andric   const MachineFrameInfo &MFI = MF.getFrameInfo();
157*0b57cec5SDimitry Andric   // Reserve call frame if the size of the maximum call frame fits into 15-bit
158*0b57cec5SDimitry Andric   // immediate field and there are no variable sized objects on the stack.
159*0b57cec5SDimitry Andric   return isInt<15>(MFI.getMaxCallFrameSize()) && !MFI.hasVarSizedObjects();
160*0b57cec5SDimitry Andric }
161*0b57cec5SDimitry Andric 
162*0b57cec5SDimitry Andric void Mips16FrameLowering::determineCalleeSaves(MachineFunction &MF,
163*0b57cec5SDimitry Andric                                                BitVector &SavedRegs,
164*0b57cec5SDimitry Andric                                                RegScavenger *RS) const {
165*0b57cec5SDimitry Andric   TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS);
166*0b57cec5SDimitry Andric   const Mips16InstrInfo &TII =
167*0b57cec5SDimitry Andric       *static_cast<const Mips16InstrInfo *>(STI.getInstrInfo());
168*0b57cec5SDimitry Andric   const MipsRegisterInfo &RI = TII.getRegisterInfo();
169*0b57cec5SDimitry Andric   const BitVector Reserved = RI.getReservedRegs(MF);
170*0b57cec5SDimitry Andric   bool SaveS2 = Reserved[Mips::S2];
171*0b57cec5SDimitry Andric   if (SaveS2)
172*0b57cec5SDimitry Andric     SavedRegs.set(Mips::S2);
173*0b57cec5SDimitry Andric   if (hasFP(MF))
174*0b57cec5SDimitry Andric     SavedRegs.set(Mips::S0);
175*0b57cec5SDimitry Andric }
176*0b57cec5SDimitry Andric 
177*0b57cec5SDimitry Andric const MipsFrameLowering *
178*0b57cec5SDimitry Andric llvm::createMips16FrameLowering(const MipsSubtarget &ST) {
179*0b57cec5SDimitry Andric   return new Mips16FrameLowering(ST);
180*0b57cec5SDimitry Andric }
181