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