LLVM API Documentation

CFGPrinter.h
Go to the documentation of this file.
00001 //===-- CFGPrinter.h - CFG printer external interface -----------*- C++ -*-===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // This file defines external functions that can be called to explicitly
00011 // instantiate the CFG printer.
00012 //
00013 //===----------------------------------------------------------------------===//
00014 
00015 #ifndef LLVM_ANALYSIS_CFGPRINTER_H
00016 #define LLVM_ANALYSIS_CFGPRINTER_H
00017 
00018 #include "llvm/IR/CFG.h"
00019 #include "llvm/IR/Constants.h"
00020 #include "llvm/IR/Function.h"
00021 #include "llvm/IR/Instructions.h"
00022 #include "llvm/Support/GraphWriter.h"
00023 
00024 namespace llvm {
00025 template<>
00026 struct DOTGraphTraits<const Function*> : public DefaultDOTGraphTraits {
00027 
00028   DOTGraphTraits (bool isSimple=false) : DefaultDOTGraphTraits(isSimple) {}
00029 
00030   static std::string getGraphName(const Function *F) {
00031     return "CFG for '" + F->getName().str() + "' function";
00032   }
00033 
00034   static std::string getSimpleNodeLabel(const BasicBlock *Node,
00035                                         const Function *) {
00036     if (!Node->getName().empty())
00037       return Node->getName().str();
00038 
00039     std::string Str;
00040     raw_string_ostream OS(Str);
00041 
00042     Node->printAsOperand(OS, false);
00043     return OS.str();
00044   }
00045 
00046   static std::string getCompleteNodeLabel(const BasicBlock *Node,
00047                                           const Function *) {
00048     enum { MaxColumns = 80 };
00049     std::string Str;
00050     raw_string_ostream OS(Str);
00051 
00052     if (Node->getName().empty()) {
00053       Node->printAsOperand(OS, false);
00054       OS << ":";
00055     }
00056 
00057     OS << *Node;
00058     std::string OutStr = OS.str();
00059     if (OutStr[0] == '\n') OutStr.erase(OutStr.begin());
00060 
00061     // Process string output to make it nicer...
00062     unsigned ColNum = 0;
00063     unsigned LastSpace = 0;
00064     for (unsigned i = 0; i != OutStr.length(); ++i) {
00065       if (OutStr[i] == '\n') {                            // Left justify
00066         OutStr[i] = '\\';
00067         OutStr.insert(OutStr.begin()+i+1, 'l');
00068         ColNum = 0;
00069         LastSpace = 0;
00070       } else if (OutStr[i] == ';') {                      // Delete comments!
00071         unsigned Idx = OutStr.find('\n', i+1);            // Find end of line
00072         OutStr.erase(OutStr.begin()+i, OutStr.begin()+Idx);
00073         --i;
00074       } else if (ColNum == MaxColumns) {                  // Wrap lines.
00075         // Wrap very long names even though we can't find a space.
00076         if (!LastSpace)
00077           LastSpace = i;
00078         OutStr.insert(LastSpace, "\\l...");
00079         ColNum = i - LastSpace;
00080         LastSpace = 0;
00081         i += 3; // The loop will advance 'i' again.
00082       }
00083       else
00084         ++ColNum;
00085       if (OutStr[i] == ' ')
00086         LastSpace = i;
00087     }
00088     return OutStr;
00089   }
00090 
00091   std::string getNodeLabel(const BasicBlock *Node,
00092                            const Function *Graph) {
00093     if (isSimple())
00094       return getSimpleNodeLabel(Node, Graph);
00095     else
00096       return getCompleteNodeLabel(Node, Graph);
00097   }
00098 
00099   static std::string getEdgeSourceLabel(const BasicBlock *Node,
00100                                         succ_const_iterator I) {
00101     // Label source of conditional branches with "T" or "F"
00102     if (const BranchInst *BI = dyn_cast<BranchInst>(Node->getTerminator()))
00103       if (BI->isConditional())
00104         return (I == succ_begin(Node)) ? "T" : "F";
00105 
00106     // Label source of switch edges with the associated value.
00107     if (const SwitchInst *SI = dyn_cast<SwitchInst>(Node->getTerminator())) {
00108       unsigned SuccNo = I.getSuccessorIndex();
00109 
00110       if (SuccNo == 0) return "def";
00111 
00112       std::string Str;
00113       raw_string_ostream OS(Str);
00114       SwitchInst::ConstCaseIt Case =
00115           SwitchInst::ConstCaseIt::fromSuccessorIndex(SI, SuccNo);
00116       OS << Case.getCaseValue()->getValue();
00117       return OS.str();
00118     }
00119     return "";
00120   }
00121 };
00122 } // End llvm namespace
00123 
00124 namespace llvm {
00125   class FunctionPass;
00126   FunctionPass *createCFGPrinterPass ();
00127   FunctionPass *createCFGOnlyPrinterPass ();
00128 } // End llvm namespace
00129 
00130 #endif