1//===- AArch64RegisterInfo.cpp - AArch64 Register Information -------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file contains the AArch64 implementation of the TargetRegisterInfo
11// class.
12//
13//===----------------------------------------------------------------------===//
14
15
16#include "AArch64RegisterInfo.h"
17#include "AArch64FrameLowering.h"
18#include "AArch64MachineFunctionInfo.h"
19#include "AArch64TargetMachine.h"
20#include "MCTargetDesc/AArch64MCTargetDesc.h"
21#include "llvm/CodeGen/MachineFrameInfo.h"
22#include "llvm/CodeGen/MachineInstrBuilder.h"
23#include "llvm/CodeGen/MachineRegisterInfo.h"
24#include "llvm/CodeGen/RegisterScavenging.h"
25#include "llvm/ADT/BitVector.h"
26
27#define GET_REGINFO_TARGET_DESC
28#include "AArch64GenRegisterInfo.inc"
29
30using namespace llvm;
31
32AArch64RegisterInfo::AArch64RegisterInfo()
33  : AArch64GenRegisterInfo(AArch64::X30) {
34}
35
36const uint16_t *
37AArch64RegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
38  return CSR_PCS_SaveList;
39}
40
41const uint32_t*
42AArch64RegisterInfo::getCallPreservedMask(CallingConv::ID) const {
43  return CSR_PCS_RegMask;
44}
45
46const uint32_t *AArch64RegisterInfo::getTLSDescCallPreservedMask() const {
47  return TLSDesc_RegMask;
48}
49
50const TargetRegisterClass *
51AArch64RegisterInfo::getCrossCopyRegClass(const TargetRegisterClass *RC) const {
52  if (RC == &AArch64::FlagClassRegClass)
53    return &AArch64::GPR64RegClass;
54
55  return RC;
56}
57
58
59
60BitVector
61AArch64RegisterInfo::getReservedRegs(const MachineFunction &MF) const {
62  BitVector Reserved(getNumRegs());
63  const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
64
65  Reserved.set(AArch64::XSP);
66  Reserved.set(AArch64::WSP);
67
68  Reserved.set(AArch64::XZR);
69  Reserved.set(AArch64::WZR);
70
71  if (TFI->hasFP(MF)) {
72    Reserved.set(AArch64::X29);
73    Reserved.set(AArch64::W29);
74  }
75
76  return Reserved;
77}
78
79void
80AArch64RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator MBBI,
81                                         int SPAdj,
82                                         unsigned FIOperandNum,
83                                         RegScavenger *RS) const {
84  assert(SPAdj == 0 && "Cannot deal with nonzero SPAdj yet");
85  MachineInstr &MI = *MBBI;
86  MachineBasicBlock &MBB = *MI.getParent();
87  MachineFunction &MF = *MBB.getParent();
88  MachineFrameInfo *MFI = MF.getFrameInfo();
89  const AArch64FrameLowering *TFI =
90   static_cast<const AArch64FrameLowering *>(MF.getTarget().getFrameLowering());
91
92  // In order to work out the base and offset for addressing, the FrameLowering
93  // code needs to know (sometimes) whether the instruction is storing/loading a
94  // callee-saved register, or whether it's a more generic
95  // operation. Fortunately the frame indices are used *only* for that purpose
96  // and are contiguous, so we can check here.
97  const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo();
98  int MinCSFI = 0;
99  int MaxCSFI = -1;
100
101  if (CSI.size()) {
102    MinCSFI = CSI[0].getFrameIdx();
103    MaxCSFI = CSI[CSI.size() - 1].getFrameIdx();
104  }
105
106  int FrameIndex = MI.getOperand(FIOperandNum).getIndex();
107  bool IsCalleeSaveOp = FrameIndex >= MinCSFI && FrameIndex <= MaxCSFI;
108
109  unsigned FrameReg;
110  int64_t Offset;
111  Offset = TFI->resolveFrameIndexReference(MF, FrameIndex, FrameReg, SPAdj,
112                                           IsCalleeSaveOp);
113
114  Offset += MI.getOperand(FIOperandNum + 1).getImm();
115
116  // DBG_VALUE instructions have no real restrictions so they can be handled
117  // easily.
118  if (MI.isDebugValue()) {
119    MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg, /*isDef=*/ false);
120    MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset);
121    return;
122  }
123
124  const AArch64InstrInfo &TII =
125    *static_cast<const AArch64InstrInfo*>(MF.getTarget().getInstrInfo());
126  int MinOffset, MaxOffset, OffsetScale;
127  if (MI.getOpcode() == AArch64::ADDxxi_lsl0_s) {
128    MinOffset = 0;
129    MaxOffset = 0xfff;
130    OffsetScale = 1;
131  } else {
132    // Load/store of a stack object
133    TII.getAddressConstraints(MI, OffsetScale, MinOffset, MaxOffset);
134  }
135
136  // The frame lowering has told us a base and offset it thinks we should use to
137  // access this variable, but it's still up to us to make sure the values are
138  // legal for the instruction in question.
139  if (Offset % OffsetScale != 0 || Offset < MinOffset || Offset > MaxOffset) {
140    unsigned BaseReg =
141      MF.getRegInfo().createVirtualRegister(&AArch64::GPR64RegClass);
142    emitRegUpdate(MBB, MBBI, MBBI->getDebugLoc(), TII,
143                  BaseReg, FrameReg, BaseReg, Offset);
144    FrameReg = BaseReg;
145    Offset = 0;
146  }
147
148  // Negative offsets are expected if we address from FP, but for
149  // now this checks nothing has gone horribly wrong.
150  assert(Offset >= 0 && "Unexpected negative offset from SP");
151
152  MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg, false, false, true);
153  MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset / OffsetScale);
154}
155
156unsigned
157AArch64RegisterInfo::getFrameRegister(const MachineFunction &MF) const {
158  const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
159
160  if (TFI->hasFP(MF))
161    return AArch64::X29;
162  else
163    return AArch64::XSP;
164}
165
166bool
167AArch64RegisterInfo::useFPForScavengingIndex(const MachineFunction &MF) const {
168  const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
169  const AArch64FrameLowering *AFI
170    = static_cast<const AArch64FrameLowering*>(TFI);
171  return AFI->useFPForAddressing(MF);
172}
173