//===-- 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/MachineConstantPool.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::hasFPImpl(const MachineFunction &MF) const {
  const TargetRegisterInfo *RegInfo = MF.getSubtarget().getRegisterInfo();

  const MachineFrameInfo &MFI = MF.getFrameInfo();
  return MF.disableFramePointerElim() || 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());
    MCRegister 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 EstimateFunctionSizeInBytes(const MachineFunction &MF,
                                            const CSKYInstrInfo &TII) {
  unsigned FnSize = 0;
  for (auto &MBB : MF) {
    for (auto &MI : MBB)
      FnSize += TII.getInstSizeInBytes(MI);
  }
  FnSize += MF.getConstantPool()->getConstants().size() * 4;
  return FnSize;
}

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 CSKYInstrInfo *TII = STI.getInstrInfo();
  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]);
        }
    }
  }

  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.CreateSpillStackObject(size, align));
  }

  unsigned FnSize = EstimateFunctionSizeInBytes(MF, *TII);
  // Force R15 to be spilled if the function size is > 65534. This enables
  // use of BSR to implement far jump.
  if (FnSize >= ((1 << (16 - 1)) * 2))
    SavedRegs.set(CSKY::R15);

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

// 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.
    MCRegister Reg = CS.getReg();
    const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg);
    TII.storeRegToStackSlot(MBB, MI, Reg, true, CS.getFrameIdx(), RC,
                            Register());
  }

  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)) {
    MCRegister Reg = CS.getReg();
    const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg);
    TII.loadRegFromStackSlot(MBB, MI, Reg, CS.getFrameIdx(), RC, Register());
    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);
}
