• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2024 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 "disassembly.h"
17 #include "codegen.h"
18 #include <mutex>
19 
20 namespace ark::compiler {
21 
22 // clang-format off
23 static constexpr std::array INDENT_STRINGS = {
24     "  ",
25     "    ",
26     "      ",
27     "        ",
28     "          ",
29     "            ",
30     "              ",
31     "                ",
32     "                  ",
33 };
34 // clang-format on
35 
GetIndent(uint32_t depth)36 std::string_view Disassembly::GetIndent(uint32_t depth)
37 {
38     return INDENT_STRINGS[depth];
39 }
40 
__anond1ab6aaa0102(std::ostream *stream) 41 static constexpr auto STREAM_DELETER = [](std::ostream *stream) {
42     if (!g_options.IsCompilerDisasmDumpStdout()) {
43         delete stream;
44     }
45 };
46 
Disassembly(const Codegen * codegen)47 Disassembly::Disassembly(const Codegen *codegen)
48     : codegen_(codegen),
49       encoder_(codegen->GetEncoder()),
50       stream_(nullptr, STREAM_DELETER),
51       isEnabled_(g_options.IsCompilerDisasmDump()),
52       isCodeEnabled_(isEnabled_ && g_options.IsCompilerDisasmDumpCode())
53 {
54 }
55 
Init()56 void Disassembly::Init()
57 {
58     if (!IsEnabled()) {
59         return;
60     }
61     if (g_options.IsCompilerDisasmDumpStdout()) {
62         stream_.reset(&std::cout);
63     } else if (g_options.IsCompilerDisasmDumpSingleFile()) {
64         auto os = new std::ofstream;
65         if (os == nullptr) {
66             UNREACHABLE();
67         }
68         static std::once_flag flag;
69         auto fileName = g_options.GetCompilerDisasmDumpFileName();
70         std::call_once(flag, [&fileName]() { std::remove(fileName.c_str()); });
71         os->open(fileName, std::ios_base::app);
72         if (!os->is_open()) {
73             LOG(FATAL, COMPILER) << "Cannot open 'disasm.txt'";
74         }
75         stream_.reset(os);
76     } else {
77         auto os = new std::ofstream;
78         if (os == nullptr) {
79             UNREACHABLE();
80         }
81         std::stringstream ss;
82         auto graph = codegen_->GetGraph();
83         auto execNum = graph->GetPassManager()->GetExecutionCounter();
84         ss << "disasm_" << execNum << '_' << codegen_->GetRuntime()->GetClassNameFromMethod(graph->GetMethod()) << '_'
85            << codegen_->GetRuntime()->GetMethodName(graph->GetMethod()) << (graph->IsOsrMode() ? "_osr" : "") << ".txt";
86         os->open(ss.str());
87         if (!os->is_open()) {
88             LOG(FATAL, COMPILER) << "Cannot open '" << ss.str() << "'";
89         }
90         stream_.reset(os);
91     }
92 }
93 
PrintChapter(std::string_view name)94 void Disassembly::PrintChapter(std::string_view name)
95 {
96     ItemAppender item(this);
97     item.GetStream() << name << ":\n";
98 }
99 
IncreaseDepth()100 void Disassembly::IncreaseDepth()
101 {
102     if ((depth_ + 1) < INDENT_STRINGS.size()) {
103         depth_++;
104     }
105 }
106 
PrintMethodEntry(const Codegen * codegen)107 void Disassembly::PrintMethodEntry(const Codegen *codegen)
108 {
109     constexpr const char *INDENT = "  ";
110     auto graph = codegen->GetGraph();
111     {
112         ItemAppender item(this);
113         item.GetStream() << "#======================================================================\n";
114     }
115     PrintChapter("METHOD_INFO");
116     {
117         ItemAppender item(this);
118         item.GetStream() << INDENT << "name: " << codegen->GetRuntime()->GetMethodFullName(graph->GetMethod(), true)
119                          << "\n";
120         item.GetStream() << INDENT << "mode: ";
121         graph->GetMode().Dump(item.GetStream());
122         item.GetStream() << "\n";
123     }
124     {
125         ItemAppender item(this);
126         item.GetStream() << INDENT << "id: " << codegen->GetRuntime()->GetMethodId(graph->GetMethod()) << "\n";
127     }
128     if (graph->IsAotMode()) {
129         ItemAppender item = ItemAppender(this);
130         item.GetStream() << INDENT << "code_offset: " << reinterpret_cast<void *>(graph->GetAotData()->GetCodeOffset())
131                          << "\n";
132     }
133 
134     {
135         auto arch = codegen->GetArch();
136         auto frame = codegen->GetFrameInfo();
137         ItemAppender item(this);
138         item.GetStream() << INDENT << "frame_size: " << frame->GetFrameSize() << "\n";
139         item.GetStream() << INDENT << "spills_count: " << frame->GetSpillsCount() << "\n";
140         item.GetStream() << INDENT << "Callees:   " << (frame->GetCalleesRelativeFp() ? "fp" : "sp") << std::showpos
141                          << frame->GetCalleesOffset() << std::noshowpos << " (" << GetCalleeRegsCount(arch, false)
142                          << ")\n";
143         item.GetStream() << INDENT << "FpCallees: " << (frame->GetCalleesRelativeFp() ? "fp" : "sp") << std::showpos
144                          << frame->GetFpCalleesOffset() << std::noshowpos << " (" << GetCalleeRegsCount(arch, true)
145                          << ")\n";
146         item.GetStream() << INDENT << "Callers:   " << (frame->GetCallersRelativeFp() ? "fp" : "sp") << std::showpos
147                          << frame->GetCallersOffset() << std::noshowpos << " (" << GetCallerRegsCount(arch, false)
148                          << ")\n";
149         item.GetStream() << INDENT << "FpCallers: " << (frame->GetCallersRelativeFp() ? "fp" : "sp") << std::showpos
150                          << frame->GetFpCallersOffset() << std::noshowpos << " (" << GetCallerRegsCount(arch, true)
151                          << ")\n";
152     }
153     if (IsCodeEnabled()) {
154         PrintChapter("DISASSEMBLY");
155     }
156 }
157 
PrintCodeInfo(const Codegen * codegen)158 void Disassembly::PrintCodeInfo(const Codegen *codegen)
159 {
160     auto graph = codegen->GetGraph();
161 
162     CodeInfo codeInfo;
163     ASSERT(!graph->GetCodeInfoData().empty());
164     codeInfo.Decode(graph->GetCodeInfoData());
165     PrintChapter("CODE_INFO");
166     ItemAppender item(this);
167     codeInfo.Dump(item.GetStream());
168 }
169 
PrintCodeStatistics(const Codegen * codegen)170 void Disassembly::PrintCodeStatistics(const Codegen *codegen)
171 {
172     auto graph = codegen->GetGraph();
173 
174     PrintChapter("CODE_STATS");
175     ItemAppender item(this);
176     item.GetStream() << "  code_size: " << std::dec << graph->GetCode().Size() << "\n";
177 }
178 
FlushDisasm()179 void Disassembly::FlushDisasm()
180 {
181     auto encoder = GetEncoder();
182     AddCode(GetPosition(), encoder->GetCursorOffset(), GetDepth());
183     SetPosition(encoder->GetCursorOffset());
184 }
185 
PrintStackMap(const Codegen * codegen)186 void Disassembly::PrintStackMap(const Codegen *codegen)
187 {
188     FlushDisasm();
189     ItemAppender item(this);
190     item.GetStream() << GetIndent(GetDepth());
191     codegen->GetCodeBuilder()->DumpCurrentStackMap(item.GetStream());
192     item.GetStream() << "\n";
193 }
194 
ScopedDisasmPrinter(Codegen * codegen,const Inst * inst)195 ScopedDisasmPrinter::ScopedDisasmPrinter(Codegen *codegen, const Inst *inst) : disasm_(codegen->GetDisasm())
196 {
197     if (disasm_->IsCodeEnabled()) {
198         disasm_->FlushDisasm();
199         ItemAppender item(disasm_);
200         item.GetStream() << disasm_->GetIndent(disasm_->GetDepth()) << "# [inst] " << *inst << "\n";
201         disasm_->IncreaseDepth();
202     }
203 }
204 
ScopedDisasmPrinter(Codegen * codegen,const std::string & msg)205 ScopedDisasmPrinter::ScopedDisasmPrinter(Codegen *codegen, const std::string &msg) : disasm_(codegen->GetDisasm())
206 {
207     if (disasm_->IsCodeEnabled()) {
208         disasm_->FlushDisasm();
209         ItemAppender item(disasm_);
210         item.GetStream() << disasm_->GetIndent(disasm_->GetDepth()) << "# " << msg << "\n";
211         disasm_->IncreaseDepth();
212     }
213 }
214 
~ScopedDisasmPrinter()215 ScopedDisasmPrinter::~ScopedDisasmPrinter()
216 {
217     if (disasm_->IsCodeEnabled()) {
218         disasm_->FlushDisasm();
219         disasm_->DecreaseDepth();
220     }
221 }
222 
223 }  // namespace ark::compiler
224