xref: /minix3/external/bsd/llvm/dist/llvm/lib/Target/Mips/Mips16FrameLowering.cpp (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1f4a2713aSLionel Sambuc //===-- Mips16FrameLowering.cpp - Mips16 Frame Information ----------------===//
2f4a2713aSLionel Sambuc //
3f4a2713aSLionel Sambuc //                     The LLVM Compiler Infrastructure
4f4a2713aSLionel Sambuc //
5f4a2713aSLionel Sambuc // This file is distributed under the University of Illinois Open Source
6f4a2713aSLionel Sambuc // License. See LICENSE.TXT for details.
7f4a2713aSLionel Sambuc //
8f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
9f4a2713aSLionel Sambuc //
10f4a2713aSLionel Sambuc // This file contains the Mips16 implementation of TargetFrameLowering class.
11f4a2713aSLionel Sambuc //
12f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
13f4a2713aSLionel Sambuc 
14f4a2713aSLionel Sambuc #include "Mips16FrameLowering.h"
15f4a2713aSLionel Sambuc #include "MCTargetDesc/MipsBaseInfo.h"
16f4a2713aSLionel Sambuc #include "Mips16InstrInfo.h"
17f4a2713aSLionel Sambuc #include "MipsInstrInfo.h"
18*0a6a1f1dSLionel Sambuc #include "MipsRegisterInfo.h"
19*0a6a1f1dSLionel Sambuc #include "MipsSubtarget.h"
20f4a2713aSLionel Sambuc #include "llvm/CodeGen/MachineFrameInfo.h"
21f4a2713aSLionel Sambuc #include "llvm/CodeGen/MachineFunction.h"
22f4a2713aSLionel Sambuc #include "llvm/CodeGen/MachineInstrBuilder.h"
23f4a2713aSLionel Sambuc #include "llvm/CodeGen/MachineModuleInfo.h"
24f4a2713aSLionel Sambuc #include "llvm/CodeGen/MachineRegisterInfo.h"
25f4a2713aSLionel Sambuc #include "llvm/IR/DataLayout.h"
26f4a2713aSLionel Sambuc #include "llvm/IR/Function.h"
27f4a2713aSLionel Sambuc #include "llvm/Support/CommandLine.h"
28f4a2713aSLionel Sambuc #include "llvm/Target/TargetOptions.h"
29f4a2713aSLionel Sambuc 
30f4a2713aSLionel Sambuc using namespace llvm;
31f4a2713aSLionel Sambuc 
Mips16FrameLowering(const MipsSubtarget & STI)32*0a6a1f1dSLionel Sambuc Mips16FrameLowering::Mips16FrameLowering(const MipsSubtarget &STI)
33*0a6a1f1dSLionel Sambuc     : MipsFrameLowering(STI, STI.stackAlignment()) {}
34*0a6a1f1dSLionel Sambuc 
emitPrologue(MachineFunction & MF) const35f4a2713aSLionel Sambuc void Mips16FrameLowering::emitPrologue(MachineFunction &MF) const {
36f4a2713aSLionel Sambuc   MachineBasicBlock &MBB = MF.front();
37f4a2713aSLionel Sambuc   MachineFrameInfo *MFI = MF.getFrameInfo();
38f4a2713aSLionel Sambuc   const Mips16InstrInfo &TII =
39*0a6a1f1dSLionel Sambuc       *static_cast<const Mips16InstrInfo *>(MF.getSubtarget().getInstrInfo());
40f4a2713aSLionel Sambuc   MachineBasicBlock::iterator MBBI = MBB.begin();
41f4a2713aSLionel Sambuc   DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
42f4a2713aSLionel Sambuc   uint64_t StackSize = MFI->getStackSize();
43f4a2713aSLionel Sambuc 
44f4a2713aSLionel Sambuc   // No need to allocate space on the stack.
45f4a2713aSLionel Sambuc   if (StackSize == 0 && !MFI->adjustsStack()) return;
46f4a2713aSLionel Sambuc 
47f4a2713aSLionel Sambuc   MachineModuleInfo &MMI = MF.getMMI();
48f4a2713aSLionel Sambuc   const MCRegisterInfo *MRI = MMI.getContext().getRegisterInfo();
49f4a2713aSLionel Sambuc   MachineLocation DstML, SrcML;
50f4a2713aSLionel Sambuc 
51f4a2713aSLionel Sambuc   // Adjust stack.
52f4a2713aSLionel Sambuc   TII.makeFrame(Mips::SP, StackSize, MBB, MBBI);
53f4a2713aSLionel Sambuc 
54f4a2713aSLionel Sambuc   // emit ".cfi_def_cfa_offset StackSize"
55*0a6a1f1dSLionel Sambuc   unsigned CFIIndex = MMI.addFrameInst(
56*0a6a1f1dSLionel Sambuc       MCCFIInstruction::createDefCfaOffset(nullptr, -StackSize));
57*0a6a1f1dSLionel Sambuc   BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION))
58*0a6a1f1dSLionel Sambuc       .addCFIIndex(CFIIndex);
59f4a2713aSLionel Sambuc 
60*0a6a1f1dSLionel Sambuc   const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo();
61f4a2713aSLionel Sambuc 
62*0a6a1f1dSLionel Sambuc   if (CSI.size()) {
63*0a6a1f1dSLionel Sambuc     const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo();
64f4a2713aSLionel Sambuc 
65*0a6a1f1dSLionel Sambuc     for (std::vector<CalleeSavedInfo>::const_iterator I = CSI.begin(),
66*0a6a1f1dSLionel Sambuc          E = CSI.end(); I != E; ++I) {
67*0a6a1f1dSLionel Sambuc       int64_t Offset = MFI->getObjectOffset(I->getFrameIdx());
68*0a6a1f1dSLionel Sambuc       unsigned Reg = I->getReg();
69*0a6a1f1dSLionel Sambuc       unsigned DReg = MRI->getDwarfRegNum(Reg, true);
70*0a6a1f1dSLionel Sambuc       unsigned CFIIndex = MMI.addFrameInst(
71*0a6a1f1dSLionel Sambuc           MCCFIInstruction::createOffset(nullptr, DReg, Offset));
72*0a6a1f1dSLionel Sambuc       BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION))
73*0a6a1f1dSLionel Sambuc           .addCFIIndex(CFIIndex);
74*0a6a1f1dSLionel Sambuc     }
75*0a6a1f1dSLionel Sambuc   }
76f4a2713aSLionel Sambuc   if (hasFP(MF))
77f4a2713aSLionel Sambuc     BuildMI(MBB, MBBI, dl, TII.get(Mips::MoveR3216), Mips::S0)
78*0a6a1f1dSLionel Sambuc       .addReg(Mips::SP).setMIFlag(MachineInstr::FrameSetup);
79f4a2713aSLionel Sambuc 
80f4a2713aSLionel Sambuc }
81f4a2713aSLionel Sambuc 
emitEpilogue(MachineFunction & MF,MachineBasicBlock & MBB) const82f4a2713aSLionel Sambuc void Mips16FrameLowering::emitEpilogue(MachineFunction &MF,
83f4a2713aSLionel Sambuc                                  MachineBasicBlock &MBB) const {
84f4a2713aSLionel Sambuc   MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
85f4a2713aSLionel Sambuc   MachineFrameInfo *MFI = MF.getFrameInfo();
86f4a2713aSLionel Sambuc   const Mips16InstrInfo &TII =
87*0a6a1f1dSLionel Sambuc       *static_cast<const Mips16InstrInfo *>(MF.getSubtarget().getInstrInfo());
88f4a2713aSLionel Sambuc   DebugLoc dl = MBBI->getDebugLoc();
89f4a2713aSLionel Sambuc   uint64_t StackSize = MFI->getStackSize();
90f4a2713aSLionel Sambuc 
91f4a2713aSLionel Sambuc   if (!StackSize)
92f4a2713aSLionel Sambuc     return;
93f4a2713aSLionel Sambuc 
94f4a2713aSLionel Sambuc   if (hasFP(MF))
95f4a2713aSLionel Sambuc     BuildMI(MBB, MBBI, dl, TII.get(Mips::Move32R16), Mips::SP)
96f4a2713aSLionel Sambuc       .addReg(Mips::S0);
97f4a2713aSLionel Sambuc 
98f4a2713aSLionel Sambuc   // Adjust stack.
99f4a2713aSLionel Sambuc   // assumes stacksize multiple of 8
100f4a2713aSLionel Sambuc   TII.restoreFrame(Mips::SP, StackSize, MBB, MBBI);
101f4a2713aSLionel Sambuc }
102f4a2713aSLionel Sambuc 
103f4a2713aSLionel Sambuc bool Mips16FrameLowering::
spillCalleeSavedRegisters(MachineBasicBlock & MBB,MachineBasicBlock::iterator MI,const std::vector<CalleeSavedInfo> & CSI,const TargetRegisterInfo * TRI) const104f4a2713aSLionel Sambuc spillCalleeSavedRegisters(MachineBasicBlock &MBB,
105f4a2713aSLionel Sambuc                           MachineBasicBlock::iterator MI,
106f4a2713aSLionel Sambuc                           const std::vector<CalleeSavedInfo> &CSI,
107f4a2713aSLionel Sambuc                           const TargetRegisterInfo *TRI) const {
108f4a2713aSLionel Sambuc   MachineFunction *MF = MBB.getParent();
109f4a2713aSLionel Sambuc   MachineBasicBlock *EntryBlock = MF->begin();
110f4a2713aSLionel Sambuc 
111f4a2713aSLionel Sambuc   //
112f4a2713aSLionel Sambuc   // Registers RA, S0,S1 are the callee saved registers and they
113f4a2713aSLionel Sambuc   // will be saved with the "save" instruction
114f4a2713aSLionel Sambuc   // during emitPrologue
115f4a2713aSLionel Sambuc   //
116f4a2713aSLionel Sambuc   for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
117f4a2713aSLionel Sambuc     // Add the callee-saved register as live-in. Do not add if the register is
118f4a2713aSLionel Sambuc     // RA and return address is taken, because it has already been added in
119f4a2713aSLionel Sambuc     // method MipsTargetLowering::LowerRETURNADDR.
120f4a2713aSLionel Sambuc     // It's killed at the spill, unless the register is RA and return address
121f4a2713aSLionel Sambuc     // is taken.
122f4a2713aSLionel Sambuc     unsigned Reg = CSI[i].getReg();
123f4a2713aSLionel Sambuc     bool IsRAAndRetAddrIsTaken = (Reg == Mips::RA)
124f4a2713aSLionel Sambuc       && MF->getFrameInfo()->isReturnAddressTaken();
125f4a2713aSLionel Sambuc     if (!IsRAAndRetAddrIsTaken)
126f4a2713aSLionel Sambuc       EntryBlock->addLiveIn(Reg);
127f4a2713aSLionel Sambuc   }
128f4a2713aSLionel Sambuc 
129f4a2713aSLionel Sambuc   return true;
130f4a2713aSLionel Sambuc }
131f4a2713aSLionel Sambuc 
restoreCalleeSavedRegisters(MachineBasicBlock & MBB,MachineBasicBlock::iterator MI,const std::vector<CalleeSavedInfo> & CSI,const TargetRegisterInfo * TRI) const132f4a2713aSLionel Sambuc bool Mips16FrameLowering::restoreCalleeSavedRegisters(MachineBasicBlock &MBB,
133f4a2713aSLionel Sambuc                                           MachineBasicBlock::iterator MI,
134f4a2713aSLionel Sambuc                                        const std::vector<CalleeSavedInfo> &CSI,
135f4a2713aSLionel Sambuc                                        const TargetRegisterInfo *TRI) const {
136f4a2713aSLionel Sambuc   //
137f4a2713aSLionel Sambuc   // Registers RA,S0,S1 are the callee saved registers and they will be restored
138f4a2713aSLionel Sambuc   // with the restore instruction during emitEpilogue.
139f4a2713aSLionel Sambuc   // We need to override this virtual function, otherwise llvm will try and
140f4a2713aSLionel Sambuc   // restore the registers on it's on from the stack.
141f4a2713aSLionel Sambuc   //
142f4a2713aSLionel Sambuc 
143f4a2713aSLionel Sambuc   return true;
144f4a2713aSLionel Sambuc }
145f4a2713aSLionel Sambuc 
146f4a2713aSLionel Sambuc // Eliminate ADJCALLSTACKDOWN, ADJCALLSTACKUP pseudo instructions
147f4a2713aSLionel Sambuc void Mips16FrameLowering::
eliminateCallFramePseudoInstr(MachineFunction & MF,MachineBasicBlock & MBB,MachineBasicBlock::iterator I) const148f4a2713aSLionel Sambuc eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
149f4a2713aSLionel Sambuc                               MachineBasicBlock::iterator I) const {
150f4a2713aSLionel Sambuc   if (!hasReservedCallFrame(MF)) {
151f4a2713aSLionel Sambuc     int64_t Amount = I->getOperand(0).getImm();
152f4a2713aSLionel Sambuc 
153f4a2713aSLionel Sambuc     if (I->getOpcode() == Mips::ADJCALLSTACKDOWN)
154f4a2713aSLionel Sambuc       Amount = -Amount;
155f4a2713aSLionel Sambuc 
156f4a2713aSLionel Sambuc     const Mips16InstrInfo &TII =
157*0a6a1f1dSLionel Sambuc         *static_cast<const Mips16InstrInfo *>(MF.getSubtarget().getInstrInfo());
158f4a2713aSLionel Sambuc 
159f4a2713aSLionel Sambuc     TII.adjustStackPtr(Mips::SP, Amount, MBB, I);
160f4a2713aSLionel Sambuc   }
161f4a2713aSLionel Sambuc 
162f4a2713aSLionel Sambuc   MBB.erase(I);
163f4a2713aSLionel Sambuc }
164f4a2713aSLionel Sambuc 
165f4a2713aSLionel Sambuc bool
hasReservedCallFrame(const MachineFunction & MF) const166f4a2713aSLionel Sambuc Mips16FrameLowering::hasReservedCallFrame(const MachineFunction &MF) const {
167f4a2713aSLionel Sambuc   const MachineFrameInfo *MFI = MF.getFrameInfo();
168f4a2713aSLionel Sambuc   // Reserve call frame if the size of the maximum call frame fits into 15-bit
169f4a2713aSLionel Sambuc   // immediate field and there are no variable sized objects on the stack.
170f4a2713aSLionel Sambuc   return isInt<15>(MFI->getMaxCallFrameSize()) && !MFI->hasVarSizedObjects();
171f4a2713aSLionel Sambuc }
172f4a2713aSLionel Sambuc 
173f4a2713aSLionel Sambuc void Mips16FrameLowering::
processFunctionBeforeCalleeSavedScan(MachineFunction & MF,RegScavenger * RS) const174f4a2713aSLionel Sambuc processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
175f4a2713aSLionel Sambuc                                      RegScavenger *RS) const {
176*0a6a1f1dSLionel Sambuc   const Mips16InstrInfo &TII =
177*0a6a1f1dSLionel Sambuc       *static_cast<const Mips16InstrInfo *>(MF.getSubtarget().getInstrInfo());
178*0a6a1f1dSLionel Sambuc   const MipsRegisterInfo &RI = TII.getRegisterInfo();
179*0a6a1f1dSLionel Sambuc   const BitVector Reserved = RI.getReservedRegs(MF);
180*0a6a1f1dSLionel Sambuc   bool SaveS2 = Reserved[Mips::S2];
181*0a6a1f1dSLionel Sambuc   if (SaveS2)
182f4a2713aSLionel Sambuc     MF.getRegInfo().setPhysRegUsed(Mips::S2);
183*0a6a1f1dSLionel Sambuc   if (hasFP(MF))
184*0a6a1f1dSLionel Sambuc     MF.getRegInfo().setPhysRegUsed(Mips::S0);
185f4a2713aSLionel Sambuc }
186f4a2713aSLionel Sambuc 
187f4a2713aSLionel Sambuc const MipsFrameLowering *
createMips16FrameLowering(const MipsSubtarget & ST)188f4a2713aSLionel Sambuc llvm::createMips16FrameLowering(const MipsSubtarget &ST) {
189f4a2713aSLionel Sambuc   return new Mips16FrameLowering(ST);
190f4a2713aSLionel Sambuc }
191