1 /*
2 * Copyright (c) 2021-2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "graph.h"
17 #include "basicblock.h"
18 #include "dump.h"
19 #include "visualizer_printer.h"
20
21 namespace panda::compiler {
Print()22 void VisualizerPrinter::Print()
23 {
24 PrintBeginTag("cfg");
25 PrintProperty("name", ArenaString(passName_, graph_->GetLocalAllocator()->Adapter()));
26 for (const auto &block : graph_->GetBlocksRPO()) {
27 PrintBasicBlock(block);
28 }
29 PrintEndTag("cfg");
30 }
31
PrintBeginTag(const char * tag)32 void VisualizerPrinter::PrintBeginTag(const char *tag)
33 {
34 (*output_) << MakeOffset() << "begin_" << tag << "\n";
35 ++offset_;
36 }
37
PrintEndTag(const char * tag)38 void VisualizerPrinter::PrintEndTag(const char *tag)
39 {
40 --offset_;
41 (*output_) << MakeOffset() << "end_" << tag << "\n";
42 }
43
MakeOffset()44 std::string VisualizerPrinter::MakeOffset()
45 {
46 return std::string(offset_ << 1U, ' ');
47 }
48
PrintProperty(const char * prop,const ArenaString & value)49 void VisualizerPrinter::PrintProperty(const char *prop, const ArenaString &value)
50 {
51 (*output_) << MakeOffset() << prop;
52 if (!value.empty()) {
53 (*output_) << " \"" << value << "\"";
54 }
55 (*output_) << "\n";
56 }
57
PrintProperty(const char * prop,int value)58 void VisualizerPrinter::PrintProperty(const char *prop, int value)
59 {
60 (*output_) << MakeOffset() << std::dec << prop << " " << value << "\n";
61 }
62
PrintDependences(const std::string & preffix,const ArenaVector<BasicBlock * > & blocks)63 void VisualizerPrinter::PrintDependences(const std::string &preffix, const ArenaVector<BasicBlock *> &blocks)
64 {
65 (*output_) << MakeOffset() << preffix << " ";
66 for (const auto &block : blocks) {
67 (*output_) << "\"B" << BBId(block, graph_->GetLocalAllocator()) << "\" ";
68 }
69 (*output_) << "\n";
70 }
71
PrintBasicBlock(BasicBlock * block)72 void VisualizerPrinter::PrintBasicBlock(BasicBlock *block)
73 {
74 PrintBeginTag("block");
75 PrintProperty("name", "B" + BBId(block, graph_->GetLocalAllocator()));
76 PrintProperty("from_bci", -1);
77 PrintProperty("to_bci", -1);
78 PrintDependences("predecessors", block->GetPredsBlocks());
79 PrintDependences("successors", block->GetSuccsBlocks());
80 PrintProperty("xhandlers", ArenaString("", graph_->GetLocalAllocator()->Adapter()));
81 PrintProperty("flags", ArenaString("", graph_->GetLocalAllocator()->Adapter()));
82 PrintProperty("loop_depth", 0);
83 PrintBeginTag("states");
84 PrintBeginTag("locals");
85 PrintProperty("size", 0);
86 PrintProperty("method", ArenaString("None", graph_->GetLocalAllocator()->Adapter()));
87 PrintEndTag("locals");
88 PrintEndTag("states");
89 PrintBeginTag("HIR");
90 PrintInsts(block);
91 PrintEndTag("HIR");
92 PrintEndTag("block");
93 }
94
PrintInsts(BasicBlock * block)95 void VisualizerPrinter::PrintInsts(BasicBlock *block)
96 {
97 if (block->AllInsts().begin() != block->AllInsts().end()) {
98 for (auto inst : block->AllInsts()) {
99 PrintInst(inst);
100 }
101 } else {
102 (*output_) << MakeOffset() << "0 0 - ";
103 if (block->IsStartBlock()) {
104 (*output_) << "EMPTY_START_BLOCK";
105 } else if (block->IsEndBlock()) {
106 (*output_) << "EXIT_BLOCK";
107 } else {
108 (*output_) << "EMPTY_BLOCK";
109 }
110 (*output_) << " <|@\n";
111 }
112 }
113
PrintInst(Inst * inst)114 void VisualizerPrinter::PrintInst(Inst *inst)
115 {
116 uint32_t usersSize = 0;
117 for (auto it = inst->GetUsers().begin(); it != inst->GetUsers().end(); ++it) {
118 usersSize++;
119 }
120 (*output_) << MakeOffset() << "0 " << std::dec << usersSize << " ";
121 (*output_) << InstId(inst, graph_->GetLocalAllocator()) << " ";
122 inst->DumpOpcode(output_);
123 (*output_) << " type:" << DataType::ToString(inst->GetType()) << " ";
124 (*output_) << "inputs: ";
125 bool hasInput = inst->DumpInputs(output_);
126 if (hasInput && !inst->GetUsers().Empty()) {
127 (*output_) << " users: ";
128 }
129 DumpUsers(inst, output_);
130 (*output_) << " <|@\n";
131 }
132 } // namespace panda::compiler
133