b42e77715678994d5e86b9f86851c567ef40f2a1
[oota-llvm.git] / lib / Target / SparcV9 / SparcV9PrologEpilogInserter.cpp
1 //===-- PrologEpilogCodeInserter.cpp - Insert Prolog & Epilog code for fn -===//
2 //
3 // Insert SAVE/RESTORE instructions for the function
4 //
5 // Insert prolog code at the unique function entry point.
6 // Insert epilog code at each function exit point.
7 // InsertPrologEpilog invokes these only if the function is not compiled
8 // with the leaf function optimization.
9 //
10 //===----------------------------------------------------------------------===//
11
12 #include "SparcInternals.h"
13 #include "SparcRegClassInfo.h"
14 #include "llvm/CodeGen/MachineCodeForMethod.h"
15 #include "llvm/CodeGen/MachineCodeForInstruction.h"
16 #include "llvm/CodeGen/MachineInstr.h"
17 #include "llvm/Pass.h"
18 #include "llvm/Function.h"
19 #include "llvm/BasicBlock.h"
20 #include "llvm/Instruction.h"
21
22 namespace {
23
24 class InsertPrologEpilogCode : public FunctionPass {
25   TargetMachine &Target;
26 public:
27   InsertPrologEpilogCode(TargetMachine &T) : Target(T) {}
28
29   const char *getPassName() const { return "Sparc Prolog/Epilog Inserter"; }
30
31   bool runOnFunction(Function *F) {
32     MachineCodeForMethod &mcodeInfo = MachineCodeForMethod::get(F);
33     if (!mcodeInfo.isCompiledAsLeafMethod()) {
34       InsertPrologCode(F);
35       InsertEpilogCode(F);
36     }
37     return false;
38   }
39
40   void InsertPrologCode(Function *F);
41   void InsertEpilogCode(Function *F);
42 };
43
44 }  // End anonymous namespace
45
46 //------------------------------------------------------------------------ 
47 // External Function: GetInstructionsForProlog
48 // External Function: GetInstructionsForEpilog
49 //
50 // Purpose:
51 //   Create prolog and epilog code for procedure entry and exit
52 //------------------------------------------------------------------------ 
53
54 void InsertPrologEpilogCode::InsertPrologCode(Function *F)
55 {
56   BasicBlock *entryBB = F->getEntryNode();
57
58   vector<MachineInstr*> mvec;
59   MachineInstr* M;
60   const MachineFrameInfo& frameInfo = Target.getFrameInfo();
61   
62   // The second operand is the stack size. If it does not fit in the
63   // immediate field, we have to use a free register to hold the size.
64   // We will assume that local register `l0' is unused since the SAVE
65   // instruction must be the first instruction in each procedure.
66   // 
67   MachineCodeForMethod& mcInfo = MachineCodeForMethod::get(F);
68   unsigned int staticStackSize = mcInfo.getStaticStackSize();
69   
70   if (staticStackSize < (unsigned) frameInfo.getMinStackFrameSize())
71     staticStackSize = (unsigned) frameInfo.getMinStackFrameSize();
72   
73   if (unsigned padsz = (staticStackSize %
74                         (unsigned) frameInfo.getStackFrameSizeAlignment()))
75     staticStackSize += frameInfo.getStackFrameSizeAlignment() - padsz;
76   
77   if (Target.getInstrInfo().constantFitsInImmedField(SAVE, staticStackSize))
78     {
79       M = new MachineInstr(SAVE);
80       M->SetMachineOperandReg(0, Target.getRegInfo().getStackPointer());
81       M->SetMachineOperandConst(1, MachineOperand::MO_SignExtendedImmed,
82                                    - (int) staticStackSize);
83       M->SetMachineOperandReg(2, Target.getRegInfo().getStackPointer());
84       mvec.push_back(M);
85     }
86   else
87     {
88       M = new MachineInstr(SETSW);
89       M->SetMachineOperandConst(0, MachineOperand::MO_SignExtendedImmed,
90                                 - (int) staticStackSize);
91       M->SetMachineOperandReg(1, MachineOperand::MO_MachineRegister,
92                                  Target.getRegInfo().getUnifiedRegNum(
93                            Target.getRegInfo().getRegClassIDOfType(Type::IntTy),
94                                   SparcIntRegOrder::l0));
95       mvec.push_back(M);
96       
97       M = new MachineInstr(SAVE);
98       M->SetMachineOperandReg(0, Target.getRegInfo().getStackPointer());
99       M->SetMachineOperandReg(1, MachineOperand::MO_MachineRegister,
100                                  Target.getRegInfo().getUnifiedRegNum(
101                            Target.getRegInfo().getRegClassIDOfType(Type::IntTy),
102                                   SparcIntRegOrder::l0));
103       M->SetMachineOperandReg(2, Target.getRegInfo().getStackPointer());
104       mvec.push_back(M);
105     }
106
107   MachineCodeForBasicBlock& bbMvec = entryBB->getMachineInstrVec();
108   bbMvec.insert(entryBB->getMachineInstrVec().begin(),
109                 mvec.begin(), mvec.end());
110 }
111
112 void InsertPrologEpilogCode::InsertEpilogCode(Function *F)
113 {
114   for (Function::iterator I = F->begin(), E = F->end(); I != E; ++I) {
115     Instruction *TermInst = (Instruction*)(*I)->getTerminator();
116     if (TermInst->getOpcode() == Instruction::Ret)
117       {
118         BasicBlock* exitBB = *I;
119
120         MachineInstr *Restore = new MachineInstr(RESTORE);
121         Restore->SetMachineOperandReg(0, Target.getRegInfo().getZeroRegNum());
122         Restore->SetMachineOperandConst(1, MachineOperand::MO_SignExtendedImmed,
123                                         (int64_t)0);
124         Restore->SetMachineOperandReg(2, Target.getRegInfo().getZeroRegNum());
125         
126         MachineCodeForBasicBlock& bbMvec = exitBB->getMachineInstrVec();
127         MachineCodeForInstruction &termMvec =
128           MachineCodeForInstruction::get(TermInst);
129         
130         // Remove the NOPs in the delay slots of the return instruction
131         const MachineInstrInfo &mii = Target.getInstrInfo();
132         unsigned numNOPs = 0;
133         while (termMvec.back()->getOpCode() == NOP)
134           {
135             assert( termMvec.back() == bbMvec.back());
136             delete bbMvec.pop_back();
137             termMvec.pop_back();
138             ++numNOPs;
139           }
140         assert(termMvec.back() == bbMvec.back());
141         
142         // Check that we found the right number of NOPs and have the right
143         // number of instructions to replace them.
144         unsigned ndelays = mii.getNumDelaySlots(termMvec.back()->getOpCode());
145         assert(numNOPs == ndelays && "Missing NOPs in delay slots?");
146         assert(ndelays == 1 && "Cannot use epilog code for delay slots?");
147         
148         // Append the epilog code to the end of the basic block.
149         bbMvec.push_back(Restore);
150       }
151   }
152 }
153
154 Pass *createPrologEpilogCodeInserter(TargetMachine &TM) {
155   return new InsertPrologEpilogCode(TM);
156 }