20#include "llvm/Config/config.h"
32#include <system_error>
39struct CreateViewBackground {
42 cl::desc(
"Execute graph viewer in the background. "
43 "Creates tmp file litter."));
51struct CreateDAGGraphWriteLocation {
55 cl::desc(
"Location to place the DAG graphs selected to be viewed"));
59struct CreateNoOpenDAGViewer {
63 cl::desc(
"Don't open the DAG viewer program, just write the file"),
82 std::string Str(Label);
83 for (
unsigned i = 0; i != Str.length(); ++i)
86 Str.insert(Str.begin()+i,
'\\');
91 Str.insert(Str.begin()+i,
' ');
96 if (i+1 != Str.length())
99 case '|':
case '{':
case '}':
100 Str.erase(Str.begin()+i);
continue;
107 Str.insert(Str.begin()+i,
'\\');
117 static const int NumColors = 20;
118 static const char* Colors[NumColors] = {
119 "aaaaaa",
"aa0000",
"00aa00",
"aa5500",
"0055ff",
"aa00aa",
"00aaaa",
120 "555555",
"ff5555",
"55ff55",
"ffff55",
"5555ff",
"ff55ff",
"55ffff",
121 "ffaaaa",
"aaffaa",
"ffffaa",
"aaaaff",
"ffaaff",
"aaffff"};
122 return Colors[ColorNumber % NumColors];
126 const char ReplacementChar) {
127 std::string IllegalChars =
130 for (
char IllegalChar : IllegalChars)
141 std::string
N = Name.str();
157 errs() <<
"Error resolving path: " << path_EC.message() <<
"\n";
162 realpath +
"/" + CleansedName +
"-%%%%%%.dot", FD,
Filename);
166 errs() <<
"Error: " << EC.message() <<
"\n";
177 std::string &ErrMsg) {
180 errs() <<
"Error: " << ErrMsg <<
"\n";
184 errs() <<
" done. \n";
187 errs() <<
"Remember to erase graph file: " <<
Filename <<
"\n";
195 std::string LogBuffer;
197 bool TryFindProgram(StringRef Names, std::string &ProgramPath) {
198 raw_string_ostream
Log(LogBuffer);
200 Names.
split(parts,
'|');
201 for (
auto Name : parts) {
206 Log <<
" Tried '" <<
Name <<
"'\n";
232 std::string
Filename = std::string(FilenameRef);
234 std::string ViewerPath;
238 errs() <<
"Not opening graph viewer program as per options.\n";
243 wait &= !*ViewBackground;
244 if (S.TryFindProgram(
"open", ViewerPath)) {
245 std::vector<StringRef>
args;
246 args.push_back(ViewerPath);
248 args.push_back(
"-W");
250 errs() <<
"Trying 'open' program... ";
255 if (S.TryFindProgram(
"xdg-open", ViewerPath)) {
256 std::vector<StringRef>
args;
257 args.push_back(ViewerPath);
259 errs() <<
"Trying 'xdg-open' program... ";
265 if (S.TryFindProgram(
"Graphviz", ViewerPath)) {
266 std::vector<StringRef>
args;
267 args.push_back(ViewerPath);
270 errs() <<
"Running 'Graphviz' program... ";
275 if (S.TryFindProgram(
"xdot|xdot.py", ViewerPath)) {
276 std::vector<StringRef>
args;
277 args.push_back(ViewerPath);
280 args.push_back(
"-f");
283 errs() <<
"Running 'xdot.py' program... ";
294 ViewerKind Viewer = VK_None;
296 if (!Viewer && S.TryFindProgram(
"open", ViewerPath))
299 if (!Viewer && S.TryFindProgram(
"gv", ViewerPath))
300 Viewer = VK_Ghostview;
301 if (!Viewer && S.TryFindProgram(
"xdg-open", ViewerPath))
304 if (!Viewer && S.TryFindProgram(
"cmd", ViewerPath)) {
305 Viewer = VK_CmdStart;
310 std::string GeneratorPath;
313 S.TryFindProgram(
"dot|fdp|neato|twopi|circo", GeneratorPath))) {
315 Filename + (Viewer == VK_CmdStart ?
".pdf" :
".ps");
317 std::vector<StringRef>
args;
318 args.push_back(GeneratorPath);
319 if (Viewer == VK_CmdStart)
320 args.push_back(
"-Tpdf");
322 args.push_back(
"-Tps");
323 args.push_back(
"-Nfontname=Courier");
324 args.push_back(
"-Gsize=7.5,10");
326 args.push_back(
"-o");
329 errs() <<
"Running '" << GeneratorPath <<
"' program... ";
336 std::string StartArg;
339 args.push_back(ViewerPath);
342 args.push_back(
"-W");
350 args.push_back(
"--spartan");
354 args.push_back(
"/S");
355 args.push_back(
"/C");
358 args.push_back(StartArg);
369 if (S.TryFindProgram(
"dotty", ViewerPath)) {
370 std::vector<StringRef>
args;
371 args.push_back(ViewerPath);
378 errs() <<
"Running 'dotty' program... ";
382 errs() <<
"Error: Couldn't find a usable graph viewer program:\n";
383 errs() << S.LogBuffer <<
"\n";
Provides ErrorOr<T> smart pointer.
static std::string replaceIllegalFilenameChars(std::string Filename, const char ReplacementChar)
static bool ExecGraphViewer(StringRef ExecPath, std::vector< StringRef > &args, StringRef Filename, bool wait, std::string &ErrMsg)
static ManagedStatic< cl::opt< std::string >, CreateDAGGraphWriteLocation > DAGGraphWriteLocation
static ManagedStatic< cl::opt< bool >, CreateNoOpenDAGViewer > NoOpenDAGViewer
static const char * getProgramName(GraphProgram::Name program)
static cl::opt< std::string > OutputFilename("o", cl::desc("Output filename"), cl::value_desc("filename"), cl::init("-"))
static constexpr StringLiteral Filename
This file defines the SmallString class.
This file defines the SmallVector class.
ManagedStatic - This transparently changes the behavior of global statics to be lazily constructed on...
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
Represent a constant reference to a string, i.e.
std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
LLVM_ABI std::string EscapeString(const std::string &Label)
LLVM_ABI StringRef getColorString(unsigned NodeNumber)
Get a color string for this node number.
template class LLVM_TEMPLATE_ABI opt< bool >
initializer< Ty > init(const Ty &Val)
template class LLVM_TEMPLATE_ABI opt< std::string >
LLVM_ABI std::error_code createUniqueFile(const Twine &Model, int &ResultFD, SmallVectorImpl< char > &ResultPath, OpenFlags Flags=OF_None, unsigned Mode=all_read|all_write)
Create a uniquely named file.
LLVM_ABI std::error_code remove(const Twine &path, bool IgnoreNonExisting=true)
Remove path.
LLVM_ABI std::error_code real_path(const Twine &path, SmallVectorImpl< char > &output, bool expand_tilde=false)
Collapse all .
LLVM_ABI std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix, int &ResultFD, SmallVectorImpl< char > &ResultPath, OpenFlags Flags=OF_None)
Create a file in the system temporary directory.
LLVM_ABI ProcessInfo ExecuteNoWait(StringRef Program, ArrayRef< StringRef > Args, std::optional< ArrayRef< StringRef > > Env, ArrayRef< std::optional< StringRef > > Redirects={}, unsigned MemoryLimit=0, std::string *ErrMsg=nullptr, bool *ExecutionFailed=nullptr, BitVector *AffinityMask=nullptr, bool DetachProcess=false)
Similar to ExecuteAndWait, but returns immediately.
LLVM_ABI ErrorOr< std::string > findProgramByName(StringRef Name, ArrayRef< StringRef > Paths={})
Find the first executable file Name in Paths.
LLVM_ABI int ExecuteAndWait(StringRef Program, ArrayRef< StringRef > Args, std::optional< ArrayRef< StringRef > > Env=std::nullopt, ArrayRef< std::optional< StringRef > > Redirects={}, unsigned SecondsToWait=0, unsigned MemoryLimit=0, std::string *ErrMsg=nullptr, bool *ExecutionFailed=nullptr, std::optional< ProcessStatistics > *ProcStat=nullptr, BitVector *AffinityMask=nullptr)
This function executes the program using the arguments provided.
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI bool DisplayGraph(StringRef Filename, bool wait=true, GraphProgram::Name program=GraphProgram::DOT)
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
LLVM_ABI std::string createGraphFilename(const Twine &Name, int &FD)
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
void replace(R &&Range, const T &OldValue, const T &NewValue)
Provide wrappers to std::replace which take ranges instead of having to pass begin/end explicitly.
void initGraphWriterOptions()