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
1465a392ebeae214ccb25f4d5ec856688e4e690e0dChris Lattner#include "llvm/Support/GraphWriter.h"
15d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include "llvm/Config/config.h"
16d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include "llvm/Support/CommandLine.h"
174d39727eaee3e7cb5c72dba469855cb538110782Rafael Espindola#include "llvm/Support/FileSystem.h"
181f6efa3996dd1929fbc129203ce5009b620e6969Michael J. Spencer#include "llvm/Support/Path.h"
191f6efa3996dd1929fbc129203ce5009b620e6969Michael J. Spencer#include "llvm/Support/Program.h"
209d5b532de9bdca37810a59a93a69128441b02c55Reid Spencerusing namespace llvm;
219d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer
22255cd51fbd771c0131a74eaf4385f1ea703a3c68Andrew Trickstatic cl::opt<bool> ViewBackground("view-background", cl::Hidden,
23255cd51fbd771c0131a74eaf4385f1ea703a3c68Andrew Trick  cl::desc("Execute graph viewer in the background. Creates tmp file litter."));
24255cd51fbd771c0131a74eaf4385f1ea703a3c68Andrew Trick
25103289e9383ad1eb66caf28c9b166aebce963a35Chris Lattnerstd::string llvm::DOT::EscapeString(const std::string &Label) {
26103289e9383ad1eb66caf28c9b166aebce963a35Chris Lattner  std::string Str(Label);
27103289e9383ad1eb66caf28c9b166aebce963a35Chris Lattner  for (unsigned i = 0; i != Str.length(); ++i)
28103289e9383ad1eb66caf28c9b166aebce963a35Chris Lattner  switch (Str[i]) {
29103289e9383ad1eb66caf28c9b166aebce963a35Chris Lattner    case '\n':
30103289e9383ad1eb66caf28c9b166aebce963a35Chris Lattner      Str.insert(Str.begin()+i, '\\');  // Escape character...
31103289e9383ad1eb66caf28c9b166aebce963a35Chris Lattner      ++i;
32103289e9383ad1eb66caf28c9b166aebce963a35Chris Lattner      Str[i] = 'n';
33103289e9383ad1eb66caf28c9b166aebce963a35Chris Lattner      break;
34103289e9383ad1eb66caf28c9b166aebce963a35Chris Lattner    case '\t':
35103289e9383ad1eb66caf28c9b166aebce963a35Chris Lattner      Str.insert(Str.begin()+i, ' ');  // Convert to two spaces
36103289e9383ad1eb66caf28c9b166aebce963a35Chris Lattner      ++i;
37103289e9383ad1eb66caf28c9b166aebce963a35Chris Lattner      Str[i] = ' ';
38103289e9383ad1eb66caf28c9b166aebce963a35Chris Lattner      break;
39103289e9383ad1eb66caf28c9b166aebce963a35Chris Lattner    case '\\':
40103289e9383ad1eb66caf28c9b166aebce963a35Chris Lattner      if (i+1 != Str.length())
41103289e9383ad1eb66caf28c9b166aebce963a35Chris Lattner        switch (Str[i+1]) {
42103289e9383ad1eb66caf28c9b166aebce963a35Chris Lattner          case 'l': continue; // don't disturb \l
43103289e9383ad1eb66caf28c9b166aebce963a35Chris Lattner          case '|': case '{': case '}':
44103289e9383ad1eb66caf28c9b166aebce963a35Chris Lattner            Str.erase(Str.begin()+i); continue;
45103289e9383ad1eb66caf28c9b166aebce963a35Chris Lattner          default: break;
46103289e9383ad1eb66caf28c9b166aebce963a35Chris Lattner        }
47103289e9383ad1eb66caf28c9b166aebce963a35Chris Lattner    case '{': case '}':
48103289e9383ad1eb66caf28c9b166aebce963a35Chris Lattner    case '<': case '>':
49103289e9383ad1eb66caf28c9b166aebce963a35Chris Lattner    case '|': case '"':
50103289e9383ad1eb66caf28c9b166aebce963a35Chris Lattner      Str.insert(Str.begin()+i, '\\');  // Escape character...
51103289e9383ad1eb66caf28c9b166aebce963a35Chris Lattner      ++i;  // don't infinite loop
52103289e9383ad1eb66caf28c9b166aebce963a35Chris Lattner      break;
53103289e9383ad1eb66caf28c9b166aebce963a35Chris Lattner  }
54103289e9383ad1eb66caf28c9b166aebce963a35Chris Lattner  return Str;
55103289e9383ad1eb66caf28c9b166aebce963a35Chris Lattner}
56103289e9383ad1eb66caf28c9b166aebce963a35Chris Lattner
57c6ada8e5f38168f13830e448f2b9e2d8e3eac72bAndrew Trick/// \brief Get a color string for this node number. Simply round-robin selects
58c6ada8e5f38168f13830e448f2b9e2d8e3eac72bAndrew Trick/// from a reasonable number of colors.
59c6ada8e5f38168f13830e448f2b9e2d8e3eac72bAndrew TrickStringRef llvm::DOT::getColorString(unsigned ColorNumber) {
60c6ada8e5f38168f13830e448f2b9e2d8e3eac72bAndrew Trick  static const int NumColors = 20;
61c6ada8e5f38168f13830e448f2b9e2d8e3eac72bAndrew Trick  static const char* Colors[NumColors] = {
62c6ada8e5f38168f13830e448f2b9e2d8e3eac72bAndrew Trick    "aaaaaa", "aa0000", "00aa00", "aa5500", "0055ff", "aa00aa", "00aaaa",
63c6ada8e5f38168f13830e448f2b9e2d8e3eac72bAndrew Trick    "555555", "ff5555", "55ff55", "ffff55", "5555ff", "ff55ff", "55ffff",
64c6ada8e5f38168f13830e448f2b9e2d8e3eac72bAndrew Trick    "ffaaaa", "aaffaa", "ffffaa", "aaaaff", "ffaaff", "aaffff"};
65c6ada8e5f38168f13830e448f2b9e2d8e3eac72bAndrew Trick  return Colors[ColorNumber % NumColors];
66c6ada8e5f38168f13830e448f2b9e2d8e3eac72bAndrew Trick}
67c6ada8e5f38168f13830e448f2b9e2d8e3eac72bAndrew Trick
68a54ba12ae7a8cf826b65d2e4a882258e952c35b1Rafael Espindolastd::string llvm::createGraphFilename(const Twine &Name, int &FD) {
69a54ba12ae7a8cf826b65d2e4a882258e952c35b1Rafael Espindola  FD = -1;
70a54ba12ae7a8cf826b65d2e4a882258e952c35b1Rafael Espindola  SmallString<128> Filename;
711276b396130a0cdbbb8e6c05a6e43123df18ed60Rafael Espindola  error_code EC = sys::fs::createTemporaryFile(Name, "dot", FD, Filename);
72a54ba12ae7a8cf826b65d2e4a882258e952c35b1Rafael Espindola  if (EC) {
73a54ba12ae7a8cf826b65d2e4a882258e952c35b1Rafael Espindola    errs() << "Error: " << EC.message() << "\n";
744d39727eaee3e7cb5c72dba469855cb538110782Rafael Espindola    return "";
754d39727eaee3e7cb5c72dba469855cb538110782Rafael Espindola  }
76a54ba12ae7a8cf826b65d2e4a882258e952c35b1Rafael Espindola
77a54ba12ae7a8cf826b65d2e4a882258e952c35b1Rafael Espindola  errs() << "Writing '" << Filename << "'... ";
784d39727eaee3e7cb5c72dba469855cb538110782Rafael Espindola  return Filename.str();
794d39727eaee3e7cb5c72dba469855cb538110782Rafael Espindola}
804d39727eaee3e7cb5c72dba469855cb538110782Rafael Espindola
81255cd51fbd771c0131a74eaf4385f1ea703a3c68Andrew Trick// Execute the graph viewer. Return true if successful.
82cdaedf9f4acc60f8a7a1042af4be04291465e213Benjamin Kramerstatic bool LLVM_ATTRIBUTE_UNUSED
834d39727eaee3e7cb5c72dba469855cb538110782Rafael EspindolaExecGraphViewer(StringRef ExecPath, std::vector<const char*> &args,
844d39727eaee3e7cb5c72dba469855cb538110782Rafael Espindola                StringRef Filename, bool wait, std::string &ErrMsg) {
85255cd51fbd771c0131a74eaf4385f1ea703a3c68Andrew Trick  if (wait) {
86675e0ac0bfd6fb78423d9fbee9f50c1dec62c111Rafael Espindola    if (sys::ExecuteAndWait(ExecPath, &args[0],0,0,0,0,&ErrMsg)) {
87255cd51fbd771c0131a74eaf4385f1ea703a3c68Andrew Trick      errs() << "Error: " << ErrMsg << "\n";
88255cd51fbd771c0131a74eaf4385f1ea703a3c68Andrew Trick      return false;
89255cd51fbd771c0131a74eaf4385f1ea703a3c68Andrew Trick    }
904d39727eaee3e7cb5c72dba469855cb538110782Rafael Espindola    bool Existed;
914d39727eaee3e7cb5c72dba469855cb538110782Rafael Espindola    sys::fs::remove(Filename, Existed);
92255cd51fbd771c0131a74eaf4385f1ea703a3c68Andrew Trick    errs() << " done. \n";
93255cd51fbd771c0131a74eaf4385f1ea703a3c68Andrew Trick  }
94255cd51fbd771c0131a74eaf4385f1ea703a3c68Andrew Trick  else {
95675e0ac0bfd6fb78423d9fbee9f50c1dec62c111Rafael Espindola    sys::ExecuteNoWait(ExecPath, &args[0],0,0,0,&ErrMsg);
96255cd51fbd771c0131a74eaf4385f1ea703a3c68Andrew Trick    errs() << "Remember to erase graph file: " << Filename.str() << "\n";
97255cd51fbd771c0131a74eaf4385f1ea703a3c68Andrew Trick  }
98255cd51fbd771c0131a74eaf4385f1ea703a3c68Andrew Trick  return true;
99255cd51fbd771c0131a74eaf4385f1ea703a3c68Andrew Trick}
100103289e9383ad1eb66caf28c9b166aebce963a35Chris Lattner
101aaf4c1e2ee0887e5e8cb9768186ff5e72e8a3e91Rafael Espindolavoid llvm::DisplayGraph(StringRef FilenameRef, bool wait,
10200ad26ff5760ff2d1b24acb18718e63541088923David Greene                        GraphProgram::Name program) {
103aaf4c1e2ee0887e5e8cb9768186ff5e72e8a3e91Rafael Espindola  std::string Filename = FilenameRef;
104255cd51fbd771c0131a74eaf4385f1ea703a3c68Andrew Trick  wait &= !ViewBackground;
1058ea5ecb0564b8822c70ad84202471f03e2690da7Reid Spencer  std::string ErrMsg;
1069d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer#if HAVE_GRAPHVIZ
107a65ee83ea96f367eff8d00b86c44b38d04819d1aRafael Espindola  std::string Graphviz(LLVM_PATH_GRAPHVIZ);
1089d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer
1099d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer  std::vector<const char*> args;
1109d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer  args.push_back(Graphviz.c_str());
1119d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer  args.push_back(Filename.c_str());
1129d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer  args.push_back(0);
113255cd51fbd771c0131a74eaf4385f1ea703a3c68Andrew Trick
114103289e9383ad1eb66caf28c9b166aebce963a35Chris Lattner  errs() << "Running 'Graphviz' program... ";
115255cd51fbd771c0131a74eaf4385f1ea703a3c68Andrew Trick  if (!ExecGraphViewer(Graphviz, args, Filename, wait, ErrMsg))
116644801a199794a74bdc4655f6af5bc05f8153dc8Dan Gohman    return;
11700ad26ff5760ff2d1b24acb18718e63541088923David Greene
118e1e7310749008a515ddd5bf6398df17644f53b33Matt Arsenault#elif HAVE_XDOT
11948fd5a79e023bf6a647dfabb2bbb4c2f98617b81Dan Gohman  std::vector<const char*> args;
120e1e7310749008a515ddd5bf6398df17644f53b33Matt Arsenault  args.push_back(LLVM_PATH_XDOT);
12148fd5a79e023bf6a647dfabb2bbb4c2f98617b81Dan Gohman  args.push_back(Filename.c_str());
12248fd5a79e023bf6a647dfabb2bbb4c2f98617b81Dan Gohman
12348fd5a79e023bf6a647dfabb2bbb4c2f98617b81Dan Gohman  switch (program) {
12448fd5a79e023bf6a647dfabb2bbb4c2f98617b81Dan Gohman  case GraphProgram::DOT:   args.push_back("-f"); args.push_back("dot"); break;
12548fd5a79e023bf6a647dfabb2bbb4c2f98617b81Dan Gohman  case GraphProgram::FDP:   args.push_back("-f"); args.push_back("fdp"); break;
12648fd5a79e023bf6a647dfabb2bbb4c2f98617b81Dan Gohman  case GraphProgram::NEATO: args.push_back("-f"); args.push_back("neato");break;
12748fd5a79e023bf6a647dfabb2bbb4c2f98617b81Dan Gohman  case GraphProgram::TWOPI: args.push_back("-f"); args.push_back("twopi");break;
12848fd5a79e023bf6a647dfabb2bbb4c2f98617b81Dan Gohman  case GraphProgram::CIRCO: args.push_back("-f"); args.push_back("circo");break;
12948fd5a79e023bf6a647dfabb2bbb4c2f98617b81Dan Gohman  }
130255cd51fbd771c0131a74eaf4385f1ea703a3c68Andrew Trick
13148fd5a79e023bf6a647dfabb2bbb4c2f98617b81Dan Gohman  args.push_back(0);
13248fd5a79e023bf6a647dfabb2bbb4c2f98617b81Dan Gohman
13348fd5a79e023bf6a647dfabb2bbb4c2f98617b81Dan Gohman  errs() << "Running 'xdot.py' program... ";
134e1e7310749008a515ddd5bf6398df17644f53b33Matt Arsenault  if (!ExecGraphViewer(LLVM_PATH_XDOT, args, Filename, wait, ErrMsg))
135644801a199794a74bdc4655f6af5bc05f8153dc8Dan Gohman    return;
13648fd5a79e023bf6a647dfabb2bbb4c2f98617b81Dan Gohman
13700ad26ff5760ff2d1b24acb18718e63541088923David Greene#elif (HAVE_GV && (HAVE_DOT || HAVE_FDP || HAVE_NEATO || \
13800ad26ff5760ff2d1b24acb18718e63541088923David Greene                   HAVE_TWOPI || HAVE_CIRCO))
1392ebb97792dceb9729df690ec53cea1a592edfe52Rafael Espindola  std::string PSFilename = Filename + ".ps";
1404d39727eaee3e7cb5c72dba469855cb538110782Rafael Espindola  std::string prog;
14100ad26ff5760ff2d1b24acb18718e63541088923David Greene
14200ad26ff5760ff2d1b24acb18718e63541088923David Greene  // Set default grapher
14300ad26ff5760ff2d1b24acb18718e63541088923David Greene#if HAVE_CIRCO
1444d39727eaee3e7cb5c72dba469855cb538110782Rafael Espindola  prog = LLVM_PATH_CIRCO;
14500ad26ff5760ff2d1b24acb18718e63541088923David Greene#endif
14600ad26ff5760ff2d1b24acb18718e63541088923David Greene#if HAVE_TWOPI
1474d39727eaee3e7cb5c72dba469855cb538110782Rafael Espindola  prog = LLVM_PATH_TWOPI;
14800ad26ff5760ff2d1b24acb18718e63541088923David Greene#endif
14900ad26ff5760ff2d1b24acb18718e63541088923David Greene#if HAVE_NEATO
1504d39727eaee3e7cb5c72dba469855cb538110782Rafael Espindola  prog = LLVM_PATH_NEATO;
15100ad26ff5760ff2d1b24acb18718e63541088923David Greene#endif
152229509a8bc2390c4c9c1bd20f777acf29911d452David Greene#if HAVE_FDP
1534d39727eaee3e7cb5c72dba469855cb538110782Rafael Espindola  prog = LLVM_PATH_FDP;
15400ad26ff5760ff2d1b24acb18718e63541088923David Greene#endif
15500ad26ff5760ff2d1b24acb18718e63541088923David Greene#if HAVE_DOT
1564d39727eaee3e7cb5c72dba469855cb538110782Rafael Espindola  prog = LLVM_PATH_DOT;
15700ad26ff5760ff2d1b24acb18718e63541088923David Greene#endif
15800ad26ff5760ff2d1b24acb18718e63541088923David Greene
15900ad26ff5760ff2d1b24acb18718e63541088923David Greene  // Find which program the user wants
16000ad26ff5760ff2d1b24acb18718e63541088923David Greene#if HAVE_DOT
16140ef79d5e24d0a66345b4c9a1b97952478850d42Chris Lattner  if (program == GraphProgram::DOT)
1624d39727eaee3e7cb5c72dba469855cb538110782Rafael Espindola    prog = LLVM_PATH_DOT;
16300ad26ff5760ff2d1b24acb18718e63541088923David Greene#endif
16400ad26ff5760ff2d1b24acb18718e63541088923David Greene#if (HAVE_FDP)
16540ef79d5e24d0a66345b4c9a1b97952478850d42Chris Lattner  if (program == GraphProgram::FDP)
1664d39727eaee3e7cb5c72dba469855cb538110782Rafael Espindola    prog = LLVM_PATH_FDP;
16700ad26ff5760ff2d1b24acb18718e63541088923David Greene#endif
16800ad26ff5760ff2d1b24acb18718e63541088923David Greene#if (HAVE_NEATO)
16940ef79d5e24d0a66345b4c9a1b97952478850d42Chris Lattner  if (program == GraphProgram::NEATO)
1704d39727eaee3e7cb5c72dba469855cb538110782Rafael Espindola    prog = LLVM_PATH_NEATO;
17100ad26ff5760ff2d1b24acb18718e63541088923David Greene#endif
17200ad26ff5760ff2d1b24acb18718e63541088923David Greene#if (HAVE_TWOPI)
17340ef79d5e24d0a66345b4c9a1b97952478850d42Chris Lattner  if (program == GraphProgram::TWOPI)
1744d39727eaee3e7cb5c72dba469855cb538110782Rafael Espindola    prog = LLVM_PATH_TWOPI;
17500ad26ff5760ff2d1b24acb18718e63541088923David Greene#endif
17600ad26ff5760ff2d1b24acb18718e63541088923David Greene#if (HAVE_CIRCO)
17740ef79d5e24d0a66345b4c9a1b97952478850d42Chris Lattner  if (program == GraphProgram::CIRCO)
1784d39727eaee3e7cb5c72dba469855cb538110782Rafael Espindola    prog = LLVM_PATH_CIRCO;
179229509a8bc2390c4c9c1bd20f777acf29911d452David Greene#endif
1809d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer
1819d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer  std::vector<const char*> args;
182229509a8bc2390c4c9c1bd20f777acf29911d452David Greene  args.push_back(prog.c_str());
1839d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer  args.push_back("-Tps");
1849d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer  args.push_back("-Nfontname=Courier");
1859d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer  args.push_back("-Gsize=7.5,10");
186aaf4c1e2ee0887e5e8cb9768186ff5e72e8a3e91Rafael Espindola  args.push_back(Filename.c_str());
1879d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer  args.push_back("-o");
1889d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer  args.push_back(PSFilename.c_str());
1899d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer  args.push_back(0);
190255cd51fbd771c0131a74eaf4385f1ea703a3c68Andrew Trick
1914d39727eaee3e7cb5c72dba469855cb538110782Rafael Espindola  errs() << "Running '" << prog << "' program... ";
192229509a8bc2390c4c9c1bd20f777acf29911d452David Greene
193255cd51fbd771c0131a74eaf4385f1ea703a3c68Andrew Trick  if (!ExecGraphViewer(prog, args, Filename, wait, ErrMsg))
194459e13a9cef943c582f55d26ce03a0dc7409edffChris Lattner    return;
1959d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer
1964d39727eaee3e7cb5c72dba469855cb538110782Rafael Espindola  std::string gv(LLVM_PATH_GV);
197459e13a9cef943c582f55d26ce03a0dc7409edffChris Lattner  args.clear();
198459e13a9cef943c582f55d26ce03a0dc7409edffChris Lattner  args.push_back(gv.c_str());
199459e13a9cef943c582f55d26ce03a0dc7409edffChris Lattner  args.push_back(PSFilename.c_str());
200459e13a9cef943c582f55d26ce03a0dc7409edffChris Lattner  args.push_back("--spartan");
201459e13a9cef943c582f55d26ce03a0dc7409edffChris Lattner  args.push_back(0);
202255cd51fbd771c0131a74eaf4385f1ea703a3c68Andrew Trick
203459e13a9cef943c582f55d26ce03a0dc7409edffChris Lattner  ErrMsg.clear();
2042ebb97792dceb9729df690ec53cea1a592edfe52Rafael Espindola  if (!ExecGraphViewer(gv, args, PSFilename, wait, ErrMsg))
205255cd51fbd771c0131a74eaf4385f1ea703a3c68Andrew Trick    return;
206255cd51fbd771c0131a74eaf4385f1ea703a3c68Andrew Trick
2079d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer#elif HAVE_DOTTY
208a65ee83ea96f367eff8d00b86c44b38d04819d1aRafael Espindola  std::string dotty(LLVM_PATH_DOTTY);
2099d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer
2109d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer  std::vector<const char*> args;
21182493289e0234e0172313e845fb87306cf3687acChris Lattner  args.push_back(dotty.c_str());
2129d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer  args.push_back(Filename.c_str());
2139d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer  args.push_back(0);
214255cd51fbd771c0131a74eaf4385f1ea703a3c68Andrew Trick
2157c57b7b80838eb48db03f4cfc7839864822c0112Chris Lattner// Dotty spawns another app and doesn't wait until it returns
2167c57b7b80838eb48db03f4cfc7839864822c0112Chris Lattner#if defined (__MINGW32__) || defined (_WINDOWS)
217255cd51fbd771c0131a74eaf4385f1ea703a3c68Andrew Trick  wait = false;
2189d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer#endif
219255cd51fbd771c0131a74eaf4385f1ea703a3c68Andrew Trick  errs() << "Running 'dotty' program... ";
220255cd51fbd771c0131a74eaf4385f1ea703a3c68Andrew Trick  if (!ExecGraphViewer(dotty, args, Filename, wait, ErrMsg))
221255cd51fbd771c0131a74eaf4385f1ea703a3c68Andrew Trick    return;
2229d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer#endif
2239d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer}
224