1f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray/*
2f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray * Copyright (C) 2014 The Android Open Source Project
3f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray *
4f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray * Licensed under the Apache License, Version 2.0 (the "License");
5f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray * you may not use this file except in compliance with the License.
6f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray * You may obtain a copy of the License at
7f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray *
8f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray *      http://www.apache.org/licenses/LICENSE-2.0
9f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray *
10f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray * Unless required by applicable law or agreed to in writing, software
11f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray * distributed under the License is distributed on an "AS IS" BASIS,
12f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray * See the License for the specific language governing permissions and
14f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray * limitations under the License.
15f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray */
16f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray
17f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray#include "graph_visualizer.h"
18f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray
19a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray#include "code_generator.h"
20f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray#include "driver/dex_compilation_unit.h"
21f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray#include "nodes.h"
22ddb311fdeca82ca628fed694c4702f463b5c4927Nicolas Geoffray#include "ssa_liveness_analysis.h"
23f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray
24f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffraynamespace art {
25f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray
26f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray/**
27f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray * HGraph visitor to generate a file suitable for the c1visualizer tool and IRHydra.
28f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray */
29f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffrayclass HGraphVisualizerPrinter : public HGraphVisitor {
30f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray public:
3186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  HGraphVisualizerPrinter(HGraph* graph,
3286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray                          std::ostream& output,
3386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray                          const char* pass_name,
3486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray                          const CodeGenerator& codegen)
3586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      : HGraphVisitor(graph),
3686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray        output_(output),
3786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray        pass_name_(pass_name),
3886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray        codegen_(codegen),
3986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray        indent_(0) {}
40f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray
41f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray  void StartTag(const char* name) {
42f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    AddIndent();
43f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    output_ << "begin_" << name << std::endl;
44f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    indent_++;
45f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray  }
46f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray
47f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray  void EndTag(const char* name) {
48f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    indent_--;
49f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    AddIndent();
50f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    output_ << "end_" << name << std::endl;
51f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray  }
52f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray
53f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray  void PrintProperty(const char* name, const char* property) {
54f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    AddIndent();
55f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    output_ << name << " \"" << property << "\"" << std::endl;
56f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray  }
57f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray
58f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray  void PrintProperty(const char* name, const char* property, int id) {
59f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    AddIndent();
60f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    output_ << name << " \"" << property << id << "\"" << std::endl;
61f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray  }
62f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray
63f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray  void PrintEmptyProperty(const char* name) {
64f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    AddIndent();
65f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    output_ << name << std::endl;
66f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray  }
67f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray
68f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray  void PrintTime(const char* name) {
69f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    AddIndent();
70f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    output_ << name << " " << time(NULL) << std::endl;
71f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray  }
72f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray
73f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray  void PrintInt(const char* name, int value) {
74f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    AddIndent();
75f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    output_ << name << " " << value << std::endl;
76f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray  }
77f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray
78f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray  void AddIndent() {
79f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    for (size_t i = 0; i < indent_; ++i) {
80f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray      output_ << "  ";
81f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    }
82f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray  }
83f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray
84f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray  void PrintPredecessors(HBasicBlock* block) {
85f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    AddIndent();
86f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    output_ << "predecessors";
87f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    for (size_t i = 0, e = block->GetPredecessors().Size(); i < e; ++i) {
88f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray      HBasicBlock* predecessor = block->GetPredecessors().Get(i);
89f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray      output_ << " \"B" << predecessor->GetBlockId() << "\" ";
90f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    }
91f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    output_<< std::endl;
92f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray  }
93f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray
94f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray  void PrintSuccessors(HBasicBlock* block) {
95f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    AddIndent();
96f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    output_ << "successors";
97f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    for (size_t i = 0, e = block->GetSuccessors().Size(); i < e; ++i) {
98f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray      HBasicBlock* successor = block->GetSuccessors().Get(i);
99f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray      output_ << " \"B" << successor->GetBlockId() << "\" ";
100f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    }
101f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    output_<< std::endl;
102f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray  }
103f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray
10486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  void DumpLocation(Location location, Primitive::Type type) {
10586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    if (location.IsRegister()) {
10686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      if (type == Primitive::kPrimDouble || type == Primitive::kPrimFloat) {
10786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray        codegen_.DumpFloatingPointRegister(output_, location.reg().RegId());
10886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      } else {
10986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray        codegen_.DumpCoreRegister(output_, location.reg().RegId());
11086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      }
11196f89a290eb67d7bf4b1636798fa28df14309cc7Nicolas Geoffray    } else if (location.IsConstant()) {
11296f89a290eb67d7bf4b1636798fa28df14309cc7Nicolas Geoffray      output_ << "constant";
11396f89a290eb67d7bf4b1636798fa28df14309cc7Nicolas Geoffray    } else if (location.IsInvalid()) {
11496f89a290eb67d7bf4b1636798fa28df14309cc7Nicolas Geoffray      output_ << "invalid";
115412f10cfed002ab617c78f2621d68446ca4dd8bdNicolas Geoffray    } else if (location.IsStackSlot()) {
11686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      output_ << location.GetStackIndex() << "(sp)";
117412f10cfed002ab617c78f2621d68446ca4dd8bdNicolas Geoffray    } else {
118412f10cfed002ab617c78f2621d68446ca4dd8bdNicolas Geoffray      DCHECK(location.IsDoubleStackSlot());
119412f10cfed002ab617c78f2621d68446ca4dd8bdNicolas Geoffray      output_ << "2x" << location.GetStackIndex() << "(sp)";
12086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    }
12186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  }
12286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray
12386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  void VisitParallelMove(HParallelMove* instruction) {
12486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    output_ << instruction->DebugName();
12586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    output_ << " (";
12686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    for (size_t i = 0, e = instruction->NumMoves(); i < e; ++i) {
12786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      MoveOperands* move = instruction->MoveOperandsAt(i);
12886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      DumpLocation(move->GetSource(), Primitive::kPrimInt);
12986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      output_ << " -> ";
13086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      DumpLocation(move->GetDestination(), Primitive::kPrimInt);
13186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      if (i + 1 != e) {
13286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray        output_ << ", ";
13386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      }
13486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    }
13586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    output_ << ")";
13686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  }
137f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray
138f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray  void VisitInstruction(HInstruction* instruction) {
139f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    output_ << instruction->DebugName();
140f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    if (instruction->InputCount() > 0) {
141f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray      output_ << " [ ";
142f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray      for (HInputIterator inputs(instruction); !inputs.Done(); inputs.Advance()) {
143f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray        output_ << "v" << inputs.Current()->GetId() << " ";
144f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray      }
145f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray      output_ << "]";
146f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    }
14786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    if (pass_name_ == kLivenessPassName && instruction->GetLifetimePosition() != kNoLifetime) {
148ddb311fdeca82ca628fed694c4702f463b5c4927Nicolas Geoffray      output_ << " (liveness: " << instruction->GetLifetimePosition();
149ddb311fdeca82ca628fed694c4702f463b5c4927Nicolas Geoffray      if (instruction->HasLiveInterval()) {
150ddb311fdeca82ca628fed694c4702f463b5c4927Nicolas Geoffray        output_ << " ";
151a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray        const LiveInterval& interval = *instruction->GetLiveInterval();
152a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray        interval.Dump(output_);
15386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      }
15486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      output_ << ")";
15586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    } else if (pass_name_ == kRegisterAllocatorPassName) {
15686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      LocationSummary* locations = instruction->GetLocations();
15786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      if (locations != nullptr) {
15886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray        output_ << " ( ";
15986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray        for (size_t i = 0; i < instruction->InputCount(); ++i) {
16086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray          DumpLocation(locations->InAt(i), instruction->InputAt(i)->GetType());
161a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray          output_ << " ";
16286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray        }
16386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray        output_ << ")";
16486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray        if (locations->Out().IsValid()) {
16586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray          output_ << " -> ";
16686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray          DumpLocation(locations->Out(), instruction->GetType());
167a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray        }
168ddb311fdeca82ca628fed694c4702f463b5c4927Nicolas Geoffray      }
169ddb311fdeca82ca628fed694c4702f463b5c4927Nicolas Geoffray    }
170f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray  }
171f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray
172f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray  void PrintInstructions(const HInstructionList& list) {
173f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    const char* kEndInstructionMarker = "<|@";
174f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    for (HInstructionIterator it(list); !it.Done(); it.Advance()) {
175f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray      HInstruction* instruction = it.Current();
176f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray      AddIndent();
177f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray      int bci = 0;
178f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray      output_ << bci << " " << instruction->NumberOfUses() << " v" << instruction->GetId() << " ";
179f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray      instruction->Accept(this);
180f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray      output_ << kEndInstructionMarker << std::endl;
181f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    }
182f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray  }
183f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray
18486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  void Run() {
185f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    StartTag("cfg");
18686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    PrintProperty("name", pass_name_);
187f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    VisitInsertionOrder();
188f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    EndTag("cfg");
189f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray  }
190f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray
191f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray  void VisitBasicBlock(HBasicBlock* block) {
192f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    StartTag("block");
193f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    PrintProperty("name", "B", block->GetBlockId());
194ddb311fdeca82ca628fed694c4702f463b5c4927Nicolas Geoffray    if (block->GetLifetimeStart() != kNoLifetime) {
195ddb311fdeca82ca628fed694c4702f463b5c4927Nicolas Geoffray      // Piggy back on these fields to show the lifetime of the block.
196ddb311fdeca82ca628fed694c4702f463b5c4927Nicolas Geoffray      PrintInt("from_bci", block->GetLifetimeStart());
197ddb311fdeca82ca628fed694c4702f463b5c4927Nicolas Geoffray      PrintInt("to_bci", block->GetLifetimeEnd());
198ddb311fdeca82ca628fed694c4702f463b5c4927Nicolas Geoffray    } else {
199ddb311fdeca82ca628fed694c4702f463b5c4927Nicolas Geoffray      PrintInt("from_bci", -1);
200ddb311fdeca82ca628fed694c4702f463b5c4927Nicolas Geoffray      PrintInt("to_bci", -1);
201ddb311fdeca82ca628fed694c4702f463b5c4927Nicolas Geoffray    }
202f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    PrintPredecessors(block);
203f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    PrintSuccessors(block);
204f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    PrintEmptyProperty("xhandlers");
205f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    PrintEmptyProperty("flags");
206f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    if (block->GetDominator() != nullptr) {
207f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray      PrintProperty("dominator", "B", block->GetDominator()->GetBlockId());
208f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    }
209f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray
210f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    StartTag("states");
211f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    StartTag("locals");
212f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    PrintInt("size", 0);
213f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    PrintProperty("method", "None");
214f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    for (HInstructionIterator it(block->GetPhis()); !it.Done(); it.Advance()) {
215f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray      AddIndent();
216f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray      HInstruction* instruction = it.Current();
217f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray      output_ << instruction->GetId() << " v" << instruction->GetId() << "[ ";
218f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray      for (HInputIterator inputs(instruction); !inputs.Done(); inputs.Advance()) {
219f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray        output_ << inputs.Current()->GetId() << " ";
220f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray      }
221f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray      output_ << "]" << std::endl;
222f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    }
223f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    EndTag("locals");
224f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    EndTag("states");
225f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray
226f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    StartTag("HIR");
227f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    PrintInstructions(block->GetPhis());
228f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    PrintInstructions(block->GetInstructions());
229f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    EndTag("HIR");
230f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    EndTag("block");
231f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray  }
232f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray
233f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray private:
234f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray  std::ostream& output_;
23586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  const char* pass_name_;
236a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  const CodeGenerator& codegen_;
237f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray  size_t indent_;
238f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray
239f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray  DISALLOW_COPY_AND_ASSIGN(HGraphVisualizerPrinter);
240f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray};
241f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray
242f635e63318447ca04731b265a86a573c9ed1737cNicolas GeoffrayHGraphVisualizer::HGraphVisualizer(std::ostream* output,
243f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray                                   HGraph* graph,
244f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray                                   const char* string_filter,
245a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray                                   const CodeGenerator& codegen,
246f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray                                   const DexCompilationUnit& cu)
247a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    : output_(output), graph_(graph), codegen_(codegen), is_enabled_(false) {
248f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray  if (output == nullptr) {
249f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    return;
250f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray  }
251f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray  std::string pretty_name = PrettyMethod(cu.GetDexMethodIndex(), *cu.GetDexFile());
252f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray  if (pretty_name.find(string_filter) == std::string::npos) {
253f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    return;
254f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray  }
255f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray
256f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray  is_enabled_ = true;
25786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  HGraphVisualizerPrinter printer(graph, *output_, "", codegen_);
258f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray  printer.StartTag("compilation");
259f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray  printer.PrintProperty("name", pretty_name.c_str());
260f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray  printer.PrintProperty("method", pretty_name.c_str());
261f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray  printer.PrintTime("date");
262f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray  printer.EndTag("compilation");
263f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray}
264f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray
2650d3f578909d0d1ea072ca68d78301b6fb7a44451Nicolas GeoffrayHGraphVisualizer::HGraphVisualizer(std::ostream* output,
2660d3f578909d0d1ea072ca68d78301b6fb7a44451Nicolas Geoffray                                   HGraph* graph,
267a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray                                   const CodeGenerator& codegen,
2680d3f578909d0d1ea072ca68d78301b6fb7a44451Nicolas Geoffray                                   const char* name)
269a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    : output_(output), graph_(graph), codegen_(codegen), is_enabled_(false) {
2700d3f578909d0d1ea072ca68d78301b6fb7a44451Nicolas Geoffray  if (output == nullptr) {
2710d3f578909d0d1ea072ca68d78301b6fb7a44451Nicolas Geoffray    return;
2720d3f578909d0d1ea072ca68d78301b6fb7a44451Nicolas Geoffray  }
2730d3f578909d0d1ea072ca68d78301b6fb7a44451Nicolas Geoffray
2740d3f578909d0d1ea072ca68d78301b6fb7a44451Nicolas Geoffray  is_enabled_ = true;
27586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  HGraphVisualizerPrinter printer(graph, *output_, "", codegen_);
2760d3f578909d0d1ea072ca68d78301b6fb7a44451Nicolas Geoffray  printer.StartTag("compilation");
2770d3f578909d0d1ea072ca68d78301b6fb7a44451Nicolas Geoffray  printer.PrintProperty("name", name);
2780d3f578909d0d1ea072ca68d78301b6fb7a44451Nicolas Geoffray  printer.PrintProperty("method", name);
2790d3f578909d0d1ea072ca68d78301b6fb7a44451Nicolas Geoffray  printer.PrintTime("date");
2800d3f578909d0d1ea072ca68d78301b6fb7a44451Nicolas Geoffray  printer.EndTag("compilation");
2810d3f578909d0d1ea072ca68d78301b6fb7a44451Nicolas Geoffray}
2820d3f578909d0d1ea072ca68d78301b6fb7a44451Nicolas Geoffray
283f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffrayvoid HGraphVisualizer::DumpGraph(const char* pass_name) {
284f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray  if (!is_enabled_) {
285f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    return;
286f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray  }
28786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  HGraphVisualizerPrinter printer(graph_, *output_, pass_name, codegen_);
28886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  printer.Run();
289f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray}
290f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray
291f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray}  // namespace art
292