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