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