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; 71cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines std::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 81cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines// Execute the graph viewer. Return true if there were errors. 82cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesstatic bool ExecGraphViewer(StringRef ExecPath, std::vector<const char *> &args, 83cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines StringRef Filename, bool wait, 84cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines std::string &ErrMsg) { 85cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines assert(args.back() == nullptr); 86255cd51fbd771c0131a74eaf4385f1ea703a3c68Andrew Trick if (wait) { 87cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines if (sys::ExecuteAndWait(ExecPath, args.data(), nullptr, nullptr, 0, 0, 88cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines &ErrMsg)) { 89255cd51fbd771c0131a74eaf4385f1ea703a3c68Andrew Trick errs() << "Error: " << ErrMsg << "\n"; 90cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines return true; 91255cd51fbd771c0131a74eaf4385f1ea703a3c68Andrew Trick } 9236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines sys::fs::remove(Filename); 93255cd51fbd771c0131a74eaf4385f1ea703a3c68Andrew Trick errs() << " done. \n"; 94cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines } else { 95cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines sys::ExecuteNoWait(ExecPath, args.data(), nullptr, nullptr, 0, &ErrMsg); 96255cd51fbd771c0131a74eaf4385f1ea703a3c68Andrew Trick errs() << "Remember to erase graph file: " << Filename.str() << "\n"; 97255cd51fbd771c0131a74eaf4385f1ea703a3c68Andrew Trick } 98cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines return false; 99cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines} 100cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines 101cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesstruct GraphSession { 102cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines std::string LogBuffer; 103cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines bool TryFindProgram(StringRef Names, std::string &ProgramPath) { 104cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines raw_string_ostream Log(LogBuffer); 105cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines SmallVector<StringRef, 8> parts; 106cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines Names.split(parts, "|"); 107cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines for (auto Name : parts) { 108cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines ProgramPath = sys::FindProgramByName(Name); 109cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines if (!ProgramPath.empty()) 110cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines return true; 111cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines Log << " Tried '" << Name << "'\n"; 112cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines } 113cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines return false; 114cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines } 115cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines}; 116cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines 117cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesstatic const char *getProgramName(GraphProgram::Name program) { 118cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines switch (program) { 119cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines case GraphProgram::DOT: 120cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines return "dot"; 121cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines case GraphProgram::FDP: 122cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines return "fdp"; 123cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines case GraphProgram::NEATO: 124cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines return "neato"; 125cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines case GraphProgram::TWOPI: 126cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines return "twopi"; 127cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines case GraphProgram::CIRCO: 128cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines return "circo"; 129cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines } 130cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines llvm_unreachable("bad kind"); 131255cd51fbd771c0131a74eaf4385f1ea703a3c68Andrew Trick} 132103289e9383ad1eb66caf28c9b166aebce963a35Chris Lattner 133cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesbool llvm::DisplayGraph(StringRef FilenameRef, bool wait, 13400ad26ff5760ff2d1b24acb18718e63541088923David Greene GraphProgram::Name program) { 135aaf4c1e2ee0887e5e8cb9768186ff5e72e8a3e91Rafael Espindola std::string Filename = FilenameRef; 136255cd51fbd771c0131a74eaf4385f1ea703a3c68Andrew Trick wait &= !ViewBackground; 1378ea5ecb0564b8822c70ad84202471f03e2690da7Reid Spencer std::string ErrMsg; 138cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines std::string ViewerPath; 139cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines GraphSession S; 140cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines 141cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines // Graphviz 142cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines if (S.TryFindProgram("Graphviz", ViewerPath)) { 143cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines std::vector<const char *> args; 144cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines args.push_back(ViewerPath.c_str()); 145cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines args.push_back(Filename.c_str()); 146cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines args.push_back(nullptr); 147cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines 148cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines errs() << "Running 'Graphviz' program... "; 149cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines return ExecGraphViewer(ViewerPath, args, Filename, wait, ErrMsg); 15048fd5a79e023bf6a647dfabb2bbb4c2f98617b81Dan Gohman } 151255cd51fbd771c0131a74eaf4385f1ea703a3c68Andrew Trick 152cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines // xdot 153cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines if (S.TryFindProgram("xdot|xdot.py", ViewerPath)) { 154cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines std::vector<const char *> args; 155cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines args.push_back(ViewerPath.c_str()); 156cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines args.push_back(Filename.c_str()); 15748fd5a79e023bf6a647dfabb2bbb4c2f98617b81Dan Gohman 158cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines args.push_back("-f"); 159cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines args.push_back(getProgramName(program)); 16048fd5a79e023bf6a647dfabb2bbb4c2f98617b81Dan Gohman 161cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines args.push_back(nullptr); 16200ad26ff5760ff2d1b24acb18718e63541088923David Greene 163cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines errs() << "Running 'xdot.py' program... "; 164cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines return ExecGraphViewer(ViewerPath, args, Filename, wait, ErrMsg); 165cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines } 16600ad26ff5760ff2d1b24acb18718e63541088923David Greene 167cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines enum PSViewerKind { PSV_None, PSV_OSXOpen, PSV_XDGOpen, PSV_Ghostview }; 168cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines PSViewerKind PSViewer = PSV_None; 169cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines#ifdef __APPLE__ 170cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines if (!PSViewer && S.TryFindProgram("open", ViewerPath)) 171cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines PSViewer = PSV_OSXOpen; 172229509a8bc2390c4c9c1bd20f777acf29911d452David Greene#endif 173cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines if (!PSViewer && S.TryFindProgram("gv", ViewerPath)) 174cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines PSViewer = PSV_Ghostview; 175cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines if (!PSViewer && S.TryFindProgram("xdg-open", ViewerPath)) 176cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines PSViewer = PSV_XDGOpen; 177cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines 178cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines // PostScript graph generator + PostScript viewer 179cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines std::string GeneratorPath; 180cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines if (PSViewer && 181cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines (S.TryFindProgram(getProgramName(program), GeneratorPath) || 182cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines S.TryFindProgram("dot|fdp|neato|twopi|circo", GeneratorPath))) { 183cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines std::string PSFilename = Filename + ".ps"; 184cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines 185cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines std::vector<const char *> args; 186cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines args.push_back(GeneratorPath.c_str()); 187cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines args.push_back("-Tps"); 188cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines args.push_back("-Nfontname=Courier"); 189cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines args.push_back("-Gsize=7.5,10"); 190cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines args.push_back(Filename.c_str()); 191cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines args.push_back("-o"); 192cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines args.push_back(PSFilename.c_str()); 193cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines args.push_back(nullptr); 194cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines 195cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines errs() << "Running '" << GeneratorPath << "' program... "; 196cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines 197cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines if (ExecGraphViewer(GeneratorPath, args, Filename, wait, ErrMsg)) 198cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines return true; 199cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines 200cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines args.clear(); 201cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines args.push_back(ViewerPath.c_str()); 202cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines switch (PSViewer) { 203cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines case PSV_OSXOpen: 204cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines args.push_back("-W"); 205cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines args.push_back(PSFilename.c_str()); 206cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines break; 207cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines case PSV_XDGOpen: 208cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines wait = false; 209cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines args.push_back(PSFilename.c_str()); 210cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines break; 211cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines case PSV_Ghostview: 212cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines args.push_back("--spartan"); 213cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines args.push_back(PSFilename.c_str()); 214cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines break; 215cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines case PSV_None: 216cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines llvm_unreachable("Invalid viewer"); 217cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines } 218cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines args.push_back(nullptr); 2199d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer 220cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines ErrMsg.clear(); 221cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines return ExecGraphViewer(ViewerPath, args, PSFilename, wait, ErrMsg); 222cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines } 2239d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer 224cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines // dotty 225cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines if (S.TryFindProgram("dotty", ViewerPath)) { 226cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines std::vector<const char *> args; 227cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines args.push_back(ViewerPath.c_str()); 228cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines args.push_back(Filename.c_str()); 229cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines args.push_back(nullptr); 230255cd51fbd771c0131a74eaf4385f1ea703a3c68Andrew Trick 2317c57b7b80838eb48db03f4cfc7839864822c0112Chris Lattner// Dotty spawns another app and doesn't wait until it returns 232cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines#ifdef LLVM_ON_WIN32 233cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines wait = false; 2349d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer#endif 235cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines errs() << "Running 'dotty' program... "; 236cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines return ExecGraphViewer(ViewerPath, args, Filename, wait, ErrMsg); 237cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines } 238cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines 239cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines errs() << "Error: Couldn't find a usable graph viewer program:\n"; 240cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines errs() << S.LogBuffer << "\n"; 241cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines return true; 2429d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer} 243