Prologue / epilogue emission
[oota-llvm.git] / lib / Target / SystemZ / SystemZRegisterInfo.cpp
1 //===- SystemZRegisterInfo.cpp - SystemZ Register Information -------*- C++ -*-===//
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 SystemZ implementation of the TargetRegisterInfo class.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "SystemZ.h"
15 #include "SystemZRegisterInfo.h"
16 #include "SystemZSubtarget.h"
17 #include "llvm/CodeGen/MachineInstrBuilder.h"
18 #include "llvm/CodeGen/MachineFrameInfo.h"
19 #include "llvm/CodeGen/MachineFunction.h"
20 #include "llvm/Target/TargetFrameInfo.h"
21 #include "llvm/Target/TargetInstrInfo.h"
22 #include "llvm/Target/TargetMachine.h"
23 #include "llvm/Target/TargetOptions.h"
24 #include "llvm/ADT/BitVector.h"
25 using namespace llvm;
26
27 SystemZRegisterInfo::SystemZRegisterInfo(SystemZTargetMachine &tm,
28                                          const TargetInstrInfo &tii)
29   : SystemZGenRegisterInfo(SystemZ::NOP, SystemZ::NOP),
30     TM(tm), TII(tii) {
31 }
32
33 const unsigned*
34 SystemZRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
35   static const unsigned CalleeSavedRegs[] = {
36     SystemZ::R6D,  SystemZ::R7D,  SystemZ::R8D,  SystemZ::R9D,
37     SystemZ::R10D, SystemZ::R11D, SystemZ::R12D, SystemZ::R13D,
38     SystemZ::F1,  SystemZ::F3,  SystemZ::F5,  SystemZ::F7,
39     0
40   };
41
42   return CalleeSavedRegs;
43 }
44
45 const TargetRegisterClass* const*
46 SystemZRegisterInfo::getCalleeSavedRegClasses(const MachineFunction *MF) const {
47   static const TargetRegisterClass * const CalleeSavedRegClasses[] = {
48     &SystemZ::GR64RegClass, &SystemZ::GR64RegClass,
49     &SystemZ::GR64RegClass, &SystemZ::GR64RegClass,
50     &SystemZ::GR64RegClass, &SystemZ::GR64RegClass,
51     &SystemZ::GR64RegClass, &SystemZ::GR64RegClass,
52     &SystemZ::FP64RegClass, &SystemZ::FP64RegClass,
53     &SystemZ::FP64RegClass, &SystemZ::FP64RegClass, 0
54   };
55   return CalleeSavedRegClasses;
56 }
57
58 BitVector SystemZRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
59   BitVector Reserved(getNumRegs());
60   if (hasFP(MF))
61     Reserved.set(SystemZ::R11D);
62   Reserved.set(SystemZ::R14D);
63   Reserved.set(SystemZ::R15D);
64   return Reserved;
65 }
66
67 // needsFP - Return true if the specified function should have a dedicated frame
68 // pointer register.  This is true if the function has variable sized allocas or
69 // if frame pointer elimination is disabled.
70 //
71 bool SystemZRegisterInfo::hasFP(const MachineFunction &MF) const {
72   const MachineFrameInfo *MFI = MF.getFrameInfo();
73   return NoFramePointerElim || MFI->hasVarSizedObjects();
74 }
75
76 void SystemZRegisterInfo::
77 eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
78                               MachineBasicBlock::iterator I) const {
79   assert(0 && "Not implemented yet!");
80 }
81
82 int SystemZRegisterInfo::getFrameIndexOffset(MachineFunction &MF, int FI) const {
83   const TargetFrameInfo &TFI = *MF.getTarget().getFrameInfo();
84   MachineFrameInfo *MFI = MF.getFrameInfo();
85   int Offset = MFI->getObjectOffset(FI) + MFI->getOffsetAdjustment();
86   uint64_t StackSize = MFI->getStackSize();
87
88   Offset += StackSize - TFI.getOffsetOfLocalArea();
89
90   // Skip the register save area if we generated the stack frame.
91   if (StackSize)
92     Offset -= TFI.getOffsetOfLocalArea();
93
94   return Offset;
95 }
96
97 void SystemZRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
98                                             int SPAdj, RegScavenger *RS) const {
99   assert(SPAdj == 0 && "Unxpected");
100
101   unsigned i = 0;
102   MachineInstr &MI = *II;
103   MachineFunction &MF = *MI.getParent()->getParent();
104   while (!MI.getOperand(i).isFI()) {
105     ++i;
106     assert(i < MI.getNumOperands() && "Instr doesn't have FrameIndex operand!");
107   }
108
109   int FrameIndex = MI.getOperand(i).getIndex();
110
111   unsigned BasePtr = (hasFP(MF) ? SystemZ::R11D : SystemZ::R15D);
112
113   // This must be part of a rri or ri operand memory reference.  Replace the
114   // FrameIndex with base register with BasePtr.  Add an offset to the
115   // displacement field.
116   MI.getOperand(i).ChangeToRegister(BasePtr, false);
117
118   // Offset is a 20-bit integer.
119   // FIXME: handle "too long" displacements.
120   int Offset = getFrameIndexOffset(MF, FrameIndex) + MI.getOperand(i+1).getImm();
121   MI.getOperand(i+1).ChangeToImmediate(Offset);
122 }
123
124 /// emitSPUpdate - Emit a series of instructions to increment / decrement the
125 /// stack pointer by a constant value.
126 static
127 void emitSPUpdate(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI,
128                   int64_t NumBytes, const TargetInstrInfo &TII) {
129   // FIXME: Handle different stack sizes here.
130   bool isSub = NumBytes < 0;
131   uint64_t Offset = isSub ? -NumBytes : NumBytes;
132   unsigned Opc = SystemZ::ADD64ri16;
133   uint64_t Chunk = (1LL << 15) - 1;
134   DebugLoc DL = (MBBI != MBB.end() ? MBBI->getDebugLoc() :
135                  DebugLoc::getUnknownLoc());
136
137   while (Offset) {
138     uint64_t ThisVal = (Offset > Chunk) ? Chunk : Offset;
139     MachineInstr *MI =
140       BuildMI(MBB, MBBI, DL, TII.get(Opc), SystemZ::R15D)
141       .addReg(SystemZ::R15D).addImm((isSub ? -(int64_t)ThisVal : ThisVal));
142     // The PSW implicit def is dead.
143     MI->getOperand(3).setIsDead();
144     Offset -= ThisVal;
145   }
146 }
147
148 void SystemZRegisterInfo::emitPrologue(MachineFunction &MF) const {
149   MachineBasicBlock &MBB = MF.front();   // Prolog goes in entry BB
150   const TargetFrameInfo &TFI = *MF.getTarget().getFrameInfo();
151   MachineFrameInfo *MFI = MF.getFrameInfo();
152   MachineBasicBlock::iterator MBBI = MBB.begin();
153   DebugLoc DL = (MBBI != MBB.end() ? MBBI->getDebugLoc() :
154                  DebugLoc::getUnknownLoc());
155
156   // Get the number of bytes to allocate from the FrameInfo.
157   uint64_t StackSize = MFI->getStackSize();
158
159   // FIXME: Skip the callee-saved push instructions.
160
161   if (MBBI != MBB.end())
162     DL = MBBI->getDebugLoc();
163
164   uint64_t NumBytes = StackSize - TFI.getOffsetOfLocalArea();
165
166   if (StackSize) // adjust stack pointer: R15 -= numbytes
167     emitSPUpdate(MBB, MBBI, -(int64_t)NumBytes, TII);
168
169   if (hasFP(MF)) {
170     // Update R11 with the new base value...
171     BuildMI(MBB, MBBI, DL, TII.get(SystemZ::MOV64rr), SystemZ::R11D)
172       .addReg(SystemZ::R15D);
173
174     // Mark the FramePtr as live-in in every block except the entry.
175     for (MachineFunction::iterator I = next(MF.begin()), E = MF.end();
176          I != E; ++I)
177       I->addLiveIn(SystemZ::R11D);
178
179   }
180 }
181
182 void SystemZRegisterInfo::emitEpilogue(MachineFunction &MF,
183                                      MachineBasicBlock &MBB) const {
184   const MachineFrameInfo *MFI = MF.getFrameInfo();
185   const TargetFrameInfo &TFI = *MF.getTarget().getFrameInfo();
186   MachineBasicBlock::iterator MBBI = prior(MBB.end());
187   unsigned RetOpcode = MBBI->getOpcode();
188   DebugLoc DL = MBBI->getDebugLoc();
189
190   switch (RetOpcode) {
191   case SystemZ::RET: break;  // These are ok
192   default:
193     assert(0 && "Can only insert epilog into returning blocks");
194   }
195
196   // Get the number of bytes to allocate from the FrameInfo
197   uint64_t StackSize = MFI->getStackSize();
198   uint64_t NumBytes = StackSize - TFI.getOffsetOfLocalArea();
199
200   // Skip the callee-saved regs load instructions.
201   MachineBasicBlock::iterator LastCSPop = MBBI;
202   while (MBBI != MBB.begin()) {
203     MachineBasicBlock::iterator PI = prior(MBBI);
204     if (!PI->getDesc().isTerminator())
205       break;
206     --MBBI;
207   }
208
209   DL = MBBI->getDebugLoc();
210
211   if (MFI->hasVarSizedObjects()) {
212     assert(0 && "Not implemented yet!");
213   } else {
214     // adjust stack pointer back: R15 += numbytes
215     if (StackSize)
216       emitSPUpdate(MBB, MBBI, NumBytes, TII);
217   }
218 }
219
220 unsigned SystemZRegisterInfo::getRARegister() const {
221   assert(0 && "What is the return address register");
222   return 0;
223 }
224
225 unsigned SystemZRegisterInfo::getFrameRegister(MachineFunction &MF) const {
226   assert(0 && "What is the frame register");
227   return 0;
228 }
229
230 unsigned SystemZRegisterInfo::getEHExceptionRegister() const {
231   assert(0 && "What is the exception register");
232   return 0;
233 }
234
235 unsigned SystemZRegisterInfo::getEHHandlerRegister() const {
236   assert(0 && "What is the exception handler register");
237   return 0;
238 }
239
240 int SystemZRegisterInfo::getDwarfRegNum(unsigned RegNum, bool isEH) const {
241   assert(0 && "What is the dwarf register number");
242   return -1;
243 }
244
245 #include "SystemZGenRegisterInfo.inc"