LLVM API Documentation
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); }