#include "llvm/CodeGen/MachineCodeForMethod.h"
#include "llvm/CodeGen/PhyRegAlloc.h"
#include "llvm/Method.h"
+#include "llvm/PassManager.h"
#include <iostream>
using std::cerr;
// Entry point for register allocation for a module
//----------------------------------------------------------------------------
-void AllocateRegisters(Method *M, TargetMachine &target)
-{
-
- if ( (M)->isExternal() ) // don't process prototypes
- return;
-
- if( DEBUG_RA )
- cerr << "\n******************** Method "<< M->getName()
- << " ********************\n";
-
- MethodLiveVarInfo LVI(M ); // Analyze live varaibles
- LVI.analyze();
-
+class RegisterAllocation : public MethodPass {
+ TargetMachine &Target;
+public:
+ inline RegisterAllocation(TargetMachine &T) : Target(T) {}
+ bool runOnMethod(Method *M) {
+ if (DEBUG_RA)
+ cerr << "\n******************** Method "<< M->getName()
+ << " ********************\n";
- PhyRegAlloc PRA(M, target, &LVI); // allocate registers
- PRA.allocateRegisters();
+ MethodLiveVarInfo LVI(M ); // Analyze live varaibles
+ LVI.analyze();
+ PhyRegAlloc PRA(M, Target, &LVI); // allocate registers
+ PRA.allocateRegisters();
- if( DEBUG_RA ) cerr << "\nRegister allocation complete!\n";
-
-}
+ if (DEBUG_RA) cerr << "\nRegister allocation complete!\n";
+ return false;
+ }
+};
+static MachineInstr* minstrVec[MAX_INSTR_PER_VMINSTR];
//---------------------------------------------------------------------------
-// Function InsertPrologCode
-// Function InsertEpilogCode
-// Function InsertPrologEpilog
-//
+// class InsertPrologEpilogCode
+//
+// Insert SAVE/RESTORE instructions for the method
+//
// Insert prolog code at the unique method entry point.
// Insert epilog code at each method exit point.
// InsertPrologEpilog invokes these only if the method is not compiled
// with the leaf method optimization.
+//
//---------------------------------------------------------------------------
-static MachineInstr* minstrVec[MAX_INSTR_PER_VMINSTR];
+class InsertPrologEpilogCode : public MethodPass {
+ TargetMachine &Target;
+public:
+ inline InsertPrologEpilogCode(TargetMachine &T) : Target(T) {}
+ bool runOnMethod(Method *M) {
+ MachineCodeForMethod &mcodeInfo = MachineCodeForMethod::get(M);
+ if (!mcodeInfo.isCompiledAsLeafMethod()) {
+ InsertPrologCode(M);
+ InsertEpilogCode(M);
+ }
+ return false;
+ }
-static void
-InsertPrologCode(Method* method, TargetMachine& target)
+ void InsertPrologCode(Method *M);
+ void InsertEpilogCode(Method *M);
+};
+
+void InsertPrologEpilogCode::InsertPrologCode(Method* method)
{
BasicBlock* entryBB = method->getEntryNode();
- unsigned N = GetInstructionsForProlog(entryBB, target, minstrVec);
+ unsigned N = GetInstructionsForProlog(entryBB, Target, minstrVec);
assert(N <= MAX_INSTR_PER_VMINSTR);
- if (N > 0)
- {
- MachineCodeForBasicBlock& bbMvec = entryBB->getMachineInstrVec();
- bbMvec.insert(bbMvec.begin(), minstrVec, minstrVec+N);
- }
+ MachineCodeForBasicBlock& bbMvec = entryBB->getMachineInstrVec();
+ bbMvec.insert(bbMvec.begin(), minstrVec, minstrVec+N);
}
-static void
-InsertEpilogCode(Method* method, TargetMachine& target)
+void InsertPrologEpilogCode::InsertEpilogCode(Method* method)
{
for (Method::iterator I=method->begin(), E=method->end(); I != E; ++I)
if ((*I)->getTerminator()->getOpcode() == Instruction::Ret)
{
BasicBlock* exitBB = *I;
- unsigned N = GetInstructionsForEpilog(exitBB, target, minstrVec);
+ unsigned N = GetInstructionsForEpilog(exitBB, Target, minstrVec);
MachineCodeForBasicBlock& bbMvec = exitBB->getMachineInstrVec();
MachineCodeForInstruction &termMvec =
MachineCodeForInstruction::get(exitBB->getTerminator());
// Remove the NOPs in the delay slots of the return instruction
- const MachineInstrInfo &mii = target.getInstrInfo();
+ const MachineInstrInfo &mii = Target.getInstrInfo();
unsigned numNOPs = 0;
while (termMvec.back()->getOpCode() == NOP)
{
}
-// Insert SAVE/RESTORE instructions for the method
-static void
-InsertPrologEpilog(Method *method, TargetMachine &target)
-{
- MachineCodeForMethod& mcodeInfo = MachineCodeForMethod::get(method);
- if (mcodeInfo.isCompiledAsLeafMethod())
- return; // nothing to do
-
- InsertPrologCode(method, target);
- InsertEpilogCode(method, target);
-}
+
//---------------------------------------------------------------------------
}
-void
-ApplyPeepholeOptimizations(Method *method, TargetMachine &target)
-{
- return;
-
- // OptimizeLeafProcedures();
- // DeleteFallThroughBranches();
- // RemoveChainedBranches(); // should be folded with previous
- // RemoveRedundantOps(); // operations with %g0, NOP, etc.
-}
+//===---------------------------------------------------------------------===//
+// GenerateCodeForTarget Pass
+//
+// Native code generation for a specified target.
+//===---------------------------------------------------------------------===//
+
+class ConstructMachineCodeForMethod : public MethodPass {
+ TargetMachine &Target;
+public:
+ inline ConstructMachineCodeForMethod(TargetMachine &T) : Target(T) {}
+ bool runOnMethod(Method *M) {
+ MachineCodeForMethod::construct(M, Target);
+ return false;
+ }
+};
+
+class InstructionSelection : public MethodPass {
+ TargetMachine &Target;
+public:
+ inline InstructionSelection(TargetMachine &T) : Target(T) {}
+ bool runOnMethod(Method *M) {
+ if (SelectInstructionsForMethod(M, Target))
+ cerr << "Instr selection failed for method " << M->getName() << "\n";
+ return false;
+ }
+};
+class InstructionScheduling : public MethodPass {
+ TargetMachine &Target;
+public:
+ inline InstructionScheduling(TargetMachine &T) : Target(T) {}
+ bool runOnMethod(Method *M) {
+ if (ScheduleInstructionsWithSSA(M, Target))
+ cerr << "Instr scheduling failed for method " << M->getName() << "\n\n";
+ return false;
+ }
+};
-bool
-UltraSparc::compileMethod(Method *method)
-{
+struct FreeMachineCodeForMethod : public MethodPass {
+ static void freeMachineCode(Instruction *I) {
+ MachineCodeForInstruction::destroy(I);
+ }
+
+ bool runOnMethod(Method *M) {
+ for_each(M->inst_begin(), M->inst_end(), freeMachineCode);
+ // Don't destruct MachineCodeForMethod - The global printer needs it
+ //MachineCodeForMethod::destruct(M);
+ return false;
+ }
+};
+
+
+void UltraSparc::addPassesToEmitAssembly(PassManager &PM, std::ostream &Out) {
// Construct and initialize the MachineCodeForMethod object for this method.
- MachineCodeForMethod::construct(method, *this);
-
- if (SelectInstructionsForMethod(method, *this))
- {
- cerr << "Instruction selection failed for method " << method->getName()
- << "\n\n";
- return true;
- }
+ PM.add(new ConstructMachineCodeForMethod(*this));
- /*
- if (ScheduleInstructionsWithSSA(method, *this))
- {
- cerr << "Instruction scheduling before allocation failed for method "
- << method->getName() << "\n\n";
- return true;
- }
- */
-
+ PM.add(new InstructionSelection(*this));
+
+ //PM.add(new InstructionScheduling(*this));
- AllocateRegisters(method, *this); // allocate registers
+ PM.add(new RegisterAllocation(*this));
- ApplyPeepholeOptimizations(method, *this); // machine-dependent peephole opts
+ //PM.add(new OptimizeLeafProcedures());
+ //PM.add(new DeleteFallThroughBranches());
+ //PM.add(new RemoveChainedBranches()); // should be folded with previous
+ //PM.add(new RemoveRedundantOps()); // operations with %g0, NOP, etc.
- InsertPrologEpilog(method, *this);
+ PM.add(new InsertPrologEpilogCode(*this));
- return false;
-}
-
-static void freeMachineCode(Instruction *I) {
- MachineCodeForInstruction::destroy(I);
-}
-
-//
-// freeCompiledMethod - Release all memory associated with the compiled image
-// for this method.
-//
-void
-UltraSparc::freeCompiledMethod(Method *M)
-{
- for_each(M->inst_begin(), M->inst_end(), freeMachineCode);
- // Don't destruct MachineCodeForMethod - The global printer needs it
- //MachineCodeForMethod::destruct(M);
+ // Output assembly language to the .s file. Assembly emission is split into
+ // two parts: Method output and Global value output. This is because method
+ // output is pipelined with all of the rest of code generation stuff,
+ // allowing machine code representations for methods to be free'd after the
+ // method has been emitted.
+ //
+ PM.add(getMethodAsmPrinterPass(PM, Out));
+ PM.add(new FreeMachineCodeForMethod()); // Free stuff no longer needed
+
+ // Emit Module level assembly after all of the methods have been processed.
+ PM.add(getModuleAsmPrinterPass(PM, Out));
}