//===- XtensaRegisterInfo.cpp - Xtensa Register Information ---------------===// // // 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 // //===----------------------------------------------------------------------===// // // This file contains the Xtensa implementation of the TargetRegisterInfo class. // //===----------------------------------------------------------------------===// #include "XtensaRegisterInfo.h" #include "XtensaInstrInfo.h" #include "XtensaSubtarget.h" #include "XtensaUtils.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" #define DEBUG_TYPE "xtensa-reg-info" #define GET_REGINFO_TARGET_DESC #include "XtensaGenRegisterInfo.inc" using namespace llvm; XtensaRegisterInfo::XtensaRegisterInfo(const XtensaSubtarget &STI) : XtensaGenRegisterInfo(Xtensa::A0), Subtarget(STI) {} const uint16_t * XtensaRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const { return CSR_Xtensa_SaveList; } const uint32_t * XtensaRegisterInfo::getCallPreservedMask(const MachineFunction &MF, CallingConv::ID) const { return CSR_Xtensa_RegMask; } BitVector XtensaRegisterInfo::getReservedRegs(const MachineFunction &MF) const { BitVector Reserved(getNumRegs()); const TargetFrameLowering *TFI = MF.getSubtarget().getFrameLowering(); Reserved.set(Xtensa::A0); if (TFI->hasFP(MF)) { // Reserve frame pointer. Reserved.set(getFrameRegister(MF)); } // Reserve stack pointer. Reserved.set(Xtensa::SP); return Reserved; } bool XtensaRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj, unsigned FIOperandNum, RegScavenger *RS) const { MachineInstr &MI = *II; MachineFunction &MF = *MI.getParent()->getParent(); int FrameIndex = MI.getOperand(FIOperandNum).getIndex(); uint64_t StackSize = MF.getFrameInfo().getStackSize(); int64_t SPOffset = MF.getFrameInfo().getObjectOffset(FrameIndex); MachineFrameInfo &MFI = MF.getFrameInfo(); const std::vector &CSI = MFI.getCalleeSavedInfo(); int MinCSFI = 0; int MaxCSFI = -1; if (CSI.size()) { MinCSFI = CSI[0].getFrameIdx(); MaxCSFI = CSI[CSI.size() - 1].getFrameIdx(); } // The following stack frame objects are always referenced relative to $sp: // 1. Outgoing arguments. // 2. Pointer to dynamically allocated stack space. // 3. Locations for callee-saved registers. // 4. Locations for eh data registers. // Everything else is referenced relative to whatever register // getFrameRegister() returns. unsigned FrameReg; if ((FrameIndex >= MinCSFI && FrameIndex <= MaxCSFI)) FrameReg = Xtensa::SP; else FrameReg = getFrameRegister(MF); // Calculate final offset. // - There is no need to change the offset if the frame object is one of the // following: an outgoing argument, pointer to a dynamically allocated // stack space or a $gp restore location, // - If the frame object is any of the following, its offset must be adjusted // by adding the size of the stack: // incoming argument, callee-saved register location or local variable. bool IsKill = false; int64_t Offset = SPOffset + (int64_t)StackSize + MI.getOperand(FIOperandNum + 1).getImm(); bool Valid = isValidAddrOffset(MI, Offset); // If MI is not a debug value, make sure Offset fits in the 16-bit immediate // field. if (!MI.isDebugValue() && !Valid) { MachineBasicBlock &MBB = *MI.getParent(); DebugLoc DL = II->getDebugLoc(); unsigned ADD = Xtensa::ADD; unsigned Reg; const XtensaInstrInfo &TII = *static_cast( MBB.getParent()->getSubtarget().getInstrInfo()); TII.loadImmediate(MBB, II, &Reg, Offset); BuildMI(MBB, II, DL, TII.get(ADD), Reg) .addReg(FrameReg) .addReg(Reg, RegState::Kill); FrameReg = Reg; Offset = 0; IsKill = true; } MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg, false, false, IsKill); MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset); return false; } Register XtensaRegisterInfo::getFrameRegister(const MachineFunction &MF) const { const TargetFrameLowering *TFI = MF.getSubtarget().getFrameLowering(); return TFI->hasFP(MF) ? Xtensa::A15 : Xtensa::SP; }