+//----------------------------------------------------------------------------
+// This method inserts caller saving/restoring instructons before/after
+// a call machine instruction. The caller saving/restoring instructions are
+// inserted like:
+//
+// ** caller saving instructions
+// other instructions inserted for the call by ColorCallArg
+// CALL instruction
+// other instructions inserted for the call ColorCallArg
+// ** caller restoring instructions
+//
+//----------------------------------------------------------------------------
+
+
+void
+UltraSparcRegInfo::insertCallerSavingCode(vector<MachineInstr*>& instrnsBefore,
+ vector<MachineInstr*>& instrnsAfter,
+ MachineInstr *CallMI,
+ const BasicBlock *BB,
+ PhyRegAlloc &PRA) const
+{
+ assert ( (target.getInstrInfo()).isCall(CallMI->getOpCode()) );
+
+ // has set to record which registers were saved/restored
+ //
+ hash_set<unsigned> PushedRegSet;
+
+ CallArgsDescriptor* argDesc = CallArgsDescriptor::get(CallMI);
+
+ // Now find the LR of the return value of the call
+ // The last *implicit operand* is the return value of a call
+ // Insert it to to he PushedRegSet since we must not save that register
+ // and restore it after the call.
+ // We do this because, we look at the LV set *after* the instruction
+ // to determine, which LRs must be saved across calls. The return value
+ // of the call is live in this set - but we must not save/restore it.
+
+ const Value *RetVal = argDesc->getReturnValue();
+
+ if (RetVal) {
+ LiveRange *RetValLR = PRA.LRI.getLiveRangeForValue( RetVal );
+ assert(RetValLR && "No LR for RetValue of call");
+
+ if (RetValLR->hasColor())
+ PushedRegSet.insert(
+ getUnifiedRegNum((RetValLR->getRegClass())->getID(),
+ RetValLR->getColor() ) );
+ }
+
+ const ValueSet &LVSetAft = PRA.LVI->getLiveVarSetAfterMInst(CallMI, BB);
+ ValueSet::const_iterator LIt = LVSetAft.begin();
+
+ // for each live var in live variable set after machine inst
+ for( ; LIt != LVSetAft.end(); ++LIt) {
+
+ // get the live range corresponding to live var
+ LiveRange *const LR = PRA.LRI.getLiveRangeForValue(*LIt );
+
+ // LR can be null if it is a const since a const
+ // doesn't have a dominating def - see Assumptions above
+ if( LR ) {
+
+ if( LR->hasColor() ) {
+
+ unsigned RCID = (LR->getRegClass())->getID();
+ unsigned Color = LR->getColor();
+
+ if ( isRegVolatile(RCID, Color) ) {
+
+ // if the value is in both LV sets (i.e., live before and after
+ // the call machine instruction)
+
+ unsigned Reg = getUnifiedRegNum(RCID, Color);
+
+ if( PushedRegSet.find(Reg) == PushedRegSet.end() ) {
+
+ // if we haven't already pushed that register
+
+ unsigned RegType = getRegType( LR );
+
+ // Now get two instructions - to push on stack and pop from stack
+ // and add them to InstrnsBefore and InstrnsAfter of the
+ // call instruction
+ //
+ int StackOff = PRA.MF.pushTempValue(target,
+ getSpilledRegSize(RegType));
+
+ vector<MachineInstr*> AdIBef, AdIAft;
+
+ //---- Insert code for pushing the reg on stack ----------
+
+ // We may need a scratch register to copy the saved value
+ // to/from memory. This may itself have to insert code to
+ // free up a scratch register. Any such code should go before
+ // the save code.
+ int scratchRegType = -1;
+ int scratchReg = -1;
+ if (regTypeNeedsScratchReg(RegType, scratchRegType))
+ { // Find a register not live in the LVSet before CallMI
+ const ValueSet &LVSetBef =
+ PRA.LVI->getLiveVarSetBeforeMInst(CallMI, BB);
+ scratchReg = PRA.getUsableUniRegAtMI(scratchRegType, &LVSetBef,
+ CallMI, AdIBef, AdIAft);
+ assert(scratchReg != getInvalidRegNum());
+ CallMI->insertUsedReg(scratchReg);
+ }
+
+ if (AdIBef.size() > 0)
+ instrnsBefore.insert(instrnsBefore.end(),
+ AdIBef.begin(), AdIBef.end());
+
+ cpReg2MemMI(instrnsBefore, Reg,getFramePointer(),StackOff,RegType,
+ scratchReg);
+
+ if (AdIAft.size() > 0)
+ instrnsBefore.insert(instrnsBefore.end(),
+ AdIAft.begin(), AdIAft.end());
+
+ //---- Insert code for popping the reg from the stack ----------
+
+ // We may need a scratch register to copy the saved value
+ // from memory. This may itself have to insert code to
+ // free up a scratch register. Any such code should go
+ // after the save code.
+ //
+ scratchRegType = -1;
+ scratchReg = -1;
+ if (regTypeNeedsScratchReg(RegType, scratchRegType))
+ { // Find a register not live in the LVSet after CallMI
+ scratchReg = PRA.getUsableUniRegAtMI(scratchRegType, &LVSetAft,
+ CallMI, AdIBef, AdIAft);
+ assert(scratchReg != getInvalidRegNum());
+ CallMI->insertUsedReg(scratchReg);
+ }
+
+ if (AdIBef.size() > 0)
+ instrnsAfter.insert(instrnsAfter.end(),
+ AdIBef.begin(), AdIBef.end());
+
+ cpMem2RegMI(instrnsAfter, getFramePointer(), StackOff,Reg,RegType,
+ scratchReg);
+
+ if (AdIAft.size() > 0)
+ instrnsAfter.insert(instrnsAfter.end(),
+ AdIAft.begin(), AdIAft.end());
+
+ PushedRegSet.insert(Reg);
+
+ if(DEBUG_RA) {
+ cerr << "\nFor call inst:" << *CallMI;
+ cerr << " -inserted caller saving instrs: Before:\n\t ";
+ for_each(instrnsBefore.begin(), instrnsBefore.end(),
+ std::mem_fun(&MachineInstr::dump));
+ cerr << " -and After:\n\t ";
+ for_each(instrnsAfter.begin(), instrnsAfter.end(),
+ std::mem_fun(&MachineInstr::dump));
+ }
+ } // if not already pushed
+
+ } // if LR has a volatile color
+
+ } // if LR has color
+
+ } // if there is a LR for Var
+
+ } // for each value in the LV set after instruction
+}
+