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"
16*5f757f3fSDimitry Andric #include "llvm/CodeGen/PseudoSourceValueManager.h"
170b57cec5SDimitry Andric #include "llvm/CodeGen/TargetRegisterInfo.h"
180b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h"
190b57cec5SDimitry Andric
200b57cec5SDimitry Andric using namespace llvm;
210b57cec5SDimitry Andric
220b57cec5SDimitry Andric static cl::opt<bool>
230b57cec5SDimitry Andric FixGlobalBaseReg("mips-fix-global-base-reg", cl::Hidden, cl::init(true),
240b57cec5SDimitry Andric cl::desc("Always use $gp as the global base register."));
250b57cec5SDimitry Andric
2681ad6265SDimitry Andric MachineFunctionInfo *
clone(BumpPtrAllocator & Allocator,MachineFunction & DestMF,const DenseMap<MachineBasicBlock *,MachineBasicBlock * > & Src2DstMBB) const2781ad6265SDimitry Andric MipsFunctionInfo::clone(BumpPtrAllocator &Allocator, MachineFunction &DestMF,
2881ad6265SDimitry Andric const DenseMap<MachineBasicBlock *, MachineBasicBlock *>
2981ad6265SDimitry Andric &Src2DstMBB) const {
3081ad6265SDimitry Andric return DestMF.cloneInfo<MipsFunctionInfo>(*this);
3181ad6265SDimitry Andric }
3281ad6265SDimitry Andric
330b57cec5SDimitry Andric MipsFunctionInfo::~MipsFunctionInfo() = default;
340b57cec5SDimitry Andric
globalBaseRegSet() const350b57cec5SDimitry Andric bool MipsFunctionInfo::globalBaseRegSet() const {
360b57cec5SDimitry Andric return GlobalBaseReg;
370b57cec5SDimitry Andric }
380b57cec5SDimitry Andric
getGlobalBaseRegClass(MachineFunction & MF)390b57cec5SDimitry Andric static const TargetRegisterClass &getGlobalBaseRegClass(MachineFunction &MF) {
4081ad6265SDimitry Andric auto &STI = MF.getSubtarget<MipsSubtarget>();
410b57cec5SDimitry Andric auto &TM = static_cast<const MipsTargetMachine &>(MF.getTarget());
420b57cec5SDimitry Andric
430b57cec5SDimitry Andric if (STI.inMips16Mode())
440b57cec5SDimitry Andric return Mips::CPU16RegsRegClass;
450b57cec5SDimitry Andric
460b57cec5SDimitry Andric if (STI.inMicroMipsMode())
470b57cec5SDimitry Andric return Mips::GPRMM16RegClass;
480b57cec5SDimitry Andric
490b57cec5SDimitry Andric if (TM.getABI().IsN64())
500b57cec5SDimitry Andric return Mips::GPR64RegClass;
510b57cec5SDimitry Andric
520b57cec5SDimitry Andric return Mips::GPR32RegClass;
530b57cec5SDimitry Andric }
540b57cec5SDimitry Andric
getGlobalBaseReg(MachineFunction & MF)555ffd83dbSDimitry Andric Register MipsFunctionInfo::getGlobalBaseReg(MachineFunction &MF) {
560b57cec5SDimitry Andric if (!GlobalBaseReg)
570b57cec5SDimitry Andric GlobalBaseReg =
580b57cec5SDimitry Andric MF.getRegInfo().createVirtualRegister(&getGlobalBaseRegClass(MF));
590b57cec5SDimitry Andric return GlobalBaseReg;
600b57cec5SDimitry Andric }
610b57cec5SDimitry Andric
getGlobalBaseRegForGlobalISel(MachineFunction & MF)625ffd83dbSDimitry Andric Register MipsFunctionInfo::getGlobalBaseRegForGlobalISel(MachineFunction &MF) {
630b57cec5SDimitry Andric if (!GlobalBaseReg) {
645ffd83dbSDimitry Andric getGlobalBaseReg(MF);
655ffd83dbSDimitry Andric initGlobalBaseReg(MF);
660b57cec5SDimitry Andric }
670b57cec5SDimitry Andric return GlobalBaseReg;
680b57cec5SDimitry Andric }
690b57cec5SDimitry Andric
initGlobalBaseReg(MachineFunction & MF)705ffd83dbSDimitry Andric void MipsFunctionInfo::initGlobalBaseReg(MachineFunction &MF) {
710b57cec5SDimitry Andric if (!GlobalBaseReg)
720b57cec5SDimitry Andric return;
730b57cec5SDimitry Andric
740b57cec5SDimitry Andric MachineBasicBlock &MBB = MF.front();
750b57cec5SDimitry Andric MachineBasicBlock::iterator I = MBB.begin();
760b57cec5SDimitry Andric MachineRegisterInfo &RegInfo = MF.getRegInfo();
770b57cec5SDimitry Andric const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo();
780b57cec5SDimitry Andric DebugLoc DL;
790b57cec5SDimitry Andric const TargetRegisterClass *RC;
800b57cec5SDimitry Andric const MipsABIInfo &ABI =
810b57cec5SDimitry Andric static_cast<const MipsTargetMachine &>(MF.getTarget()).getABI();
820b57cec5SDimitry Andric RC = (ABI.IsN64()) ? &Mips::GPR64RegClass : &Mips::GPR32RegClass;
830b57cec5SDimitry Andric
845ffd83dbSDimitry Andric Register V0 = RegInfo.createVirtualRegister(RC);
855ffd83dbSDimitry Andric Register V1 = RegInfo.createVirtualRegister(RC);
860b57cec5SDimitry Andric
870b57cec5SDimitry Andric if (ABI.IsN64()) {
880b57cec5SDimitry Andric MF.getRegInfo().addLiveIn(Mips::T9_64);
890b57cec5SDimitry Andric MBB.addLiveIn(Mips::T9_64);
900b57cec5SDimitry Andric
910b57cec5SDimitry Andric // lui $v0, %hi(%neg(%gp_rel(fname)))
920b57cec5SDimitry Andric // daddu $v1, $v0, $t9
930b57cec5SDimitry Andric // daddiu $globalbasereg, $v1, %lo(%neg(%gp_rel(fname)))
940b57cec5SDimitry Andric const GlobalValue *FName = &MF.getFunction();
950b57cec5SDimitry Andric BuildMI(MBB, I, DL, TII.get(Mips::LUi64), V0)
960b57cec5SDimitry Andric .addGlobalAddress(FName, 0, MipsII::MO_GPOFF_HI);
970b57cec5SDimitry Andric BuildMI(MBB, I, DL, TII.get(Mips::DADDu), V1).addReg(V0)
980b57cec5SDimitry Andric .addReg(Mips::T9_64);
990b57cec5SDimitry Andric BuildMI(MBB, I, DL, TII.get(Mips::DADDiu), GlobalBaseReg).addReg(V1)
1000b57cec5SDimitry Andric .addGlobalAddress(FName, 0, MipsII::MO_GPOFF_LO);
1010b57cec5SDimitry Andric return;
1020b57cec5SDimitry Andric }
1030b57cec5SDimitry Andric
1040b57cec5SDimitry Andric if (!MF.getTarget().isPositionIndependent()) {
1050b57cec5SDimitry Andric // Set global register to __gnu_local_gp.
1060b57cec5SDimitry Andric //
1070b57cec5SDimitry Andric // lui $v0, %hi(__gnu_local_gp)
1080b57cec5SDimitry Andric // addiu $globalbasereg, $v0, %lo(__gnu_local_gp)
1090b57cec5SDimitry Andric BuildMI(MBB, I, DL, TII.get(Mips::LUi), V0)
1100b57cec5SDimitry Andric .addExternalSymbol("__gnu_local_gp", MipsII::MO_ABS_HI);
1110b57cec5SDimitry Andric BuildMI(MBB, I, DL, TII.get(Mips::ADDiu), GlobalBaseReg).addReg(V0)
1120b57cec5SDimitry Andric .addExternalSymbol("__gnu_local_gp", MipsII::MO_ABS_LO);
1130b57cec5SDimitry Andric return;
1140b57cec5SDimitry Andric }
1150b57cec5SDimitry Andric
1160b57cec5SDimitry Andric MF.getRegInfo().addLiveIn(Mips::T9);
1170b57cec5SDimitry Andric MBB.addLiveIn(Mips::T9);
1180b57cec5SDimitry Andric
1190b57cec5SDimitry Andric if (ABI.IsN32()) {
1200b57cec5SDimitry Andric // lui $v0, %hi(%neg(%gp_rel(fname)))
1210b57cec5SDimitry Andric // addu $v1, $v0, $t9
1220b57cec5SDimitry Andric // addiu $globalbasereg, $v1, %lo(%neg(%gp_rel(fname)))
1230b57cec5SDimitry Andric const GlobalValue *FName = &MF.getFunction();
1240b57cec5SDimitry Andric BuildMI(MBB, I, DL, TII.get(Mips::LUi), V0)
1250b57cec5SDimitry Andric .addGlobalAddress(FName, 0, MipsII::MO_GPOFF_HI);
1260b57cec5SDimitry Andric BuildMI(MBB, I, DL, TII.get(Mips::ADDu), V1).addReg(V0).addReg(Mips::T9);
1270b57cec5SDimitry Andric BuildMI(MBB, I, DL, TII.get(Mips::ADDiu), GlobalBaseReg).addReg(V1)
1280b57cec5SDimitry Andric .addGlobalAddress(FName, 0, MipsII::MO_GPOFF_LO);
1290b57cec5SDimitry Andric return;
1300b57cec5SDimitry Andric }
1310b57cec5SDimitry Andric
1320b57cec5SDimitry Andric assert(ABI.IsO32());
1330b57cec5SDimitry Andric
1340b57cec5SDimitry Andric // For O32 ABI, the following instruction sequence is emitted to initialize
1350b57cec5SDimitry Andric // the global base register:
1360b57cec5SDimitry Andric //
1370b57cec5SDimitry Andric // 0. lui $2, %hi(_gp_disp)
1380b57cec5SDimitry Andric // 1. addiu $2, $2, %lo(_gp_disp)
1390b57cec5SDimitry Andric // 2. addu $globalbasereg, $2, $t9
1400b57cec5SDimitry Andric //
1410b57cec5SDimitry Andric // We emit only the last instruction here.
1420b57cec5SDimitry Andric //
1430b57cec5SDimitry Andric // GNU linker requires that the first two instructions appear at the beginning
1440b57cec5SDimitry Andric // of a function and no instructions be inserted before or between them.
1450b57cec5SDimitry Andric // The two instructions are emitted during lowering to MC layer in order to
1460b57cec5SDimitry Andric // avoid any reordering.
1470b57cec5SDimitry Andric //
1480b57cec5SDimitry Andric // Register $2 (Mips::V0) is added to the list of live-in registers to ensure
1490b57cec5SDimitry Andric // the value instruction 1 (addiu) defines is valid when instruction 2 (addu)
1500b57cec5SDimitry Andric // reads it.
1510b57cec5SDimitry Andric MF.getRegInfo().addLiveIn(Mips::V0);
1520b57cec5SDimitry Andric MBB.addLiveIn(Mips::V0);
1530b57cec5SDimitry Andric BuildMI(MBB, I, DL, TII.get(Mips::ADDu), GlobalBaseReg)
1540b57cec5SDimitry Andric .addReg(Mips::V0).addReg(Mips::T9);
1550b57cec5SDimitry Andric }
1560b57cec5SDimitry Andric
createEhDataRegsFI(MachineFunction & MF)1575ffd83dbSDimitry Andric void MipsFunctionInfo::createEhDataRegsFI(MachineFunction &MF) {
1580b57cec5SDimitry Andric const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo();
15904eeddc0SDimitry Andric for (int &I : EhDataRegFI) {
1600b57cec5SDimitry Andric const TargetRegisterClass &RC =
1610b57cec5SDimitry Andric static_cast<const MipsTargetMachine &>(MF.getTarget()).getABI().IsN64()
1620b57cec5SDimitry Andric ? Mips::GPR64RegClass
1630b57cec5SDimitry Andric : Mips::GPR32RegClass;
1640b57cec5SDimitry Andric
16504eeddc0SDimitry Andric I = MF.getFrameInfo().CreateStackObject(TRI.getSpillSize(RC),
16604eeddc0SDimitry Andric TRI.getSpillAlign(RC), false);
1670b57cec5SDimitry Andric }
1680b57cec5SDimitry Andric }
1690b57cec5SDimitry Andric
createISRRegFI(MachineFunction & MF)1705ffd83dbSDimitry Andric void MipsFunctionInfo::createISRRegFI(MachineFunction &MF) {
1710b57cec5SDimitry Andric // ISRs require spill slots for Status & ErrorPC Coprocessor 0 registers.
1720b57cec5SDimitry Andric // The current implementation only supports Mips32r2+ not Mips64rX. Status
1730b57cec5SDimitry Andric // is always 32 bits, ErrorPC is 32 or 64 bits dependent on architecture,
1740b57cec5SDimitry Andric // however Mips32r2+ is the supported architecture.
1750b57cec5SDimitry Andric const TargetRegisterClass &RC = Mips::GPR32RegClass;
1760b57cec5SDimitry Andric const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo();
1770b57cec5SDimitry Andric
17804eeddc0SDimitry Andric for (int &I : ISRDataRegFI)
17904eeddc0SDimitry Andric I = MF.getFrameInfo().CreateStackObject(TRI.getSpillSize(RC),
18004eeddc0SDimitry Andric TRI.getSpillAlign(RC), false);
1810b57cec5SDimitry Andric }
1820b57cec5SDimitry Andric
isEhDataRegFI(int FI) const1830b57cec5SDimitry Andric bool MipsFunctionInfo::isEhDataRegFI(int FI) const {
1840b57cec5SDimitry Andric return CallsEhReturn && (FI == EhDataRegFI[0] || FI == EhDataRegFI[1]
1850b57cec5SDimitry Andric || FI == EhDataRegFI[2] || FI == EhDataRegFI[3]);
1860b57cec5SDimitry Andric }
1870b57cec5SDimitry Andric
isISRRegFI(int FI) const1880b57cec5SDimitry Andric bool MipsFunctionInfo::isISRRegFI(int FI) const {
1890b57cec5SDimitry Andric return IsISR && (FI == ISRDataRegFI[0] || FI == ISRDataRegFI[1]);
1900b57cec5SDimitry Andric }
callPtrInfo(MachineFunction & MF,const char * ES)1915ffd83dbSDimitry Andric MachinePointerInfo MipsFunctionInfo::callPtrInfo(MachineFunction &MF,
1925ffd83dbSDimitry Andric const char *ES) {
1930b57cec5SDimitry Andric return MachinePointerInfo(MF.getPSVManager().getExternalSymbolCallEntry(ES));
1940b57cec5SDimitry Andric }
1950b57cec5SDimitry Andric
callPtrInfo(MachineFunction & MF,const GlobalValue * GV)1965ffd83dbSDimitry Andric MachinePointerInfo MipsFunctionInfo::callPtrInfo(MachineFunction &MF,
1975ffd83dbSDimitry Andric const GlobalValue *GV) {
1980b57cec5SDimitry Andric return MachinePointerInfo(MF.getPSVManager().getGlobalValueCallEntry(GV));
1990b57cec5SDimitry Andric }
2000b57cec5SDimitry Andric
getMoveF64ViaSpillFI(MachineFunction & MF,const TargetRegisterClass * RC)2015ffd83dbSDimitry Andric int MipsFunctionInfo::getMoveF64ViaSpillFI(MachineFunction &MF,
2025ffd83dbSDimitry Andric const TargetRegisterClass *RC) {
2030b57cec5SDimitry Andric const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo();
2040b57cec5SDimitry Andric if (MoveF64ViaSpillFI == -1) {
2050b57cec5SDimitry Andric MoveF64ViaSpillFI = MF.getFrameInfo().CreateStackObject(
2065ffd83dbSDimitry Andric TRI.getSpillSize(*RC), TRI.getSpillAlign(*RC), false);
2070b57cec5SDimitry Andric }
2080b57cec5SDimitry Andric return MoveF64ViaSpillFI;
2090b57cec5SDimitry Andric }
2100b57cec5SDimitry Andric
anchor()2110b57cec5SDimitry Andric void MipsFunctionInfo::anchor() {}
212