1 | //===-- MipsMachineFunctionInfo.cpp - Private data used for Mips ----------===// |
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 | #include "MipsMachineFunction.h" |
10 | #include "MCTargetDesc/MipsABIInfo.h" |
11 | #include "MipsSubtarget.h" |
12 | #include "MipsTargetMachine.h" |
13 | #include "llvm/CodeGen/MachineFrameInfo.h" |
14 | #include "llvm/CodeGen/MachineRegisterInfo.h" |
15 | #include "llvm/CodeGen/PseudoSourceValue.h" |
16 | #include "llvm/CodeGen/PseudoSourceValueManager.h" |
17 | #include "llvm/CodeGen/TargetRegisterInfo.h" |
18 | #include "llvm/Support/CommandLine.h" |
19 | |
20 | using namespace llvm; |
21 | |
22 | static cl::opt<bool> |
23 | FixGlobalBaseReg("mips-fix-global-base-reg" , cl::Hidden, cl::init(Val: true), |
24 | cl::desc("Always use $gp as the global base register." )); |
25 | |
26 | MachineFunctionInfo * |
27 | MipsFunctionInfo::clone(BumpPtrAllocator &Allocator, MachineFunction &DestMF, |
28 | const DenseMap<MachineBasicBlock *, MachineBasicBlock *> |
29 | &Src2DstMBB) const { |
30 | return DestMF.cloneInfo<MipsFunctionInfo>(Old: *this); |
31 | } |
32 | |
33 | MipsFunctionInfo::~MipsFunctionInfo() = default; |
34 | |
35 | bool MipsFunctionInfo::globalBaseRegSet() const { |
36 | return GlobalBaseReg; |
37 | } |
38 | |
39 | static const TargetRegisterClass &getGlobalBaseRegClass(MachineFunction &MF) { |
40 | auto &STI = MF.getSubtarget<MipsSubtarget>(); |
41 | auto &TM = static_cast<const MipsTargetMachine &>(MF.getTarget()); |
42 | |
43 | if (STI.inMips16Mode()) |
44 | return Mips::CPU16RegsRegClass; |
45 | |
46 | if (STI.inMicroMipsMode()) |
47 | return Mips::GPRMM16RegClass; |
48 | |
49 | if (TM.getABI().IsN64()) |
50 | return Mips::GPR64RegClass; |
51 | |
52 | return Mips::GPR32RegClass; |
53 | } |
54 | |
55 | Register MipsFunctionInfo::getGlobalBaseReg(MachineFunction &MF) { |
56 | if (!GlobalBaseReg) |
57 | GlobalBaseReg = |
58 | MF.getRegInfo().createVirtualRegister(RegClass: &getGlobalBaseRegClass(MF)); |
59 | return GlobalBaseReg; |
60 | } |
61 | |
62 | Register MipsFunctionInfo::getGlobalBaseRegForGlobalISel(MachineFunction &MF) { |
63 | if (!GlobalBaseReg) { |
64 | getGlobalBaseReg(MF); |
65 | initGlobalBaseReg(MF); |
66 | } |
67 | return GlobalBaseReg; |
68 | } |
69 | |
70 | void MipsFunctionInfo::initGlobalBaseReg(MachineFunction &MF) { |
71 | if (!GlobalBaseReg) |
72 | return; |
73 | |
74 | MachineBasicBlock &MBB = MF.front(); |
75 | MachineBasicBlock::iterator I = MBB.begin(); |
76 | MachineRegisterInfo &RegInfo = MF.getRegInfo(); |
77 | const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo(); |
78 | DebugLoc DL; |
79 | const TargetRegisterClass *RC; |
80 | const MipsABIInfo &ABI = |
81 | static_cast<const MipsTargetMachine &>(MF.getTarget()).getABI(); |
82 | RC = (ABI.IsN64()) ? &Mips::GPR64RegClass : &Mips::GPR32RegClass; |
83 | |
84 | Register V0 = RegInfo.createVirtualRegister(RegClass: RC); |
85 | Register V1 = RegInfo.createVirtualRegister(RegClass: RC); |
86 | |
87 | if (ABI.IsN64()) { |
88 | MF.getRegInfo().addLiveIn(Reg: Mips::T9_64); |
89 | MBB.addLiveIn(PhysReg: Mips::T9_64); |
90 | |
91 | // lui $v0, %hi(%neg(%gp_rel(fname))) |
92 | // daddu $v1, $v0, $t9 |
93 | // daddiu $globalbasereg, $v1, %lo(%neg(%gp_rel(fname))) |
94 | const GlobalValue *FName = &MF.getFunction(); |
95 | BuildMI(BB&: MBB, I, MIMD: DL, MCID: TII.get(Opcode: Mips::LUi64), DestReg: V0) |
96 | .addGlobalAddress(GV: FName, Offset: 0, TargetFlags: MipsII::MO_GPOFF_HI); |
97 | BuildMI(BB&: MBB, I, MIMD: DL, MCID: TII.get(Opcode: Mips::DADDu), DestReg: V1).addReg(RegNo: V0) |
98 | .addReg(RegNo: Mips::T9_64); |
99 | BuildMI(BB&: MBB, I, MIMD: DL, MCID: TII.get(Opcode: Mips::DADDiu), DestReg: GlobalBaseReg).addReg(RegNo: V1) |
100 | .addGlobalAddress(GV: FName, Offset: 0, TargetFlags: MipsII::MO_GPOFF_LO); |
101 | return; |
102 | } |
103 | |
104 | if (!MF.getTarget().isPositionIndependent()) { |
105 | // Set global register to __gnu_local_gp. |
106 | // |
107 | // lui $v0, %hi(__gnu_local_gp) |
108 | // addiu $globalbasereg, $v0, %lo(__gnu_local_gp) |
109 | BuildMI(BB&: MBB, I, MIMD: DL, MCID: TII.get(Opcode: Mips::LUi), DestReg: V0) |
110 | .addExternalSymbol(FnName: "__gnu_local_gp" , TargetFlags: MipsII::MO_ABS_HI); |
111 | BuildMI(BB&: MBB, I, MIMD: DL, MCID: TII.get(Opcode: Mips::ADDiu), DestReg: GlobalBaseReg).addReg(RegNo: V0) |
112 | .addExternalSymbol(FnName: "__gnu_local_gp" , TargetFlags: MipsII::MO_ABS_LO); |
113 | return; |
114 | } |
115 | |
116 | MF.getRegInfo().addLiveIn(Reg: Mips::T9); |
117 | MBB.addLiveIn(PhysReg: Mips::T9); |
118 | |
119 | if (ABI.IsN32()) { |
120 | // lui $v0, %hi(%neg(%gp_rel(fname))) |
121 | // addu $v1, $v0, $t9 |
122 | // addiu $globalbasereg, $v1, %lo(%neg(%gp_rel(fname))) |
123 | const GlobalValue *FName = &MF.getFunction(); |
124 | BuildMI(BB&: MBB, I, MIMD: DL, MCID: TII.get(Opcode: Mips::LUi), DestReg: V0) |
125 | .addGlobalAddress(GV: FName, Offset: 0, TargetFlags: MipsII::MO_GPOFF_HI); |
126 | BuildMI(BB&: MBB, I, MIMD: DL, MCID: TII.get(Opcode: Mips::ADDu), DestReg: V1).addReg(RegNo: V0).addReg(RegNo: Mips::T9); |
127 | BuildMI(BB&: MBB, I, MIMD: DL, MCID: TII.get(Opcode: Mips::ADDiu), DestReg: GlobalBaseReg).addReg(RegNo: V1) |
128 | .addGlobalAddress(GV: FName, Offset: 0, TargetFlags: MipsII::MO_GPOFF_LO); |
129 | return; |
130 | } |
131 | |
132 | assert(ABI.IsO32()); |
133 | |
134 | // For O32 ABI, the following instruction sequence is emitted to initialize |
135 | // the global base register: |
136 | // |
137 | // 0. lui $2, %hi(_gp_disp) |
138 | // 1. addiu $2, $2, %lo(_gp_disp) |
139 | // 2. addu $globalbasereg, $2, $t9 |
140 | // |
141 | // We emit only the last instruction here. |
142 | // |
143 | // GNU linker requires that the first two instructions appear at the beginning |
144 | // of a function and no instructions be inserted before or between them. |
145 | // The two instructions are emitted during lowering to MC layer in order to |
146 | // avoid any reordering. |
147 | // |
148 | // Register $2 (Mips::V0) is added to the list of live-in registers to ensure |
149 | // the value instruction 1 (addiu) defines is valid when instruction 2 (addu) |
150 | // reads it. |
151 | MF.getRegInfo().addLiveIn(Reg: Mips::V0); |
152 | MBB.addLiveIn(PhysReg: Mips::V0); |
153 | BuildMI(BB&: MBB, I, MIMD: DL, MCID: TII.get(Opcode: Mips::ADDu), DestReg: GlobalBaseReg) |
154 | .addReg(RegNo: Mips::V0).addReg(RegNo: Mips::T9); |
155 | } |
156 | |
157 | void MipsFunctionInfo::createEhDataRegsFI(MachineFunction &MF) { |
158 | const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo(); |
159 | for (int &I : EhDataRegFI) { |
160 | const TargetRegisterClass &RC = |
161 | static_cast<const MipsTargetMachine &>(MF.getTarget()).getABI().IsN64() |
162 | ? Mips::GPR64RegClass |
163 | : Mips::GPR32RegClass; |
164 | |
165 | I = MF.getFrameInfo().CreateStackObject(Size: TRI.getSpillSize(RC), |
166 | Alignment: TRI.getSpillAlign(RC), isSpillSlot: false); |
167 | } |
168 | } |
169 | |
170 | void MipsFunctionInfo::createISRRegFI(MachineFunction &MF) { |
171 | // ISRs require spill slots for Status & ErrorPC Coprocessor 0 registers. |
172 | // The current implementation only supports Mips32r2+ not Mips64rX. Status |
173 | // is always 32 bits, ErrorPC is 32 or 64 bits dependent on architecture, |
174 | // however Mips32r2+ is the supported architecture. |
175 | const TargetRegisterClass &RC = Mips::GPR32RegClass; |
176 | const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo(); |
177 | |
178 | for (int &I : ISRDataRegFI) |
179 | I = MF.getFrameInfo().CreateStackObject(Size: TRI.getSpillSize(RC), |
180 | Alignment: TRI.getSpillAlign(RC), isSpillSlot: false); |
181 | } |
182 | |
183 | bool MipsFunctionInfo::isEhDataRegFI(int FI) const { |
184 | return CallsEhReturn && (FI == EhDataRegFI[0] || FI == EhDataRegFI[1] |
185 | || FI == EhDataRegFI[2] || FI == EhDataRegFI[3]); |
186 | } |
187 | |
188 | bool MipsFunctionInfo::isISRRegFI(int FI) const { |
189 | return IsISR && (FI == ISRDataRegFI[0] || FI == ISRDataRegFI[1]); |
190 | } |
191 | MachinePointerInfo MipsFunctionInfo::callPtrInfo(MachineFunction &MF, |
192 | const char *ES) { |
193 | return MachinePointerInfo(MF.getPSVManager().getExternalSymbolCallEntry(ES)); |
194 | } |
195 | |
196 | MachinePointerInfo MipsFunctionInfo::callPtrInfo(MachineFunction &MF, |
197 | const GlobalValue *GV) { |
198 | return MachinePointerInfo(MF.getPSVManager().getGlobalValueCallEntry(GV)); |
199 | } |
200 | |
201 | int MipsFunctionInfo::getMoveF64ViaSpillFI(MachineFunction &MF, |
202 | const TargetRegisterClass *RC) { |
203 | const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo(); |
204 | if (MoveF64ViaSpillFI == -1) { |
205 | MoveF64ViaSpillFI = MF.getFrameInfo().CreateStackObject( |
206 | Size: TRI.getSpillSize(RC: *RC), Alignment: TRI.getSpillAlign(RC: *RC), isSpillSlot: false); |
207 | } |
208 | return MoveF64ViaSpillFI; |
209 | } |
210 | |
211 | void MipsFunctionInfo::anchor() {} |
212 | |