diff options
author | Chris Lattner <sabre@nondot.org> | 2002-04-09 05:18:31 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2002-04-09 05:18:31 +0000 |
commit | bcd6cc8951b4953b1757b2e7a3d6600c6b28ec12 (patch) | |
tree | 0bd06ec4755c30294670454ed8e1e95df5f3a87e /lib/Target | |
parent | 9aa697b82eca37ddc2bd001152a157aedc97cc49 (diff) | |
download | external_llvm-bcd6cc8951b4953b1757b2e7a3d6600c6b28ec12.zip external_llvm-bcd6cc8951b4953b1757b2e7a3d6600c6b28ec12.tar.gz external_llvm-bcd6cc8951b4953b1757b2e7a3d6600c6b28ec12.tar.bz2 |
Move the InsertPrologEpilogCode class out of the Sparc.cpp file, and include
the bodies of the GetInstructionsFor(Prolog|Epilog) functions from
SparcInstrSelection.cpp into the class. This eliminates the need for a static
global vector of instructions and a class of errors that is really unneccesary.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@2193 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Target')
-rw-r--r-- | lib/Target/SparcV9/SparcV9PrologEpilogInserter.cpp | 153 |
1 files changed, 153 insertions, 0 deletions
diff --git a/lib/Target/SparcV9/SparcV9PrologEpilogInserter.cpp b/lib/Target/SparcV9/SparcV9PrologEpilogInserter.cpp new file mode 100644 index 0000000..a763f53 --- /dev/null +++ b/lib/Target/SparcV9/SparcV9PrologEpilogInserter.cpp @@ -0,0 +1,153 @@ +//===-- PrologEpilogCodeInserter.cpp - Insert Prolog & Epilog code for fn -===// +// +// Insert SAVE/RESTORE instructions for the function +// +// Insert prolog code at the unique function entry point. +// Insert epilog code at each function exit point. +// InsertPrologEpilog invokes these only if the function is not compiled +// with the leaf function optimization. +// +//===----------------------------------------------------------------------===// + +#include "SparcInternals.h" +#include "SparcRegClassInfo.h" +#include "llvm/CodeGen/MachineCodeForMethod.h" +#include "llvm/CodeGen/MachineCodeForInstruction.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/Pass.h" +#include "llvm/Function.h" +#include "llvm/BasicBlock.h" +#include "llvm/Instruction.h" + +namespace { + +class InsertPrologEpilogCode : public MethodPass { + TargetMachine &Target; +public: + InsertPrologEpilogCode(TargetMachine &T) : Target(T) {} + bool runOnMethod(Function *F) { + MachineCodeForMethod &mcodeInfo = MachineCodeForMethod::get(F); + if (!mcodeInfo.isCompiledAsLeafMethod()) { + InsertPrologCode(F); + InsertEpilogCode(F); + } + return false; + } + + void InsertPrologCode(Function *F); + void InsertEpilogCode(Function *F); +}; + +} // End anonymous namespace + +//------------------------------------------------------------------------ +// External Function: GetInstructionsForProlog +// External Function: GetInstructionsForEpilog +// +// Purpose: +// Create prolog and epilog code for procedure entry and exit +//------------------------------------------------------------------------ + +void InsertPrologEpilogCode::InsertPrologCode(Function *F) +{ + BasicBlock *entryBB = F->getEntryNode(); + + vector<MachineInstr*> mvec; + MachineInstr* M; + const MachineFrameInfo& frameInfo = Target.getFrameInfo(); + + // The second operand is the stack size. If it does not fit in the + // immediate field, we have to use a free register to hold the size. + // We will assume that local register `l0' is unused since the SAVE + // instruction must be the first instruction in each procedure. + // + MachineCodeForMethod& mcInfo = MachineCodeForMethod::get(F); + unsigned int staticStackSize = mcInfo.getStaticStackSize(); + + if (staticStackSize < (unsigned) frameInfo.getMinStackFrameSize()) + staticStackSize = (unsigned) frameInfo.getMinStackFrameSize(); + + if (unsigned padsz = (staticStackSize % + (unsigned) frameInfo.getStackFrameSizeAlignment())) + staticStackSize += frameInfo.getStackFrameSizeAlignment() - padsz; + + if (Target.getInstrInfo().constantFitsInImmedField(SAVE, staticStackSize)) + { + M = new MachineInstr(SAVE); + M->SetMachineOperandReg(0, Target.getRegInfo().getStackPointer()); + M->SetMachineOperandConst(1, MachineOperand::MO_SignExtendedImmed, + - (int) staticStackSize); + M->SetMachineOperandReg(2, Target.getRegInfo().getStackPointer()); + mvec.push_back(M); + } + else + { + M = new MachineInstr(SETSW); + M->SetMachineOperandConst(0, MachineOperand::MO_SignExtendedImmed, + - (int) staticStackSize); + M->SetMachineOperandReg(1, MachineOperand::MO_MachineRegister, + Target.getRegInfo().getUnifiedRegNum( + Target.getRegInfo().getRegClassIDOfType(Type::IntTy), + SparcIntRegOrder::l0)); + mvec.push_back(M); + + M = new MachineInstr(SAVE); + M->SetMachineOperandReg(0, Target.getRegInfo().getStackPointer()); + M->SetMachineOperandReg(1, MachineOperand::MO_MachineRegister, + Target.getRegInfo().getUnifiedRegNum( + Target.getRegInfo().getRegClassIDOfType(Type::IntTy), + SparcIntRegOrder::l0)); + M->SetMachineOperandReg(2, Target.getRegInfo().getStackPointer()); + mvec.push_back(M); + } + + MachineCodeForBasicBlock& bbMvec = entryBB->getMachineInstrVec(); + bbMvec.insert(entryBB->getMachineInstrVec().begin(), + mvec.begin(), mvec.end()); +} + +void InsertPrologEpilogCode::InsertEpilogCode(Function *F) +{ + for (Function::iterator I = F->begin(), E = F->end(); I != E; ++I) { + Instruction *TermInst = (Instruction*)(*I)->getTerminator(); + if (TermInst->getOpcode() == Instruction::Ret) + { + BasicBlock* exitBB = *I; + + MachineInstr *Restore = new MachineInstr(RESTORE); + Restore->SetMachineOperandReg(0, Target.getRegInfo().getZeroRegNum()); + Restore->SetMachineOperandConst(1, MachineOperand::MO_SignExtendedImmed, + (int64_t)0); + Restore->SetMachineOperandReg(2, Target.getRegInfo().getZeroRegNum()); + + MachineCodeForBasicBlock& bbMvec = exitBB->getMachineInstrVec(); + MachineCodeForInstruction &termMvec = + MachineCodeForInstruction::get(TermInst); + + // Remove the NOPs in the delay slots of the return instruction + const MachineInstrInfo &mii = Target.getInstrInfo(); + unsigned numNOPs = 0; + while (termMvec.back()->getOpCode() == NOP) + { + assert( termMvec.back() == bbMvec.back()); + termMvec.pop_back(); + bbMvec.pop_back(); + ++numNOPs; + } + assert(termMvec.back() == bbMvec.back()); + + // Check that we found the right number of NOPs and have the right + // number of instructions to replace them. + unsigned ndelays = mii.getNumDelaySlots(termMvec.back()->getOpCode()); + assert(numNOPs == ndelays && "Missing NOPs in delay slots?"); + assert(ndelays == 1 && "Cannot use epilog code for delay slots?"); + + // Append the epilog code to the end of the basic block. + bbMvec.push_back(Restore); + } + } +} + +Pass *createPrologEpilogCodeInserter(TargetMachine &TM) { + return new InsertPrologEpilogCode(TM); +} |