xref: /freebsd/contrib/llvm-project/llvm/lib/Target/Mips/MipsMachineFunction.cpp (revision 5ffd83dbcc34f10e07f6d3e968ae6365869615f4)
10b57cec5SDimitry Andric //===-- MipsMachineFunctionInfo.cpp - Private data used for Mips ----------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "MipsMachineFunction.h"
100b57cec5SDimitry Andric #include "MCTargetDesc/MipsABIInfo.h"
110b57cec5SDimitry Andric #include "MipsSubtarget.h"
120b57cec5SDimitry Andric #include "MipsTargetMachine.h"
130b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h"
140b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
150b57cec5SDimitry Andric #include "llvm/CodeGen/PseudoSourceValue.h"
160b57cec5SDimitry Andric #include "llvm/CodeGen/TargetRegisterInfo.h"
170b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h"
180b57cec5SDimitry Andric 
190b57cec5SDimitry Andric using namespace llvm;
200b57cec5SDimitry Andric 
210b57cec5SDimitry Andric static cl::opt<bool>
220b57cec5SDimitry Andric FixGlobalBaseReg("mips-fix-global-base-reg", cl::Hidden, cl::init(true),
230b57cec5SDimitry Andric                  cl::desc("Always use $gp as the global base register."));
240b57cec5SDimitry Andric 
250b57cec5SDimitry Andric MipsFunctionInfo::~MipsFunctionInfo() = default;
260b57cec5SDimitry Andric 
270b57cec5SDimitry Andric bool MipsFunctionInfo::globalBaseRegSet() const {
280b57cec5SDimitry Andric   return GlobalBaseReg;
290b57cec5SDimitry Andric }
300b57cec5SDimitry Andric 
310b57cec5SDimitry Andric static const TargetRegisterClass &getGlobalBaseRegClass(MachineFunction &MF) {
320b57cec5SDimitry Andric   auto &STI = static_cast<const MipsSubtarget &>(MF.getSubtarget());
330b57cec5SDimitry Andric   auto &TM = static_cast<const MipsTargetMachine &>(MF.getTarget());
340b57cec5SDimitry Andric 
350b57cec5SDimitry Andric   if (STI.inMips16Mode())
360b57cec5SDimitry Andric     return Mips::CPU16RegsRegClass;
370b57cec5SDimitry Andric 
380b57cec5SDimitry Andric   if (STI.inMicroMipsMode())
390b57cec5SDimitry Andric     return Mips::GPRMM16RegClass;
400b57cec5SDimitry Andric 
410b57cec5SDimitry Andric   if (TM.getABI().IsN64())
420b57cec5SDimitry Andric     return Mips::GPR64RegClass;
430b57cec5SDimitry Andric 
440b57cec5SDimitry Andric   return Mips::GPR32RegClass;
450b57cec5SDimitry Andric }
460b57cec5SDimitry Andric 
47*5ffd83dbSDimitry Andric Register MipsFunctionInfo::getGlobalBaseReg(MachineFunction &MF) {
480b57cec5SDimitry Andric   if (!GlobalBaseReg)
490b57cec5SDimitry Andric     GlobalBaseReg =
500b57cec5SDimitry Andric         MF.getRegInfo().createVirtualRegister(&getGlobalBaseRegClass(MF));
510b57cec5SDimitry Andric   return GlobalBaseReg;
520b57cec5SDimitry Andric }
530b57cec5SDimitry Andric 
54*5ffd83dbSDimitry Andric Register MipsFunctionInfo::getGlobalBaseRegForGlobalISel(MachineFunction &MF) {
550b57cec5SDimitry Andric   if (!GlobalBaseReg) {
56*5ffd83dbSDimitry Andric     getGlobalBaseReg(MF);
57*5ffd83dbSDimitry Andric     initGlobalBaseReg(MF);
580b57cec5SDimitry Andric   }
590b57cec5SDimitry Andric   return GlobalBaseReg;
600b57cec5SDimitry Andric }
610b57cec5SDimitry Andric 
62*5ffd83dbSDimitry Andric void MipsFunctionInfo::initGlobalBaseReg(MachineFunction &MF) {
630b57cec5SDimitry Andric   if (!GlobalBaseReg)
640b57cec5SDimitry Andric     return;
650b57cec5SDimitry Andric 
660b57cec5SDimitry Andric   MachineBasicBlock &MBB = MF.front();
670b57cec5SDimitry Andric   MachineBasicBlock::iterator I = MBB.begin();
680b57cec5SDimitry Andric   MachineRegisterInfo &RegInfo = MF.getRegInfo();
690b57cec5SDimitry Andric   const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo();
700b57cec5SDimitry Andric   DebugLoc DL;
710b57cec5SDimitry Andric   const TargetRegisterClass *RC;
720b57cec5SDimitry Andric   const MipsABIInfo &ABI =
730b57cec5SDimitry Andric       static_cast<const MipsTargetMachine &>(MF.getTarget()).getABI();
740b57cec5SDimitry Andric   RC = (ABI.IsN64()) ? &Mips::GPR64RegClass : &Mips::GPR32RegClass;
750b57cec5SDimitry Andric 
76*5ffd83dbSDimitry Andric   Register V0 = RegInfo.createVirtualRegister(RC);
77*5ffd83dbSDimitry Andric   Register V1 = RegInfo.createVirtualRegister(RC);
780b57cec5SDimitry Andric 
790b57cec5SDimitry Andric   if (ABI.IsN64()) {
800b57cec5SDimitry Andric     MF.getRegInfo().addLiveIn(Mips::T9_64);
810b57cec5SDimitry Andric     MBB.addLiveIn(Mips::T9_64);
820b57cec5SDimitry Andric 
830b57cec5SDimitry Andric     // lui $v0, %hi(%neg(%gp_rel(fname)))
840b57cec5SDimitry Andric     // daddu $v1, $v0, $t9
850b57cec5SDimitry Andric     // daddiu $globalbasereg, $v1, %lo(%neg(%gp_rel(fname)))
860b57cec5SDimitry Andric     const GlobalValue *FName = &MF.getFunction();
870b57cec5SDimitry Andric     BuildMI(MBB, I, DL, TII.get(Mips::LUi64), V0)
880b57cec5SDimitry Andric         .addGlobalAddress(FName, 0, MipsII::MO_GPOFF_HI);
890b57cec5SDimitry Andric     BuildMI(MBB, I, DL, TII.get(Mips::DADDu), V1).addReg(V0)
900b57cec5SDimitry Andric         .addReg(Mips::T9_64);
910b57cec5SDimitry Andric     BuildMI(MBB, I, DL, TII.get(Mips::DADDiu), GlobalBaseReg).addReg(V1)
920b57cec5SDimitry Andric         .addGlobalAddress(FName, 0, MipsII::MO_GPOFF_LO);
930b57cec5SDimitry Andric     return;
940b57cec5SDimitry Andric   }
950b57cec5SDimitry Andric 
960b57cec5SDimitry Andric   if (!MF.getTarget().isPositionIndependent()) {
970b57cec5SDimitry Andric     // Set global register to __gnu_local_gp.
980b57cec5SDimitry Andric     //
990b57cec5SDimitry Andric     // lui   $v0, %hi(__gnu_local_gp)
1000b57cec5SDimitry Andric     // addiu $globalbasereg, $v0, %lo(__gnu_local_gp)
1010b57cec5SDimitry Andric     BuildMI(MBB, I, DL, TII.get(Mips::LUi), V0)
1020b57cec5SDimitry Andric         .addExternalSymbol("__gnu_local_gp", MipsII::MO_ABS_HI);
1030b57cec5SDimitry Andric     BuildMI(MBB, I, DL, TII.get(Mips::ADDiu), GlobalBaseReg).addReg(V0)
1040b57cec5SDimitry Andric         .addExternalSymbol("__gnu_local_gp", MipsII::MO_ABS_LO);
1050b57cec5SDimitry Andric     return;
1060b57cec5SDimitry Andric   }
1070b57cec5SDimitry Andric 
1080b57cec5SDimitry Andric   MF.getRegInfo().addLiveIn(Mips::T9);
1090b57cec5SDimitry Andric   MBB.addLiveIn(Mips::T9);
1100b57cec5SDimitry Andric 
1110b57cec5SDimitry Andric   if (ABI.IsN32()) {
1120b57cec5SDimitry Andric     // lui $v0, %hi(%neg(%gp_rel(fname)))
1130b57cec5SDimitry Andric     // addu $v1, $v0, $t9
1140b57cec5SDimitry Andric     // addiu $globalbasereg, $v1, %lo(%neg(%gp_rel(fname)))
1150b57cec5SDimitry Andric     const GlobalValue *FName = &MF.getFunction();
1160b57cec5SDimitry Andric     BuildMI(MBB, I, DL, TII.get(Mips::LUi), V0)
1170b57cec5SDimitry Andric         .addGlobalAddress(FName, 0, MipsII::MO_GPOFF_HI);
1180b57cec5SDimitry Andric     BuildMI(MBB, I, DL, TII.get(Mips::ADDu), V1).addReg(V0).addReg(Mips::T9);
1190b57cec5SDimitry Andric     BuildMI(MBB, I, DL, TII.get(Mips::ADDiu), GlobalBaseReg).addReg(V1)
1200b57cec5SDimitry Andric         .addGlobalAddress(FName, 0, MipsII::MO_GPOFF_LO);
1210b57cec5SDimitry Andric     return;
1220b57cec5SDimitry Andric   }
1230b57cec5SDimitry Andric 
1240b57cec5SDimitry Andric   assert(ABI.IsO32());
1250b57cec5SDimitry Andric 
1260b57cec5SDimitry Andric   // For O32 ABI, the following instruction sequence is emitted to initialize
1270b57cec5SDimitry Andric   // the global base register:
1280b57cec5SDimitry Andric   //
1290b57cec5SDimitry Andric   //  0. lui   $2, %hi(_gp_disp)
1300b57cec5SDimitry Andric   //  1. addiu $2, $2, %lo(_gp_disp)
1310b57cec5SDimitry Andric   //  2. addu  $globalbasereg, $2, $t9
1320b57cec5SDimitry Andric   //
1330b57cec5SDimitry Andric   // We emit only the last instruction here.
1340b57cec5SDimitry Andric   //
1350b57cec5SDimitry Andric   // GNU linker requires that the first two instructions appear at the beginning
1360b57cec5SDimitry Andric   // of a function and no instructions be inserted before or between them.
1370b57cec5SDimitry Andric   // The two instructions are emitted during lowering to MC layer in order to
1380b57cec5SDimitry Andric   // avoid any reordering.
1390b57cec5SDimitry Andric   //
1400b57cec5SDimitry Andric   // Register $2 (Mips::V0) is added to the list of live-in registers to ensure
1410b57cec5SDimitry Andric   // the value instruction 1 (addiu) defines is valid when instruction 2 (addu)
1420b57cec5SDimitry Andric   // reads it.
1430b57cec5SDimitry Andric   MF.getRegInfo().addLiveIn(Mips::V0);
1440b57cec5SDimitry Andric   MBB.addLiveIn(Mips::V0);
1450b57cec5SDimitry Andric   BuildMI(MBB, I, DL, TII.get(Mips::ADDu), GlobalBaseReg)
1460b57cec5SDimitry Andric       .addReg(Mips::V0).addReg(Mips::T9);
1470b57cec5SDimitry Andric }
1480b57cec5SDimitry Andric 
149*5ffd83dbSDimitry Andric void MipsFunctionInfo::createEhDataRegsFI(MachineFunction &MF) {
1500b57cec5SDimitry Andric   const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo();
1510b57cec5SDimitry Andric   for (int I = 0; I < 4; ++I) {
1520b57cec5SDimitry Andric     const TargetRegisterClass &RC =
1530b57cec5SDimitry Andric         static_cast<const MipsTargetMachine &>(MF.getTarget()).getABI().IsN64()
1540b57cec5SDimitry Andric             ? Mips::GPR64RegClass
1550b57cec5SDimitry Andric             : Mips::GPR32RegClass;
1560b57cec5SDimitry Andric 
157*5ffd83dbSDimitry Andric     EhDataRegFI[I] = MF.getFrameInfo().CreateStackObject(
158*5ffd83dbSDimitry Andric         TRI.getSpillSize(RC), TRI.getSpillAlign(RC), false);
1590b57cec5SDimitry Andric   }
1600b57cec5SDimitry Andric }
1610b57cec5SDimitry Andric 
162*5ffd83dbSDimitry Andric void MipsFunctionInfo::createISRRegFI(MachineFunction &MF) {
1630b57cec5SDimitry Andric   // ISRs require spill slots for Status & ErrorPC Coprocessor 0 registers.
1640b57cec5SDimitry Andric   // The current implementation only supports Mips32r2+ not Mips64rX. Status
1650b57cec5SDimitry Andric   // is always 32 bits, ErrorPC is 32 or 64 bits dependent on architecture,
1660b57cec5SDimitry Andric   // however Mips32r2+ is the supported architecture.
1670b57cec5SDimitry Andric   const TargetRegisterClass &RC = Mips::GPR32RegClass;
1680b57cec5SDimitry Andric   const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo();
1690b57cec5SDimitry Andric 
1700b57cec5SDimitry Andric   for (int I = 0; I < 2; ++I)
1710b57cec5SDimitry Andric     ISRDataRegFI[I] = MF.getFrameInfo().CreateStackObject(
172*5ffd83dbSDimitry Andric         TRI.getSpillSize(RC), TRI.getSpillAlign(RC), false);
1730b57cec5SDimitry Andric }
1740b57cec5SDimitry Andric 
1750b57cec5SDimitry Andric bool MipsFunctionInfo::isEhDataRegFI(int FI) const {
1760b57cec5SDimitry Andric   return CallsEhReturn && (FI == EhDataRegFI[0] || FI == EhDataRegFI[1]
1770b57cec5SDimitry Andric                         || FI == EhDataRegFI[2] || FI == EhDataRegFI[3]);
1780b57cec5SDimitry Andric }
1790b57cec5SDimitry Andric 
1800b57cec5SDimitry Andric bool MipsFunctionInfo::isISRRegFI(int FI) const {
1810b57cec5SDimitry Andric   return IsISR && (FI == ISRDataRegFI[0] || FI == ISRDataRegFI[1]);
1820b57cec5SDimitry Andric }
183*5ffd83dbSDimitry Andric MachinePointerInfo MipsFunctionInfo::callPtrInfo(MachineFunction &MF,
184*5ffd83dbSDimitry Andric                                                  const char *ES) {
1850b57cec5SDimitry Andric   return MachinePointerInfo(MF.getPSVManager().getExternalSymbolCallEntry(ES));
1860b57cec5SDimitry Andric }
1870b57cec5SDimitry Andric 
188*5ffd83dbSDimitry Andric MachinePointerInfo MipsFunctionInfo::callPtrInfo(MachineFunction &MF,
189*5ffd83dbSDimitry Andric                                                  const GlobalValue *GV) {
1900b57cec5SDimitry Andric   return MachinePointerInfo(MF.getPSVManager().getGlobalValueCallEntry(GV));
1910b57cec5SDimitry Andric }
1920b57cec5SDimitry Andric 
193*5ffd83dbSDimitry Andric int MipsFunctionInfo::getMoveF64ViaSpillFI(MachineFunction &MF,
194*5ffd83dbSDimitry Andric                                            const TargetRegisterClass *RC) {
1950b57cec5SDimitry Andric   const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo();
1960b57cec5SDimitry Andric   if (MoveF64ViaSpillFI == -1) {
1970b57cec5SDimitry Andric     MoveF64ViaSpillFI = MF.getFrameInfo().CreateStackObject(
198*5ffd83dbSDimitry Andric         TRI.getSpillSize(*RC), TRI.getSpillAlign(*RC), false);
1990b57cec5SDimitry Andric   }
2000b57cec5SDimitry Andric   return MoveF64ViaSpillFI;
2010b57cec5SDimitry Andric }
2020b57cec5SDimitry Andric 
2030b57cec5SDimitry Andric void MipsFunctionInfo::anchor() {}
204