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 "Mips16InstrInfo.h" |
15 | #include "MipsInstrInfo.h" |
16 | #include "MipsRegisterInfo.h" |
17 | #include "MipsSubtarget.h" |
18 | #include "llvm/ADT/BitVector.h" |
19 | #include "llvm/CodeGen/CFIInstBuilder.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/CodeGen/TargetFrameLowering.h" |
27 | #include "llvm/IR/DebugLoc.h" |
28 | #include "llvm/Support/MathExtras.h" |
29 | #include <cstdint> |
30 | #include <vector> |
31 | |
32 | using namespace llvm; |
33 | |
34 | Mips16FrameLowering::Mips16FrameLowering(const MipsSubtarget &STI) |
35 | : MipsFrameLowering(STI, STI.getStackAlignment()) {} |
36 | |
37 | void Mips16FrameLowering::emitPrologue(MachineFunction &MF, |
38 | MachineBasicBlock &MBB) const { |
39 | MachineFrameInfo &MFI = MF.getFrameInfo(); |
40 | const Mips16InstrInfo &TII = |
41 | *static_cast<const Mips16InstrInfo *>(STI.getInstrInfo()); |
42 | MachineBasicBlock::iterator MBBI = MBB.begin(); |
43 | |
44 | // Debug location must be unknown since the first debug location is used |
45 | // to determine the end of the prologue. |
46 | DebugLoc dl; |
47 | |
48 | uint64_t StackSize = MFI.getStackSize(); |
49 | |
50 | // No need to allocate space on the stack. |
51 | if (StackSize == 0 && !MFI.adjustsStack()) return; |
52 | |
53 | // Adjust stack. |
54 | TII.makeFrame(SP: Mips::SP, FrameSize: StackSize, MBB, I: MBBI); |
55 | |
56 | CFIInstBuilder CFIBuilder(MBB, MBBI, MachineInstr::NoFlags); |
57 | CFIBuilder.buildDefCFAOffset(Offset: StackSize); |
58 | |
59 | const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo(); |
60 | |
61 | if (!CSI.empty()) { |
62 | for (const CalleeSavedInfo &I : CSI) |
63 | CFIBuilder.buildOffset(Reg: I.getReg(), Offset: MFI.getObjectOffset(ObjectIdx: I.getFrameIdx())); |
64 | } |
65 | |
66 | if (hasFP(MF)) |
67 | BuildMI(BB&: MBB, I: MBBI, MIMD: dl, MCID: TII.get(Opcode: Mips::MoveR3216), DestReg: Mips::S0) |
68 | .addReg(RegNo: Mips::SP).setMIFlag(MachineInstr::FrameSetup); |
69 | } |
70 | |
71 | void Mips16FrameLowering::emitEpilogue(MachineFunction &MF, |
72 | MachineBasicBlock &MBB) const { |
73 | MachineBasicBlock::iterator MBBI = MBB.getFirstTerminator(); |
74 | MachineFrameInfo &MFI = MF.getFrameInfo(); |
75 | const Mips16InstrInfo &TII = |
76 | *static_cast<const Mips16InstrInfo *>(STI.getInstrInfo()); |
77 | DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); |
78 | uint64_t StackSize = MFI.getStackSize(); |
79 | |
80 | if (!StackSize) |
81 | return; |
82 | |
83 | if (hasFP(MF)) |
84 | BuildMI(BB&: MBB, I: MBBI, MIMD: dl, MCID: TII.get(Opcode: Mips::Move32R16), DestReg: Mips::SP) |
85 | .addReg(RegNo: Mips::S0); |
86 | |
87 | // Adjust stack. |
88 | // assumes stacksize multiple of 8 |
89 | TII.restoreFrame(SP: Mips::SP, FrameSize: StackSize, MBB, I: MBBI); |
90 | } |
91 | |
92 | bool Mips16FrameLowering::spillCalleeSavedRegisters( |
93 | MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, |
94 | ArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const { |
95 | MachineFunction *MF = MBB.getParent(); |
96 | |
97 | // |
98 | // Registers RA, S0,S1 are the callee saved registers and they |
99 | // will be saved with the "save" instruction |
100 | // during emitPrologue |
101 | // |
102 | for (const CalleeSavedInfo &I : CSI) { |
103 | // Add the callee-saved register as live-in. Do not add if the register is |
104 | // RA and return address is taken, because it has already been added in |
105 | // method MipsTargetLowering::lowerRETURNADDR. |
106 | // It's killed at the spill, unless the register is RA and return address |
107 | // is taken. |
108 | MCRegister Reg = I.getReg(); |
109 | bool IsRAAndRetAddrIsTaken = (Reg == Mips::RA) |
110 | && MF->getFrameInfo().isReturnAddressTaken(); |
111 | if (!IsRAAndRetAddrIsTaken) |
112 | MBB.addLiveIn(PhysReg: Reg); |
113 | } |
114 | |
115 | return true; |
116 | } |
117 | |
118 | bool Mips16FrameLowering::restoreCalleeSavedRegisters( |
119 | MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, |
120 | MutableArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const { |
121 | // |
122 | // Registers RA,S0,S1 are the callee saved registers and they will be restored |
123 | // with the restore instruction during emitEpilogue. |
124 | // We need to override this virtual function, otherwise llvm will try and |
125 | // restore the registers on it's on from the stack. |
126 | // |
127 | |
128 | return true; |
129 | } |
130 | |
131 | bool |
132 | Mips16FrameLowering::hasReservedCallFrame(const MachineFunction &MF) const { |
133 | const MachineFrameInfo &MFI = MF.getFrameInfo(); |
134 | // Reserve call frame if the size of the maximum call frame fits into 15-bit |
135 | // immediate field and there are no variable sized objects on the stack. |
136 | return isInt<15>(x: MFI.getMaxCallFrameSize()) && !MFI.hasVarSizedObjects(); |
137 | } |
138 | |
139 | void Mips16FrameLowering::determineCalleeSaves(MachineFunction &MF, |
140 | BitVector &SavedRegs, |
141 | RegScavenger *RS) const { |
142 | TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS); |
143 | const Mips16InstrInfo &TII = |
144 | *static_cast<const Mips16InstrInfo *>(STI.getInstrInfo()); |
145 | const MipsRegisterInfo &RI = TII.getRegisterInfo(); |
146 | const BitVector Reserved = RI.getReservedRegs(MF); |
147 | bool SaveS2 = Reserved[Mips::S2]; |
148 | if (SaveS2) |
149 | SavedRegs.set(Mips::S2); |
150 | if (hasFP(MF)) |
151 | SavedRegs.set(Mips::S0); |
152 | } |
153 | |
154 | const MipsFrameLowering * |
155 | llvm::createMips16FrameLowering(const MipsSubtarget &ST) { |
156 | return new Mips16FrameLowering(ST); |
157 | } |
158 | |