//===-- 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. /// //===----------------------------------------------------------------------===// #define DEBUG_TYPE "m68k-reg-info" #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" using namespace llvm; static cl::opt 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); } }; 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; }