//===-- CSKYFrameLowering.cpp - CSKY Frame 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 CSKY implementation of TargetFrameLowering class.
//
//===----------------------------------------------------------------------===//

#include "CSKYFrameLowering.h"
#include "CSKYMachineFunctionInfo.h"
#include "CSKYSubtarget.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/RegisterScavenging.h"
#include "llvm/IR/DiagnosticInfo.h"
#include "llvm/MC/MCDwarf.h"

using namespace llvm;

#define DEBUG_TYPE "csky-frame-lowering"

// Returns the register used to hold the frame pointer.
static Register getFPReg(const CSKYSubtarget &STI) { return CSKY::R8; }

// To avoid the BP value clobbered by a function call, we need to choose a
// callee saved register to save the value.
static Register getBPReg(const CSKYSubtarget &STI) { return CSKY::R7; }

bool CSKYFrameLowering::hasFP(const MachineFunction &MF) const {
  const TargetRegisterInfo *RegInfo = MF.getSubtarget().getRegisterInfo();

  const MachineFrameInfo &MFI = MF.getFrameInfo();
  return MF.getTarget().Options.DisableFramePointerElim(MF) ||
         RegInfo->hasStackRealignment(MF) || MFI.hasVarSizedObjects() ||
         MFI.isFrameAddressTaken();
}

bool CSKYFrameLowering::hasBP(const MachineFunction &MF) const {
  const MachineFrameInfo &MFI = MF.getFrameInfo();

  return MFI.hasVarSizedObjects();
}

// Determines the size of the frame and maximum call frame size.
void CSKYFrameLowering::determineFrameLayout(MachineFunction &MF) const {
  MachineFrameInfo &MFI = MF.getFrameInfo();
  const CSKYRegisterInfo *RI = STI.getRegisterInfo();

  // Get the number of bytes to allocate from the FrameInfo.
  uint64_t FrameSize = MFI.getStackSize();

  // Get the alignment.
  Align StackAlign = getStackAlign();
  if (RI->hasStackRealignment(MF)) {
    Align MaxStackAlign = std::max(StackAlign, MFI.getMaxAlign());
    FrameSize += (MaxStackAlign.value() - StackAlign.value());
    StackAlign = MaxStackAlign;
  }

  // Set Max Call Frame Size
  uint64_t MaxCallSize = alignTo(MFI.getMaxCallFrameSize(), StackAlign);
  MFI.setMaxCallFrameSize(MaxCallSize);

  // Make sure the frame is aligned.
  FrameSize = alignTo(FrameSize, StackAlign);

  // Update frame info.
  MFI.setStackSize(FrameSize);
}

void CSKYFrameLowering::emitPrologue(MachineFunction &MF,
                                     MachineBasicBlock &MBB) const {
  CSKYMachineFunctionInfo *CFI = MF.getInfo<CSKYMachineFunctionInfo>();
  MachineFrameInfo &MFI = MF.getFrameInfo();
  const CSKYRegisterInfo *RI = STI.getRegisterInfo();
  const CSKYInstrInfo *TII = STI.getInstrInfo();
  MachineBasicBlock::iterator MBBI = MBB.begin();
  const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
  const MachineRegisterInfo &MRI = MF.getRegInfo();

  Register FPReg = getFPReg(STI);
  Register SPReg = CSKY::R14;
  Register BPReg = getBPReg(STI);

  // Debug location must be unknown since the first debug location is used
  // to determine the end of the prologue.
  DebugLoc DL;

  if (MF.getFunction().hasFnAttribute("interrupt"))
    BuildMI(MBB, MBBI, DL, TII->get(CSKY::NIE));

  // Determine the correct frame layout
  determineFrameLayout(MF);

  // FIXME (note copied from Lanai): This appears to be overallocating.  Needs
  // investigation. Get the number of bytes to allocate from the FrameInfo.
  uint64_t StackSize = MFI.getStackSize();

  // Early exit if there is no need to allocate on the stack
  if (StackSize == 0 && !MFI.adjustsStack())
    return;

  const auto &CSI = MFI.getCalleeSavedInfo();

  unsigned spillAreaSize = CFI->getCalleeSaveAreaSize();

  uint64_t ActualSize = spillAreaSize + CFI->getVarArgsSaveSize();

  // First part stack allocation.
  adjustReg(MBB, MBBI, DL, SPReg, SPReg, -(static_cast<int64_t>(ActualSize)),
            MachineInstr::NoFlags);

  // Emit ".cfi_def_cfa_offset FirstSPAdjustAmount"
  unsigned CFIIndex =
      MF.addFrameInst(MCCFIInstruction::cfiDefCfaOffset(nullptr, ActualSize));
  BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION))
      .addCFIIndex(CFIIndex);

  // The frame pointer is callee-saved, and code has been generated for us to
  // save it to the stack. We need to skip over the storing of callee-saved
  // registers as the frame pointer must be modified after it has been saved
  // to the stack, not before.
  // FIXME: assumes exactly one instruction is used to save each callee-saved
  // register.
  std::advance(MBBI, CSI.size());

  // Iterate over list of callee-saved registers and emit .cfi_offset
  // directives.
  for (const auto &Entry : CSI) {
    int64_t Offset = MFI.getObjectOffset(Entry.getFrameIdx());
    Register Reg = Entry.getReg();

    unsigned Num = TRI->getRegSizeInBits(Reg, MRI) / 32;
    for (unsigned i = 0; i < Num; i++) {
      unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset(
          nullptr, RI->getDwarfRegNum(Reg, true) + i, Offset + i * 4));
      BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION))
          .addCFIIndex(CFIIndex);
    }
  }

  // Generate new FP.
  if (hasFP(MF)) {
    BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::COPY), FPReg)
        .addReg(SPReg)
        .setMIFlag(MachineInstr::FrameSetup);

    // Emit ".cfi_def_cfa_register $fp"
    unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createDefCfaRegister(
        nullptr, RI->getDwarfRegNum(FPReg, true)));
    BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION))
        .addCFIIndex(CFIIndex);

    // Second part stack allocation.
    adjustReg(MBB, MBBI, DL, SPReg, SPReg,
              -(static_cast<int64_t>(StackSize - ActualSize)),
              MachineInstr::NoFlags);

    // Realign Stack
    const CSKYRegisterInfo *RI = STI.getRegisterInfo();
    if (RI->hasStackRealignment(MF)) {
      Align MaxAlignment = MFI.getMaxAlign();

      const CSKYInstrInfo *TII = STI.getInstrInfo();
      if (STI.hasE2() && isUInt<12>(~(-(int)MaxAlignment.value()))) {
        BuildMI(MBB, MBBI, DL, TII->get(CSKY::ANDNI32), SPReg)
            .addReg(SPReg)
            .addImm(~(-(int)MaxAlignment.value()));
      } else {
        unsigned ShiftAmount = Log2(MaxAlignment);

        if (STI.hasE2()) {
          Register VR =
              MF.getRegInfo().createVirtualRegister(&CSKY::GPRRegClass);
          BuildMI(MBB, MBBI, DL, TII->get(CSKY::LSRI32), VR)
              .addReg(SPReg)
              .addImm(ShiftAmount);
          BuildMI(MBB, MBBI, DL, TII->get(CSKY::LSLI32), SPReg)
              .addReg(VR)
              .addImm(ShiftAmount);
        } else {
          Register VR =
              MF.getRegInfo().createVirtualRegister(&CSKY::mGPRRegClass);
          BuildMI(MBB, MBBI, DL, TII->get(CSKY::MOV16), VR).addReg(SPReg);
          BuildMI(MBB, MBBI, DL, TII->get(CSKY::LSRI16), VR)
              .addReg(VR)
              .addImm(ShiftAmount);
          BuildMI(MBB, MBBI, DL, TII->get(CSKY::LSLI16), VR)
              .addReg(VR)
              .addImm(ShiftAmount);
          BuildMI(MBB, MBBI, DL, TII->get(CSKY::MOV16), SPReg).addReg(VR);
        }
      }
    }

    // FP will be used to restore the frame in the epilogue, so we need
    // another base register BP to record SP after re-alignment. SP will
    // track the current stack after allocating variable sized objects.
    if (hasBP(MF)) {
      // move BP, SP
      BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::COPY), BPReg).addReg(SPReg);
    }

  } else {
    adjustReg(MBB, MBBI, DL, SPReg, SPReg,
              -(static_cast<int64_t>(StackSize - ActualSize)),
              MachineInstr::NoFlags);
    // Emit ".cfi_def_cfa_offset StackSize"
    unsigned CFIIndex = MF.addFrameInst(
        MCCFIInstruction::cfiDefCfaOffset(nullptr, MFI.getStackSize()));
    BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION))
        .addCFIIndex(CFIIndex);
  }
}

void CSKYFrameLowering::emitEpilogue(MachineFunction &MF,
                                     MachineBasicBlock &MBB) const {
  CSKYMachineFunctionInfo *CFI = MF.getInfo<CSKYMachineFunctionInfo>();

  MachineFrameInfo &MFI = MF.getFrameInfo();
  Register FPReg = getFPReg(STI);
  Register SPReg = CSKY::R14;

  // Get the insert location for the epilogue. If there were no terminators in
  // the block, get the last instruction.
  MachineBasicBlock::iterator MBBI = MBB.end();
  DebugLoc DL;
  if (!MBB.empty()) {
    MBBI = MBB.getFirstTerminator();
    if (MBBI == MBB.end())
      MBBI = MBB.getLastNonDebugInstr();
    DL = MBBI->getDebugLoc();

    // If this is not a terminator, the actual insert location should be after
    // the last instruction.
    if (!MBBI->isTerminator())
      MBBI = std::next(MBBI);
  }

  const auto &CSI = MFI.getCalleeSavedInfo();
  uint64_t StackSize = MFI.getStackSize();

  uint64_t ActualSize =
      CFI->getCalleeSaveAreaSize() + CFI->getVarArgsSaveSize();

  // Skip to before the restores of callee-saved registers
  // FIXME: assumes exactly one instruction is used to restore each
  // callee-saved register.
  auto LastFrameDestroy = MBBI;
  if (!CSI.empty())
    LastFrameDestroy = std::prev(MBBI, CSI.size());

  if (hasFP(MF)) {
    const CSKYInstrInfo *TII = STI.getInstrInfo();
    BuildMI(MBB, LastFrameDestroy, DL, TII->get(TargetOpcode::COPY), SPReg)
        .addReg(FPReg)
        .setMIFlag(MachineInstr::NoFlags);
  } else {
    adjustReg(MBB, LastFrameDestroy, DL, SPReg, SPReg, (StackSize - ActualSize),
              MachineInstr::FrameDestroy);
  }

  adjustReg(MBB, MBBI, DL, SPReg, SPReg, ActualSize,
            MachineInstr::FrameDestroy);
}

static unsigned estimateRSStackSizeLimit(MachineFunction &MF,
                                         const CSKYSubtarget &STI) {
  unsigned Limit = (1 << 12) - 1;

  for (auto &MBB : MF) {
    for (auto &MI : MBB) {
      if (MI.isDebugInstr())
        continue;

      for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) {
        if (!MI.getOperand(i).isFI())
          continue;

        if (MI.getOpcode() == CSKY::SPILL_CARRY ||
            MI.getOpcode() == CSKY::RESTORE_CARRY ||
            MI.getOpcode() == CSKY::STORE_PAIR ||
            MI.getOpcode() == CSKY::LOAD_PAIR) {
          Limit = std::min(Limit, ((1U << 12) - 1) * 4);
          break;
        }

        if (MI.getOpcode() == CSKY::ADDI32) {
          Limit = std::min(Limit, (1U << 12));
          break;
        }

        if (MI.getOpcode() == CSKY::ADDI16XZ) {
          Limit = std::min(Limit, (1U << 3));
          break;
        }

        // ADDI16 will not require an extra register,
        // it can reuse the destination.
        if (MI.getOpcode() == CSKY::ADDI16)
          break;

        // Otherwise check the addressing mode.
        switch (MI.getDesc().TSFlags & CSKYII::AddrModeMask) {
        default:
          LLVM_DEBUG(MI.dump());
          llvm_unreachable(
              "Unhandled addressing mode in stack size limit calculation");
        case CSKYII::AddrMode32B:
          Limit = std::min(Limit, (1U << 12) - 1);
          break;
        case CSKYII::AddrMode32H:
          Limit = std::min(Limit, ((1U << 12) - 1) * 2);
          break;
        case CSKYII::AddrMode32WD:
          Limit = std::min(Limit, ((1U << 12) - 1) * 4);
          break;
        case CSKYII::AddrMode16B:
          Limit = std::min(Limit, (1U << 5) - 1);
          break;
        case CSKYII::AddrMode16H:
          Limit = std::min(Limit, ((1U << 5) - 1) * 2);
          break;
        case CSKYII::AddrMode16W:
          Limit = std::min(Limit, ((1U << 5) - 1) * 4);
          break;
        case CSKYII::AddrMode32SDF:
          Limit = std::min(Limit, ((1U << 8) - 1) * 4);
          break;
        }
        break; // At most one FI per instruction
      }
    }
  }

  return Limit;
}

void CSKYFrameLowering::determineCalleeSaves(MachineFunction &MF,
                                             BitVector &SavedRegs,
                                             RegScavenger *RS) const {
  TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS);

  CSKYMachineFunctionInfo *CFI = MF.getInfo<CSKYMachineFunctionInfo>();
  const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
  const MachineRegisterInfo &MRI = MF.getRegInfo();
  MachineFrameInfo &MFI = MF.getFrameInfo();

  if (hasFP(MF))
    SavedRegs.set(CSKY::R8);

  // Mark BP as used if function has dedicated base pointer.
  if (hasBP(MF))
    SavedRegs.set(CSKY::R7);

  // If interrupt is enabled and there are calls in the handler,
  // unconditionally save all Caller-saved registers and
  // all FP registers, regardless whether they are used.
  if (MF.getFunction().hasFnAttribute("interrupt") && MFI.hasCalls()) {

    static const MCPhysReg CSRegs[] = {CSKY::R0,  CSKY::R1,  CSKY::R2, CSKY::R3,
                                       CSKY::R12, CSKY::R13, 0};

    for (unsigned i = 0; CSRegs[i]; ++i)
      SavedRegs.set(CSRegs[i]);

    if (STI.hasHighRegisters()) {

      static const MCPhysReg CSHRegs[] = {CSKY::R18, CSKY::R19, CSKY::R20,
                                          CSKY::R21, CSKY::R22, CSKY::R23,
                                          CSKY::R24, CSKY::R25, 0};

      for (unsigned i = 0; CSHRegs[i]; ++i)
        SavedRegs.set(CSHRegs[i]);
    }

    static const MCPhysReg CSF32Regs[] = {
        CSKY::F8_32,  CSKY::F9_32,  CSKY::F10_32,
        CSKY::F11_32, CSKY::F12_32, CSKY::F13_32,
        CSKY::F14_32, CSKY::F15_32, 0};
    static const MCPhysReg CSF64Regs[] = {
        CSKY::F8_64,  CSKY::F9_64,  CSKY::F10_64,
        CSKY::F11_64, CSKY::F12_64, CSKY::F13_64,
        CSKY::F14_64, CSKY::F15_64, 0};

    const MCPhysReg *FRegs = NULL;
    if (STI.hasFPUv2DoubleFloat() || STI.hasFPUv3DoubleFloat())
      FRegs = CSF64Regs;
    else if (STI.hasFPUv2SingleFloat() || STI.hasFPUv3SingleFloat())
      FRegs = CSF32Regs;

    if (FRegs != NULL) {
      const MCPhysReg *Regs = MF.getRegInfo().getCalleeSavedRegs();

      for (unsigned i = 0; Regs[i]; ++i)
        if (CSKY::FPR32RegClass.contains(Regs[i]) ||
            CSKY::FPR64RegClass.contains(Regs[i])) {
          unsigned x = 0;
          for (; FRegs[x]; ++x)
            if (FRegs[x] == Regs[i])
              break;
          if (FRegs[x] == 0)
            SavedRegs.set(Regs[i]);
        }
    }
  }

  CFI->setLRIsSpilled(SavedRegs.test(CSKY::R15));

  unsigned CSStackSize = 0;
  for (unsigned Reg : SavedRegs.set_bits()) {
    auto RegSize = TRI->getRegSizeInBits(Reg, MRI) / 8;
    CSStackSize += RegSize;
  }

  CFI->setCalleeSaveAreaSize(CSStackSize);

  uint64_t Limit = estimateRSStackSizeLimit(MF, STI);

  bool BigFrame = (MFI.estimateStackSize(MF) + CSStackSize >= Limit);

  if (BigFrame || CFI->isCRSpilled() || !STI.hasE2()) {
    const TargetRegisterClass *RC = &CSKY::GPRRegClass;
    unsigned size = TRI->getSpillSize(*RC);
    Align align = TRI->getSpillAlign(*RC);

    RS->addScavengingFrameIndex(MFI.CreateStackObject(size, align, false));
  }
}

// Not preserve stack space within prologue for outgoing variables when the
// function contains variable size objects and let eliminateCallFramePseudoInstr
// preserve stack space for it.
bool CSKYFrameLowering::hasReservedCallFrame(const MachineFunction &MF) const {
  return !MF.getFrameInfo().hasVarSizedObjects();
}

bool CSKYFrameLowering::spillCalleeSavedRegisters(
    MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
    ArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const {
  if (CSI.empty())
    return true;

  MachineFunction *MF = MBB.getParent();
  const TargetInstrInfo &TII = *MF->getSubtarget().getInstrInfo();
  DebugLoc DL;
  if (MI != MBB.end() && !MI->isDebugInstr())
    DL = MI->getDebugLoc();

  for (auto &CS : CSI) {
    // Insert the spill to the stack frame.
    Register Reg = CS.getReg();
    const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg);
    TII.storeRegToStackSlot(MBB, MI, Reg, true, CS.getFrameIdx(), RC, TRI);
  }

  return true;
}

bool CSKYFrameLowering::restoreCalleeSavedRegisters(
    MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
    MutableArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const {
  if (CSI.empty())
    return true;

  MachineFunction *MF = MBB.getParent();
  const TargetInstrInfo &TII = *MF->getSubtarget().getInstrInfo();
  DebugLoc DL;
  if (MI != MBB.end() && !MI->isDebugInstr())
    DL = MI->getDebugLoc();

  for (auto &CS : reverse(CSI)) {
    Register Reg = CS.getReg();
    const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg);
    TII.loadRegFromStackSlot(MBB, MI, Reg, CS.getFrameIdx(), RC, TRI);
    assert(MI != MBB.begin() && "loadRegFromStackSlot didn't insert any code!");
  }

  return true;
}

// Eliminate ADJCALLSTACKDOWN, ADJCALLSTACKUP pseudo instructions.
MachineBasicBlock::iterator CSKYFrameLowering::eliminateCallFramePseudoInstr(
    MachineFunction &MF, MachineBasicBlock &MBB,
    MachineBasicBlock::iterator MI) const {
  Register SPReg = CSKY::R14;
  DebugLoc DL = MI->getDebugLoc();

  if (!hasReservedCallFrame(MF)) {
    // If space has not been reserved for a call frame, ADJCALLSTACKDOWN and
    // ADJCALLSTACKUP must be converted to instructions manipulating the stack
    // pointer. This is necessary when there is a variable length stack
    // allocation (e.g. alloca), which means it's not possible to allocate
    // space for outgoing arguments from within the function prologue.
    int64_t Amount = MI->getOperand(0).getImm();

    if (Amount != 0) {
      // Ensure the stack remains aligned after adjustment.
      Amount = alignSPAdjust(Amount);

      if (MI->getOpcode() == CSKY::ADJCALLSTACKDOWN)
        Amount = -Amount;

      adjustReg(MBB, MI, DL, SPReg, SPReg, Amount, MachineInstr::NoFlags);
    }
  }

  return MBB.erase(MI);
}

void CSKYFrameLowering::adjustReg(MachineBasicBlock &MBB,
                                  MachineBasicBlock::iterator MBBI,
                                  const DebugLoc &DL, Register DestReg,
                                  Register SrcReg, int64_t Val,
                                  MachineInstr::MIFlag Flag) const {
  const CSKYInstrInfo *TII = STI.getInstrInfo();

  if (DestReg == SrcReg && Val == 0)
    return;

  // TODO: Add 16-bit instruction support with immediate num
  if (STI.hasE2() && isUInt<12>(std::abs(Val) - 1)) {
    BuildMI(MBB, MBBI, DL, TII->get(Val < 0 ? CSKY::SUBI32 : CSKY::ADDI32),
            DestReg)
        .addReg(SrcReg)
        .addImm(std::abs(Val))
        .setMIFlag(Flag);
  } else if (!STI.hasE2() && isShiftedUInt<7, 2>(std::abs(Val))) {
    BuildMI(MBB, MBBI, DL,
            TII->get(Val < 0 ? CSKY::SUBI16SPSP : CSKY::ADDI16SPSP), CSKY::R14)
        .addReg(CSKY::R14, RegState::Kill)
        .addImm(std::abs(Val))
        .setMIFlag(Flag);
  } else {

    unsigned Op = 0;

    if (STI.hasE2()) {
      Op = Val < 0 ? CSKY::SUBU32 : CSKY::ADDU32;
    } else {
      assert(SrcReg == DestReg);
      Op = Val < 0 ? CSKY::SUBU16XZ : CSKY::ADDU16XZ;
    }

    Register ScratchReg = TII->movImm(MBB, MBBI, DL, std::abs(Val), Flag);

    BuildMI(MBB, MBBI, DL, TII->get(Op), DestReg)
        .addReg(SrcReg)
        .addReg(ScratchReg, RegState::Kill)
        .setMIFlag(Flag);
  }
}

StackOffset
CSKYFrameLowering::getFrameIndexReference(const MachineFunction &MF, int FI,
                                          Register &FrameReg) const {
  const CSKYMachineFunctionInfo *CFI = MF.getInfo<CSKYMachineFunctionInfo>();
  const MachineFrameInfo &MFI = MF.getFrameInfo();
  const TargetRegisterInfo *RI = MF.getSubtarget().getRegisterInfo();
  const auto &CSI = MFI.getCalleeSavedInfo();

  int MinCSFI = 0;
  int MaxCSFI = -1;

  int Offset = MFI.getObjectOffset(FI) + MFI.getOffsetAdjustment();

  if (CSI.size()) {
    MinCSFI = CSI[0].getFrameIdx();
    MaxCSFI = CSI[CSI.size() - 1].getFrameIdx();
  }

  if (FI >= MinCSFI && FI <= MaxCSFI) {
    FrameReg = CSKY::R14;
    Offset += CFI->getVarArgsSaveSize() + CFI->getCalleeSaveAreaSize();
  } else if (RI->hasStackRealignment(MF)) {
    assert(hasFP(MF));
    if (!MFI.isFixedObjectIndex(FI)) {
      FrameReg = hasBP(MF) ? getBPReg(STI) : CSKY::R14;
      Offset += MFI.getStackSize();
    } else {
      FrameReg = getFPReg(STI);
      Offset += CFI->getVarArgsSaveSize() + CFI->getCalleeSaveAreaSize();
    }
  } else {
    if (MFI.isFixedObjectIndex(FI) && hasFP(MF)) {
      FrameReg = getFPReg(STI);
      Offset += CFI->getVarArgsSaveSize() + CFI->getCalleeSaveAreaSize();
    } else {
      FrameReg = hasBP(MF) ? getBPReg(STI) : CSKY::R14;
      Offset += MFI.getStackSize();
    }
  }

  return StackOffset::getFixed(Offset);
}
