16447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea/*
26447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea * Copyright (C) 2013 The Android Open Source Project
36447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea *
46447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea * Licensed under the Apache License, Version 2.0 (the "License");
56447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea * you may not use this file except in compliance with the License.
66447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea * You may obtain a copy of the License at
76447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea *
86447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea *      http://www.apache.org/licenses/LICENSE-2.0
96447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea *
106447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea * Unless required by applicable law or agreed to in writing, software
116447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea * distributed under the License is distributed on an "AS IS" BASIS,
126447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
136447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea * See the License for the specific language governing permissions and
146447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea * limitations under the License.
156447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea */
166447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea
176547fa9749d0e32cc367d64f8cc6b3d65bf43a5dDragos Sbirlea
18147c00cd39840e6ec3fd940c14ac75a59f205297Dragos Sbirlea#include "scoped_thread_state_change.h"
196447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea#include "sea_ir/debug/dot_gen.h"
206447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea
216447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirleanamespace sea_ir {
226447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea
236447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirleavoid DotGenerationVisitor::Initialize(SeaGraph* graph) {
246447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea  graph_ = graph;
256447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea  Region* root_region;
266447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea  ordered_regions_.clear();
276447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea  for (std::vector<Region*>::const_iterator cit = graph->GetRegions()->begin();
286447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea      cit != graph->GetRegions()->end(); cit++ ) {
296447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea    if ((*cit)->GetIDominator() == (*cit)) {
306447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea      root_region = *cit;
316447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea    }
326447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea  }
336447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea  ordered_regions_.push_back(root_region);
346447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea  for (unsigned int id = 0; id < ordered_regions_.size(); id++) {
356447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea    Region* current_region = ordered_regions_.at(id);
366447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea    const std::set<Region*>* dominated_regions = current_region->GetIDominatedSet();
376447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea    for (std::set<Region*>::const_iterator cit = dominated_regions->begin();
386447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea        cit != dominated_regions->end(); cit++ ) {
396447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea      ordered_regions_.push_back(*cit);
406447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea    }
416447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea  }
426447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea}
436447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea
446447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirleavoid DotGenerationVisitor::ToDotSSAEdges(InstructionNode* instruction) {
456447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea  std::map<int, InstructionNode*>* definition_edges = instruction->GetSSAProducersMap();
466447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea  // SSA definitions:
476447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea  for (std::map<int, InstructionNode*>::const_iterator
486447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea      def_it = definition_edges->begin();
496447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea      def_it != definition_edges->end(); def_it++) {
506447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea    if (NULL != def_it->second) {
516447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea      dot_text_ += def_it->second->StringId() + " -> ";
526447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea      dot_text_ += instruction->StringId() + "[color=gray,label=\"";
536447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea      dot_text_ += art::StringPrintf("vR = %d", def_it->first);
546547fa9749d0e32cc367d64f8cc6b3d65bf43a5dDragos Sbirlea      art::SafeMap<int, const Type*>::const_iterator type_it = types_->find(def_it->second->Id());
556447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea      if (type_it != types_->end()) {
56147c00cd39840e6ec3fd940c14ac75a59f205297Dragos Sbirlea        art::ScopedObjectAccess soa(art::Thread::Current());
576447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea        dot_text_ += "(" + type_it->second->Dump() + ")";
586447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea      } else {
596447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea        dot_text_ += "()";
606447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea      }
616447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea      dot_text_ += "\"] ; // SSA edge\n";
626447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea    }
636447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea  }
646447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea
656447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea  // SSA used-by:
666447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea  if (options_->WillSaveUseEdges()) {
676447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea    std::vector<InstructionNode*>* used_in = instruction->GetSSAConsumers();
686447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea    for (std::vector<InstructionNode*>::const_iterator cit = used_in->begin();
696447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea        cit != used_in->end(); cit++) {
706447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea      dot_text_ += (*cit)->StringId() + " -> " + instruction->StringId() + "[color=gray,label=\"";
716447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea      dot_text_ += "\"] ; // SSA used-by edge\n";
726447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea    }
736447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea  }
746447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea}
756447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea
767b89bc0d1e73ae5a4265f93bb5497019b1a9bf17Dragos Sbirleavoid DotGenerationVisitor::ToDotSSAEdges(PhiInstructionNode* instruction) {
777b89bc0d1e73ae5a4265f93bb5497019b1a9bf17Dragos Sbirlea  std::vector<InstructionNode*> definition_edges = instruction->GetSSAProducers();
787b89bc0d1e73ae5a4265f93bb5497019b1a9bf17Dragos Sbirlea  // SSA definitions:
797b89bc0d1e73ae5a4265f93bb5497019b1a9bf17Dragos Sbirlea  for (std::vector<InstructionNode*>::const_iterator
807b89bc0d1e73ae5a4265f93bb5497019b1a9bf17Dragos Sbirlea      def_it = definition_edges.begin();
817b89bc0d1e73ae5a4265f93bb5497019b1a9bf17Dragos Sbirlea      def_it != definition_edges.end(); def_it++) {
827b89bc0d1e73ae5a4265f93bb5497019b1a9bf17Dragos Sbirlea    if (NULL != *def_it) {
837b89bc0d1e73ae5a4265f93bb5497019b1a9bf17Dragos Sbirlea      dot_text_ += (*def_it)->StringId() + " -> ";
847b89bc0d1e73ae5a4265f93bb5497019b1a9bf17Dragos Sbirlea      dot_text_ += instruction->StringId() + "[color=gray,label=\"";
857b89bc0d1e73ae5a4265f93bb5497019b1a9bf17Dragos Sbirlea      dot_text_ += art::StringPrintf("vR = %d", instruction->GetRegisterNumber());
866547fa9749d0e32cc367d64f8cc6b3d65bf43a5dDragos Sbirlea      art::SafeMap<int, const Type*>::const_iterator type_it = types_->find((*def_it)->Id());
877b89bc0d1e73ae5a4265f93bb5497019b1a9bf17Dragos Sbirlea      if (type_it != types_->end()) {
887b89bc0d1e73ae5a4265f93bb5497019b1a9bf17Dragos Sbirlea        art::ScopedObjectAccess soa(art::Thread::Current());
897b89bc0d1e73ae5a4265f93bb5497019b1a9bf17Dragos Sbirlea        dot_text_ += "(" + type_it->second->Dump() + ")";
907b89bc0d1e73ae5a4265f93bb5497019b1a9bf17Dragos Sbirlea      } else {
917b89bc0d1e73ae5a4265f93bb5497019b1a9bf17Dragos Sbirlea        dot_text_ += "()";
927b89bc0d1e73ae5a4265f93bb5497019b1a9bf17Dragos Sbirlea      }
937b89bc0d1e73ae5a4265f93bb5497019b1a9bf17Dragos Sbirlea      dot_text_ += "\"] ; // SSA edge\n";
947b89bc0d1e73ae5a4265f93bb5497019b1a9bf17Dragos Sbirlea    }
957b89bc0d1e73ae5a4265f93bb5497019b1a9bf17Dragos Sbirlea  }
967b89bc0d1e73ae5a4265f93bb5497019b1a9bf17Dragos Sbirlea
977b89bc0d1e73ae5a4265f93bb5497019b1a9bf17Dragos Sbirlea  // SSA used-by:
987b89bc0d1e73ae5a4265f93bb5497019b1a9bf17Dragos Sbirlea  if (options_->WillSaveUseEdges()) {
997b89bc0d1e73ae5a4265f93bb5497019b1a9bf17Dragos Sbirlea    std::vector<InstructionNode*>* used_in = instruction->GetSSAConsumers();
1007b89bc0d1e73ae5a4265f93bb5497019b1a9bf17Dragos Sbirlea    for (std::vector<InstructionNode*>::const_iterator cit = used_in->begin();
1017b89bc0d1e73ae5a4265f93bb5497019b1a9bf17Dragos Sbirlea        cit != used_in->end(); cit++) {
1027b89bc0d1e73ae5a4265f93bb5497019b1a9bf17Dragos Sbirlea      dot_text_ += (*cit)->StringId() + " -> " + instruction->StringId() + "[color=gray,label=\"";
1037b89bc0d1e73ae5a4265f93bb5497019b1a9bf17Dragos Sbirlea      dot_text_ += "\"] ; // SSA used-by edge\n";
1047b89bc0d1e73ae5a4265f93bb5497019b1a9bf17Dragos Sbirlea    }
1057b89bc0d1e73ae5a4265f93bb5497019b1a9bf17Dragos Sbirlea  }
1067b89bc0d1e73ae5a4265f93bb5497019b1a9bf17Dragos Sbirlea}
1077b89bc0d1e73ae5a4265f93bb5497019b1a9bf17Dragos Sbirlea
1086447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirleavoid DotGenerationVisitor::Visit(SignatureNode* parameter) {
1097b89bc0d1e73ae5a4265f93bb5497019b1a9bf17Dragos Sbirlea  dot_text_ += parameter->StringId() +" [label=\"[" + parameter->StringId() + "] signature:";
1106447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea  dot_text_ += art::StringPrintf("r%d", parameter->GetResultRegister());
1116447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea  dot_text_ += "\"] // signature node\n";
1126447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea  ToDotSSAEdges(parameter);
1136447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea}
1146447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea
1156447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea// Appends to @result a dot language formatted string representing the node and
1166447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea//    (by convention) outgoing edges, so that the composition of theToDot() of all nodes
1176447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea//    builds a complete dot graph (without prolog and epilog though).
1186447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirleavoid DotGenerationVisitor::Visit(Region* region) {
1196447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea  dot_text_ += "\n// Region: \nsubgraph " + region->StringId();
1206447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea  dot_text_ += " { label=\"region " + region->StringId() + "(rpo=";
1216447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea  dot_text_ += art::StringPrintf("%d", region->GetRPO());
1226447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea  if (NULL != region->GetIDominator()) {
1236447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea    dot_text_ += " dom=" + region->GetIDominator()->StringId();
1246447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea  }
1256447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea  dot_text_ += ")\";\n";
1266447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea
1276447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea  std::vector<PhiInstructionNode*>* phi_instructions = region->GetPhiNodes();
1286447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea  for (std::vector<PhiInstructionNode*>::const_iterator cit = phi_instructions->begin();
1296447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea        cit != phi_instructions->end(); cit++) {
1306447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea    dot_text_ += (*cit)->StringId() +";\n";
1316447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea  }
1326447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea  std::vector<InstructionNode*>* instructions = region->GetInstructions();
1336447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea  for (std::vector<InstructionNode*>::const_iterator cit = instructions->begin();
1346447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea        cit != instructions->end(); cit++) {
1356447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea      dot_text_ += (*cit)->StringId() +";\n";
1366447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea    }
1376447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea
1386447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea  dot_text_ += "} // End Region.\n";
1396447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea  std::vector<Region*>* successors =  region->GetSuccessors();
1406447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea  for (std::vector<Region*>::const_iterator cit = successors->begin(); cit != successors->end();
1416447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea      cit++) {
1426447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea    DCHECK(NULL != *cit) << "Null successor found for SeaNode" <<
1436447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea        region->GetLastChild()->StringId() << ".";
1446447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea    dot_text_ += region->GetLastChild()->StringId() + " -> " +
1456447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea        (*cit)->GetLastChild()->StringId() +
1466447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea        "[lhead=" + (*cit)->StringId() + ", " + "ltail=" + region->StringId() + "];\n\n";
1476447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea  }
1486447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea}
1496447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirleavoid DotGenerationVisitor::Visit(InstructionNode* instruction) {
1506447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea  dot_text_ += "// Instruction ("+instruction->StringId()+"): \n" + instruction->StringId() +
1517b89bc0d1e73ae5a4265f93bb5497019b1a9bf17Dragos Sbirlea      " [label=\"[" + instruction->StringId() + "] " +
1527b89bc0d1e73ae5a4265f93bb5497019b1a9bf17Dragos Sbirlea      instruction->GetInstruction()->DumpString(graph_->GetDexFile()) + "\"";
1536447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea  dot_text_ += "];\n";
1546447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea  ToDotSSAEdges(instruction);
1556447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea}
1566447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea
1576447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirleavoid DotGenerationVisitor::Visit(UnnamedConstInstructionNode* instruction) {
1586447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea  dot_text_ += "// Instruction ("+instruction->StringId()+"): \n" + instruction->StringId() +
1597b89bc0d1e73ae5a4265f93bb5497019b1a9bf17Dragos Sbirlea        " [label=\"[" + instruction->StringId() + "] const/x v-3, #" +
1607b89bc0d1e73ae5a4265f93bb5497019b1a9bf17Dragos Sbirlea        art::StringPrintf("%d", instruction->GetConstValue()) + "\"";
1616447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea  dot_text_ += "];\n";
1626447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea  ToDotSSAEdges(instruction);
1636447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea}
1646447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea
1656447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirleavoid DotGenerationVisitor::Visit(PhiInstructionNode* phi) {
1666447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea  dot_text_ += "// PhiInstruction: \n" + phi->StringId() +
1677b89bc0d1e73ae5a4265f93bb5497019b1a9bf17Dragos Sbirlea      " [label=\"[" + phi->StringId() + "] PHI(";
1686447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea  dot_text_ += art::StringPrintf("%d", phi->GetRegisterNumber());
1696447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea  dot_text_ += ")\"";
1706447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea  dot_text_ += "];\n";
1716447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea  ToDotSSAEdges(phi);
1726447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea}
1736447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea}  // namespace sea_ir
174