4f9054bf62204f1f384c7ed622c71c9ce17e8b5f
[oota-llvm.git] / lib / Target / Blackfin / BlackfinFrameInfo.cpp
1 //====- BlackfinFrameInfo.cpp - Blackfin Frame 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 Blackfin implementation of TargetFrameInfo class.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "BlackfinFrameInfo.h"
15 #include "BlackfinInstrInfo.h"
16 #include "llvm/CodeGen/MachineFrameInfo.h"
17 #include "llvm/CodeGen/MachineFunction.h"
18 #include "llvm/CodeGen/MachineInstrBuilder.h"
19 #include "llvm/Target/TargetOptions.h"
20
21 using namespace llvm;
22
23
24 // hasFP - Return true if the specified function should have a dedicated frame
25 // pointer register.  This is true if the function has variable sized allocas or
26 // if frame pointer elimination is disabled.
27 bool BlackfinFrameInfo::hasFP(const MachineFunction &MF) const {
28   const MachineFrameInfo *MFI = MF.getFrameInfo();
29   return DisableFramePointerElim(MF) ||
30     MFI->adjustsStack() || MFI->hasVarSizedObjects();
31 }
32
33 // Emit a prologue that sets up a stack frame.
34 // On function entry, R0-R2 and P0 may hold arguments.
35 // R3, P1, and P2 may be used as scratch registers
36 void BlackfinFrameInfo::emitPrologue(MachineFunction &MF) const {
37   MachineBasicBlock &MBB = MF.front();   // Prolog goes in entry BB
38   MachineBasicBlock::iterator MBBI = MBB.begin();
39   MachineFrameInfo *MFI = MF.getFrameInfo();
40   const BlackfinRegisterInfo *RegInfo =
41     static_cast<const BlackfinRegisterInfo*>(MF.getTarget().getRegisterInfo());
42   const BlackfinInstrInfo &TII =
43     *static_cast<const BlackfinInstrInfo*>(MF.getTarget().getInstrInfo());
44
45   DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
46
47   int FrameSize = MFI->getStackSize();
48   if (FrameSize%4) {
49     FrameSize = (FrameSize+3) & ~3;
50     MFI->setStackSize(FrameSize);
51   }
52
53   if (!hasFP(MF)) {
54     assert(!MFI->adjustsStack() &&
55            "FP elimination on a non-leaf function is not supported");
56     RegInfo->adjustRegister(MBB, MBBI, dl, BF::SP, BF::P1, -FrameSize);
57     return;
58   }
59
60   // emit a LINK instruction
61   if (FrameSize <= 0x3ffff) {
62     BuildMI(MBB, MBBI, dl, TII.get(BF::LINK)).addImm(FrameSize);
63     return;
64   }
65
66   // Frame is too big, do a manual LINK:
67   // [--SP] = RETS;
68   // [--SP] = FP;
69   // FP = SP;
70   // P1 = -FrameSize;
71   // SP = SP + P1;
72   BuildMI(MBB, MBBI, dl, TII.get(BF::PUSH))
73     .addReg(BF::RETS, RegState::Kill);
74   BuildMI(MBB, MBBI, dl, TII.get(BF::PUSH))
75     .addReg(BF::FP, RegState::Kill);
76   BuildMI(MBB, MBBI, dl, TII.get(BF::MOVE), BF::FP)
77     .addReg(BF::SP);
78   RegInfo->loadConstant(MBB, MBBI, dl, BF::P1, -FrameSize);
79   BuildMI(MBB, MBBI, dl, TII.get(BF::ADDpp), BF::SP)
80     .addReg(BF::SP, RegState::Kill)
81     .addReg(BF::P1, RegState::Kill);
82
83 }
84
85 void BlackfinFrameInfo::emitEpilogue(MachineFunction &MF,
86                                      MachineBasicBlock &MBB) const {
87   MachineFrameInfo *MFI = MF.getFrameInfo();
88   const BlackfinRegisterInfo *RegInfo =
89     static_cast<const BlackfinRegisterInfo*>(MF.getTarget().getRegisterInfo());
90   const BlackfinInstrInfo &TII =
91     *static_cast<const BlackfinInstrInfo*>(MF.getTarget().getInstrInfo());
92   MachineBasicBlock::iterator MBBI = prior(MBB.end());
93   DebugLoc dl = MBBI->getDebugLoc();
94
95   int FrameSize = MFI->getStackSize();
96   assert(FrameSize%4 == 0 && "Misaligned frame size");
97
98   if (!hasFP(MF)) {
99     assert(!MFI->adjustsStack() &&
100            "FP elimination on a non-leaf function is not supported");
101     RegInfo->adjustRegister(MBB, MBBI, dl, BF::SP, BF::P1, FrameSize);
102     return;
103   }
104
105   // emit an UNLINK instruction
106   BuildMI(MBB, MBBI, dl, TII.get(BF::UNLINK));
107 }