LLVM API Documentation

Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

MachineFunction.cpp

Go to the documentation of this file.
00001 //===-- MachineFunction.cpp -----------------------------------------------===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file was developed by the LLVM research group and is distributed under
00006 // the University of Illinois Open Source License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // Collect native machine code information for a function.  This allows
00011 // target-specific information about the generated code to be stored with each
00012 // function.
00013 //
00014 //===----------------------------------------------------------------------===//
00015 
00016 #include "llvm/CodeGen/MachineFunctionPass.h"
00017 #include "llvm/CodeGen/MachineInstr.h"
00018 #include "llvm/CodeGen/SSARegMap.h"
00019 #include "llvm/CodeGen/MachineFrameInfo.h"
00020 #include "llvm/CodeGen/MachineConstantPool.h"
00021 #include "llvm/CodeGen/Passes.h"
00022 #include "llvm/Target/TargetMachine.h"
00023 #include "llvm/Target/TargetFrameInfo.h"
00024 #include "llvm/Function.h"
00025 #include "llvm/Instructions.h"
00026 #include "llvm/Support/LeakDetector.h"
00027 #include "llvm/Support/GraphWriter.h"
00028 #include <fstream>
00029 #include <iostream>
00030 #include <sstream>
00031 
00032 using namespace llvm;
00033 
00034 static AnnotationID MF_AID(
00035   AnnotationManager::getID("CodeGen::MachineCodeForFunction"));
00036 
00037 
00038 namespace {
00039   struct Printer : public MachineFunctionPass {
00040     std::ostream *OS;
00041     const std::string Banner;
00042 
00043     Printer (std::ostream *_OS, const std::string &_Banner) :
00044       OS (_OS), Banner (_Banner) { }
00045 
00046     const char *getPassName() const { return "MachineFunction Printer"; }
00047 
00048     virtual void getAnalysisUsage(AnalysisUsage &AU) const {
00049       AU.setPreservesAll();
00050     }
00051 
00052     bool runOnMachineFunction(MachineFunction &MF) {
00053       (*OS) << Banner;
00054       MF.print (*OS);
00055       return false;
00056     }
00057   };
00058 }
00059 
00060 /// Returns a newly-created MachineFunction Printer pass. The default output
00061 /// stream is std::cerr; the default banner is empty.
00062 ///
00063 FunctionPass *llvm::createMachineFunctionPrinterPass(std::ostream *OS,
00064                                                      const std::string &Banner) {
00065   return new Printer(OS, Banner);
00066 }
00067 
00068 namespace {
00069   struct Deleter : public MachineFunctionPass {
00070     const char *getPassName() const { return "Machine Code Deleter"; }
00071 
00072     bool runOnMachineFunction(MachineFunction &MF) {
00073       // Delete the annotation from the function now.
00074       MachineFunction::destruct(MF.getFunction());
00075       return true;
00076     }
00077   };
00078 }
00079 
00080 /// MachineCodeDeletion Pass - This pass deletes all of the machine code for
00081 /// the current function, which should happen after the function has been
00082 /// emitted to a .s file or to memory.
00083 FunctionPass *llvm::createMachineCodeDeleter() {
00084   return new Deleter();
00085 }
00086 
00087 
00088 
00089 //===---------------------------------------------------------------------===//
00090 // MachineFunction implementation
00091 //===---------------------------------------------------------------------===//
00092 MachineBasicBlock* ilist_traits<MachineBasicBlock>::createNode()
00093 {
00094   MachineBasicBlock* dummy = new MachineBasicBlock();
00095   LeakDetector::removeGarbageObject(dummy);
00096   return dummy;
00097 }
00098 
00099 void ilist_traits<MachineBasicBlock>::transferNodesFromList(
00100   iplist<MachineBasicBlock, ilist_traits<MachineBasicBlock> >& toList,
00101   ilist_iterator<MachineBasicBlock> first,
00102   ilist_iterator<MachineBasicBlock> last)
00103 {
00104   if (Parent != toList.Parent)
00105     for (; first != last; ++first)
00106       first->Parent = toList.Parent;
00107 }
00108 
00109 MachineFunction::MachineFunction(const Function *F,
00110                                  const TargetMachine &TM)
00111   : Annotation(MF_AID), Fn(F), Target(TM) {
00112   SSARegMapping = new SSARegMap();
00113   MFInfo = 0;
00114   FrameInfo = new MachineFrameInfo();
00115   ConstantPool = new MachineConstantPool();
00116   BasicBlocks.Parent = this;
00117 }
00118 
00119 MachineFunction::~MachineFunction() {
00120   BasicBlocks.clear();
00121   delete SSARegMapping;
00122   delete MFInfo;
00123   delete FrameInfo;
00124   delete ConstantPool;
00125 }
00126 
00127 void MachineFunction::dump() const { print(std::cerr); }
00128 
00129 void MachineFunction::print(std::ostream &OS) const {
00130   OS << "# Machine code for " << Fn->getName () << "():\n";
00131 
00132   // Print Frame Information
00133   getFrameInfo()->print(*this, OS);
00134 
00135   // Print Constant Pool
00136   getConstantPool()->print(OS);
00137 
00138   for (const_iterator BB = begin(); BB != end(); ++BB)
00139     BB->print(OS);
00140 
00141   OS << "\n# End machine code for " << Fn->getName () << "().\n\n";
00142 }
00143 
00144 /// CFGOnly flag - This is used to control whether or not the CFG graph printer
00145 /// prints out the contents of basic blocks or not.  This is acceptable because
00146 /// this code is only really used for debugging purposes.
00147 ///
00148 static bool CFGOnly = false;
00149 
00150 namespace llvm {
00151   template<>
00152   struct DOTGraphTraits<const MachineFunction*> : public DefaultDOTGraphTraits {
00153     static std::string getGraphName(const MachineFunction *F) {
00154       return "CFG for '" + F->getFunction()->getName() + "' function";
00155     }
00156 
00157     static std::string getNodeLabel(const MachineBasicBlock *Node,
00158                                     const MachineFunction *Graph) {
00159       if (CFGOnly && Node->getBasicBlock() &&
00160           !Node->getBasicBlock()->getName().empty())
00161         return Node->getBasicBlock()->getName() + ":";
00162 
00163       std::ostringstream Out;
00164       if (CFGOnly) {
00165         Out << Node->getNumber() << ':';
00166         return Out.str();
00167       }
00168 
00169       Node->print(Out);
00170 
00171       std::string OutStr = Out.str();
00172       if (OutStr[0] == '\n') OutStr.erase(OutStr.begin());
00173 
00174       // Process string output to make it nicer...
00175       for (unsigned i = 0; i != OutStr.length(); ++i)
00176         if (OutStr[i] == '\n') {                            // Left justify
00177           OutStr[i] = '\\';
00178           OutStr.insert(OutStr.begin()+i+1, 'l');
00179         }
00180       return OutStr;
00181     }
00182   };
00183 }
00184 
00185 void MachineFunction::viewCFG() const
00186 {
00187   std::string Filename = "/tmp/cfg." + getFunction()->getName() + ".dot";
00188   std::cerr << "Writing '" << Filename << "'... ";
00189   std::ofstream F(Filename.c_str());
00190 
00191   if (!F) {
00192     std::cerr << "  error opening file for writing!\n";
00193     return;
00194   }
00195 
00196   WriteGraph(F, this);
00197   F.close();
00198   std::cerr << "\n";
00199 
00200   std::cerr << "Running 'dot' program... " << std::flush;
00201   if (system(("dot -Tps -Nfontname=Courier -Gsize=7.5,10 " + Filename
00202               + " > /tmp/cfg.tempgraph.ps").c_str())) {
00203     std::cerr << "Error running dot: 'dot' not in path?\n";
00204   } else {
00205     std::cerr << "\n";
00206     system("gv /tmp/cfg.tempgraph.ps");
00207   }
00208   system(("rm " + Filename + " /tmp/cfg.tempgraph.ps").c_str());
00209 }
00210 
00211 void MachineFunction::viewCFGOnly() const
00212 {
00213   CFGOnly = true;
00214   viewCFG();
00215   CFGOnly = false;
00216 }
00217 
00218 // The next two methods are used to construct and to retrieve
00219 // the MachineCodeForFunction object for the given function.
00220 // construct() -- Allocates and initializes for a given function and target
00221 // get()       -- Returns a handle to the object.
00222 //                This should not be called before "construct()"
00223 //                for a given Function.
00224 //
00225 MachineFunction&
00226 MachineFunction::construct(const Function *Fn, const TargetMachine &Tar)
00227 {
00228   assert(Fn->getAnnotation(MF_AID) == 0 &&
00229          "Object already exists for this function!");
00230   MachineFunction* mcInfo = new MachineFunction(Fn, Tar);
00231   Fn->addAnnotation(mcInfo);
00232   return *mcInfo;
00233 }
00234 
00235 void MachineFunction::destruct(const Function *Fn) {
00236   bool Deleted = Fn->deleteAnnotation(MF_AID);
00237   assert(Deleted && "Machine code did not exist for function!");
00238 }
00239 
00240 MachineFunction& MachineFunction::get(const Function *F)
00241 {
00242   MachineFunction *mc = (MachineFunction*)F->getAnnotation(MF_AID);
00243   assert(mc && "Call construct() method first to allocate the object");
00244   return *mc;
00245 }
00246 
00247 void MachineFunction::clearSSARegMap() {
00248   delete SSARegMapping;
00249   SSARegMapping = 0;
00250 }
00251 
00252 //===----------------------------------------------------------------------===//
00253 //  MachineFrameInfo implementation
00254 //===----------------------------------------------------------------------===//
00255 
00256 /// CreateStackObject - Create a stack object for a value of the specified type.
00257 ///
00258 int MachineFrameInfo::CreateStackObject(const Type *Ty, const TargetData &TD) {
00259   return CreateStackObject(TD.getTypeSize(Ty), TD.getTypeAlignment(Ty));
00260 }
00261 
00262 
00263 void MachineFrameInfo::print(const MachineFunction &MF, std::ostream &OS) const{
00264   int ValOffset = MF.getTarget().getFrameInfo()->getOffsetOfLocalArea();
00265 
00266   for (unsigned i = 0, e = Objects.size(); i != e; ++i) {
00267     const StackObject &SO = Objects[i];
00268     OS << "  <fi #" << (int)(i-NumFixedObjects) << "> is ";
00269     if (SO.Size == 0)
00270       OS << "variable sized";
00271     else
00272       OS << SO.Size << " byte" << (SO.Size != 1 ? "s" : " ");
00273 
00274     if (i < NumFixedObjects)
00275       OS << " fixed";
00276     if (i < NumFixedObjects || SO.SPOffset != -1) {
00277       int Off = SO.SPOffset - ValOffset;
00278       OS << " at location [SP";
00279       if (Off > 0)
00280         OS << "+" << Off;
00281       else if (Off < 0)
00282         OS << Off;
00283       OS << "]";
00284     }
00285     OS << "\n";
00286   }
00287 
00288   if (HasVarSizedObjects)
00289     OS << "  Stack frame contains variable sized objects\n";
00290 }
00291 
00292 void MachineFrameInfo::dump(const MachineFunction &MF) const {
00293   print(MF, std::cerr);
00294 }
00295 
00296 
00297 //===----------------------------------------------------------------------===//
00298 //  MachineConstantPool implementation
00299 //===----------------------------------------------------------------------===//
00300 
00301 void MachineConstantPool::print(std::ostream &OS) const {
00302   for (unsigned i = 0, e = Constants.size(); i != e; ++i)
00303     OS << "  <cp #" << i << "> is" << *(Value*)Constants[i] << "\n";
00304 }
00305 
00306 void MachineConstantPool::dump() const { print(std::cerr); }