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 *
26 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 
34 bool MipsFunctionInfo::globalBaseRegSet() const {
35   return GlobalBaseReg;
36 }
37 
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 
54 Register MipsFunctionInfo::getGlobalBaseReg(MachineFunction &MF) {
55   if (!GlobalBaseReg)
56     GlobalBaseReg =
57         MF.getRegInfo().createVirtualRegister(&getGlobalBaseRegClass(MF));
58   return GlobalBaseReg;
59 }
60 
61 Register MipsFunctionInfo::getGlobalBaseRegForGlobalISel(MachineFunction &MF) {
62   if (!GlobalBaseReg) {
63     getGlobalBaseReg(MF);
64     initGlobalBaseReg(MF);
65   }
66   return GlobalBaseReg;
67 }
68 
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 
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 
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 
182 bool MipsFunctionInfo::isEhDataRegFI(int FI) const {
183   return CallsEhReturn && (FI == EhDataRegFI[0] || FI == EhDataRegFI[1]
184                         || FI == EhDataRegFI[2] || FI == EhDataRegFI[3]);
185 }
186 
187 bool MipsFunctionInfo::isISRRegFI(int FI) const {
188   return IsISR && (FI == ISRDataRegFI[0] || FI == ISRDataRegFI[1]);
189 }
190 MachinePointerInfo MipsFunctionInfo::callPtrInfo(MachineFunction &MF,
191                                                  const char *ES) {
192   return MachinePointerInfo(MF.getPSVManager().getExternalSymbolCallEntry(ES));
193 }
194 
195 MachinePointerInfo MipsFunctionInfo::callPtrInfo(MachineFunction &MF,
196                                                  const GlobalValue *GV) {
197   return MachinePointerInfo(MF.getPSVManager().getGlobalValueCallEntry(GV));
198 }
199 
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 
210 void MipsFunctionInfo::anchor() {}
211