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