163faed5bSDimitry Andric //===-- MipsMachineFunctionInfo.cpp - Private data used for Mips ----------===//
263faed5bSDimitry Andric //
3e6d15924SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e6d15924SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5e6d15924SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
663faed5bSDimitry Andric //
763faed5bSDimitry Andric //===----------------------------------------------------------------------===//
863faed5bSDimitry Andric
95a5ac124SDimitry Andric #include "MipsMachineFunction.h"
107ab83427SDimitry Andric #include "MCTargetDesc/MipsABIInfo.h"
1163faed5bSDimitry Andric #include "MipsSubtarget.h"
125a5ac124SDimitry Andric #include "MipsTargetMachine.h"
1371d5a254SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h"
1463faed5bSDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
1571d5a254SDimitry Andric #include "llvm/CodeGen/PseudoSourceValue.h"
16b1c73532SDimitry Andric #include "llvm/CodeGen/PseudoSourceValueManager.h"
17044eb2f6SDimitry Andric #include "llvm/CodeGen/TargetRegisterInfo.h"
1863faed5bSDimitry Andric #include "llvm/Support/CommandLine.h"
1963faed5bSDimitry Andric
2063faed5bSDimitry Andric using namespace llvm;
2163faed5bSDimitry Andric
2263faed5bSDimitry Andric static cl::opt<bool>
2363faed5bSDimitry Andric FixGlobalBaseReg("mips-fix-global-base-reg", cl::Hidden, cl::init(true),
2463faed5bSDimitry Andric cl::desc("Always use $gp as the global base register."));
2563faed5bSDimitry Andric
26145449b1SDimitry Andric MachineFunctionInfo *
clone(BumpPtrAllocator & Allocator,MachineFunction & DestMF,const DenseMap<MachineBasicBlock *,MachineBasicBlock * > & Src2DstMBB) const27145449b1SDimitry Andric MipsFunctionInfo::clone(BumpPtrAllocator &Allocator, MachineFunction &DestMF,
28145449b1SDimitry Andric const DenseMap<MachineBasicBlock *, MachineBasicBlock *>
29145449b1SDimitry Andric &Src2DstMBB) const {
30145449b1SDimitry Andric return DestMF.cloneInfo<MipsFunctionInfo>(*this);
31145449b1SDimitry Andric }
32145449b1SDimitry Andric
3371d5a254SDimitry Andric MipsFunctionInfo::~MipsFunctionInfo() = default;
34f8af5cf6SDimitry Andric
globalBaseRegSet() const3563faed5bSDimitry Andric bool MipsFunctionInfo::globalBaseRegSet() const {
3663faed5bSDimitry Andric return GlobalBaseReg;
3763faed5bSDimitry Andric }
3863faed5bSDimitry Andric
getGlobalBaseRegClass(MachineFunction & MF)39eb11fae6SDimitry Andric static const TargetRegisterClass &getGlobalBaseRegClass(MachineFunction &MF) {
40145449b1SDimitry Andric auto &STI = MF.getSubtarget<MipsSubtarget>();
41eb11fae6SDimitry Andric auto &TM = static_cast<const MipsTargetMachine &>(MF.getTarget());
42eb11fae6SDimitry Andric
43eb11fae6SDimitry Andric if (STI.inMips16Mode())
44eb11fae6SDimitry Andric return Mips::CPU16RegsRegClass;
45eb11fae6SDimitry Andric
46eb11fae6SDimitry Andric if (STI.inMicroMipsMode())
47eb11fae6SDimitry Andric return Mips::GPRMM16RegClass;
48eb11fae6SDimitry Andric
49eb11fae6SDimitry Andric if (TM.getABI().IsN64())
50eb11fae6SDimitry Andric return Mips::GPR64RegClass;
51eb11fae6SDimitry Andric
52eb11fae6SDimitry Andric return Mips::GPR32RegClass;
53eb11fae6SDimitry Andric }
54eb11fae6SDimitry Andric
getGlobalBaseReg(MachineFunction & MF)55cfca06d7SDimitry Andric Register MipsFunctionInfo::getGlobalBaseReg(MachineFunction &MF) {
56eb11fae6SDimitry Andric if (!GlobalBaseReg)
57eb11fae6SDimitry Andric GlobalBaseReg =
58eb11fae6SDimitry Andric MF.getRegInfo().createVirtualRegister(&getGlobalBaseRegClass(MF));
5963faed5bSDimitry Andric return GlobalBaseReg;
6063faed5bSDimitry Andric }
6163faed5bSDimitry Andric
getGlobalBaseRegForGlobalISel(MachineFunction & MF)62cfca06d7SDimitry Andric Register MipsFunctionInfo::getGlobalBaseRegForGlobalISel(MachineFunction &MF) {
63e6d15924SDimitry Andric if (!GlobalBaseReg) {
64cfca06d7SDimitry Andric getGlobalBaseReg(MF);
65cfca06d7SDimitry Andric initGlobalBaseReg(MF);
66e6d15924SDimitry Andric }
67e6d15924SDimitry Andric return GlobalBaseReg;
68e6d15924SDimitry Andric }
69e6d15924SDimitry Andric
initGlobalBaseReg(MachineFunction & MF)70cfca06d7SDimitry Andric void MipsFunctionInfo::initGlobalBaseReg(MachineFunction &MF) {
71e6d15924SDimitry Andric if (!GlobalBaseReg)
72e6d15924SDimitry Andric return;
73e6d15924SDimitry Andric
74e6d15924SDimitry Andric MachineBasicBlock &MBB = MF.front();
75e6d15924SDimitry Andric MachineBasicBlock::iterator I = MBB.begin();
76e6d15924SDimitry Andric MachineRegisterInfo &RegInfo = MF.getRegInfo();
77e6d15924SDimitry Andric const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo();
78e6d15924SDimitry Andric DebugLoc DL;
79e6d15924SDimitry Andric const TargetRegisterClass *RC;
80e6d15924SDimitry Andric const MipsABIInfo &ABI =
81e6d15924SDimitry Andric static_cast<const MipsTargetMachine &>(MF.getTarget()).getABI();
82e6d15924SDimitry Andric RC = (ABI.IsN64()) ? &Mips::GPR64RegClass : &Mips::GPR32RegClass;
83e6d15924SDimitry Andric
84cfca06d7SDimitry Andric Register V0 = RegInfo.createVirtualRegister(RC);
85cfca06d7SDimitry Andric Register V1 = RegInfo.createVirtualRegister(RC);
86e6d15924SDimitry Andric
87e6d15924SDimitry Andric if (ABI.IsN64()) {
88e6d15924SDimitry Andric MF.getRegInfo().addLiveIn(Mips::T9_64);
89e6d15924SDimitry Andric MBB.addLiveIn(Mips::T9_64);
90e6d15924SDimitry Andric
91e6d15924SDimitry Andric // lui $v0, %hi(%neg(%gp_rel(fname)))
92e6d15924SDimitry Andric // daddu $v1, $v0, $t9
93e6d15924SDimitry Andric // daddiu $globalbasereg, $v1, %lo(%neg(%gp_rel(fname)))
94e6d15924SDimitry Andric const GlobalValue *FName = &MF.getFunction();
95e6d15924SDimitry Andric BuildMI(MBB, I, DL, TII.get(Mips::LUi64), V0)
96e6d15924SDimitry Andric .addGlobalAddress(FName, 0, MipsII::MO_GPOFF_HI);
97e6d15924SDimitry Andric BuildMI(MBB, I, DL, TII.get(Mips::DADDu), V1).addReg(V0)
98e6d15924SDimitry Andric .addReg(Mips::T9_64);
99e6d15924SDimitry Andric BuildMI(MBB, I, DL, TII.get(Mips::DADDiu), GlobalBaseReg).addReg(V1)
100e6d15924SDimitry Andric .addGlobalAddress(FName, 0, MipsII::MO_GPOFF_LO);
101e6d15924SDimitry Andric return;
102e6d15924SDimitry Andric }
103e6d15924SDimitry Andric
104e6d15924SDimitry Andric if (!MF.getTarget().isPositionIndependent()) {
105e6d15924SDimitry Andric // Set global register to __gnu_local_gp.
106e6d15924SDimitry Andric //
107e6d15924SDimitry Andric // lui $v0, %hi(__gnu_local_gp)
108e6d15924SDimitry Andric // addiu $globalbasereg, $v0, %lo(__gnu_local_gp)
109e6d15924SDimitry Andric BuildMI(MBB, I, DL, TII.get(Mips::LUi), V0)
110e6d15924SDimitry Andric .addExternalSymbol("__gnu_local_gp", MipsII::MO_ABS_HI);
111e6d15924SDimitry Andric BuildMI(MBB, I, DL, TII.get(Mips::ADDiu), GlobalBaseReg).addReg(V0)
112e6d15924SDimitry Andric .addExternalSymbol("__gnu_local_gp", MipsII::MO_ABS_LO);
113e6d15924SDimitry Andric return;
114e6d15924SDimitry Andric }
115e6d15924SDimitry Andric
116e6d15924SDimitry Andric MF.getRegInfo().addLiveIn(Mips::T9);
117e6d15924SDimitry Andric MBB.addLiveIn(Mips::T9);
118e6d15924SDimitry Andric
119e6d15924SDimitry Andric if (ABI.IsN32()) {
120e6d15924SDimitry Andric // lui $v0, %hi(%neg(%gp_rel(fname)))
121e6d15924SDimitry Andric // addu $v1, $v0, $t9
122e6d15924SDimitry Andric // addiu $globalbasereg, $v1, %lo(%neg(%gp_rel(fname)))
123e6d15924SDimitry Andric const GlobalValue *FName = &MF.getFunction();
124e6d15924SDimitry Andric BuildMI(MBB, I, DL, TII.get(Mips::LUi), V0)
125e6d15924SDimitry Andric .addGlobalAddress(FName, 0, MipsII::MO_GPOFF_HI);
126e6d15924SDimitry Andric BuildMI(MBB, I, DL, TII.get(Mips::ADDu), V1).addReg(V0).addReg(Mips::T9);
127e6d15924SDimitry Andric BuildMI(MBB, I, DL, TII.get(Mips::ADDiu), GlobalBaseReg).addReg(V1)
128e6d15924SDimitry Andric .addGlobalAddress(FName, 0, MipsII::MO_GPOFF_LO);
129e6d15924SDimitry Andric return;
130e6d15924SDimitry Andric }
131e6d15924SDimitry Andric
132e6d15924SDimitry Andric assert(ABI.IsO32());
133e6d15924SDimitry Andric
134e6d15924SDimitry Andric // For O32 ABI, the following instruction sequence is emitted to initialize
135e6d15924SDimitry Andric // the global base register:
136e6d15924SDimitry Andric //
137e6d15924SDimitry Andric // 0. lui $2, %hi(_gp_disp)
138e6d15924SDimitry Andric // 1. addiu $2, $2, %lo(_gp_disp)
139e6d15924SDimitry Andric // 2. addu $globalbasereg, $2, $t9
140e6d15924SDimitry Andric //
141e6d15924SDimitry Andric // We emit only the last instruction here.
142e6d15924SDimitry Andric //
143e6d15924SDimitry Andric // GNU linker requires that the first two instructions appear at the beginning
144e6d15924SDimitry Andric // of a function and no instructions be inserted before or between them.
145e6d15924SDimitry Andric // The two instructions are emitted during lowering to MC layer in order to
146e6d15924SDimitry Andric // avoid any reordering.
147e6d15924SDimitry Andric //
148e6d15924SDimitry Andric // Register $2 (Mips::V0) is added to the list of live-in registers to ensure
149e6d15924SDimitry Andric // the value instruction 1 (addiu) defines is valid when instruction 2 (addu)
150e6d15924SDimitry Andric // reads it.
151e6d15924SDimitry Andric MF.getRegInfo().addLiveIn(Mips::V0);
152e6d15924SDimitry Andric MBB.addLiveIn(Mips::V0);
153e6d15924SDimitry Andric BuildMI(MBB, I, DL, TII.get(Mips::ADDu), GlobalBaseReg)
154e6d15924SDimitry Andric .addReg(Mips::V0).addReg(Mips::T9);
155e6d15924SDimitry Andric }
156e6d15924SDimitry Andric
createEhDataRegsFI(MachineFunction & MF)157cfca06d7SDimitry Andric void MipsFunctionInfo::createEhDataRegsFI(MachineFunction &MF) {
15812f3ca4cSDimitry Andric const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo();
1596f8fc217SDimitry Andric for (int &I : EhDataRegFI) {
16012f3ca4cSDimitry Andric const TargetRegisterClass &RC =
1615a5ac124SDimitry Andric static_cast<const MipsTargetMachine &>(MF.getTarget()).getABI().IsN64()
16212f3ca4cSDimitry Andric ? Mips::GPR64RegClass
16312f3ca4cSDimitry Andric : Mips::GPR32RegClass;
1644a16efa3SDimitry Andric
1656f8fc217SDimitry Andric I = MF.getFrameInfo().CreateStackObject(TRI.getSpillSize(RC),
1666f8fc217SDimitry Andric TRI.getSpillAlign(RC), false);
1674a16efa3SDimitry Andric }
1684a16efa3SDimitry Andric }
1694a16efa3SDimitry Andric
createISRRegFI(MachineFunction & MF)170cfca06d7SDimitry Andric void MipsFunctionInfo::createISRRegFI(MachineFunction &MF) {
171dd58ef01SDimitry Andric // ISRs require spill slots for Status & ErrorPC Coprocessor 0 registers.
172dd58ef01SDimitry Andric // The current implementation only supports Mips32r2+ not Mips64rX. Status
173b915e9e0SDimitry Andric // is always 32 bits, ErrorPC is 32 or 64 bits dependent on architecture,
174dd58ef01SDimitry Andric // however Mips32r2+ is the supported architecture.
17512f3ca4cSDimitry Andric const TargetRegisterClass &RC = Mips::GPR32RegClass;
17612f3ca4cSDimitry Andric const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo();
177dd58ef01SDimitry Andric
1786f8fc217SDimitry Andric for (int &I : ISRDataRegFI)
1796f8fc217SDimitry Andric I = MF.getFrameInfo().CreateStackObject(TRI.getSpillSize(RC),
1806f8fc217SDimitry Andric TRI.getSpillAlign(RC), false);
181dd58ef01SDimitry Andric }
182dd58ef01SDimitry Andric
isEhDataRegFI(int FI) const1834a16efa3SDimitry Andric bool MipsFunctionInfo::isEhDataRegFI(int FI) const {
1844a16efa3SDimitry Andric return CallsEhReturn && (FI == EhDataRegFI[0] || FI == EhDataRegFI[1]
1854a16efa3SDimitry Andric || FI == EhDataRegFI[2] || FI == EhDataRegFI[3]);
1864a16efa3SDimitry Andric }
1874a16efa3SDimitry Andric
isISRRegFI(int FI) const188dd58ef01SDimitry Andric bool MipsFunctionInfo::isISRRegFI(int FI) const {
189dd58ef01SDimitry Andric return IsISR && (FI == ISRDataRegFI[0] || FI == ISRDataRegFI[1]);
190dd58ef01SDimitry Andric }
callPtrInfo(MachineFunction & MF,const char * ES)191cfca06d7SDimitry Andric MachinePointerInfo MipsFunctionInfo::callPtrInfo(MachineFunction &MF,
192cfca06d7SDimitry Andric const char *ES) {
193dd58ef01SDimitry Andric return MachinePointerInfo(MF.getPSVManager().getExternalSymbolCallEntry(ES));
194f8af5cf6SDimitry Andric }
195f8af5cf6SDimitry Andric
callPtrInfo(MachineFunction & MF,const GlobalValue * GV)196cfca06d7SDimitry Andric MachinePointerInfo MipsFunctionInfo::callPtrInfo(MachineFunction &MF,
197cfca06d7SDimitry Andric const GlobalValue *GV) {
198dd58ef01SDimitry Andric return MachinePointerInfo(MF.getPSVManager().getGlobalValueCallEntry(GV));
199f8af5cf6SDimitry Andric }
200f8af5cf6SDimitry Andric
getMoveF64ViaSpillFI(MachineFunction & MF,const TargetRegisterClass * RC)201cfca06d7SDimitry Andric int MipsFunctionInfo::getMoveF64ViaSpillFI(MachineFunction &MF,
202cfca06d7SDimitry Andric const TargetRegisterClass *RC) {
20312f3ca4cSDimitry Andric const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo();
2045ca98fd9SDimitry Andric if (MoveF64ViaSpillFI == -1) {
205b915e9e0SDimitry Andric MoveF64ViaSpillFI = MF.getFrameInfo().CreateStackObject(
206cfca06d7SDimitry Andric TRI.getSpillSize(*RC), TRI.getSpillAlign(*RC), false);
2075ca98fd9SDimitry Andric }
2085ca98fd9SDimitry Andric return MoveF64ViaSpillFI;
2095ca98fd9SDimitry Andric }
2105ca98fd9SDimitry Andric
anchor()21163faed5bSDimitry Andric void MipsFunctionInfo::anchor() {}
212