//===- AArch64RegisterInfo.cpp - AArch64 Register Information -------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains the AArch64 implementation of the TargetRegisterInfo
// class.
//
//===----------------------------------------------------------------------===//


#include "AArch64RegisterInfo.h"
#include "AArch64FrameLowering.h"
#include "AArch64MachineFunctionInfo.h"
#include "AArch64TargetMachine.h"
#include "MCTargetDesc/AArch64MCTargetDesc.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/RegisterScavenging.h"
#include "llvm/ADT/BitVector.h"

#define GET_REGINFO_TARGET_DESC
#include "AArch64GenRegisterInfo.inc"

using namespace llvm;

AArch64RegisterInfo::AArch64RegisterInfo(const AArch64InstrInfo &tii,
                                         const AArch64Subtarget &sti)
  : AArch64GenRegisterInfo(AArch64::X30), TII(tii) {
}

const uint16_t *
AArch64RegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
  return CSR_PCS_SaveList;
}

const uint32_t*
AArch64RegisterInfo::getCallPreservedMask(CallingConv::ID) const {
  return CSR_PCS_RegMask;
}

const uint32_t *AArch64RegisterInfo::getTLSDescCallPreservedMask() const {
  return TLSDesc_RegMask;
}

const TargetRegisterClass *
AArch64RegisterInfo::getCrossCopyRegClass(const TargetRegisterClass *RC) const {
  if (RC == &AArch64::FlagClassRegClass)
    return &AArch64::GPR64RegClass;

  return RC;
}



BitVector
AArch64RegisterInfo::getReservedRegs(const MachineFunction &MF) const {
  BitVector Reserved(getNumRegs());
  const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();

  Reserved.set(AArch64::XSP);
  Reserved.set(AArch64::WSP);

  Reserved.set(AArch64::XZR);
  Reserved.set(AArch64::WZR);

  if (TFI->hasFP(MF)) {
    Reserved.set(AArch64::X29);
    Reserved.set(AArch64::W29);
  }

  return Reserved;
}

void
AArch64RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator MBBI,
                                         int SPAdj,
                                         unsigned FIOperandNum,
                                         RegScavenger *RS) const {
  assert(SPAdj == 0 && "Cannot deal with nonzero SPAdj yet");
  MachineInstr &MI = *MBBI;
  MachineBasicBlock &MBB = *MI.getParent();
  MachineFunction &MF = *MBB.getParent();
  MachineFrameInfo *MFI = MF.getFrameInfo();
  const AArch64FrameLowering *TFI =
   static_cast<const AArch64FrameLowering *>(MF.getTarget().getFrameLowering());

  // In order to work out the base and offset for addressing, the FrameLowering
  // code needs to know (sometimes) whether the instruction is storing/loading a
  // callee-saved register, or whether it's a more generic
  // operation. Fortunately the frame indices are used *only* for that purpose
  // and are contiguous, so we can check here.
  const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo();
  int MinCSFI = 0;
  int MaxCSFI = -1;

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

  int FrameIndex = MI.getOperand(FIOperandNum).getIndex();
  bool IsCalleeSaveOp = FrameIndex >= MinCSFI && FrameIndex <= MaxCSFI;

  unsigned FrameReg;
  int64_t Offset;
  Offset = TFI->resolveFrameIndexReference(MF, FrameIndex, FrameReg, SPAdj,
                                           IsCalleeSaveOp);

  Offset += MI.getOperand(FIOperandNum + 1).getImm();

  // DBG_VALUE instructions have no real restrictions so they can be handled
  // easily.
  if (MI.isDebugValue()) {
    MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg, /*isDef=*/ false);
    MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset);
    return;
  }

  int MinOffset, MaxOffset, OffsetScale;
  if (MI.getOpcode() == AArch64::ADDxxi_lsl0_s) {
    MinOffset = 0;
    MaxOffset = 0xfff;
    OffsetScale = 1;
  } else {
    // Load/store of a stack object
    TII.getAddressConstraints(MI, OffsetScale, MinOffset, MaxOffset);
  }

  // The frame lowering has told us a base and offset it thinks we should use to
  // access this variable, but it's still up to us to make sure the values are
  // legal for the instruction in question.
  if (Offset % OffsetScale != 0 || Offset < MinOffset || Offset > MaxOffset) {
    unsigned BaseReg =
      MF.getRegInfo().createVirtualRegister(&AArch64::GPR64RegClass);
    emitRegUpdate(MBB, MBBI, MBBI->getDebugLoc(), TII,
                  BaseReg, FrameReg, BaseReg, Offset);
    FrameReg = BaseReg;
    Offset = 0;
  }

  // Negative offsets are expected if we address from FP, but for
  // now this checks nothing has gone horribly wrong.
  assert(Offset >= 0 && "Unexpected negative offset from SP");

  MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg, false, false, true);
  MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset / OffsetScale);
}

unsigned
AArch64RegisterInfo::getFrameRegister(const MachineFunction &MF) const {
  const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();

  if (TFI->hasFP(MF))
    return AArch64::X29;
  else
    return AArch64::XSP;
}

bool
AArch64RegisterInfo::useFPForScavengingIndex(const MachineFunction &MF) const {
  const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
  const AArch64FrameLowering *AFI
    = static_cast<const AArch64FrameLowering*>(TFI);
  return AFI->useFPForAddressing(MF);
}
