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 * 2781ad6265SDimitry 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 350b57cec5SDimitry Andric bool MipsFunctionInfo::globalBaseRegSet() const { 360b57cec5SDimitry Andric return GlobalBaseReg; 370b57cec5SDimitry Andric } 380b57cec5SDimitry Andric 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 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 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 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 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 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 1830b57cec5SDimitry 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 1880b57cec5SDimitry Andric bool MipsFunctionInfo::isISRRegFI(int FI) const { 1890b57cec5SDimitry Andric return IsISR && (FI == ISRDataRegFI[0] || FI == ISRDataRegFI[1]); 1900b57cec5SDimitry Andric } 1915ffd83dbSDimitry Andric MachinePointerInfo MipsFunctionInfo::callPtrInfo(MachineFunction &MF, 1925ffd83dbSDimitry Andric const char *ES) { 1930b57cec5SDimitry Andric return MachinePointerInfo(MF.getPSVManager().getExternalSymbolCallEntry(ES)); 1940b57cec5SDimitry Andric } 1950b57cec5SDimitry Andric 1965ffd83dbSDimitry Andric MachinePointerInfo MipsFunctionInfo::callPtrInfo(MachineFunction &MF, 1975ffd83dbSDimitry Andric const GlobalValue *GV) { 1980b57cec5SDimitry Andric return MachinePointerInfo(MF.getPSVManager().getGlobalValueCallEntry(GV)); 1990b57cec5SDimitry Andric } 2000b57cec5SDimitry Andric 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 2110b57cec5SDimitry Andric void MipsFunctionInfo::anchor() {} 212