MachineFunction.cpp revision b8973bd8f50d7321635e1e07b81a880a0828d185
1//===-- MachineFunction.cpp -----------------------------------------------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file was developed by the LLVM research group and is distributed under 6// the University of Illinois Open Source License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// Collect native machine code information for a function. This allows 11// target-specific information about the generated code to be stored with each 12// function. 13// 14//===----------------------------------------------------------------------===// 15 16#include "llvm/CodeGen/MachineFunctionPass.h" 17#include "llvm/CodeGen/MachineInstr.h" 18#include "llvm/CodeGen/SSARegMap.h" 19#include "llvm/CodeGen/MachineFrameInfo.h" 20#include "llvm/CodeGen/MachineConstantPool.h" 21#include "llvm/CodeGen/Passes.h" 22#include "llvm/Target/TargetMachine.h" 23#include "llvm/Target/TargetFrameInfo.h" 24#include "llvm/Function.h" 25#include "llvm/Instructions.h" 26#include "llvm/Support/LeakDetector.h" 27#include "llvm/Support/GraphWriter.h" 28#include "llvm/Config/config.h" 29#include <fstream> 30#include <iostream> 31#include <sstream> 32 33using namespace llvm; 34 35static AnnotationID MF_AID( 36 AnnotationManager::getID("CodeGen::MachineCodeForFunction")); 37 38 39namespace { 40 struct Printer : public MachineFunctionPass { 41 std::ostream *OS; 42 const std::string Banner; 43 44 Printer (std::ostream *_OS, const std::string &_Banner) : 45 OS (_OS), Banner (_Banner) { } 46 47 const char *getPassName() const { return "MachineFunction Printer"; } 48 49 virtual void getAnalysisUsage(AnalysisUsage &AU) const { 50 AU.setPreservesAll(); 51 } 52 53 bool runOnMachineFunction(MachineFunction &MF) { 54 (*OS) << Banner; 55 MF.print (*OS); 56 return false; 57 } 58 }; 59} 60 61/// Returns a newly-created MachineFunction Printer pass. The default output 62/// stream is std::cerr; the default banner is empty. 63/// 64FunctionPass *llvm::createMachineFunctionPrinterPass(std::ostream *OS, 65 const std::string &Banner){ 66 return new Printer(OS, Banner); 67} 68 69namespace { 70 struct Deleter : public MachineFunctionPass { 71 const char *getPassName() const { return "Machine Code Deleter"; } 72 73 bool runOnMachineFunction(MachineFunction &MF) { 74 // Delete the annotation from the function now. 75 MachineFunction::destruct(MF.getFunction()); 76 return true; 77 } 78 }; 79} 80 81/// MachineCodeDeletion Pass - This pass deletes all of the machine code for 82/// the current function, which should happen after the function has been 83/// emitted to a .s file or to memory. 84FunctionPass *llvm::createMachineCodeDeleter() { 85 return new Deleter(); 86} 87 88 89 90//===---------------------------------------------------------------------===// 91// MachineFunction implementation 92//===---------------------------------------------------------------------===// 93 94MachineBasicBlock* ilist_traits<MachineBasicBlock>::createSentinel() { 95 MachineBasicBlock* dummy = new MachineBasicBlock(); 96 LeakDetector::removeGarbageObject(dummy); 97 return dummy; 98} 99 100void ilist_traits<MachineBasicBlock>::transferNodesFromList( 101 iplist<MachineBasicBlock, ilist_traits<MachineBasicBlock> >& toList, 102 ilist_iterator<MachineBasicBlock> first, 103 ilist_iterator<MachineBasicBlock> last) { 104 if (Parent != toList.Parent) 105 for (; first != last; ++first) 106 first->Parent = toList.Parent; 107} 108 109MachineFunction::MachineFunction(const Function *F, 110 const TargetMachine &TM) 111 : Annotation(MF_AID), Fn(F), Target(TM), UsedPhysRegs(0) { 112 SSARegMapping = new SSARegMap(); 113 MFInfo = 0; 114 FrameInfo = new MachineFrameInfo(); 115 ConstantPool = new MachineConstantPool(); 116 BasicBlocks.Parent = this; 117} 118 119MachineFunction::~MachineFunction() { 120 BasicBlocks.clear(); 121 delete SSARegMapping; 122 delete MFInfo; 123 delete FrameInfo; 124 delete ConstantPool; 125 delete[] UsedPhysRegs; 126} 127 128void MachineFunction::dump() const { print(std::cerr); } 129 130void MachineFunction::print(std::ostream &OS) const { 131 OS << "# Machine code for " << Fn->getName () << "():\n"; 132 133 // Print Frame Information 134 getFrameInfo()->print(*this, OS); 135 136 // Print Constant Pool 137 getConstantPool()->print(OS); 138 139 const MRegisterInfo *MRI = getTarget().getRegisterInfo(); 140 141 if (livein_begin() != livein_end()) { 142 OS << "Live Ins:"; 143 for (livein_iterator I = livein_begin(), E = livein_end(); I != E; ++I) { 144 if (MRI) 145 OS << " " << MRI->getName(I->first); 146 else 147 OS << " Reg #" << I->first; 148 } 149 OS << "\n"; 150 } 151 if (liveout_begin() != liveout_end()) { 152 OS << "Live Outs:"; 153 for (liveout_iterator I = liveout_begin(), E = liveout_end(); I != E; ++I) 154 if (MRI) 155 OS << " " << MRI->getName(*I); 156 else 157 OS << " Reg #" << *I; 158 OS << "\n"; 159 } 160 161 for (const_iterator BB = begin(); BB != end(); ++BB) 162 BB->print(OS); 163 164 OS << "\n# End machine code for " << Fn->getName () << "().\n\n"; 165} 166 167/// CFGOnly flag - This is used to control whether or not the CFG graph printer 168/// prints out the contents of basic blocks or not. This is acceptable because 169/// this code is only really used for debugging purposes. 170/// 171static bool CFGOnly = false; 172 173namespace llvm { 174 template<> 175 struct DOTGraphTraits<const MachineFunction*> : public DefaultDOTGraphTraits { 176 static std::string getGraphName(const MachineFunction *F) { 177 return "CFG for '" + F->getFunction()->getName() + "' function"; 178 } 179 180 static std::string getNodeLabel(const MachineBasicBlock *Node, 181 const MachineFunction *Graph) { 182 if (CFGOnly && Node->getBasicBlock() && 183 !Node->getBasicBlock()->getName().empty()) 184 return Node->getBasicBlock()->getName() + ":"; 185 186 std::ostringstream Out; 187 if (CFGOnly) { 188 Out << Node->getNumber() << ':'; 189 return Out.str(); 190 } 191 192 Node->print(Out); 193 194 std::string OutStr = Out.str(); 195 if (OutStr[0] == '\n') OutStr.erase(OutStr.begin()); 196 197 // Process string output to make it nicer... 198 for (unsigned i = 0; i != OutStr.length(); ++i) 199 if (OutStr[i] == '\n') { // Left justify 200 OutStr[i] = '\\'; 201 OutStr.insert(OutStr.begin()+i+1, 'l'); 202 } 203 return OutStr; 204 } 205 }; 206} 207 208void MachineFunction::viewCFG() const 209{ 210#ifndef NDEBUG 211 std::string Filename = "/tmp/cfg." + getFunction()->getName() + ".dot"; 212 std::cerr << "Writing '" << Filename << "'... "; 213 std::ofstream F(Filename.c_str()); 214 215 if (!F) { 216 std::cerr << " error opening file for writing!\n"; 217 return; 218 } 219 220 WriteGraph(F, this); 221 F.close(); 222 std::cerr << "\n"; 223 224#ifdef HAVE_GRAPHVIZ 225 std::cerr << "Running 'Graphviz' program... " << std::flush; 226 if (system((LLVM_PATH_GRAPHVIZ " " + Filename).c_str())) { 227 std::cerr << "Error viewing graph: 'Graphviz' not in path?\n"; 228 } else { 229 system(("rm " + Filename).c_str()); 230 return; 231 } 232#endif // HAVE_GRAPHVIZ 233 234#ifdef HAVE_GV 235 std::cerr << "Running 'dot' program... " << std::flush; 236 if (system(("dot -Tps -Nfontname=Courier -Gsize=7.5,10 " + Filename 237 + " > /tmp/cfg.tempgraph.ps").c_str())) { 238 std::cerr << "Error running dot: 'dot' not in path?\n"; 239 } else { 240 std::cerr << "\n"; 241 system("gv /tmp/cfg.tempgraph.ps"); 242 } 243 system(("rm " + Filename + " /tmp/cfg.tempgraph.ps").c_str()); 244 return; 245#endif // HAVE_GV 246#endif // NDEBUG 247 std::cerr << "MachineFunction::viewCFG is only available in debug builds on " 248 << "systems with Graphviz or gv!\n"; 249 250#ifndef NDEBUG 251 system(("rm " + Filename).c_str()); 252#endif 253} 254 255void MachineFunction::viewCFGOnly() const 256{ 257 CFGOnly = true; 258 viewCFG(); 259 CFGOnly = false; 260} 261 262// The next two methods are used to construct and to retrieve 263// the MachineCodeForFunction object for the given function. 264// construct() -- Allocates and initializes for a given function and target 265// get() -- Returns a handle to the object. 266// This should not be called before "construct()" 267// for a given Function. 268// 269MachineFunction& 270MachineFunction::construct(const Function *Fn, const TargetMachine &Tar) 271{ 272 assert(Fn->getAnnotation(MF_AID) == 0 && 273 "Object already exists for this function!"); 274 MachineFunction* mcInfo = new MachineFunction(Fn, Tar); 275 Fn->addAnnotation(mcInfo); 276 return *mcInfo; 277} 278 279void MachineFunction::destruct(const Function *Fn) { 280 bool Deleted = Fn->deleteAnnotation(MF_AID); 281 assert(Deleted && "Machine code did not exist for function!"); 282} 283 284MachineFunction& MachineFunction::get(const Function *F) 285{ 286 MachineFunction *mc = (MachineFunction*)F->getAnnotation(MF_AID); 287 assert(mc && "Call construct() method first to allocate the object"); 288 return *mc; 289} 290 291void MachineFunction::clearSSARegMap() { 292 delete SSARegMapping; 293 SSARegMapping = 0; 294} 295 296//===----------------------------------------------------------------------===// 297// MachineFrameInfo implementation 298//===----------------------------------------------------------------------===// 299 300/// CreateStackObject - Create a stack object for a value of the specified type. 301/// 302int MachineFrameInfo::CreateStackObject(const Type *Ty, const TargetData &TD) { 303 return CreateStackObject((unsigned)TD.getTypeSize(Ty), 304 TD.getTypeAlignment(Ty)); 305} 306 307 308void MachineFrameInfo::print(const MachineFunction &MF, std::ostream &OS) const{ 309 int ValOffset = MF.getTarget().getFrameInfo()->getOffsetOfLocalArea(); 310 311 for (unsigned i = 0, e = Objects.size(); i != e; ++i) { 312 const StackObject &SO = Objects[i]; 313 OS << " <fi #" << (int)(i-NumFixedObjects) << ">: "; 314 if (SO.Size == 0) 315 OS << "variable sized"; 316 else 317 OS << "size is " << SO.Size << " byte" << (SO.Size != 1 ? "s," : ","); 318 OS << " alignment is " << SO.Alignment << " byte" 319 << (SO.Alignment != 1 ? "s," : ","); 320 321 if (i < NumFixedObjects) 322 OS << " fixed"; 323 if (i < NumFixedObjects || SO.SPOffset != -1) { 324 int Off = SO.SPOffset - ValOffset; 325 OS << " at location [SP"; 326 if (Off > 0) 327 OS << "+" << Off; 328 else if (Off < 0) 329 OS << Off; 330 OS << "]"; 331 } 332 OS << "\n"; 333 } 334 335 if (HasVarSizedObjects) 336 OS << " Stack frame contains variable sized objects\n"; 337} 338 339void MachineFrameInfo::dump(const MachineFunction &MF) const { 340 print(MF, std::cerr); 341} 342 343 344//===----------------------------------------------------------------------===// 345// MachineConstantPool implementation 346//===----------------------------------------------------------------------===// 347 348void MachineConstantPool::print(std::ostream &OS) const { 349 for (unsigned i = 0, e = Constants.size(); i != e; ++i) { 350 OS << " <cp #" << i << "> is" << *(Value*)Constants[i].first; 351 if (Constants[i].second != 0) OS << " , align=" << Constants[i].second; 352 OS << "\n"; 353 } 354} 355 356void MachineConstantPool::dump() const { print(std::cerr); } 357