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 | MachineModuleInfo &MMI = MF.getMMI(); |
58 | const MCRegisterInfo *MRI = MMI.getContext().getRegisterInfo(); |
59 | |
60 | // Adjust stack. |
61 | TII.makeFrame(Mips::SP: SP, FrameSize: StackSize, MBB, I: MBBI); |
62 | |
63 | // emit ".cfi_def_cfa_offset StackSize" |
64 | unsigned CFIIndex = |
65 | MF.addFrameInst(Inst: MCCFIInstruction::cfiDefCfaOffset(L: nullptr, Offset: StackSize)); |
66 | BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) |
67 | .addCFIIndex(CFIIndex); |
68 | |
69 | const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo(); |
70 | |
71 | if (!CSI.empty()) { |
72 | const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo(); |
73 | |
74 | for (const CalleeSavedInfo &I : CSI) { |
75 | int64_t Offset = MFI.getObjectOffset(ObjectIdx: I.getFrameIdx()); |
76 | Register Reg = I.getReg(); |
77 | unsigned DReg = MRI->getDwarfRegNum(RegNum: Reg, isEH: true); |
78 | unsigned CFIIndex = MF.addFrameInst( |
79 | Inst: MCCFIInstruction::createOffset(L: nullptr, Register: DReg, Offset)); |
80 | BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) |
81 | .addCFIIndex(CFIIndex); |
82 | } |
83 | } |
84 | if (hasFP(MF)) |
85 | BuildMI(MBB, MBBI, dl, TII.get(Mips::MoveR3216), Mips::S0) |
86 | .addReg(Mips::SP).setMIFlag(MachineInstr::FrameSetup); |
87 | } |
88 | |
89 | void Mips16FrameLowering::emitEpilogue(MachineFunction &MF, |
90 | MachineBasicBlock &MBB) const { |
91 | MachineBasicBlock::iterator MBBI = MBB.getFirstTerminator(); |
92 | MachineFrameInfo &MFI = MF.getFrameInfo(); |
93 | const Mips16InstrInfo &TII = |
94 | *static_cast<const Mips16InstrInfo *>(STI.getInstrInfo()); |
95 | DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); |
96 | uint64_t StackSize = MFI.getStackSize(); |
97 | |
98 | if (!StackSize) |
99 | return; |
100 | |
101 | if (hasFP(MF)) |
102 | BuildMI(MBB, MBBI, dl, TII.get(Mips::Move32R16), Mips::SP) |
103 | .addReg(Mips::S0); |
104 | |
105 | // Adjust stack. |
106 | // assumes stacksize multiple of 8 |
107 | TII.restoreFrame(Mips::SP: SP, FrameSize: StackSize, MBB, I: MBBI); |
108 | } |
109 | |
110 | bool Mips16FrameLowering::spillCalleeSavedRegisters( |
111 | MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, |
112 | ArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const { |
113 | MachineFunction *MF = MBB.getParent(); |
114 | |
115 | // |
116 | // Registers RA, S0,S1 are the callee saved registers and they |
117 | // will be saved with the "save" instruction |
118 | // during emitPrologue |
119 | // |
120 | for (const CalleeSavedInfo &I : CSI) { |
121 | // Add the callee-saved register as live-in. Do not add if the register is |
122 | // RA and return address is taken, because it has already been added in |
123 | // method MipsTargetLowering::lowerRETURNADDR. |
124 | // It's killed at the spill, unless the register is RA and return address |
125 | // is taken. |
126 | Register Reg = I.getReg(); |
127 | bool IsRAAndRetAddrIsTaken = (Reg == Mips::RA) |
128 | && MF->getFrameInfo().isReturnAddressTaken(); |
129 | if (!IsRAAndRetAddrIsTaken) |
130 | MBB.addLiveIn(PhysReg: Reg); |
131 | } |
132 | |
133 | return true; |
134 | } |
135 | |
136 | bool Mips16FrameLowering::restoreCalleeSavedRegisters( |
137 | MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, |
138 | MutableArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const { |
139 | // |
140 | // Registers RA,S0,S1 are the callee saved registers and they will be restored |
141 | // with the restore instruction during emitEpilogue. |
142 | // We need to override this virtual function, otherwise llvm will try and |
143 | // restore the registers on it's on from the stack. |
144 | // |
145 | |
146 | return true; |
147 | } |
148 | |
149 | bool |
150 | Mips16FrameLowering::hasReservedCallFrame(const MachineFunction &MF) const { |
151 | const MachineFrameInfo &MFI = MF.getFrameInfo(); |
152 | // Reserve call frame if the size of the maximum call frame fits into 15-bit |
153 | // immediate field and there are no variable sized objects on the stack. |
154 | return isInt<15>(x: MFI.getMaxCallFrameSize()) && !MFI.hasVarSizedObjects(); |
155 | } |
156 | |
157 | void Mips16FrameLowering::determineCalleeSaves(MachineFunction &MF, |
158 | BitVector &SavedRegs, |
159 | RegScavenger *RS) const { |
160 | TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS); |
161 | const Mips16InstrInfo &TII = |
162 | *static_cast<const Mips16InstrInfo *>(STI.getInstrInfo()); |
163 | const MipsRegisterInfo &RI = TII.getRegisterInfo(); |
164 | const BitVector Reserved = RI.getReservedRegs(MF); |
165 | bool SaveS2 = Reserved[Mips::S2]; |
166 | if (SaveS2) |
167 | SavedRegs.set(Mips::S2); |
168 | if (hasFP(MF)) |
169 | SavedRegs.set(Mips::S0); |
170 | } |
171 | |
172 | const MipsFrameLowering * |
173 | llvm::createMips16FrameLowering(const MipsSubtarget &ST) { |
174 | return new Mips16FrameLowering(ST); |
175 | } |
176 | |