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(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>(*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(&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(RC);
85   Register V1 = RegInfo.createVirtualRegister(RC);
86 
87   if (ABI.IsN64()) {
88     MF.getRegInfo().addLiveIn(Mips::T9_64);
89     MBB.addLiveIn(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(MBB, I, DL, TII.get(Mips::LUi64), V0)
96         .addGlobalAddress(FName, 0, MipsII::MO_GPOFF_HI);
97     BuildMI(MBB, I, DL, TII.get(Mips::DADDu), V1).addReg(V0)
98         .addReg(Mips::T9_64);
99     BuildMI(MBB, I, DL, TII.get(Mips::DADDiu), GlobalBaseReg).addReg(V1)
100         .addGlobalAddress(FName, 0, 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(MBB, I, DL, TII.get(Mips::LUi), V0)
110         .addExternalSymbol("__gnu_local_gp", MipsII::MO_ABS_HI);
111     BuildMI(MBB, I, DL, TII.get(Mips::ADDiu), GlobalBaseReg).addReg(V0)
112         .addExternalSymbol("__gnu_local_gp", MipsII::MO_ABS_LO);
113     return;
114   }
115 
116   MF.getRegInfo().addLiveIn(Mips::T9);
117   MBB.addLiveIn(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(MBB, I, DL, TII.get(Mips::LUi), V0)
125         .addGlobalAddress(FName, 0, MipsII::MO_GPOFF_HI);
126     BuildMI(MBB, I, DL, TII.get(Mips::ADDu), V1).addReg(V0).addReg(Mips::T9);
127     BuildMI(MBB, I, DL, TII.get(Mips::ADDiu), GlobalBaseReg).addReg(V1)
128         .addGlobalAddress(FName, 0, 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(Mips::V0);
152   MBB.addLiveIn(Mips::V0);
153   BuildMI(MBB, I, DL, TII.get(Mips::ADDu), GlobalBaseReg)
154       .addReg(Mips::V0).addReg(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(TRI.getSpillSize(RC),
166                                             TRI.getSpillAlign(RC), 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(TRI.getSpillSize(RC),
180                                             TRI.getSpillAlign(RC), 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         TRI.getSpillSize(*RC), TRI.getSpillAlign(*RC), false);
207   }
208   return MoveF64ViaSpillFI;
209 }
210 
211 void MipsFunctionInfo::anchor() {}
212