GraphWriter.cpp revision 255cd51fbd771c0131a74eaf4385f1ea703a3c68
19d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer//===-- GraphWriter.cpp - Implements GraphWriter support routines ---------===// 29d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer// 39d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer// The LLVM Compiler Infrastructure 49d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer// 54ee451de366474b9c228b4e5fa573795a715216dChris Lattner// This file is distributed under the University of Illinois Open Source 64ee451de366474b9c228b4e5fa573795a715216dChris Lattner// License. See LICENSE.TXT for details. 79d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer// 89d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer//===----------------------------------------------------------------------===// 99d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer// 109d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer// This file implements misc. GraphWriter support routines. 119d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer// 129d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer//===----------------------------------------------------------------------===// 139d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer 14255cd51fbd771c0131a74eaf4385f1ea703a3c68Andrew Trick#include "llvm/Support/CommandLine.h" 1565a392ebeae214ccb25f4d5ec856688e4e690e0dChris Lattner#include "llvm/Support/GraphWriter.h" 161f6efa3996dd1929fbc129203ce5009b620e6969Michael J. Spencer#include "llvm/Support/Path.h" 171f6efa3996dd1929fbc129203ce5009b620e6969Michael J. Spencer#include "llvm/Support/Program.h" 189d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer#include "llvm/Config/config.h" 199d5b532de9bdca37810a59a93a69128441b02c55Reid Spencerusing namespace llvm; 209d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer 21255cd51fbd771c0131a74eaf4385f1ea703a3c68Andrew Trickstatic cl::opt<bool> ViewBackground("view-background", cl::Hidden, 22255cd51fbd771c0131a74eaf4385f1ea703a3c68Andrew Trick cl::desc("Execute graph viewer in the background. Creates tmp file litter.")); 23255cd51fbd771c0131a74eaf4385f1ea703a3c68Andrew Trick 24103289e9383ad1eb66caf28c9b166aebce963a35Chris Lattnerstd::string llvm::DOT::EscapeString(const std::string &Label) { 25103289e9383ad1eb66caf28c9b166aebce963a35Chris Lattner std::string Str(Label); 26103289e9383ad1eb66caf28c9b166aebce963a35Chris Lattner for (unsigned i = 0; i != Str.length(); ++i) 27103289e9383ad1eb66caf28c9b166aebce963a35Chris Lattner switch (Str[i]) { 28103289e9383ad1eb66caf28c9b166aebce963a35Chris Lattner case '\n': 29103289e9383ad1eb66caf28c9b166aebce963a35Chris Lattner Str.insert(Str.begin()+i, '\\'); // Escape character... 30103289e9383ad1eb66caf28c9b166aebce963a35Chris Lattner ++i; 31103289e9383ad1eb66caf28c9b166aebce963a35Chris Lattner Str[i] = 'n'; 32103289e9383ad1eb66caf28c9b166aebce963a35Chris Lattner break; 33103289e9383ad1eb66caf28c9b166aebce963a35Chris Lattner case '\t': 34103289e9383ad1eb66caf28c9b166aebce963a35Chris Lattner Str.insert(Str.begin()+i, ' '); // Convert to two spaces 35103289e9383ad1eb66caf28c9b166aebce963a35Chris Lattner ++i; 36103289e9383ad1eb66caf28c9b166aebce963a35Chris Lattner Str[i] = ' '; 37103289e9383ad1eb66caf28c9b166aebce963a35Chris Lattner break; 38103289e9383ad1eb66caf28c9b166aebce963a35Chris Lattner case '\\': 39103289e9383ad1eb66caf28c9b166aebce963a35Chris Lattner if (i+1 != Str.length()) 40103289e9383ad1eb66caf28c9b166aebce963a35Chris Lattner switch (Str[i+1]) { 41103289e9383ad1eb66caf28c9b166aebce963a35Chris Lattner case 'l': continue; // don't disturb \l 42103289e9383ad1eb66caf28c9b166aebce963a35Chris Lattner case '|': case '{': case '}': 43103289e9383ad1eb66caf28c9b166aebce963a35Chris Lattner Str.erase(Str.begin()+i); continue; 44103289e9383ad1eb66caf28c9b166aebce963a35Chris Lattner default: break; 45103289e9383ad1eb66caf28c9b166aebce963a35Chris Lattner } 46103289e9383ad1eb66caf28c9b166aebce963a35Chris Lattner case '{': case '}': 47103289e9383ad1eb66caf28c9b166aebce963a35Chris Lattner case '<': case '>': 48103289e9383ad1eb66caf28c9b166aebce963a35Chris Lattner case '|': case '"': 49103289e9383ad1eb66caf28c9b166aebce963a35Chris Lattner Str.insert(Str.begin()+i, '\\'); // Escape character... 50103289e9383ad1eb66caf28c9b166aebce963a35Chris Lattner ++i; // don't infinite loop 51103289e9383ad1eb66caf28c9b166aebce963a35Chris Lattner break; 52103289e9383ad1eb66caf28c9b166aebce963a35Chris Lattner } 53103289e9383ad1eb66caf28c9b166aebce963a35Chris Lattner return Str; 54103289e9383ad1eb66caf28c9b166aebce963a35Chris Lattner} 55103289e9383ad1eb66caf28c9b166aebce963a35Chris Lattner 56255cd51fbd771c0131a74eaf4385f1ea703a3c68Andrew Trick// Execute the graph viewer. Return true if successful. 57255cd51fbd771c0131a74eaf4385f1ea703a3c68Andrew Trickstatic bool ExecGraphViewer(const sys::Path &ExecPath, 58255cd51fbd771c0131a74eaf4385f1ea703a3c68Andrew Trick std::vector<const char*> &args, 59255cd51fbd771c0131a74eaf4385f1ea703a3c68Andrew Trick const sys::Path &Filename, 60255cd51fbd771c0131a74eaf4385f1ea703a3c68Andrew Trick bool wait, 61255cd51fbd771c0131a74eaf4385f1ea703a3c68Andrew Trick std::string &ErrMsg) { 62255cd51fbd771c0131a74eaf4385f1ea703a3c68Andrew Trick if (wait) { 63255cd51fbd771c0131a74eaf4385f1ea703a3c68Andrew Trick if (sys::Program::ExecuteAndWait(ExecPath, &args[0],0,0,0,0,&ErrMsg)) { 64255cd51fbd771c0131a74eaf4385f1ea703a3c68Andrew Trick errs() << "Error: " << ErrMsg << "\n"; 65255cd51fbd771c0131a74eaf4385f1ea703a3c68Andrew Trick return false; 66255cd51fbd771c0131a74eaf4385f1ea703a3c68Andrew Trick } 67255cd51fbd771c0131a74eaf4385f1ea703a3c68Andrew Trick Filename.eraseFromDisk(); 68255cd51fbd771c0131a74eaf4385f1ea703a3c68Andrew Trick errs() << " done. \n"; 69255cd51fbd771c0131a74eaf4385f1ea703a3c68Andrew Trick } 70255cd51fbd771c0131a74eaf4385f1ea703a3c68Andrew Trick else { 71255cd51fbd771c0131a74eaf4385f1ea703a3c68Andrew Trick sys::Program::ExecuteNoWait(ExecPath, &args[0],0,0,0,&ErrMsg); 72255cd51fbd771c0131a74eaf4385f1ea703a3c68Andrew Trick errs() << "Remember to erase graph file: " << Filename.str() << "\n"; 73255cd51fbd771c0131a74eaf4385f1ea703a3c68Andrew Trick } 74255cd51fbd771c0131a74eaf4385f1ea703a3c68Andrew Trick return true; 75255cd51fbd771c0131a74eaf4385f1ea703a3c68Andrew Trick} 76103289e9383ad1eb66caf28c9b166aebce963a35Chris Lattner 7700ad26ff5760ff2d1b24acb18718e63541088923David Greenevoid llvm::DisplayGraph(const sys::Path &Filename, bool wait, 7800ad26ff5760ff2d1b24acb18718e63541088923David Greene GraphProgram::Name program) { 79255cd51fbd771c0131a74eaf4385f1ea703a3c68Andrew Trick wait &= !ViewBackground; 808ea5ecb0564b8822c70ad84202471f03e2690da7Reid Spencer std::string ErrMsg; 819d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer#if HAVE_GRAPHVIZ 829d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer sys::Path Graphviz(LLVM_PATH_GRAPHVIZ); 839d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer 849d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer std::vector<const char*> args; 859d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer args.push_back(Graphviz.c_str()); 869d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer args.push_back(Filename.c_str()); 879d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer args.push_back(0); 88255cd51fbd771c0131a74eaf4385f1ea703a3c68Andrew Trick 89103289e9383ad1eb66caf28c9b166aebce963a35Chris Lattner errs() << "Running 'Graphviz' program... "; 90255cd51fbd771c0131a74eaf4385f1ea703a3c68Andrew Trick if (!ExecGraphViewer(Graphviz, args, Filename, wait, ErrMsg)) 91644801a199794a74bdc4655f6af5bc05f8153dc8Dan Gohman return; 9200ad26ff5760ff2d1b24acb18718e63541088923David Greene 9348fd5a79e023bf6a647dfabb2bbb4c2f98617b81Dan Gohman#elif HAVE_XDOT_PY 9448fd5a79e023bf6a647dfabb2bbb4c2f98617b81Dan Gohman std::vector<const char*> args; 9548fd5a79e023bf6a647dfabb2bbb4c2f98617b81Dan Gohman args.push_back(LLVM_PATH_XDOT_PY); 9648fd5a79e023bf6a647dfabb2bbb4c2f98617b81Dan Gohman args.push_back(Filename.c_str()); 9748fd5a79e023bf6a647dfabb2bbb4c2f98617b81Dan Gohman 9848fd5a79e023bf6a647dfabb2bbb4c2f98617b81Dan Gohman switch (program) { 9948fd5a79e023bf6a647dfabb2bbb4c2f98617b81Dan Gohman case GraphProgram::DOT: args.push_back("-f"); args.push_back("dot"); break; 10048fd5a79e023bf6a647dfabb2bbb4c2f98617b81Dan Gohman case GraphProgram::FDP: args.push_back("-f"); args.push_back("fdp"); break; 10148fd5a79e023bf6a647dfabb2bbb4c2f98617b81Dan Gohman case GraphProgram::NEATO: args.push_back("-f"); args.push_back("neato");break; 10248fd5a79e023bf6a647dfabb2bbb4c2f98617b81Dan Gohman case GraphProgram::TWOPI: args.push_back("-f"); args.push_back("twopi");break; 10348fd5a79e023bf6a647dfabb2bbb4c2f98617b81Dan Gohman case GraphProgram::CIRCO: args.push_back("-f"); args.push_back("circo");break; 10448fd5a79e023bf6a647dfabb2bbb4c2f98617b81Dan Gohman default: errs() << "Unknown graph layout name; using default.\n"; 10548fd5a79e023bf6a647dfabb2bbb4c2f98617b81Dan Gohman } 106255cd51fbd771c0131a74eaf4385f1ea703a3c68Andrew Trick 10748fd5a79e023bf6a647dfabb2bbb4c2f98617b81Dan Gohman args.push_back(0); 10848fd5a79e023bf6a647dfabb2bbb4c2f98617b81Dan Gohman 10948fd5a79e023bf6a647dfabb2bbb4c2f98617b81Dan Gohman errs() << "Running 'xdot.py' program... "; 110255cd51fbd771c0131a74eaf4385f1ea703a3c68Andrew Trick if (!ExecGraphViewer(sys::Path(LLVM_PATH_XDOT_PY), args, Filename, wait, ErrMsg)) 111644801a199794a74bdc4655f6af5bc05f8153dc8Dan Gohman return; 11248fd5a79e023bf6a647dfabb2bbb4c2f98617b81Dan Gohman 11300ad26ff5760ff2d1b24acb18718e63541088923David Greene#elif (HAVE_GV && (HAVE_DOT || HAVE_FDP || HAVE_NEATO || \ 11400ad26ff5760ff2d1b24acb18718e63541088923David Greene HAVE_TWOPI || HAVE_CIRCO)) 1159d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer sys::Path PSFilename = Filename; 1169d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer PSFilename.appendSuffix("ps"); 117229509a8bc2390c4c9c1bd20f777acf29911d452David Greene 11800ad26ff5760ff2d1b24acb18718e63541088923David Greene sys::Path prog; 11900ad26ff5760ff2d1b24acb18718e63541088923David Greene 12000ad26ff5760ff2d1b24acb18718e63541088923David Greene // Set default grapher 12100ad26ff5760ff2d1b24acb18718e63541088923David Greene#if HAVE_CIRCO 12200ad26ff5760ff2d1b24acb18718e63541088923David Greene prog = sys::Path(LLVM_PATH_CIRCO); 12300ad26ff5760ff2d1b24acb18718e63541088923David Greene#endif 12400ad26ff5760ff2d1b24acb18718e63541088923David Greene#if HAVE_TWOPI 12500ad26ff5760ff2d1b24acb18718e63541088923David Greene prog = sys::Path(LLVM_PATH_TWOPI); 12600ad26ff5760ff2d1b24acb18718e63541088923David Greene#endif 12700ad26ff5760ff2d1b24acb18718e63541088923David Greene#if HAVE_NEATO 12800ad26ff5760ff2d1b24acb18718e63541088923David Greene prog = sys::Path(LLVM_PATH_NEATO); 12900ad26ff5760ff2d1b24acb18718e63541088923David Greene#endif 130229509a8bc2390c4c9c1bd20f777acf29911d452David Greene#if HAVE_FDP 13100ad26ff5760ff2d1b24acb18718e63541088923David Greene prog = sys::Path(LLVM_PATH_FDP); 13200ad26ff5760ff2d1b24acb18718e63541088923David Greene#endif 13300ad26ff5760ff2d1b24acb18718e63541088923David Greene#if HAVE_DOT 13400ad26ff5760ff2d1b24acb18718e63541088923David Greene prog = sys::Path(LLVM_PATH_DOT); 13500ad26ff5760ff2d1b24acb18718e63541088923David Greene#endif 13600ad26ff5760ff2d1b24acb18718e63541088923David Greene 13700ad26ff5760ff2d1b24acb18718e63541088923David Greene // Find which program the user wants 13800ad26ff5760ff2d1b24acb18718e63541088923David Greene#if HAVE_DOT 13940ef79d5e24d0a66345b4c9a1b97952478850d42Chris Lattner if (program == GraphProgram::DOT) 14000ad26ff5760ff2d1b24acb18718e63541088923David Greene prog = sys::Path(LLVM_PATH_DOT); 14100ad26ff5760ff2d1b24acb18718e63541088923David Greene#endif 14200ad26ff5760ff2d1b24acb18718e63541088923David Greene#if (HAVE_FDP) 14340ef79d5e24d0a66345b4c9a1b97952478850d42Chris Lattner if (program == GraphProgram::FDP) 14400ad26ff5760ff2d1b24acb18718e63541088923David Greene prog = sys::Path(LLVM_PATH_FDP); 14500ad26ff5760ff2d1b24acb18718e63541088923David Greene#endif 14600ad26ff5760ff2d1b24acb18718e63541088923David Greene#if (HAVE_NEATO) 14740ef79d5e24d0a66345b4c9a1b97952478850d42Chris Lattner if (program == GraphProgram::NEATO) 14800ad26ff5760ff2d1b24acb18718e63541088923David Greene prog = sys::Path(LLVM_PATH_NEATO); 14900ad26ff5760ff2d1b24acb18718e63541088923David Greene#endif 15000ad26ff5760ff2d1b24acb18718e63541088923David Greene#if (HAVE_TWOPI) 15140ef79d5e24d0a66345b4c9a1b97952478850d42Chris Lattner if (program == GraphProgram::TWOPI) 15200ad26ff5760ff2d1b24acb18718e63541088923David Greene prog = sys::Path(LLVM_PATH_TWOPI); 15300ad26ff5760ff2d1b24acb18718e63541088923David Greene#endif 15400ad26ff5760ff2d1b24acb18718e63541088923David Greene#if (HAVE_CIRCO) 15540ef79d5e24d0a66345b4c9a1b97952478850d42Chris Lattner if (program == GraphProgram::CIRCO) 15600ad26ff5760ff2d1b24acb18718e63541088923David Greene prog = sys::Path(LLVM_PATH_CIRCO); 157229509a8bc2390c4c9c1bd20f777acf29911d452David Greene#endif 1589d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer 1599d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer std::vector<const char*> args; 160229509a8bc2390c4c9c1bd20f777acf29911d452David Greene args.push_back(prog.c_str()); 1619d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer args.push_back("-Tps"); 1629d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer args.push_back("-Nfontname=Courier"); 1639d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer args.push_back("-Gsize=7.5,10"); 1649d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer args.push_back(Filename.c_str()); 1659d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer args.push_back("-o"); 1669d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer args.push_back(PSFilename.c_str()); 1679d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer args.push_back(0); 168255cd51fbd771c0131a74eaf4385f1ea703a3c68Andrew Trick 1692d5e3acd2a69070c4e3550e014a54626e18bf12cDan Gohman errs() << "Running '" << prog.str() << "' program... "; 170229509a8bc2390c4c9c1bd20f777acf29911d452David Greene 171255cd51fbd771c0131a74eaf4385f1ea703a3c68Andrew Trick if (!ExecGraphViewer(prog, args, Filename, wait, ErrMsg)) 172459e13a9cef943c582f55d26ce03a0dc7409edffChris Lattner return; 1739d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer 174459e13a9cef943c582f55d26ce03a0dc7409edffChris Lattner sys::Path gv(LLVM_PATH_GV); 175459e13a9cef943c582f55d26ce03a0dc7409edffChris Lattner args.clear(); 176459e13a9cef943c582f55d26ce03a0dc7409edffChris Lattner args.push_back(gv.c_str()); 177459e13a9cef943c582f55d26ce03a0dc7409edffChris Lattner args.push_back(PSFilename.c_str()); 178459e13a9cef943c582f55d26ce03a0dc7409edffChris Lattner args.push_back("--spartan"); 179459e13a9cef943c582f55d26ce03a0dc7409edffChris Lattner args.push_back(0); 180255cd51fbd771c0131a74eaf4385f1ea703a3c68Andrew Trick 181459e13a9cef943c582f55d26ce03a0dc7409edffChris Lattner ErrMsg.clear(); 182255cd51fbd771c0131a74eaf4385f1ea703a3c68Andrew Trick if (!ExecGraphViewer(gv, args, PSFilename, wait, ErrMsg)) 183255cd51fbd771c0131a74eaf4385f1ea703a3c68Andrew Trick return; 184255cd51fbd771c0131a74eaf4385f1ea703a3c68Andrew Trick 1859d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer#elif HAVE_DOTTY 1869d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer sys::Path dotty(LLVM_PATH_DOTTY); 1879d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer 1889d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer std::vector<const char*> args; 18982493289e0234e0172313e845fb87306cf3687acChris Lattner args.push_back(dotty.c_str()); 1909d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer args.push_back(Filename.c_str()); 1919d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer args.push_back(0); 192255cd51fbd771c0131a74eaf4385f1ea703a3c68Andrew Trick 1937c57b7b80838eb48db03f4cfc7839864822c0112Chris Lattner// Dotty spawns another app and doesn't wait until it returns 1947c57b7b80838eb48db03f4cfc7839864822c0112Chris Lattner#if defined (__MINGW32__) || defined (_WINDOWS) 195255cd51fbd771c0131a74eaf4385f1ea703a3c68Andrew Trick wait = false; 1969d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer#endif 197255cd51fbd771c0131a74eaf4385f1ea703a3c68Andrew Trick errs() << "Running 'dotty' program... "; 198255cd51fbd771c0131a74eaf4385f1ea703a3c68Andrew Trick if (!ExecGraphViewer(dotty, args, Filename, wait, ErrMsg)) 199255cd51fbd771c0131a74eaf4385f1ea703a3c68Andrew Trick return; 2009d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer#endif 2019d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer} 202