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 #ifndef ART_COMPILER_SEA_IR_DEBUG_DOT_GEN_H_
18 #define ART_COMPILER_SEA_IR_DEBUG_DOT_GEN_H_
19 
20 #include "safe_map.h"
21 #include "base/stringprintf.h"
22 #include "file_output_stream.h"
23 #include "os.h"
24 #include "sea_ir/ir/sea.h"
25 #include "sea_ir/types/type_inference.h"
26 
27 namespace sea_ir {
28 
29 class DotConversionOptions {
30  public:
DotConversionOptions()31   DotConversionOptions(): save_use_edges_(false) { }
WillSaveUseEdges()32   bool WillSaveUseEdges() const {
33     return save_use_edges_;
34   }
35  private:
36   bool save_use_edges_;
37 };
38 
39 class DotGenerationVisitor: public IRVisitor {
40  public:
DotGenerationVisitor(const DotConversionOptions * const options,art::SafeMap<int,const Type * > * types)41   explicit DotGenerationVisitor(const DotConversionOptions* const options,
42       art::SafeMap<int, const Type*>* types): graph_(), types_(types), options_(options) { }
43 
44   virtual void Initialize(SeaGraph* graph);
45   // Saves the ssa def->use edges corresponding to @instruction.
46   void ToDotSSAEdges(InstructionNode* instruction);
47   void ToDotSSAEdges(PhiInstructionNode* instruction);
Visit(SeaGraph * graph)48   void Visit(SeaGraph* graph) {
49     dot_text_ += "digraph seaOfNodes {\ncompound=true\n";
50   }
51   void Visit(SignatureNode* parameter);
52 
53   // Appends to @result a dot language formatted string representing the node and
54   //    (by convention) outgoing edges, so that the composition of theToDot() of all nodes
55   //    builds a complete dot graph (without prolog and epilog though).
56   void Visit(Region* region);
57   void Visit(InstructionNode* instruction);
58   void Visit(PhiInstructionNode* phi);
59   void Visit(UnnamedConstInstructionNode* instruction);
60 
Visit(ConstInstructionNode * instruction)61   void Visit(ConstInstructionNode* instruction) {
62     Visit(reinterpret_cast<InstructionNode*>(instruction));
63   }
Visit(ReturnInstructionNode * instruction)64   void Visit(ReturnInstructionNode* instruction) {
65     Visit(reinterpret_cast<InstructionNode*>(instruction));
66   }
Visit(IfNeInstructionNode * instruction)67   void Visit(IfNeInstructionNode* instruction) {
68     Visit(reinterpret_cast<InstructionNode*>(instruction));
69   }
Visit(MoveResultInstructionNode * instruction)70   void Visit(MoveResultInstructionNode* instruction) {
71     Visit(reinterpret_cast<InstructionNode*>(instruction));
72   }
Visit(InvokeStaticInstructionNode * instruction)73   void Visit(InvokeStaticInstructionNode* instruction) {
74     Visit(reinterpret_cast<InstructionNode*>(instruction));
75   }
Visit(AddIntInstructionNode * instruction)76   void Visit(AddIntInstructionNode* instruction) {
77     Visit(reinterpret_cast<InstructionNode*>(instruction));
78   }
Visit(GotoInstructionNode * instruction)79   void Visit(GotoInstructionNode* instruction) {
80     Visit(reinterpret_cast<InstructionNode*>(instruction));
81   }
Visit(IfEqzInstructionNode * instruction)82   void Visit(IfEqzInstructionNode* instruction) {
83     Visit(reinterpret_cast<InstructionNode*>(instruction));
84   }
85 
GetResult()86   std::string GetResult() const {
87     return dot_text_;
88   }
89 
90  private:
91   std::string dot_text_;
92   SeaGraph* graph_;
93   art::SafeMap<int, const Type*>* types_;
94   const DotConversionOptions* const options_;
95 };
96 
97 // Stores options for turning a SEA IR graph to a .dot file.
98 class DotConversion {
99  public:
DotConversion()100   DotConversion(): options_() { }
101   // Saves to @filename the .dot representation of @graph with the options @options.
DumpSea(SeaGraph * graph,std::string filename,art::SafeMap<int,const Type * > * types)102   void DumpSea(SeaGraph* graph, std::string filename,
103       art::SafeMap<int, const Type*>* types) const {
104     LOG(INFO) << "Starting to write SEA string to file " << filename << std::endl;
105     DotGenerationVisitor dgv = DotGenerationVisitor(&options_, types);
106     graph->Accept(&dgv);
107     // TODO: std::unique_ptr to close file properly. Switch to BufferedOutputStream.
108     art::File* file = art::OS::CreateEmptyFile(filename.c_str());
109     art::FileOutputStream fos(file);
110     std::string graph_as_string = dgv.GetResult();
111     graph_as_string += "}";
112     fos.WriteFully(graph_as_string.c_str(), graph_as_string.size());
113     LOG(INFO) << "Written SEA string to file.";
114   }
115 
116  private:
117   DotConversionOptions options_;
118 };
119 
120 }  // namespace sea_ir
121 #endif  // ART_COMPILER_SEA_IR_DEBUG_DOT_GEN_H_
122