b74c7df344f3d1d9712ccb0bdcae5fa7e7ae7cde
[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/MachineFunctionPass.h"
15 #include "llvm/CodeGen/MachineFunctionInfo.h"
16 #include "llvm/CodeGen/MachineCodeForInstruction.h"
17 #include "llvm/CodeGen/MachineInstrBuilder.h"
18 #include "llvm/Pass.h"
19 #include "llvm/Function.h"
20 #include "llvm/DerivedTypes.h"
21 #include "llvm/Intrinsics.h"
22
23 namespace {
24   struct InsertPrologEpilogCode : public MachineFunctionPass {
25     const char *getPassName() const { return "Sparc Prolog/Epilog Inserter"; }
26     
27     bool runOnMachineFunction(MachineFunction &F) {
28       if (!F.getInfo()->isCompiledAsLeafMethod()) {
29         InsertPrologCode(F);
30         InsertEpilogCode(F);
31       }
32       return false;
33     }
34     
35     void InsertPrologCode(MachineFunction &F);
36     void InsertEpilogCode(MachineFunction &F);
37   };
38
39 }  // End anonymous namespace
40
41 //------------------------------------------------------------------------ 
42 //   Create prolog and epilog code for procedure entry and exit
43 //------------------------------------------------------------------------ 
44
45 void InsertPrologEpilogCode::InsertPrologCode(MachineFunction &MF)
46 {
47   std::vector<MachineInstr*> mvec;
48   const TargetMachine &TM = MF.getTarget();
49   const TargetFrameInfo& frameInfo = TM.getFrameInfo();
50   
51   // The second operand is the stack size. If it does not fit in the
52   // immediate field, we have to use a free register to hold the size.
53   // See the comments below for the choice of this register.
54   // 
55   unsigned staticStackSize = MF.getInfo()->getStaticStackSize();
56   
57   if (staticStackSize < (unsigned) frameInfo.getMinStackFrameSize())
58     staticStackSize = (unsigned) frameInfo.getMinStackFrameSize();
59
60   if (unsigned padsz = (staticStackSize %
61                         (unsigned) frameInfo.getStackFrameSizeAlignment()))
62     staticStackSize += frameInfo.getStackFrameSizeAlignment() - padsz;
63   
64   int32_t C = - (int) staticStackSize;
65   int SP = TM.getRegInfo().getStackPointer();
66   if (TM.getInstrInfo().constantFitsInImmedField(V9::SAVEi,staticStackSize)) {
67     mvec.push_back(BuildMI(V9::SAVEi, 3).addMReg(SP).addSImm(C)
68                    .addMReg(SP, MOTy::Def));
69   } else {
70     // We have to put the stack size value into a register before SAVE.
71     // Use register %g1 since it is volatile across calls.  Note that the
72     // local (%l) and in (%i) registers cannot be used before the SAVE!
73     // Do this by creating a code sequence equivalent to:
74     //        SETSW -(stackSize), %g1
75     int uregNum = TM.getRegInfo().getUnifiedRegNum(
76                          TM.getRegInfo().getRegClassIDOfType(Type::IntTy),
77                          SparcIntRegClass::g1);
78
79     MachineInstr* M = BuildMI(V9::SETHI, 2).addSImm(C)
80       .addMReg(uregNum, MOTy::Def);
81     M->setOperandHi32(0);
82     mvec.push_back(M);
83     
84     M = BuildMI(V9::ORi, 3).addMReg(uregNum).addSImm(C)
85       .addMReg(uregNum, MOTy::Def);
86     M->setOperandLo32(1);
87     mvec.push_back(M);
88     
89     M = BuildMI(V9::SRAi5, 3).addMReg(uregNum).addZImm(0)
90       .addMReg(uregNum, MOTy::Def);
91     mvec.push_back(M);
92     
93     // Now generate the SAVE using the value in register %g1
94     M = BuildMI(V9::SAVEr,3).addMReg(SP).addMReg(uregNum).addMReg(SP,MOTy::Def);
95     mvec.push_back(M);
96   }
97
98   // For varargs function bodies, insert instructions to copy incoming
99   // register arguments for the ... list to the stack.
100   // The first K=6 arguments are always received via int arg regs
101   // (%i0 ... %i5 if K=6) .
102   // By copying the varargs arguments to the stack, va_arg() then can
103   // simply assume that all vararg arguments are in an array on the stack. 
104   // 
105   if (MF.getFunction()->getFunctionType()->isVarArg()) {
106     int numFixedArgs    = MF.getFunction()->getFunctionType()->getNumParams();
107     int numArgRegs      = TM.getRegInfo().getNumOfIntArgRegs();
108     if (numFixedArgs < numArgRegs) {
109       bool ignore;
110       int firstArgReg   = TM.getRegInfo().getUnifiedRegNum(
111                              TM.getRegInfo().getRegClassIDOfType(Type::IntTy),
112                              SparcIntRegClass::i0);
113       int fpReg         = TM.getFrameInfo().getIncomingArgBaseRegNum();
114       int argSize       = TM.getFrameInfo().getSizeOfEachArgOnStack();
115       int firstArgOffset=TM.getFrameInfo().getFirstIncomingArgOffset(MF,ignore);
116       int nextArgOffset = firstArgOffset + numFixedArgs * argSize;
117
118       for (int i=numFixedArgs; i < numArgRegs; ++i) {
119         mvec.push_back(BuildMI(V9::STXi, 3).addMReg(firstArgReg+i).
120                        addMReg(fpReg).addSImm(nextArgOffset));
121         nextArgOffset += argSize;
122       }
123     }
124   }
125
126   MF.front().insert(MF.front().begin(), mvec.begin(), mvec.end());
127 }
128
129 void InsertPrologEpilogCode::InsertEpilogCode(MachineFunction &MF)
130 {
131   const TargetMachine &TM = MF.getTarget();
132   const TargetInstrInfo &MII = TM.getInstrInfo();
133
134   for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I) {
135     MachineBasicBlock &MBB = *I;
136     const BasicBlock &BB = *I->getBasicBlock();
137     const Instruction *TermInst = (Instruction*)BB.getTerminator();
138     if (TermInst->getOpcode() == Instruction::Ret)
139     {
140       int ZR = TM.getRegInfo().getZeroRegNum();
141       MachineInstr *Restore = 
142         BuildMI(V9::RESTOREi, 3).addMReg(ZR).addSImm(0).addMReg(ZR, MOTy::Def);
143       
144       MachineCodeForInstruction &termMvec =
145         MachineCodeForInstruction::get(TermInst);
146       
147       // Remove the NOPs in the delay slots of the return instruction
148       unsigned numNOPs = 0;
149       while (termMvec.back()->getOpCode() == V9::NOP)
150       {
151         assert( termMvec.back() == MBB.back());
152         delete MBB.pop_back();
153         termMvec.pop_back();
154         ++numNOPs;
155       }
156       assert(termMvec.back() == MBB.back());
157         
158       // Check that we found the right number of NOPs and have the right
159       // number of instructions to replace them.
160       unsigned ndelays = MII.getNumDelaySlots(termMvec.back()->getOpCode());
161       assert(numNOPs == ndelays && "Missing NOPs in delay slots?");
162       assert(ndelays == 1 && "Cannot use epilog code for delay slots?");
163         
164       // Append the epilog code to the end of the basic block.
165       MBB.push_back(Restore);
166     }
167   }
168 }
169
170 FunctionPass *UltraSparc::getPrologEpilogInsertionPass() {
171   return new InsertPrologEpilogCode();
172 }