class MachineCodeForBasicBlock is now an annotation on BasicBlock.
[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/MachineCodeForBasicBlock.h"
16 #include "llvm/CodeGen/MachineCodeForInstruction.h"
17 #include "llvm/CodeGen/MachineInstr.h"
18 #include "llvm/Pass.h"
19 #include "llvm/Function.h"
20 #include "llvm/BasicBlock.h"
21 #include "llvm/Instruction.h"
22
23 namespace {
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   std::vector<MachineInstr*> mvec;
57   MachineInstr* M;
58   const MachineFrameInfo& frameInfo = Target.getFrameInfo();
59   
60   // The second operand is the stack size. If it does not fit in the
61   // immediate field, we have to use a free register to hold the size.
62   // We will assume that local register `l0' is unused since the SAVE
63   // instruction must be the first instruction in each procedure.
64   // 
65   MachineCodeForMethod& mcInfo = MachineCodeForMethod::get(&F);
66   unsigned int staticStackSize = mcInfo.getStaticStackSize();
67   
68   if (staticStackSize < (unsigned) frameInfo.getMinStackFrameSize())
69     staticStackSize = (unsigned) frameInfo.getMinStackFrameSize();
70   
71   if (unsigned padsz = (staticStackSize %
72                         (unsigned) frameInfo.getStackFrameSizeAlignment()))
73     staticStackSize += frameInfo.getStackFrameSizeAlignment() - padsz;
74   
75   if (Target.getInstrInfo().constantFitsInImmedField(SAVE, staticStackSize))
76     {
77       M = new MachineInstr(SAVE);
78       M->SetMachineOperandReg(0, Target.getRegInfo().getStackPointer());
79       M->SetMachineOperandConst(1, MachineOperand::MO_SignExtendedImmed,
80                                    - (int) staticStackSize);
81       M->SetMachineOperandReg(2, Target.getRegInfo().getStackPointer());
82       mvec.push_back(M);
83     }
84   else
85     {
86       M = new MachineInstr(SETSW);
87       M->SetMachineOperandConst(0, MachineOperand::MO_SignExtendedImmed,
88                                 - (int) staticStackSize);
89       M->SetMachineOperandReg(1, MachineOperand::MO_MachineRegister,
90                                  Target.getRegInfo().getUnifiedRegNum(
91                            Target.getRegInfo().getRegClassIDOfType(Type::IntTy),
92                                   SparcIntRegOrder::l0));
93       mvec.push_back(M);
94       
95       M = new MachineInstr(SAVE);
96       M->SetMachineOperandReg(0, Target.getRegInfo().getStackPointer());
97       M->SetMachineOperandReg(1, MachineOperand::MO_MachineRegister,
98                                  Target.getRegInfo().getUnifiedRegNum(
99                            Target.getRegInfo().getRegClassIDOfType(Type::IntTy),
100                                   SparcIntRegOrder::l0));
101       M->SetMachineOperandReg(2, Target.getRegInfo().getStackPointer());
102       mvec.push_back(M);
103     }
104
105   MachineCodeForBasicBlock& bbMvec = MachineCodeForBasicBlock::get(&F.getEntryNode());
106   bbMvec.insert(bbMvec.begin(), mvec.begin(), mvec.end());
107 }
108
109 void InsertPrologEpilogCode::InsertEpilogCode(Function &F)
110 {
111   for (Function::iterator I = F.begin(), E = F.end(); I != E; ++I) {
112     Instruction *TermInst = (Instruction*)I->getTerminator();
113     if (TermInst->getOpcode() == Instruction::Ret)
114       {
115         MachineInstr *Restore = new MachineInstr(RESTORE);
116         Restore->SetMachineOperandReg(0, Target.getRegInfo().getZeroRegNum());
117         Restore->SetMachineOperandConst(1, MachineOperand::MO_SignExtendedImmed,
118                                         (int64_t)0);
119         Restore->SetMachineOperandReg(2, Target.getRegInfo().getZeroRegNum());
120         
121         MachineCodeForBasicBlock& bbMvec = MachineCodeForBasicBlock::get(I);
122         MachineCodeForInstruction &termMvec =
123           MachineCodeForInstruction::get(TermInst);
124         
125         // Remove the NOPs in the delay slots of the return instruction
126         const MachineInstrInfo &mii = Target.getInstrInfo();
127         unsigned numNOPs = 0;
128         while (termMvec.back()->getOpCode() == NOP)
129           {
130             assert( termMvec.back() == bbMvec.back());
131             delete bbMvec.pop_back();
132             termMvec.pop_back();
133             ++numNOPs;
134           }
135         assert(termMvec.back() == bbMvec.back());
136         
137         // Check that we found the right number of NOPs and have the right
138         // number of instructions to replace them.
139         unsigned ndelays = mii.getNumDelaySlots(termMvec.back()->getOpCode());
140         assert(numNOPs == ndelays && "Missing NOPs in delay slots?");
141         assert(ndelays == 1 && "Cannot use epilog code for delay slots?");
142         
143         // Append the epilog code to the end of the basic block.
144         bbMvec.push_back(Restore);
145       }
146   }
147 }
148
149 Pass *createPrologEpilogCodeInserter(TargetMachine &TM) {
150   return new InsertPrologEpilogCode(TM);
151 }