1 /*
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
17
18 #include "scoped_thread_state_change.h"
19 #include "sea_ir/debug/dot_gen.h"
20
21 namespace sea_ir {
22
Initialize(SeaGraph * graph)23 void DotGenerationVisitor::Initialize(SeaGraph* graph) {
24 graph_ = graph;
25 Region* root_region;
26 ordered_regions_.clear();
27 for (std::vector<Region*>::const_iterator cit = graph->GetRegions()->begin();
28 cit != graph->GetRegions()->end(); cit++ ) {
29 if ((*cit)->GetIDominator() == (*cit)) {
30 root_region = *cit;
31 }
32 }
33 ordered_regions_.push_back(root_region);
34 for (unsigned int id = 0; id < ordered_regions_.size(); id++) {
35 Region* current_region = ordered_regions_.at(id);
36 const std::set<Region*>* dominated_regions = current_region->GetIDominatedSet();
37 for (std::set<Region*>::const_iterator cit = dominated_regions->begin();
38 cit != dominated_regions->end(); cit++ ) {
39 ordered_regions_.push_back(*cit);
40 }
41 }
42 }
43
ToDotSSAEdges(InstructionNode * instruction)44 void DotGenerationVisitor::ToDotSSAEdges(InstructionNode* instruction) {
45 std::map<int, InstructionNode*>* definition_edges = instruction->GetSSAProducersMap();
46 // SSA definitions:
47 for (std::map<int, InstructionNode*>::const_iterator
48 def_it = definition_edges->begin();
49 def_it != definition_edges->end(); def_it++) {
50 if (NULL != def_it->second) {
51 dot_text_ += def_it->second->StringId() + " -> ";
52 dot_text_ += instruction->StringId() + "[color=gray,label=\"";
53 dot_text_ += art::StringPrintf("vR = %d", def_it->first);
54 art::SafeMap<int, const Type*>::const_iterator type_it = types_->find(def_it->second->Id());
55 if (type_it != types_->end()) {
56 art::ScopedObjectAccess soa(art::Thread::Current());
57 dot_text_ += "(" + type_it->second->Dump() + ")";
58 } else {
59 dot_text_ += "()";
60 }
61 dot_text_ += "\"] ; // SSA edge\n";
62 }
63 }
64
65 // SSA used-by:
66 if (options_->WillSaveUseEdges()) {
67 std::vector<InstructionNode*>* used_in = instruction->GetSSAConsumers();
68 for (std::vector<InstructionNode*>::const_iterator cit = used_in->begin();
69 cit != used_in->end(); cit++) {
70 dot_text_ += (*cit)->StringId() + " -> " + instruction->StringId() + "[color=gray,label=\"";
71 dot_text_ += "\"] ; // SSA used-by edge\n";
72 }
73 }
74 }
75
ToDotSSAEdges(PhiInstructionNode * instruction)76 void DotGenerationVisitor::ToDotSSAEdges(PhiInstructionNode* instruction) {
77 std::vector<InstructionNode*> definition_edges = instruction->GetSSAProducers();
78 // SSA definitions:
79 for (std::vector<InstructionNode*>::const_iterator
80 def_it = definition_edges.begin();
81 def_it != definition_edges.end(); def_it++) {
82 if (NULL != *def_it) {
83 dot_text_ += (*def_it)->StringId() + " -> ";
84 dot_text_ += instruction->StringId() + "[color=gray,label=\"";
85 dot_text_ += art::StringPrintf("vR = %d", instruction->GetRegisterNumber());
86 art::SafeMap<int, const Type*>::const_iterator type_it = types_->find((*def_it)->Id());
87 if (type_it != types_->end()) {
88 art::ScopedObjectAccess soa(art::Thread::Current());
89 dot_text_ += "(" + type_it->second->Dump() + ")";
90 } else {
91 dot_text_ += "()";
92 }
93 dot_text_ += "\"] ; // SSA edge\n";
94 }
95 }
96
97 // SSA used-by:
98 if (options_->WillSaveUseEdges()) {
99 std::vector<InstructionNode*>* used_in = instruction->GetSSAConsumers();
100 for (std::vector<InstructionNode*>::const_iterator cit = used_in->begin();
101 cit != used_in->end(); cit++) {
102 dot_text_ += (*cit)->StringId() + " -> " + instruction->StringId() + "[color=gray,label=\"";
103 dot_text_ += "\"] ; // SSA used-by edge\n";
104 }
105 }
106 }
107
Visit(SignatureNode * parameter)108 void DotGenerationVisitor::Visit(SignatureNode* parameter) {
109 dot_text_ += parameter->StringId() +" [label=\"[" + parameter->StringId() + "] signature:";
110 dot_text_ += art::StringPrintf("r%d", parameter->GetResultRegister());
111 dot_text_ += "\"] // signature node\n";
112 ToDotSSAEdges(parameter);
113 }
114
115 // Appends to @result a dot language formatted string representing the node and
116 // (by convention) outgoing edges, so that the composition of theToDot() of all nodes
117 // builds a complete dot graph (without prolog and epilog though).
Visit(Region * region)118 void DotGenerationVisitor::Visit(Region* region) {
119 dot_text_ += "\n// Region: \nsubgraph " + region->StringId();
120 dot_text_ += " { label=\"region " + region->StringId() + "(rpo=";
121 dot_text_ += art::StringPrintf("%d", region->GetRPO());
122 if (NULL != region->GetIDominator()) {
123 dot_text_ += " dom=" + region->GetIDominator()->StringId();
124 }
125 dot_text_ += ")\";\n";
126
127 std::vector<PhiInstructionNode*>* phi_instructions = region->GetPhiNodes();
128 for (std::vector<PhiInstructionNode*>::const_iterator cit = phi_instructions->begin();
129 cit != phi_instructions->end(); cit++) {
130 dot_text_ += (*cit)->StringId() +";\n";
131 }
132 std::vector<InstructionNode*>* instructions = region->GetInstructions();
133 for (std::vector<InstructionNode*>::const_iterator cit = instructions->begin();
134 cit != instructions->end(); cit++) {
135 dot_text_ += (*cit)->StringId() +";\n";
136 }
137
138 dot_text_ += "} // End Region.\n";
139 std::vector<Region*>* successors = region->GetSuccessors();
140 for (std::vector<Region*>::const_iterator cit = successors->begin(); cit != successors->end();
141 cit++) {
142 DCHECK(NULL != *cit) << "Null successor found for SeaNode" <<
143 region->GetLastChild()->StringId() << ".";
144 dot_text_ += region->GetLastChild()->StringId() + " -> " +
145 (*cit)->GetLastChild()->StringId() +
146 "[lhead=" + (*cit)->StringId() + ", " + "ltail=" + region->StringId() + "];\n\n";
147 }
148 }
Visit(InstructionNode * instruction)149 void DotGenerationVisitor::Visit(InstructionNode* instruction) {
150 dot_text_ += "// Instruction ("+instruction->StringId()+"): \n" + instruction->StringId() +
151 " [label=\"[" + instruction->StringId() + "] " +
152 instruction->GetInstruction()->DumpString(graph_->GetDexFile()) + "\"";
153 dot_text_ += "];\n";
154 ToDotSSAEdges(instruction);
155 }
156
Visit(UnnamedConstInstructionNode * instruction)157 void DotGenerationVisitor::Visit(UnnamedConstInstructionNode* instruction) {
158 dot_text_ += "// Instruction ("+instruction->StringId()+"): \n" + instruction->StringId() +
159 " [label=\"[" + instruction->StringId() + "] const/x v-3, #" +
160 art::StringPrintf("%d", instruction->GetConstValue()) + "\"";
161 dot_text_ += "];\n";
162 ToDotSSAEdges(instruction);
163 }
164
Visit(PhiInstructionNode * phi)165 void DotGenerationVisitor::Visit(PhiInstructionNode* phi) {
166 dot_text_ += "// PhiInstruction: \n" + phi->StringId() +
167 " [label=\"[" + phi->StringId() + "] PHI(";
168 dot_text_ += art::StringPrintf("%d", phi->GetRegisterNumber());
169 dot_text_ += ")\"";
170 dot_text_ += "];\n";
171 ToDotSSAEdges(phi);
172 }
173 } // namespace sea_ir
174