WOW, function calls still seem to work after this.
[oota-llvm.git] / lib / Target / Alpha / AlphaRegisterInfo.cpp
1 //===- AlphaRegisterInfo.cpp - Alpha Register Information -------*- C++ -*-===//
2 // 
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file was developed by the LLVM research group and is distributed under
6 // the University of Illinois Open Source License. See LICENSE.TXT for details.
7 // 
8 //===----------------------------------------------------------------------===//
9 //
10 // This file contains the Alpha implementation of the MRegisterInfo class.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #define DEBUG_TYPE "reginfo"
15 #include "Alpha.h"
16 #include "AlphaRegisterInfo.h"
17 #include "llvm/Constants.h"
18 #include "llvm/Type.h"
19 #include "llvm/Function.h"
20 #include "llvm/CodeGen/ValueTypes.h"
21 #include "llvm/CodeGen/MachineInstrBuilder.h"
22 #include "llvm/CodeGen/MachineFunction.h"
23 #include "llvm/CodeGen/MachineFrameInfo.h"
24 #include "llvm/Target/TargetFrameInfo.h"
25 #include "llvm/Target/TargetMachine.h"
26 #include "llvm/Target/TargetOptions.h"
27 #include "llvm/Support/CommandLine.h"
28 #include "llvm/Support/Debug.h"
29 #include "llvm/ADT/STLExtras.h"
30 #include <cstdlib>
31 #include <iostream>
32 using namespace llvm;
33
34 //These describe LDAx
35 static const int IMM_LOW  = -32768;
36 static const int IMM_HIGH = 32767;
37 static const int IMM_MULT = 65536;
38
39 static long getUpper16(long l)
40 {
41   long y = l / IMM_MULT;
42   if (l % IMM_MULT > IMM_HIGH)
43     ++y;
44   return y;
45 }
46
47 static long getLower16(long l)
48 {
49   long h = getUpper16(l);
50   return l - h * IMM_MULT;
51 }
52
53 AlphaRegisterInfo::AlphaRegisterInfo()
54   : AlphaGenRegisterInfo(Alpha::ADJUSTSTACKDOWN, Alpha::ADJUSTSTACKUP)
55 {
56 }
57
58 static const TargetRegisterClass *getClass(unsigned SrcReg) {
59   if (Alpha::FPRCRegisterClass->contains(SrcReg))
60     return Alpha::FPRCRegisterClass;
61   assert(Alpha::GPRCRegisterClass->contains(SrcReg) && "Reg not FPR or GPR");
62   return Alpha::GPRCRegisterClass;
63 }
64
65 void 
66 AlphaRegisterInfo::storeRegToStackSlot(MachineBasicBlock &MBB,
67                                        MachineBasicBlock::iterator MI,
68                                        unsigned SrcReg, int FrameIdx) const {
69   //std::cerr << "Trying to store " << getPrettyName(SrcReg) << " to " << FrameIdx << "\n";
70   //BuildMI(MBB, MI, Alpha::WTF, 0).addReg(SrcReg);
71   if (getClass(SrcReg) == Alpha::FPRCRegisterClass)
72     BuildMI(MBB, MI, Alpha::STT, 3).addReg(SrcReg).addFrameIndex(FrameIdx).addReg(Alpha::F31);
73   else if (getClass(SrcReg) == Alpha::GPRCRegisterClass)
74     BuildMI(MBB, MI, Alpha::STQ, 3).addReg(SrcReg).addFrameIndex(FrameIdx).addReg(Alpha::F31);
75   else
76     abort();
77 }
78
79 void
80 AlphaRegisterInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
81                                         MachineBasicBlock::iterator MI,
82                                         unsigned DestReg, int FrameIdx) const{
83   //std::cerr << "Trying to load " << getPrettyName(DestReg) << " to " << FrameIdx << "\n";
84   if (getClass(DestReg) == Alpha::FPRCRegisterClass)
85     BuildMI(MBB, MI, Alpha::LDT, 2, DestReg).addFrameIndex(FrameIdx).addReg(Alpha::F31);
86   else if (getClass(DestReg) == Alpha::GPRCRegisterClass)
87     BuildMI(MBB, MI, Alpha::LDQ, 2, DestReg).addFrameIndex(FrameIdx).addReg(Alpha::F31);
88   else
89     abort();
90 }
91
92 void AlphaRegisterInfo::copyRegToReg(MachineBasicBlock &MBB,
93                                      MachineBasicBlock::iterator MI,
94                                      unsigned DestReg, unsigned SrcReg,
95                                      const TargetRegisterClass *RC) const {
96   //  std::cerr << "copyRegToReg " << DestReg << " <- " << SrcReg << "\n";
97   if (RC == Alpha::GPRCRegisterClass) {
98     BuildMI(MBB, MI, Alpha::BIS, 2, DestReg).addReg(SrcReg).addReg(SrcReg);
99   } else if (RC == Alpha::FPRCRegisterClass) {
100     BuildMI(MBB, MI, Alpha::CPYS, 2, DestReg).addReg(SrcReg).addReg(SrcReg);
101   } else { 
102     std::cerr << "Attempt to copy register that is not GPR or FPR";
103      abort();
104   }
105 }
106
107 //===----------------------------------------------------------------------===//
108 // Stack Frame Processing methods
109 //===----------------------------------------------------------------------===//
110
111 // hasFP - Return true if the specified function should have a dedicated frame
112 // pointer register.  This is true if the function has variable sized allocas or
113 // if frame pointer elimination is disabled.
114 //
115 static bool hasFP(MachineFunction &MF) {
116   MachineFrameInfo *MFI = MF.getFrameInfo();
117   return MFI->hasVarSizedObjects();
118 }
119
120 void AlphaRegisterInfo::
121 eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
122                               MachineBasicBlock::iterator I) const {
123   if (hasFP(MF)) {
124     // If we have a frame pointer, turn the adjcallstackup instruction into a
125     // 'sub ESP, <amt>' and the adjcallstackdown instruction into 'add ESP,
126     // <amt>'
127     MachineInstr *Old = I;
128     unsigned Amount = Old->getOperand(0).getImmedValue();
129     if (Amount != 0) {
130       // We need to keep the stack aligned properly.  To do this, we round the
131       // amount of space needed for the outgoing arguments up to the next
132       // alignment boundary.
133       unsigned Align = MF.getTarget().getFrameInfo()->getStackAlignment();
134       Amount = (Amount+Align-1)/Align*Align;
135
136       MachineInstr *New;
137       if (Old->getOpcode() == Alpha::ADJUSTSTACKDOWN) {
138         New=BuildMI(Alpha::LDA, 2, Alpha::R30)
139           .addImm(-Amount).addReg(Alpha::R30);
140       } else {
141         assert(Old->getOpcode() == Alpha::ADJUSTSTACKUP);
142         New=BuildMI(Alpha::LDA, 2, Alpha::R30)
143           .addImm(Amount).addReg(Alpha::R30);
144       }
145       
146       // Replace the pseudo instruction with a new instruction...
147       MBB.insert(I, New);
148     }
149   }
150
151   MBB.erase(I);
152 }
153
154 //Alpha has a slightly funny stack:
155 //Args 
156 //<- incoming SP
157 //fixed locals (and spills, callee saved, etc)
158 //<- FP
159 //variable locals
160 //<- SP
161
162 void
163 AlphaRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II) const {
164   unsigned i = 0;
165   MachineInstr &MI = *II;
166   MachineBasicBlock &MBB = *MI.getParent();
167   MachineFunction &MF = *MBB.getParent();
168   bool FP = hasFP(MF);
169
170   while (!MI.getOperand(i).isFrameIndex()) {
171     ++i;
172     assert(i < MI.getNumOperands() && "Instr doesn't have FrameIndex operand!");
173   }
174
175   int FrameIndex = MI.getOperand(i).getFrameIndex();
176
177   // Add the base register of R30 (SP) or R15 (FP).
178   MI.SetMachineOperandReg(i + 1, FP ? Alpha::R15 : Alpha::R30);
179   
180   // Now add the frame object offset to the offset from the virtual frame index.
181   int Offset = MF.getFrameInfo()->getObjectOffset(FrameIndex);
182
183   DEBUG(std::cerr << "FI: " << FrameIndex << " Offset: " << Offset << "\n");
184
185   Offset += MF.getFrameInfo()->getStackSize();
186   
187   DEBUG(std::cerr << "Corrected Offset " << Offset << 
188         " for stack size: " << MF.getFrameInfo()->getStackSize() << "\n");
189
190   if (Offset > IMM_HIGH || Offset < IMM_LOW) {
191     //so in this case, we need to use a temporary register, and move the original
192     //inst off the SP/FP
193     //fix up the old:
194     MI.SetMachineOperandReg(i + 1, Alpha::R28);
195     MI.SetMachineOperandConst(i, MachineOperand::MO_SignExtendedImmed, 
196                               getLower16(Offset));
197     //insert the new
198     MachineInstr* nMI=BuildMI(Alpha::LDAH, 2, Alpha::R28)
199       .addImm(getUpper16(Offset)).addReg(FP ? Alpha::R15 : Alpha::R30);
200     MBB.insert(II, nMI);
201   } else {
202     MI.SetMachineOperandConst(i, MachineOperand::MO_SignExtendedImmed, Offset);
203   }
204 }
205
206
207 void AlphaRegisterInfo::emitPrologue(MachineFunction &MF) const {
208   MachineBasicBlock &MBB = MF.front();   // Prolog goes in entry BB
209   MachineBasicBlock::iterator MBBI = MBB.begin();
210   MachineFrameInfo *MFI = MF.getFrameInfo();
211   MachineInstr *MI;
212   bool FP = hasFP(MF);
213   
214   //handle GOP offset
215   MI = BuildMI(Alpha::LDGP, 0);
216   MBB.insert(MBBI, MI);
217   //evil const_cast until MO stuff setup to handle const
218   MI = BuildMI(Alpha::ALTENT, 1).addGlobalAddress(const_cast<Function*>(MF.getFunction()), true);
219   MBB.insert(MBBI, MI);
220                                                   
221   // Get the number of bytes to allocate from the FrameInfo
222   long NumBytes = MFI->getStackSize();
223
224   if (MFI->hasCalls() && !FP) {
225     // We reserve argument space for call sites in the function immediately on 
226     // entry to the current function.  This eliminates the need for add/sub 
227     // brackets around call sites.
228     //If there is a frame pointer, then we don't do this
229     NumBytes += MFI->getMaxCallFrameSize();
230     DEBUG(std::cerr << "Added " << MFI->getMaxCallFrameSize() 
231           << " to the stack due to calls\n");
232   }
233
234   if (FP)
235     NumBytes += 8; //reserve space for the old FP
236
237   // Do we need to allocate space on the stack?
238   if (NumBytes == 0) return;
239
240   // Update frame info to pretend that this is part of the stack...
241   MFI->setStackSize(NumBytes);
242
243   // adjust stack pointer: r30 -= numbytes
244   NumBytes = -NumBytes;
245   if (NumBytes >= IMM_LOW) {
246     MI=BuildMI(Alpha::LDA, 2, Alpha::R30).addImm(NumBytes).addReg(Alpha::R30);
247     MBB.insert(MBBI, MI);
248   } else if (getUpper16(NumBytes) >= IMM_LOW) {
249     MI=BuildMI(Alpha::LDAH, 2, Alpha::R30).addImm(getUpper16(NumBytes)).addReg(Alpha::R30);
250     MBB.insert(MBBI, MI);
251     MI=BuildMI(Alpha::LDA, 2, Alpha::R30).addImm(getLower16(NumBytes)).addReg(Alpha::R30);
252     MBB.insert(MBBI, MI);
253   } else {
254     std::cerr << "Too big a stack frame at " << NumBytes << "\n";
255     abort();
256   }
257
258   //now if we need to, save the old FP and set the new
259   if (FP)
260   {
261     MI=BuildMI(Alpha::STQ, 3).addReg(Alpha::R15).addImm(0).addReg(Alpha::R30);
262     MBB.insert(MBBI, MI);
263     //this must be the last instr in the prolog
264     MI=BuildMI(Alpha::BIS, 2, Alpha::R15).addReg(Alpha::R30).addReg(Alpha::R30);
265     MBB.insert(MBBI, MI);
266   }
267
268 }
269
270 void AlphaRegisterInfo::emitEpilogue(MachineFunction &MF,
271                                      MachineBasicBlock &MBB) const {
272   const MachineFrameInfo *MFI = MF.getFrameInfo();
273   MachineBasicBlock::iterator MBBI = prior(MBB.end());
274   MachineInstr *MI;
275   assert((MBBI->getOpcode() == Alpha::RET || MBBI->getOpcode() == Alpha::RETURN) &&
276          "Can only insert epilog into returning blocks");
277   
278   bool FP = hasFP(MF);
279  
280   // Get the number of bytes allocated from the FrameInfo...
281   long NumBytes = MFI->getStackSize();
282
283   //now if we need to, restore the old FP
284   if (FP)
285   {
286     //copy the FP into the SP (discards allocas)
287     MI=BuildMI(Alpha::BIS, 2, Alpha::R30).addReg(Alpha::R15).addReg(Alpha::R15);
288     MBB.insert(MBBI, MI);
289     //restore the FP
290     MI=BuildMI(Alpha::LDQ, 2, Alpha::R15).addImm(0).addReg(Alpha::R15);
291     MBB.insert(MBBI, MI);
292   }
293
294    if (NumBytes != 0) 
295      {
296        if (NumBytes <= IMM_HIGH) {
297          MI=BuildMI(Alpha::LDA, 2, Alpha::R30).addImm(NumBytes).addReg(Alpha::R30);
298          MBB.insert(MBBI, MI);
299        } else if (getUpper16(NumBytes) <= IMM_HIGH) {
300          MI=BuildMI(Alpha::LDAH, 2, Alpha::R30).addImm(getUpper16(NumBytes)).addReg(Alpha::R30);
301          MBB.insert(MBBI, MI);
302          MI=BuildMI(Alpha::LDA, 2, Alpha::R30).addImm(getLower16(NumBytes)).addReg(Alpha::R30);
303          MBB.insert(MBBI, MI);
304        } else {
305          std::cerr << "Too big a stack frame at " << NumBytes << "\n";
306          abort();
307        }
308      }
309 }
310
311 #include "AlphaGenRegisterInfo.inc"
312
313 const TargetRegisterClass*
314 AlphaRegisterInfo::getRegClassForType(const Type* Ty) const {
315   switch (Ty->getTypeID()) {
316     default:              assert(0 && "Invalid type to getClass!");
317     case Type::BoolTyID:
318     case Type::SByteTyID:
319     case Type::UByteTyID:
320     case Type::ShortTyID:
321     case Type::UShortTyID:
322     case Type::IntTyID:
323     case Type::UIntTyID:
324     case Type::PointerTyID:
325     case Type::LongTyID:
326     case Type::ULongTyID:  return &GPRCInstance;
327      
328   case Type::FloatTyID:
329   case Type::DoubleTyID: return &FPRCInstance;
330   }
331 }
332
333 std::string AlphaRegisterInfo::getPrettyName(unsigned reg)
334 {
335   std::string s(RegisterDescriptors[reg].Name);
336   return s;
337 }