MachineFunction.cpp revision ce9c41e77a2ec75d48a173b9baf0f4a3bf49fac7
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 <fstream> 29#include <iostream> 30#include <sstream> 31 32using namespace llvm; 33 34static AnnotationID MF_AID( 35 AnnotationManager::getID("CodeGen::MachineCodeForFunction")); 36 37 38namespace { 39 struct Printer : public MachineFunctionPass { 40 std::ostream *OS; 41 const std::string Banner; 42 43 Printer (std::ostream *_OS, const std::string &_Banner) : 44 OS (_OS), Banner (_Banner) { } 45 46 const char *getPassName() const { return "MachineFunction Printer"; } 47 48 virtual void getAnalysisUsage(AnalysisUsage &AU) const { 49 AU.setPreservesAll(); 50 } 51 52 bool runOnMachineFunction(MachineFunction &MF) { 53 (*OS) << Banner; 54 MF.print (*OS); 55 return false; 56 } 57 }; 58} 59 60/// Returns a newly-created MachineFunction Printer pass. The default output 61/// stream is std::cerr; the default banner is empty. 62/// 63FunctionPass *llvm::createMachineFunctionPrinterPass(std::ostream *OS, 64 const std::string &Banner){ 65 return new Printer(OS, Banner); 66} 67 68namespace { 69 struct Deleter : public MachineFunctionPass { 70 const char *getPassName() const { return "Machine Code Deleter"; } 71 72 bool runOnMachineFunction(MachineFunction &MF) { 73 // Delete the annotation from the function now. 74 MachineFunction::destruct(MF.getFunction()); 75 return true; 76 } 77 }; 78} 79 80/// MachineCodeDeletion Pass - This pass deletes all of the machine code for 81/// the current function, which should happen after the function has been 82/// emitted to a .s file or to memory. 83FunctionPass *llvm::createMachineCodeDeleter() { 84 return new Deleter(); 85} 86 87 88 89//===---------------------------------------------------------------------===// 90// MachineFunction implementation 91//===---------------------------------------------------------------------===// 92MachineBasicBlock* ilist_traits<MachineBasicBlock>::createNode() 93{ 94 MachineBasicBlock* dummy = new MachineBasicBlock(); 95 LeakDetector::removeGarbageObject(dummy); 96 return dummy; 97} 98 99void ilist_traits<MachineBasicBlock>::transferNodesFromList( 100 iplist<MachineBasicBlock, ilist_traits<MachineBasicBlock> >& toList, 101 ilist_iterator<MachineBasicBlock> first, 102 ilist_iterator<MachineBasicBlock> last) 103{ 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 for (const_iterator BB = begin(); BB != end(); ++BB) 140 BB->print(OS); 141 142 OS << "\n# End machine code for " << Fn->getName () << "().\n\n"; 143} 144 145/// CFGOnly flag - This is used to control whether or not the CFG graph printer 146/// prints out the contents of basic blocks or not. This is acceptable because 147/// this code is only really used for debugging purposes. 148/// 149static bool CFGOnly = false; 150 151namespace llvm { 152 template<> 153 struct DOTGraphTraits<const MachineFunction*> : public DefaultDOTGraphTraits { 154 static std::string getGraphName(const MachineFunction *F) { 155 return "CFG for '" + F->getFunction()->getName() + "' function"; 156 } 157 158 static std::string getNodeLabel(const MachineBasicBlock *Node, 159 const MachineFunction *Graph) { 160 if (CFGOnly && Node->getBasicBlock() && 161 !Node->getBasicBlock()->getName().empty()) 162 return Node->getBasicBlock()->getName() + ":"; 163 164 std::ostringstream Out; 165 if (CFGOnly) { 166 Out << Node->getNumber() << ':'; 167 return Out.str(); 168 } 169 170 Node->print(Out); 171 172 std::string OutStr = Out.str(); 173 if (OutStr[0] == '\n') OutStr.erase(OutStr.begin()); 174 175 // Process string output to make it nicer... 176 for (unsigned i = 0; i != OutStr.length(); ++i) 177 if (OutStr[i] == '\n') { // Left justify 178 OutStr[i] = '\\'; 179 OutStr.insert(OutStr.begin()+i+1, 'l'); 180 } 181 return OutStr; 182 } 183 }; 184} 185 186void MachineFunction::viewCFG() const 187{ 188 std::string Filename = "/tmp/cfg." + getFunction()->getName() + ".dot"; 189 std::cerr << "Writing '" << Filename << "'... "; 190 std::ofstream F(Filename.c_str()); 191 192 if (!F) { 193 std::cerr << " error opening file for writing!\n"; 194 return; 195 } 196 197 WriteGraph(F, this); 198 F.close(); 199 std::cerr << "\n"; 200 201 std::cerr << "Running 'dot' program... " << std::flush; 202 if (system(("dot -Tps -Nfontname=Courier -Gsize=7.5,10 " + Filename 203 + " > /tmp/cfg.tempgraph.ps").c_str())) { 204 std::cerr << "Error running dot: 'dot' not in path?\n"; 205 } else { 206 std::cerr << "\n"; 207 system("gv /tmp/cfg.tempgraph.ps"); 208 } 209 system(("rm " + Filename + " /tmp/cfg.tempgraph.ps").c_str()); 210} 211 212void MachineFunction::viewCFGOnly() const 213{ 214 CFGOnly = true; 215 viewCFG(); 216 CFGOnly = false; 217} 218 219// The next two methods are used to construct and to retrieve 220// the MachineCodeForFunction object for the given function. 221// construct() -- Allocates and initializes for a given function and target 222// get() -- Returns a handle to the object. 223// This should not be called before "construct()" 224// for a given Function. 225// 226MachineFunction& 227MachineFunction::construct(const Function *Fn, const TargetMachine &Tar) 228{ 229 assert(Fn->getAnnotation(MF_AID) == 0 && 230 "Object already exists for this function!"); 231 MachineFunction* mcInfo = new MachineFunction(Fn, Tar); 232 Fn->addAnnotation(mcInfo); 233 return *mcInfo; 234} 235 236void MachineFunction::destruct(const Function *Fn) { 237 bool Deleted = Fn->deleteAnnotation(MF_AID); 238 assert(Deleted && "Machine code did not exist for function!"); 239} 240 241MachineFunction& MachineFunction::get(const Function *F) 242{ 243 MachineFunction *mc = (MachineFunction*)F->getAnnotation(MF_AID); 244 assert(mc && "Call construct() method first to allocate the object"); 245 return *mc; 246} 247 248void MachineFunction::clearSSARegMap() { 249 delete SSARegMapping; 250 SSARegMapping = 0; 251} 252 253//===----------------------------------------------------------------------===// 254// MachineFrameInfo implementation 255//===----------------------------------------------------------------------===// 256 257/// CreateStackObject - Create a stack object for a value of the specified type. 258/// 259int MachineFrameInfo::CreateStackObject(const Type *Ty, const TargetData &TD) { 260 return CreateStackObject((unsigned)TD.getTypeSize(Ty), 261 TD.getTypeAlignment(Ty)); 262} 263 264 265void MachineFrameInfo::print(const MachineFunction &MF, std::ostream &OS) const{ 266 int ValOffset = MF.getTarget().getFrameInfo()->getOffsetOfLocalArea(); 267 268 for (unsigned i = 0, e = Objects.size(); i != e; ++i) { 269 const StackObject &SO = Objects[i]; 270 OS << " <fi #" << (int)(i-NumFixedObjects) << "> is "; 271 if (SO.Size == 0) 272 OS << "variable sized"; 273 else 274 OS << SO.Size << " byte" << (SO.Size != 1 ? "s" : " "); 275 276 if (i < NumFixedObjects) 277 OS << " fixed"; 278 if (i < NumFixedObjects || SO.SPOffset != -1) { 279 int Off = SO.SPOffset - ValOffset; 280 OS << " at location [SP"; 281 if (Off > 0) 282 OS << "+" << Off; 283 else if (Off < 0) 284 OS << Off; 285 OS << "]"; 286 } 287 OS << "\n"; 288 } 289 290 if (HasVarSizedObjects) 291 OS << " Stack frame contains variable sized objects\n"; 292} 293 294void MachineFrameInfo::dump(const MachineFunction &MF) const { 295 print(MF, std::cerr); 296} 297 298 299//===----------------------------------------------------------------------===// 300// MachineConstantPool implementation 301//===----------------------------------------------------------------------===// 302 303void MachineConstantPool::print(std::ostream &OS) const { 304 for (unsigned i = 0, e = Constants.size(); i != e; ++i) 305 OS << " <cp #" << i << "> is" << *(Value*)Constants[i] << "\n"; 306} 307 308void MachineConstantPool::dump() const { print(std::cerr); } 309