Add a compilation tracing mechanism to the new compiler.

Code mostly imported from: https://android-review.googlesource.com/#/c/81653/.

Change-Id: I150fe942be0fb270e03fabb19032180f7a065d13
diff --git a/compiler/optimizing/graph_visualizer.cc b/compiler/optimizing/graph_visualizer.cc
new file mode 100644
index 0000000..a7604be
--- /dev/null
+++ b/compiler/optimizing/graph_visualizer.cc
@@ -0,0 +1,199 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "graph_visualizer.h"
+
+#include "driver/dex_compilation_unit.h"
+#include "nodes.h"
+
+namespace art {
+
+/**
+ * HGraph visitor to generate a file suitable for the c1visualizer tool and IRHydra.
+ */
+class HGraphVisualizerPrinter : public HGraphVisitor {
+ public:
+  HGraphVisualizerPrinter(HGraph* graph, std::ostream& output)
+      : HGraphVisitor(graph), output_(output), indent_(0) {}
+
+  void StartTag(const char* name) {
+    AddIndent();
+    output_ << "begin_" << name << std::endl;
+    indent_++;
+  }
+
+  void EndTag(const char* name) {
+    indent_--;
+    AddIndent();
+    output_ << "end_" << name << std::endl;
+  }
+
+  void PrintProperty(const char* name, const char* property) {
+    AddIndent();
+    output_ << name << " \"" << property << "\"" << std::endl;
+  }
+
+  void PrintProperty(const char* name, const char* property, int id) {
+    AddIndent();
+    output_ << name << " \"" << property << id << "\"" << std::endl;
+  }
+
+  void PrintEmptyProperty(const char* name) {
+    AddIndent();
+    output_ << name << std::endl;
+  }
+
+  void PrintTime(const char* name) {
+    AddIndent();
+    output_ << name << " " << time(NULL) << std::endl;
+  }
+
+  void PrintInt(const char* name, int value) {
+    AddIndent();
+    output_ << name << " " << value << std::endl;
+  }
+
+  void AddIndent() {
+    for (size_t i = 0; i < indent_; ++i) {
+      output_ << "  ";
+    }
+  }
+
+  void PrintPredecessors(HBasicBlock* block) {
+    AddIndent();
+    output_ << "predecessors";
+    for (size_t i = 0, e = block->GetPredecessors().Size(); i < e; ++i) {
+      HBasicBlock* predecessor = block->GetPredecessors().Get(i);
+      output_ << " \"B" << predecessor->GetBlockId() << "\" ";
+    }
+    output_<< std::endl;
+  }
+
+  void PrintSuccessors(HBasicBlock* block) {
+    AddIndent();
+    output_ << "successors";
+    for (size_t i = 0, e = block->GetSuccessors().Size(); i < e; ++i) {
+      HBasicBlock* successor = block->GetSuccessors().Get(i);
+      output_ << " \"B" << successor->GetBlockId() << "\" ";
+    }
+    output_<< std::endl;
+  }
+
+
+  void VisitInstruction(HInstruction* instruction) {
+    output_ << instruction->DebugName();
+    if (instruction->InputCount() > 0) {
+      output_ << " [ ";
+      for (HInputIterator inputs(instruction); !inputs.Done(); inputs.Advance()) {
+        output_ << "v" << inputs.Current()->GetId() << " ";
+      }
+      output_ << "]";
+    }
+  }
+
+  void PrintInstructions(const HInstructionList& list) {
+    const char* kEndInstructionMarker = "<|@";
+    for (HInstructionIterator it(list); !it.Done(); it.Advance()) {
+      HInstruction* instruction = it.Current();
+      AddIndent();
+      int bci = 0;
+      output_ << bci << " " << instruction->NumberOfUses() << " v" << instruction->GetId() << " ";
+      instruction->Accept(this);
+      output_ << kEndInstructionMarker << std::endl;
+    }
+  }
+
+  void Run(const char* pass_name) {
+    StartTag("cfg");
+    PrintProperty("name", pass_name);
+    VisitInsertionOrder();
+    EndTag("cfg");
+  }
+
+  void VisitBasicBlock(HBasicBlock* block) {
+    StartTag("block");
+    PrintProperty("name", "B", block->GetBlockId());
+    PrintInt("from_bci", -1);
+    PrintInt("to_bci", -1);
+    PrintPredecessors(block);
+    PrintSuccessors(block);
+    PrintEmptyProperty("xhandlers");
+    PrintEmptyProperty("flags");
+    if (block->GetDominator() != nullptr) {
+      PrintProperty("dominator", "B", block->GetDominator()->GetBlockId());
+    }
+
+    StartTag("states");
+    StartTag("locals");
+    PrintInt("size", 0);
+    PrintProperty("method", "None");
+    for (HInstructionIterator it(block->GetPhis()); !it.Done(); it.Advance()) {
+      AddIndent();
+      HInstruction* instruction = it.Current();
+      output_ << instruction->GetId() << " v" << instruction->GetId() << "[ ";
+      for (HInputIterator inputs(instruction); !inputs.Done(); inputs.Advance()) {
+        output_ << inputs.Current()->GetId() << " ";
+      }
+      output_ << "]" << std::endl;
+    }
+    EndTag("locals");
+    EndTag("states");
+
+    StartTag("HIR");
+    PrintInstructions(block->GetPhis());
+    PrintInstructions(block->GetInstructions());
+    EndTag("HIR");
+    EndTag("block");
+  }
+
+ private:
+  std::ostream& output_;
+  size_t indent_;
+
+  DISALLOW_COPY_AND_ASSIGN(HGraphVisualizerPrinter);
+};
+
+HGraphVisualizer::HGraphVisualizer(std::ostream* output,
+                                   HGraph* graph,
+                                   const char* string_filter,
+                                   const DexCompilationUnit& cu)
+    : output_(output), graph_(graph), is_enabled_(false) {
+  if (output == nullptr) {
+    return;
+  }
+  std::string pretty_name = PrettyMethod(cu.GetDexMethodIndex(), *cu.GetDexFile());
+  if (pretty_name.find(string_filter) == std::string::npos) {
+    return;
+  }
+
+  is_enabled_ = true;
+  HGraphVisualizerPrinter printer(graph, *output_);
+  printer.StartTag("compilation");
+  printer.PrintProperty("name", pretty_name.c_str());
+  printer.PrintProperty("method", pretty_name.c_str());
+  printer.PrintTime("date");
+  printer.EndTag("compilation");
+}
+
+void HGraphVisualizer::DumpGraph(const char* pass_name) {
+  if (!is_enabled_) {
+    return;
+  }
+  HGraphVisualizerPrinter printer(graph_, *output_);
+  printer.Run(pass_name);
+}
+
+}  // namespace art