+/// \brief Get a color string for this node number. Simply round-robin selects
+/// from a reasonable number of colors.
+StringRef llvm::DOT::getColorString(unsigned ColorNumber) {
+ static const int NumColors = 20;
+ static const char* Colors[NumColors] = {
+ "aaaaaa", "aa0000", "00aa00", "aa5500", "0055ff", "aa00aa", "00aaaa",
+ "555555", "ff5555", "55ff55", "ffff55", "5555ff", "ff55ff", "55ffff",
+ "ffaaaa", "aaffaa", "ffffaa", "aaaaff", "ffaaff", "aaffff"};
+ return Colors[ColorNumber % NumColors];
+}
+
+std::string llvm::createGraphFilename(const Twine &Name, int &FD) {
+ FD = -1;
+ SmallString<128> Filename;
+ std::error_code EC = sys::fs::createTemporaryFile(Name, "dot", FD, Filename);
+ if (EC) {
+ errs() << "Error: " << EC.message() << "\n";
+ return "";
+ }
+
+ errs() << "Writing '" << Filename << "'... ";
+ return Filename.str();
+}
+
+// Execute the graph viewer. Return true if there were errors.
+static bool ExecGraphViewer(StringRef ExecPath, std::vector<const char *> &args,
+ StringRef Filename, bool wait,
+ std::string &ErrMsg) {
+ assert(args.back() == nullptr);
+ if (wait) {
+ if (sys::ExecuteAndWait(ExecPath, args.data(), nullptr, nullptr, 0, 0,
+ &ErrMsg)) {
+ errs() << "Error: " << ErrMsg << "\n";
+ return true;
+ }
+ sys::fs::remove(Filename);
+ errs() << " done. \n";
+ } else {
+ sys::ExecuteNoWait(ExecPath, args.data(), nullptr, nullptr, 0, &ErrMsg);
+ errs() << "Remember to erase graph file: " << Filename << "\n";
+ }
+ return false;
+}
+
+namespace {
+struct GraphSession {
+ std::string LogBuffer;
+ bool TryFindProgram(StringRef Names, std::string &ProgramPath) {
+ raw_string_ostream Log(LogBuffer);
+ SmallVector<StringRef, 8> parts;
+ Names.split(parts, "|");
+ for (auto Name : parts) {
+ if (ErrorOr<std::string> P = sys::findProgramByName(Name)) {
+ ProgramPath = *P;
+ return true;
+ }
+ Log << " Tried '" << Name << "'\n";
+ }
+ return false;
+ }
+};
+} // namespace