16c507926532d609b1225c29878b37c562e4277f2Eric Christopher//===-- CFGPrinter.h - CFG printer external interface -----------*- C++ -*-===//
29769ab22265b313171d201b5928688524a01bd87Misha Brukman//
321e232501a9d5ace29187b20a211ca73b09a1c75Brian Gaeke//                     The LLVM Compiler Infrastructure
421e232501a9d5ace29187b20a211ca73b09a1c75Brian Gaeke//
57ed47a13356daed2a34cd2209a31f92552e3bdd8Chris Lattner// This file is distributed under the University of Illinois Open Source
67ed47a13356daed2a34cd2209a31f92552e3bdd8Chris Lattner// License. See LICENSE.TXT for details.
79769ab22265b313171d201b5928688524a01bd87Misha Brukman//
821e232501a9d5ace29187b20a211ca73b09a1c75Brian Gaeke//===----------------------------------------------------------------------===//
921e232501a9d5ace29187b20a211ca73b09a1c75Brian Gaeke//
1021e232501a9d5ace29187b20a211ca73b09a1c75Brian Gaeke// This file defines external functions that can be called to explicitly
1121e232501a9d5ace29187b20a211ca73b09a1c75Brian Gaeke// instantiate the CFG printer.
1221e232501a9d5ace29187b20a211ca73b09a1c75Brian Gaeke//
1321e232501a9d5ace29187b20a211ca73b09a1c75Brian Gaeke//===----------------------------------------------------------------------===//
1421e232501a9d5ace29187b20a211ca73b09a1c75Brian Gaeke
1521e232501a9d5ace29187b20a211ca73b09a1c75Brian Gaeke#ifndef LLVM_ANALYSIS_CFGPRINTER_H
1621e232501a9d5ace29187b20a211ca73b09a1c75Brian Gaeke#define LLVM_ANALYSIS_CFGPRINTER_H
1721e232501a9d5ace29187b20a211ca73b09a1c75Brian Gaeke
1836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include "llvm/IR/CFG.h"
190b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth#include "llvm/IR/Constants.h"
200b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth#include "llvm/IR/Function.h"
210b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth#include "llvm/IR/Instructions.h"
2288067b9133103de3bfadd4f5166f4fb082ba2496Chris Lattner#include "llvm/Support/GraphWriter.h"
2388067b9133103de3bfadd4f5166f4fb082ba2496Chris Lattner
2488067b9133103de3bfadd4f5166f4fb082ba2496Chris Lattnernamespace llvm {
2588067b9133103de3bfadd4f5166f4fb082ba2496Chris Lattnertemplate<>
2688067b9133103de3bfadd4f5166f4fb082ba2496Chris Lattnerstruct DOTGraphTraits<const Function*> : public DefaultDOTGraphTraits {
27a10d598602308549d87d2c5d9848f5a72fda2b43Tobias Grosser
28a10d598602308549d87d2c5d9848f5a72fda2b43Tobias Grosser  DOTGraphTraits (bool isSimple=false) : DefaultDOTGraphTraits(isSimple) {}
29a10d598602308549d87d2c5d9848f5a72fda2b43Tobias Grosser
3088067b9133103de3bfadd4f5166f4fb082ba2496Chris Lattner  static std::string getGraphName(const Function *F) {
31a7b0cb759433c715065440ee2a963a04db7f2b0bBenjamin Kramer    return "CFG for '" + F->getName().str() + "' function";
3288067b9133103de3bfadd4f5166f4fb082ba2496Chris Lattner  }
3388067b9133103de3bfadd4f5166f4fb082ba2496Chris Lattner
3456f4ef3232850e29c4635d0923910acce8887bd0Tobias Grosser  static std::string getSimpleNodeLabel(const BasicBlock *Node,
35b39e25ef2c8d8c840ec4155e57c737ac7bd4f167Eli Friedman                                        const Function *) {
3656f4ef3232850e29c4635d0923910acce8887bd0Tobias Grosser    if (!Node->getName().empty())
37a7b0cb759433c715065440ee2a963a04db7f2b0bBenjamin Kramer      return Node->getName().str();
3888067b9133103de3bfadd4f5166f4fb082ba2496Chris Lattner
3988067b9133103de3bfadd4f5166f4fb082ba2496Chris Lattner    std::string Str;
4088067b9133103de3bfadd4f5166f4fb082ba2496Chris Lattner    raw_string_ostream OS(Str);
4188067b9133103de3bfadd4f5166f4fb082ba2496Chris Lattner
4236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    Node->printAsOperand(OS, false);
4356f4ef3232850e29c4635d0923910acce8887bd0Tobias Grosser    return OS.str();
4456f4ef3232850e29c4635d0923910acce8887bd0Tobias Grosser  }
4556f4ef3232850e29c4635d0923910acce8887bd0Tobias Grosser
464be0c592c42739b1927aaf2a20b3fabbf6adf335Andrew Trick  static std::string getCompleteNodeLabel(const BasicBlock *Node,
47b39e25ef2c8d8c840ec4155e57c737ac7bd4f167Eli Friedman                                          const Function *) {
482f08e75a45b9fa698a49277f6cc11e041bf5fa51Andrew Trick    enum { MaxColumns = 80 };
4956f4ef3232850e29c4635d0923910acce8887bd0Tobias Grosser    std::string Str;
5056f4ef3232850e29c4635d0923910acce8887bd0Tobias Grosser    raw_string_ostream OS(Str);
5188067b9133103de3bfadd4f5166f4fb082ba2496Chris Lattner
5288067b9133103de3bfadd4f5166f4fb082ba2496Chris Lattner    if (Node->getName().empty()) {
5336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      Node->printAsOperand(OS, false);
5488067b9133103de3bfadd4f5166f4fb082ba2496Chris Lattner      OS << ":";
5588067b9133103de3bfadd4f5166f4fb082ba2496Chris Lattner    }
5688067b9133103de3bfadd4f5166f4fb082ba2496Chris Lattner
5788067b9133103de3bfadd4f5166f4fb082ba2496Chris Lattner    OS << *Node;
5888067b9133103de3bfadd4f5166f4fb082ba2496Chris Lattner    std::string OutStr = OS.str();
5988067b9133103de3bfadd4f5166f4fb082ba2496Chris Lattner    if (OutStr[0] == '\n') OutStr.erase(OutStr.begin());
6088067b9133103de3bfadd4f5166f4fb082ba2496Chris Lattner
6188067b9133103de3bfadd4f5166f4fb082ba2496Chris Lattner    // Process string output to make it nicer...
622f08e75a45b9fa698a49277f6cc11e041bf5fa51Andrew Trick    unsigned ColNum = 0;
632f08e75a45b9fa698a49277f6cc11e041bf5fa51Andrew Trick    unsigned LastSpace = 0;
642f08e75a45b9fa698a49277f6cc11e041bf5fa51Andrew Trick    for (unsigned i = 0; i != OutStr.length(); ++i) {
6588067b9133103de3bfadd4f5166f4fb082ba2496Chris Lattner      if (OutStr[i] == '\n') {                            // Left justify
6688067b9133103de3bfadd4f5166f4fb082ba2496Chris Lattner        OutStr[i] = '\\';
6788067b9133103de3bfadd4f5166f4fb082ba2496Chris Lattner        OutStr.insert(OutStr.begin()+i+1, 'l');
682f08e75a45b9fa698a49277f6cc11e041bf5fa51Andrew Trick        ColNum = 0;
692f08e75a45b9fa698a49277f6cc11e041bf5fa51Andrew Trick        LastSpace = 0;
7088067b9133103de3bfadd4f5166f4fb082ba2496Chris Lattner      } else if (OutStr[i] == ';') {                      // Delete comments!
7188067b9133103de3bfadd4f5166f4fb082ba2496Chris Lattner        unsigned Idx = OutStr.find('\n', i+1);            // Find end of line
7288067b9133103de3bfadd4f5166f4fb082ba2496Chris Lattner        OutStr.erase(OutStr.begin()+i, OutStr.begin()+Idx);
7388067b9133103de3bfadd4f5166f4fb082ba2496Chris Lattner        --i;
742f08e75a45b9fa698a49277f6cc11e041bf5fa51Andrew Trick      } else if (ColNum == MaxColumns) {                  // Wrap lines.
7537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines        // Wrap very long names even though we can't find a space.
7637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines        if (!LastSpace)
7737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines          LastSpace = i;
7837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines        OutStr.insert(LastSpace, "\\l...");
7937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines        ColNum = i - LastSpace;
8037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines        LastSpace = 0;
8137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines        i += 3; // The loop will advance 'i' again.
8288067b9133103de3bfadd4f5166f4fb082ba2496Chris Lattner      }
832f08e75a45b9fa698a49277f6cc11e041bf5fa51Andrew Trick      else
842f08e75a45b9fa698a49277f6cc11e041bf5fa51Andrew Trick        ++ColNum;
852f08e75a45b9fa698a49277f6cc11e041bf5fa51Andrew Trick      if (OutStr[i] == ' ')
862f08e75a45b9fa698a49277f6cc11e041bf5fa51Andrew Trick        LastSpace = i;
872f08e75a45b9fa698a49277f6cc11e041bf5fa51Andrew Trick    }
8888067b9133103de3bfadd4f5166f4fb082ba2496Chris Lattner    return OutStr;
8988067b9133103de3bfadd4f5166f4fb082ba2496Chris Lattner  }
9088067b9133103de3bfadd4f5166f4fb082ba2496Chris Lattner
9156f4ef3232850e29c4635d0923910acce8887bd0Tobias Grosser  std::string getNodeLabel(const BasicBlock *Node,
9256f4ef3232850e29c4635d0923910acce8887bd0Tobias Grosser                           const Function *Graph) {
9356f4ef3232850e29c4635d0923910acce8887bd0Tobias Grosser    if (isSimple())
9456f4ef3232850e29c4635d0923910acce8887bd0Tobias Grosser      return getSimpleNodeLabel(Node, Graph);
9556f4ef3232850e29c4635d0923910acce8887bd0Tobias Grosser    else
9656f4ef3232850e29c4635d0923910acce8887bd0Tobias Grosser      return getCompleteNodeLabel(Node, Graph);
9756f4ef3232850e29c4635d0923910acce8887bd0Tobias Grosser  }
9856f4ef3232850e29c4635d0923910acce8887bd0Tobias Grosser
9988067b9133103de3bfadd4f5166f4fb082ba2496Chris Lattner  static std::string getEdgeSourceLabel(const BasicBlock *Node,
10088067b9133103de3bfadd4f5166f4fb082ba2496Chris Lattner                                        succ_const_iterator I) {
10188067b9133103de3bfadd4f5166f4fb082ba2496Chris Lattner    // Label source of conditional branches with "T" or "F"
10288067b9133103de3bfadd4f5166f4fb082ba2496Chris Lattner    if (const BranchInst *BI = dyn_cast<BranchInst>(Node->getTerminator()))
10388067b9133103de3bfadd4f5166f4fb082ba2496Chris Lattner      if (BI->isConditional())
10488067b9133103de3bfadd4f5166f4fb082ba2496Chris Lattner        return (I == succ_begin(Node)) ? "T" : "F";
1054be0c592c42739b1927aaf2a20b3fabbf6adf335Andrew Trick
106641c6f983eb4e40ab23732ab46ffa85bab7f0ba9Dan Gohman    // Label source of switch edges with the associated value.
1070a26870d921c4f5507126f3068fc13148c426496Chris Lattner    if (const SwitchInst *SI = dyn_cast<SwitchInst>(Node->getTerminator())) {
1080a26870d921c4f5507126f3068fc13148c426496Chris Lattner      unsigned SuccNo = I.getSuccessorIndex();
1090a26870d921c4f5507126f3068fc13148c426496Chris Lattner
1100a26870d921c4f5507126f3068fc13148c426496Chris Lattner      if (SuccNo == 0) return "def";
1114be0c592c42739b1927aaf2a20b3fabbf6adf335Andrew Trick
1120a26870d921c4f5507126f3068fc13148c426496Chris Lattner      std::string Str;
1130a26870d921c4f5507126f3068fc13148c426496Chris Lattner      raw_string_ostream OS(Str);
114c10fa6c801e48771b5eade50afc2fe6abaf08227Stepan Dyatkovskiy      SwitchInst::ConstCaseIt Case =
1154be0c592c42739b1927aaf2a20b3fabbf6adf335Andrew Trick          SwitchInst::ConstCaseIt::fromSuccessorIndex(SI, SuccNo);
116c10fa6c801e48771b5eade50afc2fe6abaf08227Stepan Dyatkovskiy      OS << Case.getCaseValue()->getValue();
1170a26870d921c4f5507126f3068fc13148c426496Chris Lattner      return OS.str();
1184be0c592c42739b1927aaf2a20b3fabbf6adf335Andrew Trick    }
11988067b9133103de3bfadd4f5166f4fb082ba2496Chris Lattner    return "";
12088067b9133103de3bfadd4f5166f4fb082ba2496Chris Lattner  }
12188067b9133103de3bfadd4f5166f4fb082ba2496Chris Lattner};
12288067b9133103de3bfadd4f5166f4fb082ba2496Chris Lattner} // End llvm namespace
12388067b9133103de3bfadd4f5166f4fb082ba2496Chris Lattner
12421e232501a9d5ace29187b20a211ca73b09a1c75Brian Gaekenamespace llvm {
12521e232501a9d5ace29187b20a211ca73b09a1c75Brian Gaeke  class FunctionPass;
12621e232501a9d5ace29187b20a211ca73b09a1c75Brian Gaeke  FunctionPass *createCFGPrinterPass ();
12721e232501a9d5ace29187b20a211ca73b09a1c75Brian Gaeke  FunctionPass *createCFGOnlyPrinterPass ();
12821e232501a9d5ace29187b20a211ca73b09a1c75Brian Gaeke} // End llvm namespace
12921e232501a9d5ace29187b20a211ca73b09a1c75Brian Gaeke
13021e232501a9d5ace29187b20a211ca73b09a1c75Brian Gaeke#endif
131