Generation of dot files through visitor.Added type info to .dot.

visitor.h: Fixed formatting.
type_inference.cc: Changed GetSSAConsumers() to return pointer.
sea_node.h, sea.cc: Removed ToDot classes functions.
instruction_nodes.h: Added acessor for SSA producers.
                     Marked GetUses() as const.
sea.h: Marked fields as const.
frontend.cc: Changed .dot generation code.
code_gen.h: Fixed include to have full path.

Change-Id: Ia84371c171c4537d9cf2f56644baa075f1706df1
diff --git a/compiler/Android.mk b/compiler/Android.mk
index 86f5213..bffda6c 100644
--- a/compiler/Android.mk
+++ b/compiler/Android.mk
@@ -97,7 +97,9 @@
 	sea_ir/instruction_tools.cc \
 	sea_ir/sea.cc \
 	sea_ir/code_gen.cc \
-	sea_ir/types/type_inference.cc
+	sea_ir/types/type_inference.cc \
+	sea_ir/types/type_inference_visitor.cc \
+	sea_ir/debug/dot_gen.cc
 endif
 
 LIBART_COMPILER_CFLAGS :=
diff --git a/compiler/sea_ir/code_gen.h b/compiler/sea_ir/code_gen.h
index f656453..5fea79a 100644
--- a/compiler/sea_ir/code_gen.h
+++ b/compiler/sea_ir/code_gen.h
@@ -22,7 +22,7 @@
 #include "llvm/IR/LLVMContext.h"
 #include "llvm/IR/Module.h"
 #include "llvm/Analysis/Verifier.h"
-#include "visitor.h"
+#include "sea_ir/visitor.h"
 
 namespace sea_ir {
 // Abstracts away the containers we use to map SEA IR objects to LLVM IR objects.
diff --git a/compiler/sea_ir/debug/dot_gen.cc b/compiler/sea_ir/debug/dot_gen.cc
new file mode 100644
index 0000000..9e071e1
--- /dev/null
+++ b/compiler/sea_ir/debug/dot_gen.cc
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2013 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 "sea_ir/debug/dot_gen.h"
+
+namespace sea_ir {
+
+void DotGenerationVisitor::Initialize(SeaGraph* graph) {
+  graph_ = graph;
+  Region* root_region;
+  ordered_regions_.clear();
+  for (std::vector<Region*>::const_iterator cit = graph->GetRegions()->begin();
+      cit != graph->GetRegions()->end(); cit++ ) {
+    if ((*cit)->GetIDominator() == (*cit)) {
+      root_region = *cit;
+    }
+  }
+  ordered_regions_.push_back(root_region);
+  for (unsigned int id = 0; id < ordered_regions_.size(); id++) {
+    Region* current_region = ordered_regions_.at(id);
+    const std::set<Region*>* dominated_regions = current_region->GetIDominatedSet();
+    for (std::set<Region*>::const_iterator cit = dominated_regions->begin();
+        cit != dominated_regions->end(); cit++ ) {
+      ordered_regions_.push_back(*cit);
+    }
+  }
+}
+
+void DotGenerationVisitor::ToDotSSAEdges(InstructionNode* instruction) {
+  std::map<int, InstructionNode*>* definition_edges = instruction->GetSSAProducersMap();
+  // SSA definitions:
+  for (std::map<int, InstructionNode*>::const_iterator
+      def_it = definition_edges->begin();
+      def_it != definition_edges->end(); def_it++) {
+    if (NULL != def_it->second) {
+      dot_text_ += def_it->second->StringId() + " -> ";
+      dot_text_ += instruction->StringId() + "[color=gray,label=\"";
+      dot_text_ += art::StringPrintf("vR = %d", def_it->first);
+      std::map<int, const Type*>::const_iterator type_it = types_->find(def_it->second->Id());
+      if (type_it != types_->end()) {
+        dot_text_ += "(" + type_it->second->Dump() + ")";
+      } else {
+        dot_text_ += "()";
+      }
+      dot_text_ += "\"] ; // SSA edge\n";
+    }
+  }
+
+  // SSA used-by:
+  if (options_->WillSaveUseEdges()) {
+    std::vector<InstructionNode*>* used_in = instruction->GetSSAConsumers();
+    for (std::vector<InstructionNode*>::const_iterator cit = used_in->begin();
+        cit != used_in->end(); cit++) {
+      dot_text_ += (*cit)->StringId() + " -> " + instruction->StringId() + "[color=gray,label=\"";
+      dot_text_ += "\"] ; // SSA used-by edge\n";
+    }
+  }
+}
+
+void DotGenerationVisitor::Visit(SignatureNode* parameter) {
+  dot_text_ += parameter->StringId() +" [label=\"signature:";
+  dot_text_ += art::StringPrintf("r%d", parameter->GetResultRegister());
+  dot_text_ += "\"] // signature node\n";
+  ToDotSSAEdges(parameter);
+}
+
+// Appends to @result a dot language formatted string representing the node and
+//    (by convention) outgoing edges, so that the composition of theToDot() of all nodes
+//    builds a complete dot graph (without prolog and epilog though).
+void DotGenerationVisitor::Visit(Region* region) {
+  dot_text_ += "\n// Region: \nsubgraph " + region->StringId();
+  dot_text_ += " { label=\"region " + region->StringId() + "(rpo=";
+  dot_text_ += art::StringPrintf("%d", region->GetRPO());
+  if (NULL != region->GetIDominator()) {
+    dot_text_ += " dom=" + region->GetIDominator()->StringId();
+  }
+  dot_text_ += ")\";\n";
+
+  std::vector<PhiInstructionNode*>* phi_instructions = region->GetPhiNodes();
+  for (std::vector<PhiInstructionNode*>::const_iterator cit = phi_instructions->begin();
+        cit != phi_instructions->end(); cit++) {
+    dot_text_ += (*cit)->StringId() +";\n";
+  }
+  std::vector<InstructionNode*>* instructions = region->GetInstructions();
+  for (std::vector<InstructionNode*>::const_iterator cit = instructions->begin();
+        cit != instructions->end(); cit++) {
+      dot_text_ += (*cit)->StringId() +";\n";
+    }
+
+  dot_text_ += "} // End Region.\n";
+  std::vector<Region*>* successors =  region->GetSuccessors();
+  for (std::vector<Region*>::const_iterator cit = successors->begin(); cit != successors->end();
+      cit++) {
+    DCHECK(NULL != *cit) << "Null successor found for SeaNode" <<
+        region->GetLastChild()->StringId() << ".";
+    dot_text_ += region->GetLastChild()->StringId() + " -> " +
+        (*cit)->GetLastChild()->StringId() +
+        "[lhead=" + (*cit)->StringId() + ", " + "ltail=" + region->StringId() + "];\n\n";
+  }
+}
+void DotGenerationVisitor::Visit(InstructionNode* instruction) {
+  dot_text_ += "// Instruction ("+instruction->StringId()+"): \n" + instruction->StringId() +
+      " [label=\"" + instruction->GetInstruction()->DumpString(graph_->GetDexFile()) + "\"";
+  dot_text_ += "];\n";
+  ToDotSSAEdges(instruction);
+}
+
+void DotGenerationVisitor::Visit(UnnamedConstInstructionNode* instruction) {
+  dot_text_ += "// Instruction ("+instruction->StringId()+"): \n" + instruction->StringId() +
+        " [label=\"const/x v-3, #"+ art::StringPrintf("%d", instruction->GetConstValue()) + "\"";
+  dot_text_ += "];\n";
+  ToDotSSAEdges(instruction);
+}
+
+void DotGenerationVisitor::Visit(PhiInstructionNode* phi) {
+  dot_text_ += "// PhiInstruction: \n" + phi->StringId() +
+      " [label=\"" + "PHI(";
+  dot_text_ += art::StringPrintf("%d", phi->GetRegisterNumber());
+  dot_text_ += ")\"";
+  dot_text_ += "];\n";
+  ToDotSSAEdges(phi);
+}
+}  // namespace sea_ir
diff --git a/compiler/sea_ir/debug/dot_gen.h b/compiler/sea_ir/debug/dot_gen.h
new file mode 100644
index 0000000..520d9df
--- /dev/null
+++ b/compiler/sea_ir/debug/dot_gen.h
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+
+#ifndef ART_COMPILER_SEA_IR_DEBUG_DOT_GEN_H_
+#define ART_COMPILER_SEA_IR_DEBUG_DOT_GEN_H_
+
+#include "base/stringprintf.h"
+#include "file_output_stream.h"
+#include "sea_ir/sea.h"
+#include "sea_ir/types/type_inference.h"
+
+namespace sea_ir {
+
+class DotConversionOptions {
+ public:
+  DotConversionOptions(): save_use_edges_(false) { }
+  bool WillSaveUseEdges() const {
+    return save_use_edges_;
+  }
+ private:
+  bool save_use_edges_;
+};
+
+class DotGenerationVisitor: public IRVisitor {
+ public:
+  explicit DotGenerationVisitor(const DotConversionOptions* const options,
+      std::map<int, const Type*>* types): graph_(), types_(types), options_(options) { }
+
+  virtual void Initialize(SeaGraph* graph);
+  // Saves the ssa def->use edges corresponding to @instruction.
+  void ToDotSSAEdges(InstructionNode* instruction) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  void Visit(SeaGraph* graph) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    dot_text_ += "digraph seaOfNodes {\ncompound=true\n";
+  }
+  void Visit(SignatureNode* parameter) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  // Appends to @result a dot language formatted string representing the node and
+  //    (by convention) outgoing edges, so that the composition of theToDot() of all nodes
+  //    builds a complete dot graph (without prolog and epilog though).
+  void Visit(Region* region) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  void Visit(InstructionNode* instruction) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  void Visit(PhiInstructionNode* phi) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  void Visit(UnnamedConstInstructionNode* instruction) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  void Visit(ConstInstructionNode* instruction) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    Visit(reinterpret_cast<InstructionNode*>(instruction));
+  }
+  void Visit(ReturnInstructionNode* instruction) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    Visit(reinterpret_cast<InstructionNode*>(instruction));
+  }
+  void Visit(IfNeInstructionNode* instruction) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    Visit(reinterpret_cast<InstructionNode*>(instruction));
+  }
+  void Visit(MoveResultInstructionNode* instruction) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    Visit(reinterpret_cast<InstructionNode*>(instruction));
+  }
+  void Visit(InvokeStaticInstructionNode* instruction) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    Visit(reinterpret_cast<InstructionNode*>(instruction));
+  }
+  void Visit(AddIntInstructionNode* instruction) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    Visit(reinterpret_cast<InstructionNode*>(instruction));
+  }
+  void Visit(GotoInstructionNode* instruction) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    Visit(reinterpret_cast<InstructionNode*>(instruction));
+  }
+  void Visit(IfEqzInstructionNode* instruction) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    Visit(reinterpret_cast<InstructionNode*>(instruction));
+  }
+
+  std::string GetResult() const {
+    return dot_text_;
+  }
+
+ private:
+  std::string dot_text_;
+  SeaGraph* graph_;
+  std::map<int, const Type*>* types_;
+  const DotConversionOptions* const options_;
+};
+
+// Stores options for turning a SEA IR graph to a .dot file.
+class DotConversion {
+ public:
+  DotConversion(): options_() { }
+  // Saves to @filename the .dot representation of @graph with the options @options.
+  void DumpSea(SeaGraph* graph, std::string filename,  std::map<int, const Type*>* types) const {
+    LOG(INFO) << "Starting to write SEA string to file.";
+    DotGenerationVisitor dgv = DotGenerationVisitor(&options_, types);
+    graph->Accept(&dgv);
+    art::File* file = art::OS::OpenFile(filename.c_str(), true, true);
+    art::FileOutputStream fos(file);
+    std::string graph_as_string = dgv.GetResult();
+    graph_as_string += "}";
+    fos.WriteFully(graph_as_string.c_str(), graph_as_string.size());
+    LOG(INFO) << "Written SEA string to file.";
+  }
+
+ private:
+  DotConversionOptions options_;
+};
+
+}  // namespace sea_ir
+#endif  // ART_COMPILER_SEA_IR_DEBUG_DOT_GEN_H_
diff --git a/compiler/sea_ir/frontend.cc b/compiler/sea_ir/frontend.cc
index cc49ea5..951273c 100644
--- a/compiler/sea_ir/frontend.cc
+++ b/compiler/sea_ir/frontend.cc
@@ -23,8 +23,11 @@
 #include "llvm/llvm_compilation_unit.h"
 #include "mirror/object.h"
 #include "runtime.h"
-#include "sea_ir/sea.h"
 
+
+#include "sea_ir/sea.h"
+#include "sea_ir/debug/dot_gen.h"
+#include "sea_ir/types/types.h"
 namespace art {
 
 static CompiledMethod* CompileMethodWithSeaIr(CompilerDriver& compiler,
@@ -40,9 +43,11 @@
   // NOTE: Instead of keeping the convention from the Dalvik frontend.cc
   //       and silencing the cpplint.py warning, I just corrected the formatting.
   VLOG(compiler) << "Compiling " << PrettyMethod(method_idx, dex_file) << "...";
-  sea_ir::SeaGraph* sg = sea_ir::SeaGraph::GetCurrentGraph(dex_file);
-  sg->CompileMethod(code_item, class_def_idx, method_idx, method_access_flags, dex_file);
-  sg->DumpSea("/tmp/temp.dot");
+  sea_ir::SeaGraph* ir_graph = sea_ir::SeaGraph::GetCurrentGraph(dex_file);
+  ir_graph->CompileMethod(code_item, class_def_idx, method_idx, method_access_flags, dex_file);
+  sea_ir::DotConversion dc;
+  std::map<int, const sea_ir::Type*>  types = ir_graph->ti_->GetTypeMap();
+  dc.DumpSea(ir_graph, "/tmp/temp.dot", &types);
   CHECK(0 && "No SEA compiled function exists yet.");
   return NULL;
 }
diff --git a/compiler/sea_ir/instruction_nodes.h b/compiler/sea_ir/instruction_nodes.h
index 1b81e9a..fb1f83f 100644
--- a/compiler/sea_ir/instruction_nodes.h
+++ b/compiler/sea_ir/instruction_nodes.h
@@ -16,9 +16,10 @@
 
 #ifndef ART_COMPILER_SEA_IR_INSTRUCTION_NODES_H_
 #define ART_COMPILER_SEA_IR_INSTRUCTION_NODES_H_
-#include "sea_node.h"
-#include "visitor.h"
 #include "dex_instruction-inl.h"
+#include "sea_ir/sea_node.h"
+#include "sea_ir/visitor.h"
+
 
 namespace sea_ir {
 
@@ -48,9 +49,7 @@
   // Returns the set of registers defined by the current instruction.
   virtual std::vector<int> GetDefinitions() const;
   // Returns the set of register numbers that are used by the instruction.
-  virtual std::vector<int> GetUses();
-  // Appends to @result the .dot string representation of the instruction.
-  virtual void ToDot(std::string& result, const art::DexFile& dex_file) const;
+  virtual std::vector<int> GetUses() const;
   // Mark the current instruction as a downward exposed definition.
   void MarkAsDEDef();
   // Rename the use of @reg_no to refer to the instruction @definition,
@@ -69,15 +68,15 @@
     }
     return ssa_uses;
   }
-
-  std::vector<InstructionNode*> GetSSAConsumers() {
-    return used_in_;
+  std::map<int, InstructionNode* >* GetSSAProducersMap() {
+    return &definition_edges_;
   }
-
+  std::vector<InstructionNode*>* GetSSAConsumers() {
+    return &used_in_;
+  }
   virtual void AddSSAUse(InstructionNode* use) {
     used_in_.push_back(use);
   }
-
   void Accept(IRVisitor* v) {
     v->Visit(this);
     v->Traverse(this);
@@ -95,11 +94,10 @@
  protected:
   explicit InstructionNode(const art::Instruction* in):
       SeaNode(), instruction_(in), used_in_(), de_def_(false), region_(NULL) { }
-  void ToDotSSAEdges(std::string& result) const;
 
  protected:
   const art::Instruction* const instruction_;
-  std::map<int, InstructionNode* > definition_edges_;
+  std::map<int, InstructionNode* > definition_edges_;  // Maps used registers to their definitions.
   // Stores pointers to instructions that use the result of the current instruction.
   std::vector<InstructionNode*> used_in_;
   bool de_def_;
@@ -125,6 +123,7 @@
  public:
   explicit UnnamedConstInstructionNode(const art::Instruction* inst, int32_t value):
       ConstInstructionNode(inst), value_(value) { }
+
   void Accept(IRVisitor* v) {
     v->Visit(this);
     v->Traverse(this);
@@ -138,19 +137,6 @@
     return value_;
   }
 
-  void ToDot(std::string& result, const art::DexFile& dex_file) const {
-    std::ostringstream sstream;
-    sstream << GetConstValue();
-    const std::string value_as_string(sstream.str());
-    result += "// Instruction ("+StringId()+"): \n" + StringId() +
-        " [label=\"const/x v-3, #"+ value_as_string + "\"";
-    if (de_def_) {
-      result += "style=bold";
-    }
-    result += "];\n";
-    ToDotSSAEdges(result);
-  }
-
  private:
   const int32_t value_;
 };
@@ -180,7 +166,7 @@
 class MoveResultInstructionNode: public InstructionNode {
  public:
   explicit MoveResultInstructionNode(const art::Instruction* inst): InstructionNode(inst) { }
-  std::vector<int> GetUses() {
+  std::vector<int> GetUses() const {
     std::vector<int> uses;  // Using vector<> instead of set<> because order matters.
     uses.push_back(RETURN_REGISTER);
     return uses;
@@ -217,7 +203,7 @@
   explicit AddIntLitInstructionNode(const art::Instruction* inst):
       AddIntInstructionNode(inst) { }
 
-  std::vector<int> GetUses() {
+  std::vector<int> GetUses() const {
     std::vector<int> uses =  AddIntInstructionNode::GetUses();
     uses.push_back(UNNAMED_CONST_REGISTER);
     return uses;
diff --git a/compiler/sea_ir/sea.cc b/compiler/sea_ir/sea.cc
index 585b2aa..cb159e1 100644
--- a/compiler/sea_ir/sea.cc
+++ b/compiler/sea_ir/sea.cc
@@ -14,7 +14,6 @@
  * limitations under the License.
  */
 #include "base/stringprintf.h"
-#include "file_output_stream.h"
 #include "instruction_tools.h"
 #include "sea.h"
 #include "code_gen.h"
@@ -36,7 +35,6 @@
       cit != phis->end(); cit++) {
     (*cit)->Accept(this);
   }
-
   std::vector<InstructionNode*>* instructions = region->GetInstructions();
   for (std::vector<InstructionNode*>::const_iterator cit = instructions->begin();
       cit != instructions->end(); cit++) {
@@ -55,20 +53,6 @@
   return new SeaGraph(dex_file);
 }
 
-void SeaGraph::DumpSea(std::string filename) const {
-  LOG(INFO) << "Starting to write SEA string to file.";
-  std::string result;
-  result += "digraph seaOfNodes {\ncompound=true\n";
-  for (std::vector<Region*>::const_iterator cit = regions_.begin(); cit != regions_.end(); cit++) {
-    (*cit)->ToDot(result, dex_file_);
-  }
-  result += "}\n";
-  art::File* file = art::OS::OpenFile(filename.c_str(), true, true);
-  art::FileOutputStream fos(file);
-  fos.WriteFully(result.c_str(), result.size());
-  LOG(INFO) << "Written SEA string to file.";
-}
-
 void SeaGraph::AddEdge(Region* src, Region* dst) const {
   src->AddSuccessor(dst);
   dst->AddPredecessor(src);
@@ -264,6 +248,7 @@
         }
         r = nextRegion;
       }
+      r->AddChild(node);
     }
     i += inst->SizeInCodeUnits();
   }
@@ -433,8 +418,8 @@
   // Two Passes: Phi node insertion.
   ConvertToSSA();
   // Pass: type inference
-  TypeInference ti = TypeInference();
-  ti.ComputeTypes(this);
+  std::cout << "TYPES." << std::endl;
+  ti_->ComputeTypes(this);
   // Pass: Generate LLVM IR.
   GenerateLLVM();
 }
@@ -467,18 +452,10 @@
   regions_.push_back(r);
 }
 
-/*
-void SeaNode::AddSuccessor(Region* successor) {
-  DCHECK(successor) << "Tried to add NULL successor to SEA node.";
-  successors_.push_back(successor);
-  return;
-}
+SeaGraph::SeaGraph(const art::DexFile& df)
+    :ti_(new TypeInference()), class_def_idx_(0), method_idx_(0),  method_access_flags_(),
+     regions_(), parameters_(), dex_file_(df), code_item_(NULL) { }
 
-void SeaNode::AddPredecessor(Region* predecessor) {
-  DCHECK(predecessor) << "Tried to add NULL predecessor to SEA node.";
-  predecessors_.push_back(predecessor);
-}
-*/
 void Region::AddChild(sea_ir::InstructionNode* instruction) {
   DCHECK(instruction) << "Tried to add NULL instruction to region node.";
   instructions_.push_back(instruction);
@@ -492,46 +469,6 @@
   return NULL;
 }
 
-void Region::ToDot(std::string& result, const art::DexFile& dex_file) const {
-  result += "\n// Region: \nsubgraph " + StringId() + " { label=\"region " + StringId() + "(rpo=";
-  result += art::StringPrintf("%d", rpo_number_);
-  if (NULL != GetIDominator()) {
-    result += " dom=" + GetIDominator()->StringId();
-  }
-  result += ")\";\n";
-
-  for (std::vector<PhiInstructionNode*>::const_iterator cit = phi_instructions_.begin();
-        cit != phi_instructions_.end(); cit++) {
-    result += (*cit)->StringId() +";\n";
-  }
-
-  for (std::vector<InstructionNode*>::const_iterator cit = instructions_.begin();
-        cit != instructions_.end(); cit++) {
-      result += (*cit)->StringId() +";\n";
-    }
-
-  result += "} // End Region.\n";
-
-  // Save phi-nodes.
-  for (std::vector<PhiInstructionNode*>::const_iterator cit = phi_instructions_.begin();
-      cit != phi_instructions_.end(); cit++) {
-    (*cit)->ToDot(result, dex_file);
-  }
-
-  // Save instruction nodes.
-  for (std::vector<InstructionNode*>::const_iterator cit = instructions_.begin();
-      cit != instructions_.end(); cit++) {
-    (*cit)->ToDot(result, dex_file);
-  }
-
-  for (std::vector<Region*>::const_iterator cit = successors_.begin(); cit != successors_.end();
-      cit++) {
-    DCHECK(NULL != *cit) << "Null successor found for SeaNode" << GetLastChild()->StringId() << ".";
-    result += GetLastChild()->StringId() + " -> " + (*cit)->GetLastChild()->StringId() +
-         "[lhead=" + (*cit)->StringId() + ", " + "ltail=" + StringId() + "];\n\n";
-  }
-}
-
 void Region::ComputeDownExposedDefs() {
   for (std::vector<InstructionNode*>::const_iterator inst_it = instructions_.begin();
       inst_it != instructions_.end(); inst_it++) {
@@ -694,38 +631,6 @@
   return sea_instructions;
 }
 
-void InstructionNode::ToDotSSAEdges(std::string& result) const {
-  // SSA definitions:
-  for (std::map<int, InstructionNode*>::const_iterator def_it = definition_edges_.begin();
-      def_it != definition_edges_.end(); def_it++) {
-    if (NULL != def_it->second) {
-      result += def_it->second->StringId() + " -> " + StringId() + "[color=gray,label=\"";
-      result += art::StringPrintf("vR = %d", def_it->first);
-      result += "\"] ; // ssa edge\n";
-    }
-  }
-
-  // SSA used-by:
-  if (DotConversion::SaveUseEdges()) {
-    for (std::vector<InstructionNode*>::const_iterator cit = used_in_.begin();
-        cit != used_in_.end(); cit++) {
-      result += (*cit)->StringId() + " -> " + StringId() + "[color=gray,label=\"";
-      result += "\"] ; // SSA used-by edge\n";
-    }
-  }
-}
-
-void InstructionNode::ToDot(std::string& result, const art::DexFile& dex_file) const {
-  result += "// Instruction ("+StringId()+"): \n" + StringId() +
-      " [label=\"" + instruction_->DumpString(&dex_file) + "\"";
-  if (de_def_) {
-    result += "style=bold";
-  }
-  result += "];\n";
-
-  ToDotSSAEdges(result);
-}
-
 void InstructionNode::MarkAsDEDef() {
   de_def_ = true;
 }
@@ -749,7 +654,7 @@
   return definitions;
 }
 
-std::vector<int> InstructionNode::GetUses() {
+std::vector<int> InstructionNode::GetUses() const {
   std::vector<int> uses;  // Using vector<> instead of set<> because order matters.
   if (!InstructionTools::IsDefinition(instruction_) && (instruction_->HasVRegA())) {
     int vA = instruction_->VRegA();
@@ -765,13 +670,4 @@
   }
   return uses;
 }
-
-void PhiInstructionNode::ToDot(std::string& result, const art::DexFile& dex_file) const {
-  result += "// PhiInstruction: \n" + StringId() +
-      " [label=\"" + "PHI(";
-  result += art::StringPrintf("%d", register_no_);
-  result += ")\"";
-  result += "];\n";
-  ToDotSSAEdges(result);
-}
 }  // namespace sea_ir
diff --git a/compiler/sea_ir/sea.h b/compiler/sea_ir/sea.h
index efdbb3b..3a8efcd 100644
--- a/compiler/sea_ir/sea.h
+++ b/compiler/sea_ir/sea.h
@@ -23,8 +23,8 @@
 
 #include "dex_file.h"
 #include "dex_instruction.h"
-#include "instruction_tools.h"
-#include "instruction_nodes.h"
+#include "sea_ir/instruction_tools.h"
+#include "sea_ir/instruction_nodes.h"
 #include "utils/scoped_hashtable.h"
 
 namespace sea_ir {
@@ -35,19 +35,9 @@
   VISITING = -2
 };
 
-// Stores options for turning a SEA IR graph to a .dot file.
-class DotConversion {
- public:
-  static bool SaveUseEdges() {
-    return save_use_edges_;
-  }
-
- private:
-  static const bool save_use_edges_ =  false;  // TODO: Enable per-sea graph configuration.
-};
+class TypeInference;
 
 class Region;
-
 class InstructionNode;
 class PhiInstructionNode;
 class SignatureNode;
@@ -62,22 +52,15 @@
   explicit SignatureNode(unsigned int parameter_register, unsigned int position):
     InstructionNode(NULL), parameter_register_(parameter_register), position_(position) { }
 
-  void ToDot(std::string& result, const art::DexFile& dex_file) const {
-    result += StringId() +" [label=\"signature:";
-    result += art::StringPrintf("r%d", GetResultRegister());
-    result += "\"] // signature node\n";
-    ToDotSSAEdges(result);
-  }
-
   int GetResultRegister() const {
     return parameter_register_;
   }
 
-  unsigned int GetPositionInSignature() {
+  unsigned int GetPositionInSignature() const {
     return position_;
   }
 
-  std::vector<int> GetUses() {
+  std::vector<int> GetUses() const {
     return std::vector<int>();
   }
 
@@ -87,16 +70,15 @@
   }
 
  private:
-  unsigned int parameter_register_;
-  unsigned int position_;  // The position of this parameter node is in the function parameter list.
+  const unsigned int parameter_register_;
+  const unsigned int position_;     // The position of this parameter node is
+                                    // in the function parameter list.
 };
 
 class PhiInstructionNode: public InstructionNode {
  public:
   explicit PhiInstructionNode(int register_no):
     InstructionNode(NULL), register_no_(register_no), definition_edges_() {}
-  // Appends to @result the .dot string representation of the instruction.
-  void ToDot(std::string& result, const art::DexFile& dex_file) const;
   // Returns the register on which this phi-function is used.
   int GetRegisterNumber() const {
     return register_no_;
@@ -157,10 +139,7 @@
   std::vector<InstructionNode*>* GetInstructions() {
     return &instructions_;
   }
-  // Appends to @result a dot language formatted string representing the node and
-  //    (by convention) outgoing edges, so that the composition of theToDot() of all nodes
-  //    builds a complete dot graph (without prolog and epilog though).
-  virtual void ToDot(std::string& result, const art::DexFile& dex_file) const;
+
   // Computes Downward Exposed Definitions for the current node.
   void ComputeDownExposedDefs();
   const std::map<int, sea_ir::InstructionNode*>* GetDownExposedDefs() const;
@@ -272,8 +251,6 @@
   std::vector<Region*>* GetRegions() {
     return &regions_;
   }
-  // Returns a string representation of the region and its Instruction children.
-  void DumpSea(std::string filename) const;
   // Recursively computes the reverse postorder value for @crt_bb and successors.
   static void ComputeRPO(Region* crt_bb, int& crt_rpo);
   // Returns the "lowest common ancestor" of @i and @j in the dominator tree.
@@ -287,15 +264,19 @@
     return &dex_file_;
   }
 
+  virtual void Accept(IRVisitor* visitor) {
+    visitor->Initialize(this);
+    visitor->Visit(this);
+    visitor->Traverse(this);
+  }
+
+  TypeInference* ti_;
   uint32_t class_def_idx_;
   uint32_t method_idx_;
   uint32_t method_access_flags_;
 
  private:
-  explicit SeaGraph(const art::DexFile& df):
-    class_def_idx_(0), method_idx_(0),  method_access_flags_(), regions_(),
-    parameters_(), dex_file_(df), code_item_(NULL) {
-  }
+  explicit SeaGraph(const art::DexFile& df);
   // Registers @childReg as a region belonging to the SeaGraph instance.
   void AddRegion(Region* childReg);
   // Returns new region and registers it with the  SeaGraph instance.
@@ -336,11 +317,7 @@
   // by using the scoped hashtable of names @ scoped_table.
   void RenameAsSSA(Region* node, utils::ScopedHashtable<int, InstructionNode*>* scoped_table);
 
-  virtual void Accept(IRVisitor* visitor) {
-    visitor->Initialize(this);
-    visitor->Visit(this);
-    visitor->Traverse(this);
-  }
+
 
   virtual ~SeaGraph() {}
   // Generate LLVM IR for the method.
diff --git a/compiler/sea_ir/sea_node.h b/compiler/sea_ir/sea_node.h
index c13e5d6..98bbe9e 100644
--- a/compiler/sea_ir/sea_node.h
+++ b/compiler/sea_ir/sea_node.h
@@ -56,10 +56,6 @@
   int Id() const {
     return id_;
   }
-  // Appends to @result a dot language formatted string representing the node and
-  //    (by convention) outgoing edges, so that the composition of theToDot() of all nodes
-  //    builds a complete dot graph, but without prolog ("digraph {") and epilog ("}").
-  virtual void ToDot(std::string& result, const art::DexFile& dex_file) const = 0;
 
   virtual ~SeaNode() { }
 
diff --git a/compiler/sea_ir/types/type_inference.cc b/compiler/sea_ir/types/type_inference.cc
index ad81310..78888f3 100644
--- a/compiler/sea_ir/types/type_inference.cc
+++ b/compiler/sea_ir/types/type_inference.cc
@@ -15,6 +15,8 @@
  */
 
 #include "sea_ir/types/type_inference.h"
+#include "sea_ir/types/type_inference_visitor.h"
+#include "sea_ir/sea.h"
 
 namespace sea_ir {
 
@@ -133,9 +135,10 @@
   //       maintain this invariant, but they should.
   //       [1] http://www.sgi.com/tech/stl/List.html
   // TODO: Making this conditional (as in sparse conditional constant propagation) would be good.
+  // TODO: Remove elements as I go.
   for (std::list<InstructionNode*>::const_iterator instruction_it = worklist.begin();
         instruction_it != worklist.end(); instruction_it++) {
-    std::cout << "Instruction: " << (*instruction_it)->Id() << std::endl;
+    std::cout << "[TI] Instruction: " << (*instruction_it)->Id() << std::endl;
     (*instruction_it)->Accept(&tiv);
     std::map<int, const Type*>::const_iterator old_result_it =
         type_map_.find((*instruction_it)->Id());
@@ -144,16 +147,15 @@
     bool type_changed = (old_result_it != type_map_.end()) && ((*old_result_it).second != new_type);
     if (first_time_set || type_changed) {
       std::cout << " New type:" << new_type->IsIntegralTypes() << std::endl;
-      std::cout << " Descriptor:" << new_type->Dump() << std::endl;
+      std::cout << " Descrip:" << new_type->Dump()<< "on " << (*instruction_it)->Id() << std::endl;
       type_map_[(*instruction_it)->Id()] = new_type;
       // Add SSA consumers of the current instruction to the work-list.
-      std::vector<InstructionNode*> consumers = (*instruction_it)->GetSSAConsumers();
-      for (std::vector<InstructionNode*>::iterator consumer = consumers.begin();
-          consumer != consumers.end(); consumer++) {
+      std::vector<InstructionNode*>* consumers = (*instruction_it)->GetSSAConsumers();
+      for (std::vector<InstructionNode*>::iterator consumer = consumers->begin();
+          consumer != consumers->end(); consumer++) {
         worklist.push_back(*consumer);
       }
     }
   }
 }
-
 }   // namespace sea_ir
diff --git a/compiler/sea_ir/types/type_inference.h b/compiler/sea_ir/types/type_inference.h
index 1c0d42e..9014c96 100644
--- a/compiler/sea_ir/types/type_inference.h
+++ b/compiler/sea_ir/types/type_inference.h
@@ -17,15 +17,12 @@
 #ifndef ART_COMPILER_SEA_IR_TYPES_TYPE_INFERENCE_H_
 #define ART_COMPILER_SEA_IR_TYPES_TYPE_INFERENCE_H_
 
-#include "sea_ir/sea.h"
 #include "dex_file-inl.h"
-#include "verifier/reg_type.h"
-#include "verifier/reg_type_cache.h"
-#include "verifier/reg_type_cache.h"
+#include "sea_ir/types/types.h"
+
 namespace sea_ir {
 
-typedef art::verifier::RegType Type;
-
+class SeaGraph;
 
 // The type inference in SEA IR is different from the verifier in that it is concerned
 // with a rich type hierarchy (TODO) usable in optimization and does not perform
@@ -39,6 +36,9 @@
   // Computes the types for the method with SEA IR representation provided by @graph.
   void ComputeTypes(SeaGraph* graph);
 
+  std::map<int, const Type*> GetTypeMap() const {
+    return type_map_;
+  }
   // Returns true if @descriptor corresponds to a primitive type.
   static bool IsPrimitiveDescriptor(char descriptor);
 
@@ -76,77 +76,6 @@
   art::verifier::RegTypeCache* type_cache_;
   const uint32_t method_access_flags_;  // Method's access flags.
 };
-
-// The TypeInferenceVisitor visits each instruction and computes its type taking into account
-//   the current type of the operands. The type is stored in the visitor.
-// We may be better off by using a separate visitor type hierarchy that has return values
-//   or that passes data as parameters, than to use fields to store information that should
-//   in fact be returned after visiting each element. Ideally, I would prefer to use templates
-//   to specify the returned value type, but I am not aware of a possible implementation
-//   that does not horribly duplicate the visitor infrastructure code (version 1: no return value,
-//   version 2: with template return value).
-class TypeInferenceVisitor: public IRVisitor {
- public:
-  TypeInferenceVisitor(SeaGraph* graph, art::verifier::RegTypeCache* types):
-    graph_(graph), type_cache_(types), crt_type_() { }
-  void Initialize(SeaGraph* graph) { }
-  // There are no type related actions to be performed on these classes.
-  void Visit(SeaGraph* graph) { }
-  void Visit(Region* region) { }
-
-  void Visit(PhiInstructionNode* instruction) {
-    std::cout << "[TI] Visiting node:" << instruction->Id() << std::endl;
-  }
-  void Visit(SignatureNode* parameter) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    std::cout << "[TI] Visiting signature node:" << parameter->GetResultRegister() << std::endl;
-    FunctionTypeInfo fti(graph_, type_cache_);
-    std::vector<const Type*> arguments = fti.GetDeclaredArgumentTypes();
-    crt_type_.clear();
-    std::cout << "Pos:" << parameter->GetPositionInSignature() << "/" << arguments.size() <<std::endl;
-    DCHECK_LT(parameter->GetPositionInSignature(), arguments.size())
-      << "Signature node position not present in signature.";
-    crt_type_.push_back(arguments.at(parameter->GetPositionInSignature()));
-  }
-  void Visit(InstructionNode* instruction) {
-    std::cout << "[TI] Visiting node:" << instruction->Id() << std::endl;
-  }
-  void Visit(ConstInstructionNode* instruction) {
-    std::cout << "[TI] Visiting node:" << instruction->Id() << std::endl;
-  }
-  void Visit(ReturnInstructionNode* instruction) {
-    std::cout << "[TI] Visiting node:" << instruction->Id() << std::endl;
-  }
-  void Visit(IfNeInstructionNode* instruction) {
-    std::cout << "[TI] Visiting node:" << instruction->Id() << std::endl;
-  }
-  void Visit(MoveResultInstructionNode* instruction) {
-    std::cout << "[TI] Visiting node:" << instruction->Id() << std::endl;
-  }
-  void Visit(InvokeStaticInstructionNode* instruction) {
-    std::cout << "[TI] Visiting node:" << instruction->Id() << std::endl;
-  }
-  void Visit(AddIntInstructionNode* instruction) {
-    std::cout << "[TI] Visiting node:" << instruction->Id() << std::endl;
-  }
-  void Visit(GotoInstructionNode* instruction) {
-    std::cout << "[TI] Visiting node:" << instruction->Id() << std::endl;
-  }
-  void Visit(IfEqzInstructionNode* instruction) {
-    std::cout << "[TI] Visiting node:" << instruction->Id() << std::endl;
-  }
-
-  const Type* GetType() const {
-    // TODO: Currently multiple defined types are not supported.
-    if (crt_type_.size()>0) return crt_type_.at(0);
-    return NULL;
-  }
-
- protected:
-  const SeaGraph* graph_;
-  art::verifier::RegTypeCache* type_cache_;
-  std::vector<const Type*> crt_type_;             // Stored temporarily between two calls to Visit.
-};
-
 }  // namespace sea_ir
 
 #endif  // ART_COMPILER_SEA_IR_TYPES_TYPE_INFERENCE_H_
diff --git a/compiler/sea_ir/types/type_inference_visitor.cc b/compiler/sea_ir/types/type_inference_visitor.cc
new file mode 100644
index 0000000..8faa4d5
--- /dev/null
+++ b/compiler/sea_ir/types/type_inference_visitor.cc
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2013 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 "sea_ir/types/type_inference_visitor.h"
+#include "sea_ir/types/type_inference.h"
+#include "sea_ir/sea.h"
+
+namespace sea_ir {
+
+void TypeInferenceVisitor::Visit(SignatureNode* parameter) {
+  std::cout << "[TI] Visiting signature node:" << parameter->GetResultRegister() << std::endl;
+  FunctionTypeInfo fti(graph_, type_cache_);
+  std::vector<const Type*> arguments = fti.GetDeclaredArgumentTypes();
+  crt_type_.clear();
+  DCHECK_LT(parameter->GetPositionInSignature(), arguments.size())
+    << "Signature node position not present in signature.";
+  crt_type_.push_back(arguments.at(parameter->GetPositionInSignature()));
+}
+
+}   // namespace sea_ir
diff --git a/compiler/sea_ir/types/type_inference_visitor.h b/compiler/sea_ir/types/type_inference_visitor.h
new file mode 100644
index 0000000..9518c97
--- /dev/null
+++ b/compiler/sea_ir/types/type_inference_visitor.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#ifndef ART_COMPILER_SEA_IR_TYPES_TYPE_INFERENCE_VISITOR_H_
+#define ART_COMPILER_SEA_IR_TYPES_TYPE_INFERENCE_VISITOR_H_
+
+
+#include "dex_file-inl.h"
+#include "sea_ir/visitor.h"
+#include "sea_ir/types/types.h"
+
+namespace sea_ir {
+
+// The TypeInferenceVisitor visits each instruction and computes its type taking into account
+//   the current type of the operands. The type is stored in the visitor.
+// We may be better off by using a separate visitor type hierarchy that has return values
+//   or that passes data as parameters, than to use fields to store information that should
+//   in fact be returned after visiting each element. Ideally, I would prefer to use templates
+//   to specify the returned value type, but I am not aware of a possible implementation
+//   that does not horribly duplicate the visitor infrastructure code (version 1: no return value,
+//   version 2: with template return value).
+class TypeInferenceVisitor: public IRVisitor {
+ public:
+  TypeInferenceVisitor(SeaGraph* graph, art::verifier::RegTypeCache* types):
+    graph_(graph), type_cache_(types), crt_type_() {
+  }
+  // There are no type related actions to be performed on these classes.
+  void Initialize(SeaGraph* graph) { }
+  void Visit(SeaGraph* graph) { }
+  void Visit(Region* region) { }
+
+  void Visit(PhiInstructionNode* instruction) { }
+  void Visit(SignatureNode* parameter) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  void Visit(InstructionNode* instruction) { }
+  void Visit(ConstInstructionNode* instruction) { }
+  void Visit(ReturnInstructionNode* instruction) { }
+  void Visit(IfNeInstructionNode* instruction) { }
+  void Visit(MoveResultInstructionNode* instruction) { }
+  void Visit(InvokeStaticInstructionNode* instruction) { }
+  void Visit(AddIntInstructionNode* instruction) { }
+  void Visit(GotoInstructionNode* instruction) { }
+  void Visit(IfEqzInstructionNode* instruction) { }
+
+  const Type* GetType() const {
+    // TODO: Currently multiple defined types are not supported.
+    if (crt_type_.size()>0) return crt_type_.at(0);
+    return NULL;
+  }
+
+ protected:
+  const SeaGraph* const graph_;
+  art::verifier::RegTypeCache* type_cache_;
+  std::vector<const Type*> crt_type_;             // Stored temporarily between two calls to Visit.
+};
+
+}  // namespace sea_ir
+
+#endif  // ART_COMPILER_SEA_IR_TYPES_TYPE_INFERENCE_VISITOR_H_
diff --git a/compiler/sea_ir/types/types.h b/compiler/sea_ir/types/types.h
new file mode 100644
index 0000000..8aa5d16
--- /dev/null
+++ b/compiler/sea_ir/types/types.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+
+#ifndef ART_COMPILER_SEA_IR_TYPES_TYPES_H_
+#define ART_COMPILER_SEA_IR_TYPES_TYPES_H_
+
+#include "verifier/reg_type.h"
+#include "verifier/reg_type_cache.h"
+
+namespace sea_ir {
+
+// TODO: Replace typedef with an actual class implementation when we have more types.
+typedef art::verifier::RegType Type;
+
+}  // namespace sea_ir
+#endif  // ART_COMPILER_SEA_IR_TYPES_TYPES_H_
diff --git a/compiler/sea_ir/visitor.h b/compiler/sea_ir/visitor.h
index f4cecd8..ffb073e 100644
--- a/compiler/sea_ir/visitor.h
+++ b/compiler/sea_ir/visitor.h
@@ -40,7 +40,7 @@
 
 class IRVisitor {
  public:
-  explicit IRVisitor():ordered_regions_() { }
+  explicit IRVisitor(): ordered_regions_() { }
   virtual void Initialize(SeaGraph* graph) = 0;
   virtual void Visit(SeaGraph* graph) = 0;
   virtual void Visit(Region* region) = 0;