blob: ecb641e6615fa9cdff3f2afd18be9ad4119c92da [file] [log] [blame]
Dragos Sbirlea64479192013-08-01 15:38:43 -07001/*
2 * Copyright (C) 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Dragos Sbirlea147c00c2013-08-05 11:35:48 -070017#include "scoped_thread_state_change.h"
Dragos Sbirlea64479192013-08-01 15:38:43 -070018#include "sea_ir/debug/dot_gen.h"
19
20namespace sea_ir {
21
22void DotGenerationVisitor::Initialize(SeaGraph* graph) {
23 graph_ = graph;
24 Region* root_region;
25 ordered_regions_.clear();
26 for (std::vector<Region*>::const_iterator cit = graph->GetRegions()->begin();
27 cit != graph->GetRegions()->end(); cit++ ) {
28 if ((*cit)->GetIDominator() == (*cit)) {
29 root_region = *cit;
30 }
31 }
32 ordered_regions_.push_back(root_region);
33 for (unsigned int id = 0; id < ordered_regions_.size(); id++) {
34 Region* current_region = ordered_regions_.at(id);
35 const std::set<Region*>* dominated_regions = current_region->GetIDominatedSet();
36 for (std::set<Region*>::const_iterator cit = dominated_regions->begin();
37 cit != dominated_regions->end(); cit++ ) {
38 ordered_regions_.push_back(*cit);
39 }
40 }
41}
42
43void DotGenerationVisitor::ToDotSSAEdges(InstructionNode* instruction) {
44 std::map<int, InstructionNode*>* definition_edges = instruction->GetSSAProducersMap();
45 // SSA definitions:
46 for (std::map<int, InstructionNode*>::const_iterator
47 def_it = definition_edges->begin();
48 def_it != definition_edges->end(); def_it++) {
49 if (NULL != def_it->second) {
50 dot_text_ += def_it->second->StringId() + " -> ";
51 dot_text_ += instruction->StringId() + "[color=gray,label=\"";
52 dot_text_ += art::StringPrintf("vR = %d", def_it->first);
53 std::map<int, const Type*>::const_iterator type_it = types_->find(def_it->second->Id());
54 if (type_it != types_->end()) {
Dragos Sbirlea147c00c2013-08-05 11:35:48 -070055 art::ScopedObjectAccess soa(art::Thread::Current());
Dragos Sbirlea64479192013-08-01 15:38:43 -070056 dot_text_ += "(" + type_it->second->Dump() + ")";
57 } else {
58 dot_text_ += "()";
59 }
60 dot_text_ += "\"] ; // SSA edge\n";
61 }
62 }
63
64 // SSA used-by:
65 if (options_->WillSaveUseEdges()) {
66 std::vector<InstructionNode*>* used_in = instruction->GetSSAConsumers();
67 for (std::vector<InstructionNode*>::const_iterator cit = used_in->begin();
68 cit != used_in->end(); cit++) {
69 dot_text_ += (*cit)->StringId() + " -> " + instruction->StringId() + "[color=gray,label=\"";
70 dot_text_ += "\"] ; // SSA used-by edge\n";
71 }
72 }
73}
74
Dragos Sbirlea7b89bc02013-08-05 16:24:57 -070075void DotGenerationVisitor::ToDotSSAEdges(PhiInstructionNode* instruction) {
76 std::vector<InstructionNode*> definition_edges = instruction->GetSSAProducers();
77 // SSA definitions:
78 for (std::vector<InstructionNode*>::const_iterator
79 def_it = definition_edges.begin();
80 def_it != definition_edges.end(); def_it++) {
81 if (NULL != *def_it) {
82 dot_text_ += (*def_it)->StringId() + " -> ";
83 dot_text_ += instruction->StringId() + "[color=gray,label=\"";
84 dot_text_ += art::StringPrintf("vR = %d", instruction->GetRegisterNumber());
85 std::map<int, const Type*>::const_iterator type_it = types_->find((*def_it)->Id());
86 if (type_it != types_->end()) {
87 art::ScopedObjectAccess soa(art::Thread::Current());
88 dot_text_ += "(" + type_it->second->Dump() + ")";
89 } else {
90 dot_text_ += "()";
91 }
92 dot_text_ += "\"] ; // SSA edge\n";
93 }
94 }
95
96 // SSA used-by:
97 if (options_->WillSaveUseEdges()) {
98 std::vector<InstructionNode*>* used_in = instruction->GetSSAConsumers();
99 for (std::vector<InstructionNode*>::const_iterator cit = used_in->begin();
100 cit != used_in->end(); cit++) {
101 dot_text_ += (*cit)->StringId() + " -> " + instruction->StringId() + "[color=gray,label=\"";
102 dot_text_ += "\"] ; // SSA used-by edge\n";
103 }
104 }
105}
106
Dragos Sbirlea64479192013-08-01 15:38:43 -0700107void DotGenerationVisitor::Visit(SignatureNode* parameter) {
Dragos Sbirlea7b89bc02013-08-05 16:24:57 -0700108 dot_text_ += parameter->StringId() +" [label=\"[" + parameter->StringId() + "] signature:";
Dragos Sbirlea64479192013-08-01 15:38:43 -0700109 dot_text_ += art::StringPrintf("r%d", parameter->GetResultRegister());
110 dot_text_ += "\"] // signature node\n";
111 ToDotSSAEdges(parameter);
112}
113
114// Appends to @result a dot language formatted string representing the node and
115// (by convention) outgoing edges, so that the composition of theToDot() of all nodes
116// builds a complete dot graph (without prolog and epilog though).
117void DotGenerationVisitor::Visit(Region* region) {
118 dot_text_ += "\n// Region: \nsubgraph " + region->StringId();
119 dot_text_ += " { label=\"region " + region->StringId() + "(rpo=";
120 dot_text_ += art::StringPrintf("%d", region->GetRPO());
121 if (NULL != region->GetIDominator()) {
122 dot_text_ += " dom=" + region->GetIDominator()->StringId();
123 }
124 dot_text_ += ")\";\n";
125
126 std::vector<PhiInstructionNode*>* phi_instructions = region->GetPhiNodes();
127 for (std::vector<PhiInstructionNode*>::const_iterator cit = phi_instructions->begin();
128 cit != phi_instructions->end(); cit++) {
129 dot_text_ += (*cit)->StringId() +";\n";
130 }
131 std::vector<InstructionNode*>* instructions = region->GetInstructions();
132 for (std::vector<InstructionNode*>::const_iterator cit = instructions->begin();
133 cit != instructions->end(); cit++) {
134 dot_text_ += (*cit)->StringId() +";\n";
135 }
136
137 dot_text_ += "} // End Region.\n";
138 std::vector<Region*>* successors = region->GetSuccessors();
139 for (std::vector<Region*>::const_iterator cit = successors->begin(); cit != successors->end();
140 cit++) {
141 DCHECK(NULL != *cit) << "Null successor found for SeaNode" <<
142 region->GetLastChild()->StringId() << ".";
143 dot_text_ += region->GetLastChild()->StringId() + " -> " +
144 (*cit)->GetLastChild()->StringId() +
145 "[lhead=" + (*cit)->StringId() + ", " + "ltail=" + region->StringId() + "];\n\n";
146 }
147}
148void DotGenerationVisitor::Visit(InstructionNode* instruction) {
149 dot_text_ += "// Instruction ("+instruction->StringId()+"): \n" + instruction->StringId() +
Dragos Sbirlea7b89bc02013-08-05 16:24:57 -0700150 " [label=\"[" + instruction->StringId() + "] " +
151 instruction->GetInstruction()->DumpString(graph_->GetDexFile()) + "\"";
Dragos Sbirlea64479192013-08-01 15:38:43 -0700152 dot_text_ += "];\n";
153 ToDotSSAEdges(instruction);
154}
155
156void DotGenerationVisitor::Visit(UnnamedConstInstructionNode* instruction) {
157 dot_text_ += "// Instruction ("+instruction->StringId()+"): \n" + instruction->StringId() +
Dragos Sbirlea7b89bc02013-08-05 16:24:57 -0700158 " [label=\"[" + instruction->StringId() + "] const/x v-3, #" +
159 art::StringPrintf("%d", instruction->GetConstValue()) + "\"";
Dragos Sbirlea64479192013-08-01 15:38:43 -0700160 dot_text_ += "];\n";
161 ToDotSSAEdges(instruction);
162}
163
164void DotGenerationVisitor::Visit(PhiInstructionNode* phi) {
165 dot_text_ += "// PhiInstruction: \n" + phi->StringId() +
Dragos Sbirlea7b89bc02013-08-05 16:24:57 -0700166 " [label=\"[" + phi->StringId() + "] PHI(";
Dragos Sbirlea64479192013-08-01 15:38:43 -0700167 dot_text_ += art::StringPrintf("%d", phi->GetRegisterNumber());
168 dot_text_ += ")\"";
169 dot_text_ += "];\n";
170 ToDotSSAEdges(phi);
171}
172} // namespace sea_ir