1dff0c46cSDimitry Andric //===-- MipsMachineFunctionInfo.cpp - Private data used for Mips ----------===//
2dff0c46cSDimitry Andric //
3dff0c46cSDimitry Andric //                     The LLVM Compiler Infrastructure
4dff0c46cSDimitry Andric //
5dff0c46cSDimitry Andric // This file is distributed under the University of Illinois Open Source
6dff0c46cSDimitry Andric // License. See LICENSE.TXT for details.
7dff0c46cSDimitry Andric //
8dff0c46cSDimitry Andric //===----------------------------------------------------------------------===//
9dff0c46cSDimitry Andric 
10ff0cc061SDimitry Andric #include "MipsMachineFunction.h"
11db17bf38SDimitry Andric #include "MCTargetDesc/MipsABIInfo.h"
12dff0c46cSDimitry Andric #include "MipsSubtarget.h"
13ff0cc061SDimitry Andric #include "MipsTargetMachine.h"
147a7e6055SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h"
15dff0c46cSDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
167a7e6055SDimitry Andric #include "llvm/CodeGen/PseudoSourceValue.h"
172cab237bSDimitry Andric #include "llvm/CodeGen/TargetRegisterInfo.h"
18dff0c46cSDimitry Andric #include "llvm/Support/CommandLine.h"
19dff0c46cSDimitry Andric 
20dff0c46cSDimitry Andric using namespace llvm;
21dff0c46cSDimitry Andric 
22dff0c46cSDimitry Andric static cl::opt<bool>
23dff0c46cSDimitry Andric FixGlobalBaseReg("mips-fix-global-base-reg", cl::Hidden, cl::init(true),
24dff0c46cSDimitry Andric                  cl::desc("Always use $gp as the global base register."));
25dff0c46cSDimitry Andric 
267a7e6055SDimitry Andric MipsFunctionInfo::~MipsFunctionInfo() = default;
27f785676fSDimitry Andric 
globalBaseRegSet() const28dff0c46cSDimitry Andric bool MipsFunctionInfo::globalBaseRegSet() const {
29dff0c46cSDimitry Andric   return GlobalBaseReg;
30dff0c46cSDimitry Andric }
31dff0c46cSDimitry Andric 
getGlobalBaseRegClass(MachineFunction & MF)32*4ba319b5SDimitry Andric static const TargetRegisterClass &getGlobalBaseRegClass(MachineFunction &MF) {
33*4ba319b5SDimitry Andric   auto &STI = static_cast<const MipsSubtarget &>(MF.getSubtarget());
34*4ba319b5SDimitry Andric   auto &TM = static_cast<const MipsTargetMachine &>(MF.getTarget());
35*4ba319b5SDimitry Andric 
36*4ba319b5SDimitry Andric   if (STI.inMips16Mode())
37*4ba319b5SDimitry Andric     return Mips::CPU16RegsRegClass;
38*4ba319b5SDimitry Andric 
39*4ba319b5SDimitry Andric   if (STI.inMicroMipsMode())
40*4ba319b5SDimitry Andric     return Mips::GPRMM16RegClass;
41*4ba319b5SDimitry Andric 
42*4ba319b5SDimitry Andric   if (TM.getABI().IsN64())
43*4ba319b5SDimitry Andric     return Mips::GPR64RegClass;
44*4ba319b5SDimitry Andric 
45*4ba319b5SDimitry Andric   return Mips::GPR32RegClass;
46*4ba319b5SDimitry Andric }
47*4ba319b5SDimitry Andric 
getGlobalBaseReg()48dff0c46cSDimitry Andric unsigned MipsFunctionInfo::getGlobalBaseReg() {
49*4ba319b5SDimitry Andric   if (!GlobalBaseReg)
50*4ba319b5SDimitry Andric     GlobalBaseReg =
51*4ba319b5SDimitry Andric         MF.getRegInfo().createVirtualRegister(&getGlobalBaseRegClass(MF));
52dff0c46cSDimitry Andric   return GlobalBaseReg;
53dff0c46cSDimitry Andric }
54dff0c46cSDimitry Andric 
createEhDataRegsFI()55139f7f9bSDimitry Andric void MipsFunctionInfo::createEhDataRegsFI() {
5651690af2SDimitry Andric   const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo();
57139f7f9bSDimitry Andric   for (int I = 0; I < 4; ++I) {
5851690af2SDimitry Andric     const TargetRegisterClass &RC =
59ff0cc061SDimitry Andric         static_cast<const MipsTargetMachine &>(MF.getTarget()).getABI().IsN64()
6051690af2SDimitry Andric             ? Mips::GPR64RegClass
6151690af2SDimitry Andric             : Mips::GPR32RegClass;
62139f7f9bSDimitry Andric 
6351690af2SDimitry Andric     EhDataRegFI[I] = MF.getFrameInfo().CreateStackObject(TRI.getSpillSize(RC),
6451690af2SDimitry Andric         TRI.getSpillAlignment(RC), false);
65139f7f9bSDimitry Andric   }
66139f7f9bSDimitry Andric }
67139f7f9bSDimitry Andric 
createISRRegFI()687d523365SDimitry Andric void MipsFunctionInfo::createISRRegFI() {
697d523365SDimitry Andric   // ISRs require spill slots for Status & ErrorPC Coprocessor 0 registers.
707d523365SDimitry Andric   // The current implementation only supports Mips32r2+ not Mips64rX. Status
71d88c1a5aSDimitry Andric   // is always 32 bits, ErrorPC is 32 or 64 bits dependent on architecture,
727d523365SDimitry Andric   // however Mips32r2+ is the supported architecture.
7351690af2SDimitry Andric   const TargetRegisterClass &RC = Mips::GPR32RegClass;
7451690af2SDimitry Andric   const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo();
757d523365SDimitry Andric 
767d523365SDimitry Andric   for (int I = 0; I < 2; ++I)
77d88c1a5aSDimitry Andric     ISRDataRegFI[I] = MF.getFrameInfo().CreateStackObject(
7851690af2SDimitry Andric         TRI.getSpillSize(RC), TRI.getSpillAlignment(RC), false);
797d523365SDimitry Andric }
807d523365SDimitry Andric 
isEhDataRegFI(int FI) const81139f7f9bSDimitry Andric bool MipsFunctionInfo::isEhDataRegFI(int FI) const {
82139f7f9bSDimitry Andric   return CallsEhReturn && (FI == EhDataRegFI[0] || FI == EhDataRegFI[1]
83139f7f9bSDimitry Andric                         || FI == EhDataRegFI[2] || FI == EhDataRegFI[3]);
84139f7f9bSDimitry Andric }
85139f7f9bSDimitry Andric 
isISRRegFI(int FI) const867d523365SDimitry Andric bool MipsFunctionInfo::isISRRegFI(int FI) const {
877d523365SDimitry Andric   return IsISR && (FI == ISRDataRegFI[0] || FI == ISRDataRegFI[1]);
887d523365SDimitry Andric }
callPtrInfo(const char * ES)897d523365SDimitry Andric MachinePointerInfo MipsFunctionInfo::callPtrInfo(const char *ES) {
907d523365SDimitry Andric   return MachinePointerInfo(MF.getPSVManager().getExternalSymbolCallEntry(ES));
91f785676fSDimitry Andric }
92f785676fSDimitry Andric 
callPtrInfo(const GlobalValue * GV)937d523365SDimitry Andric MachinePointerInfo MipsFunctionInfo::callPtrInfo(const GlobalValue *GV) {
947d523365SDimitry Andric   return MachinePointerInfo(MF.getPSVManager().getGlobalValueCallEntry(GV));
95f785676fSDimitry Andric }
96f785676fSDimitry Andric 
getMoveF64ViaSpillFI(const TargetRegisterClass * RC)9791bc56edSDimitry Andric int MipsFunctionInfo::getMoveF64ViaSpillFI(const TargetRegisterClass *RC) {
9851690af2SDimitry Andric   const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo();
9991bc56edSDimitry Andric   if (MoveF64ViaSpillFI == -1) {
100d88c1a5aSDimitry Andric     MoveF64ViaSpillFI = MF.getFrameInfo().CreateStackObject(
10151690af2SDimitry Andric         TRI.getSpillSize(*RC), TRI.getSpillAlignment(*RC), false);
10291bc56edSDimitry Andric   }
10391bc56edSDimitry Andric   return MoveF64ViaSpillFI;
10491bc56edSDimitry Andric }
10591bc56edSDimitry Andric 
anchor()106dff0c46cSDimitry Andric void MipsFunctionInfo::anchor() {}
107