LLVM API Documentation
00001 //===-- GraphWriter.cpp - Implements GraphWriter support routines ---------===// 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 implements misc. GraphWriter support routines. 00011 // 00012 //===----------------------------------------------------------------------===// 00013 00014 #include "llvm/Support/GraphWriter.h" 00015 #include "llvm/Config/config.h" 00016 #include "llvm/Support/CommandLine.h" 00017 #include "llvm/Support/Path.h" 00018 #include "llvm/Support/Program.h" 00019 using namespace llvm; 00020 00021 static cl::opt<bool> ViewBackground("view-background", cl::Hidden, 00022 cl::desc("Execute graph viewer in the background. Creates tmp file litter.")); 00023 00024 std::string llvm::DOT::EscapeString(const std::string &Label) { 00025 std::string Str(Label); 00026 for (unsigned i = 0; i != Str.length(); ++i) 00027 switch (Str[i]) { 00028 case '\n': 00029 Str.insert(Str.begin()+i, '\\'); // Escape character... 00030 ++i; 00031 Str[i] = 'n'; 00032 break; 00033 case '\t': 00034 Str.insert(Str.begin()+i, ' '); // Convert to two spaces 00035 ++i; 00036 Str[i] = ' '; 00037 break; 00038 case '\\': 00039 if (i+1 != Str.length()) 00040 switch (Str[i+1]) { 00041 case 'l': continue; // don't disturb \l 00042 case '|': case '{': case '}': 00043 Str.erase(Str.begin()+i); continue; 00044 default: break; 00045 } 00046 case '{': case '}': 00047 case '<': case '>': 00048 case '|': case '"': 00049 Str.insert(Str.begin()+i, '\\'); // Escape character... 00050 ++i; // don't infinite loop 00051 break; 00052 } 00053 return Str; 00054 } 00055 00056 /// \brief Get a color string for this node number. Simply round-robin selects 00057 /// from a reasonable number of colors. 00058 StringRef llvm::DOT::getColorString(unsigned ColorNumber) { 00059 static const int NumColors = 20; 00060 static const char* Colors[NumColors] = { 00061 "aaaaaa", "aa0000", "00aa00", "aa5500", "0055ff", "aa00aa", "00aaaa", 00062 "555555", "ff5555", "55ff55", "ffff55", "5555ff", "ff55ff", "55ffff", 00063 "ffaaaa", "aaffaa", "ffffaa", "aaaaff", "ffaaff", "aaffff"}; 00064 return Colors[ColorNumber % NumColors]; 00065 } 00066 00067 // Execute the graph viewer. Return true if successful. 00068 static bool LLVM_ATTRIBUTE_UNUSED 00069 ExecGraphViewer(const sys::Path &ExecPath, std::vector<const char*> &args, 00070 const sys::Path &Filename, bool wait, std::string &ErrMsg) { 00071 if (wait) { 00072 if (sys::Program::ExecuteAndWait(ExecPath, &args[0],0,0,0,0,&ErrMsg)) { 00073 errs() << "Error: " << ErrMsg << "\n"; 00074 return false; 00075 } 00076 Filename.eraseFromDisk(); 00077 errs() << " done. \n"; 00078 } 00079 else { 00080 sys::Program::ExecuteNoWait(ExecPath, &args[0],0,0,0,&ErrMsg); 00081 errs() << "Remember to erase graph file: " << Filename.str() << "\n"; 00082 } 00083 return true; 00084 } 00085 00086 void llvm::DisplayGraph(const sys::Path &Filename, bool wait, 00087 GraphProgram::Name program) { 00088 wait &= !ViewBackground; 00089 std::string ErrMsg; 00090 #if HAVE_GRAPHVIZ 00091 sys::Path Graphviz(LLVM_PATH_GRAPHVIZ); 00092 00093 std::vector<const char*> args; 00094 args.push_back(Graphviz.c_str()); 00095 args.push_back(Filename.c_str()); 00096 args.push_back(0); 00097 00098 errs() << "Running 'Graphviz' program... "; 00099 if (!ExecGraphViewer(Graphviz, args, Filename, wait, ErrMsg)) 00100 return; 00101 00102 #elif HAVE_XDOT_PY 00103 std::vector<const char*> args; 00104 args.push_back(LLVM_PATH_XDOT_PY); 00105 args.push_back(Filename.c_str()); 00106 00107 switch (program) { 00108 case GraphProgram::DOT: args.push_back("-f"); args.push_back("dot"); break; 00109 case GraphProgram::FDP: args.push_back("-f"); args.push_back("fdp"); break; 00110 case GraphProgram::NEATO: args.push_back("-f"); args.push_back("neato");break; 00111 case GraphProgram::TWOPI: args.push_back("-f"); args.push_back("twopi");break; 00112 case GraphProgram::CIRCO: args.push_back("-f"); args.push_back("circo");break; 00113 } 00114 00115 args.push_back(0); 00116 00117 errs() << "Running 'xdot.py' program... "; 00118 if (!ExecGraphViewer(sys::Path(LLVM_PATH_XDOT_PY), args, Filename, wait, ErrMsg)) 00119 return; 00120 00121 #elif (HAVE_GV && (HAVE_DOT || HAVE_FDP || HAVE_NEATO || \ 00122 HAVE_TWOPI || HAVE_CIRCO)) 00123 sys::Path PSFilename = Filename; 00124 PSFilename.appendSuffix("ps"); 00125 00126 sys::Path prog; 00127 00128 // Set default grapher 00129 #if HAVE_CIRCO 00130 prog = sys::Path(LLVM_PATH_CIRCO); 00131 #endif 00132 #if HAVE_TWOPI 00133 prog = sys::Path(LLVM_PATH_TWOPI); 00134 #endif 00135 #if HAVE_NEATO 00136 prog = sys::Path(LLVM_PATH_NEATO); 00137 #endif 00138 #if HAVE_FDP 00139 prog = sys::Path(LLVM_PATH_FDP); 00140 #endif 00141 #if HAVE_DOT 00142 prog = sys::Path(LLVM_PATH_DOT); 00143 #endif 00144 00145 // Find which program the user wants 00146 #if HAVE_DOT 00147 if (program == GraphProgram::DOT) 00148 prog = sys::Path(LLVM_PATH_DOT); 00149 #endif 00150 #if (HAVE_FDP) 00151 if (program == GraphProgram::FDP) 00152 prog = sys::Path(LLVM_PATH_FDP); 00153 #endif 00154 #if (HAVE_NEATO) 00155 if (program == GraphProgram::NEATO) 00156 prog = sys::Path(LLVM_PATH_NEATO); 00157 #endif 00158 #if (HAVE_TWOPI) 00159 if (program == GraphProgram::TWOPI) 00160 prog = sys::Path(LLVM_PATH_TWOPI); 00161 #endif 00162 #if (HAVE_CIRCO) 00163 if (program == GraphProgram::CIRCO) 00164 prog = sys::Path(LLVM_PATH_CIRCO); 00165 #endif 00166 00167 std::vector<const char*> args; 00168 args.push_back(prog.c_str()); 00169 args.push_back("-Tps"); 00170 args.push_back("-Nfontname=Courier"); 00171 args.push_back("-Gsize=7.5,10"); 00172 args.push_back(Filename.c_str()); 00173 args.push_back("-o"); 00174 args.push_back(PSFilename.c_str()); 00175 args.push_back(0); 00176 00177 errs() << "Running '" << prog.str() << "' program... "; 00178 00179 if (!ExecGraphViewer(prog, args, Filename, wait, ErrMsg)) 00180 return; 00181 00182 sys::Path gv(LLVM_PATH_GV); 00183 args.clear(); 00184 args.push_back(gv.c_str()); 00185 args.push_back(PSFilename.c_str()); 00186 args.push_back("--spartan"); 00187 args.push_back(0); 00188 00189 ErrMsg.clear(); 00190 if (!ExecGraphViewer(gv, args, PSFilename, wait, ErrMsg)) 00191 return; 00192 00193 #elif HAVE_DOTTY 00194 sys::Path dotty(LLVM_PATH_DOTTY); 00195 00196 std::vector<const char*> args; 00197 args.push_back(dotty.c_str()); 00198 args.push_back(Filename.c_str()); 00199 args.push_back(0); 00200 00201 // Dotty spawns another app and doesn't wait until it returns 00202 #if defined (__MINGW32__) || defined (_WINDOWS) 00203 wait = false; 00204 #endif 00205 errs() << "Running 'dotty' program... "; 00206 if (!ExecGraphViewer(dotty, args, Filename, wait, ErrMsg)) 00207 return; 00208 #endif 00209 }