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