| //===-- M68kRegisterInfo.cpp - CPU0 Register Information -----*- C++ -*--===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| /// |
| /// \file |
| /// This file contains the CPU0 implementation of the TargetRegisterInfo class. |
| /// |
| //===----------------------------------------------------------------------===// |
| |
| #include "M68kRegisterInfo.h" |
| |
| #include "M68k.h" |
| #include "M68kMachineFunction.h" |
| #include "M68kSubtarget.h" |
| |
| #include "MCTargetDesc/M68kMCTargetDesc.h" |
| |
| #include "llvm/CodeGen/MachineRegisterInfo.h" |
| #include "llvm/IR/Function.h" |
| #include "llvm/IR/Type.h" |
| #include "llvm/Support/CommandLine.h" |
| #include "llvm/Support/Debug.h" |
| #include "llvm/Support/ErrorHandling.h" |
| #include "llvm/Support/raw_ostream.h" |
| |
| #define GET_REGINFO_TARGET_DESC |
| #include "M68kGenRegisterInfo.inc" |
| |
| #define DEBUG_TYPE "m68k-reg-info" |
| |
| using namespace llvm; |
| |
| static cl::opt<bool> EnableBasePointer( |
| "m68k-use-base-pointer", cl::Hidden, cl::init(true), |
| cl::desc("Enable use of a base pointer for complex stack frames")); |
| |
| // Pin the vtable to this file. |
| void M68kRegisterInfo::anchor() {} |
| |
| M68kRegisterInfo::M68kRegisterInfo(const M68kSubtarget &ST) |
| // FIXME x26 not sure it this the correct value, it expects RA, but M68k |
| // passes IP anyway, how this works? |
| : M68kGenRegisterInfo(M68k::A0, 0, 0, M68k::PC), Subtarget(ST) { |
| StackPtr = M68k::SP; |
| FramePtr = M68k::A6; |
| GlobalBasePtr = M68k::A5; |
| BasePtr = M68k::A4; |
| } |
| |
| //===----------------------------------------------------------------------===// |
| // Callee Saved Registers methods |
| //===----------------------------------------------------------------------===// |
| |
| const MCPhysReg * |
| M68kRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const { |
| return CSR_STD_SaveList; |
| } |
| |
| const uint32_t * |
| M68kRegisterInfo::getCallPreservedMask(const MachineFunction &MF, |
| CallingConv::ID) const { |
| return CSR_STD_RegMask; |
| } |
| |
| const TargetRegisterClass * |
| M68kRegisterInfo::getRegsForTailCall(const MachineFunction &MF) const { |
| return &M68k::XR32_TCRegClass; |
| } |
| |
| unsigned |
| M68kRegisterInfo::getMatchingMegaReg(unsigned Reg, |
| const TargetRegisterClass *RC) const { |
| for (MCSuperRegIterator Super(Reg, this); Super.isValid(); ++Super) |
| if (RC->contains(*Super)) |
| return *Super; |
| return 0; |
| } |
| |
| const TargetRegisterClass * |
| M68kRegisterInfo::getMaximalPhysRegClass(unsigned reg, MVT VT) const { |
| assert(Register::isPhysicalRegister(reg) && |
| "reg must be a physical register"); |
| |
| // Pick the most sub register class of the right type that contains |
| // this physreg. |
| const TargetRegisterClass *BestRC = nullptr; |
| for (regclass_iterator I = regclass_begin(), E = regclass_end(); I != E; |
| ++I) { |
| const TargetRegisterClass *RC = *I; |
| if ((VT == MVT::Other || isTypeLegalForClass(*RC, VT)) && |
| RC->contains(reg) && |
| (!BestRC || |
| (BestRC->hasSubClass(RC) && RC->getNumRegs() > BestRC->getNumRegs()))) |
| BestRC = RC; |
| } |
| |
| assert(BestRC && "Couldn't find the register class"); |
| return BestRC; |
| } |
| |
| int M68kRegisterInfo::getRegisterOrder(unsigned Reg, |
| const TargetRegisterClass &TRC) const { |
| for (unsigned i = 0; i < TRC.getNumRegs(); ++i) { |
| if (regsOverlap(Reg, TRC.getRegister(i))) { |
| return i; |
| } |
| } |
| return -1; |
| } |
| |
| int M68kRegisterInfo::getSpillRegisterOrder(unsigned Reg) const { |
| int Result = getRegisterOrder(Reg, *getRegClass(M68k::SPILLRegClassID)); |
| assert(Result >= 0 && "Can not determine spill order"); |
| return Result; |
| } |
| |
| BitVector M68kRegisterInfo::getReservedRegs(const MachineFunction &MF) const { |
| const M68kFrameLowering *TFI = getFrameLowering(MF); |
| |
| BitVector Reserved(getNumRegs()); |
| |
| // Set a register's and its sub-registers and aliases as reserved. |
| auto setBitVector = [&Reserved, this](unsigned Reg) { |
| for (MCRegAliasIterator I(Reg, this, /* self */ true); I.isValid(); ++I) { |
| Reserved.set(*I); |
| } |
| for (MCSubRegIterator I(Reg, this, /* self */ true); I.isValid(); ++I) { |
| Reserved.set(*I); |
| } |
| }; |
| |
| // Registers reserved by users |
| for (size_t Reg = 0, Total = getNumRegs(); Reg != Total; ++Reg) { |
| if (MF.getSubtarget<M68kSubtarget>().isRegisterReservedByUser(Reg)) |
| setBitVector(Reg); |
| } |
| |
| setBitVector(M68k::PC); |
| setBitVector(M68k::SP); |
| |
| if (TFI->hasFP(MF)) { |
| setBitVector(FramePtr); |
| } |
| |
| // Set the base-pointer register and its aliases as reserved if needed. |
| if (hasBasePointer(MF)) { |
| CallingConv::ID CC = MF.getFunction().getCallingConv(); |
| const uint32_t *RegMask = getCallPreservedMask(MF, CC); |
| if (MachineOperand::clobbersPhysReg(RegMask, getBaseRegister())) |
| report_fatal_error("Stack realignment in presence of dynamic allocas is " |
| "not supported with" |
| "this calling convention."); |
| |
| setBitVector(getBaseRegister()); |
| } |
| |
| return Reserved; |
| } |
| |
| void M68kRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, |
| int SPAdj, unsigned FIOperandNum, |
| RegScavenger *RS) const { |
| MachineInstr &MI = *II; |
| MachineFunction &MF = *MI.getParent()->getParent(); |
| const M68kFrameLowering *TFI = getFrameLowering(MF); |
| |
| // We have either (i,An,Rn) or (i,An) EA form |
| // NOTE Base contains the FI and we need to backtrace a bit to get Disp |
| MachineOperand &Disp = MI.getOperand(FIOperandNum - 1); |
| MachineOperand &Base = MI.getOperand(FIOperandNum); |
| |
| int Imm = (int)(Disp.getImm()); |
| int FIndex = (int)(Base.getIndex()); |
| |
| // FIXME tail call: implement jmp from mem |
| bool AfterFPPop = false; |
| |
| unsigned BasePtr; |
| if (hasBasePointer(MF)) |
| BasePtr = (FIndex < 0 ? FramePtr : getBaseRegister()); |
| else if (hasStackRealignment(MF)) |
| BasePtr = (FIndex < 0 ? FramePtr : StackPtr); |
| else if (AfterFPPop) |
| BasePtr = StackPtr; |
| else |
| BasePtr = (TFI->hasFP(MF) ? FramePtr : StackPtr); |
| |
| Base.ChangeToRegister(BasePtr, false); |
| |
| // Now add the frame object offset to the offset from FP. |
| int64_t FIOffset; |
| Register IgnoredFrameReg; |
| if (AfterFPPop) { |
| // Tail call jmp happens after FP is popped. |
| const MachineFrameInfo &MFI = MF.getFrameInfo(); |
| FIOffset = MFI.getObjectOffset(FIndex) - TFI->getOffsetOfLocalArea(); |
| } else { |
| FIOffset = |
| TFI->getFrameIndexReference(MF, FIndex, IgnoredFrameReg).getFixed(); |
| } |
| |
| if (BasePtr == StackPtr) |
| FIOffset += SPAdj; |
| |
| Disp.ChangeToImmediate(FIOffset + Imm); |
| } |
| |
| bool M68kRegisterInfo::requiresRegisterScavenging( |
| const MachineFunction &MF) const { |
| return true; |
| } |
| |
| bool M68kRegisterInfo::trackLivenessAfterRegAlloc( |
| const MachineFunction &MF) const { |
| return true; |
| } |
| |
| static bool CantUseSP(const MachineFrameInfo &MFI) { |
| return MFI.hasVarSizedObjects() || MFI.hasOpaqueSPAdjustment(); |
| } |
| |
| bool M68kRegisterInfo::hasBasePointer(const MachineFunction &MF) const { |
| const MachineFrameInfo &MFI = MF.getFrameInfo(); |
| |
| if (!EnableBasePointer) |
| return false; |
| |
| // When we need stack realignment, we can't address the stack from the frame |
| // pointer. When we have dynamic allocas or stack-adjusting inline asm, we |
| // can't address variables from the stack pointer. MS inline asm can |
| // reference locals while also adjusting the stack pointer. When we can't |
| // use both the SP and the FP, we need a separate base pointer register. |
| bool CantUseFP = hasStackRealignment(MF); |
| return CantUseFP && CantUseSP(MFI); |
| } |
| |
| bool M68kRegisterInfo::canRealignStack(const MachineFunction &MF) const { |
| if (!TargetRegisterInfo::canRealignStack(MF)) |
| return false; |
| |
| const MachineFrameInfo &MFI = MF.getFrameInfo(); |
| const MachineRegisterInfo *MRI = &MF.getRegInfo(); |
| |
| // Stack realignment requires a frame pointer. If we already started |
| // register allocation with frame pointer elimination, it is too late now. |
| if (!MRI->canReserveReg(FramePtr)) |
| return false; |
| |
| // If a base pointer is necessary. Check that it isn't too late to reserve it. |
| if (CantUseSP(MFI)) |
| return MRI->canReserveReg(BasePtr); |
| |
| return true; |
| } |
| |
| Register M68kRegisterInfo::getFrameRegister(const MachineFunction &MF) const { |
| const TargetFrameLowering *TFI = MF.getSubtarget().getFrameLowering(); |
| return TFI->hasFP(MF) ? FramePtr : StackPtr; |
| } |
| |
| const TargetRegisterClass *M68kRegisterInfo::intRegClass(unsigned size) const { |
| return &M68k::DR32RegClass; |
| } |