• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright 2020-2022 Huawei Technologies Co., Ltd
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 #include "utils/trace_base.h"
18 
19 #include <vector>
20 #include <string>
21 #include <utility>
22 #include <algorithm>
23 
24 #include "ir/graph_utils.h"
25 
26 namespace mindspore {
27 namespace trace {
28 namespace {
GetSourceCodeDebugInfoVec(DebugInfoPtr debug_info,bool is_debug=false)29 std::vector<DebugInfoPtr> GetSourceCodeDebugInfoVec(DebugInfoPtr debug_info, bool is_debug = false) {
30   std::vector<DebugInfoPtr> debug_with_loc_vec;
31   HashSet<DebugInfoPtr> visited;
32   while (debug_info != nullptr) {
33     if (visited.find(debug_info) != visited.end()) {
34       int i = 0;
35       for (const auto &info : debug_with_loc_vec) {
36         auto loc = info->location();
37         MS_LOG(ERROR) << "[" << std::to_string(i) << "]: " << info.get()
38                       << ", loc: " << (loc == nullptr ? "null" : loc->ToString());
39         ++i;
40       }
41       auto loc = debug_info->location();
42       MS_LOG(INTERNAL_EXCEPTION) << "Find loop debug info: " << debug_info.get()
43                                  << ", loc: " << (loc == nullptr ? "null" : loc->ToString()) << ".\n"
44                                  << "Please set 'compile_config.ENABLE_FIX_CODE_LINE=0' to avoid this problem.";
45     }
46     auto loc = debug_info->location();
47     MS_LOG(DEBUG) << "Visited Insert debug info: " << debug_info.get()
48                   << ", loc: " << (loc == nullptr ? "null" : loc->ToString());
49     (void)visited.insert(debug_info);
50     if (is_debug || debug_info->location() != nullptr) {
51       debug_with_loc_vec.push_back(debug_info);
52       MS_LOG(DEBUG) << "debug loc: " << debug_info->location()->DebugString();
53     }
54     if (debug_info->trace_info() != nullptr) {
55       MS_LOG(DEBUG) << "trace: " << debug_info->trace_info()->name();
56       debug_info = debug_info->trace_info()->debug_info();
57     } else {
58       break;
59     }
60   }
61   return debug_with_loc_vec;
62 }
63 
ReplaceLinefeed(std::string * txt)64 void ReplaceLinefeed(std::string *txt) {
65   MS_EXCEPTION_IF_NULL(txt);
66   std::vector<int> erases;
67   constexpr char cr = '\r';
68   constexpr char lf = '\n';
69   constexpr char slash = '/';
70   for (size_t i = 0; i < txt->length(); i++) {
71     if ((*txt)[i] == lf) {
72       (*txt)[i] = slash;
73     }
74     if ((*txt)[i] == cr) {
75       (*txt)[i] = slash;
76       if (i + 1 < txt->length() && (*txt)[i + 1] == lf) {
77         erases.emplace_back(i + 1);
78         i++;
79       }
80     }
81   }
82   constexpr auto n = 1;
83   std::reverse(erases.begin(), erases.end());
84   for (const auto &index : erases) {
85     txt->erase(index, n);
86   }
87 }
88 }  // namespace
89 
GetSourceCodeDebugInfo(const DebugInfoPtr & info)90 DebugInfoPtr GetSourceCodeDebugInfo(const DebugInfoPtr &info) {
91   DebugInfoPtr debug_info = info;
92   while (debug_info != nullptr) {
93     auto loc = debug_info->location();
94     if (debug_info->location() != nullptr) {
95       MS_LOG(DEBUG) << "debug loc: " << debug_info->location()->DebugString();
96       return debug_info;
97     }
98     if (debug_info->trace_info() == nullptr) {
99       break;
100     }
101     MS_LOG(DEBUG) << "trace: " << debug_info->trace_info()->name();
102     debug_info = debug_info->trace_info()->debug_info();
103   }
104   return info;
105 }
106 
GetDebugInfoStr(const DebugInfoPtr & info,const std::string & prefix,SourceLineTip tip,bool is_debug)107 std::string GetDebugInfoStr(const DebugInfoPtr &info, const std::string &prefix, SourceLineTip tip, bool is_debug) {
108   if (info == nullptr) {
109     return "";
110   }
111   DebugInfoPtr debug_info;
112   if (!is_debug) {
113     debug_info = GetSourceCodeDebugInfo(info);
114   } else {
115     debug_info = info;
116   }
117   bool has_shadow = false;
118   if (!debug_info->shadow_debug_infos_map().empty()) {
119     has_shadow = true;
120   }
121 
122   if (debug_info->location() == nullptr) {
123     return "";
124   }
125   auto line_str = debug_info->location()->ToString(tip);
126   if (tip == kSourceLineTipDiscard) {
127     ReplaceLinefeed(&line_str);
128   }
129   std::stringstream ss;
130   ss << prefix << line_str;
131   if (has_shadow) {
132     ss << "\n[shadow]";
133   }
134   return ss.str();
135 }
136 
DumpSourceLines(const AnfNodePtr & node,bool has_title)137 std::string DumpSourceLines(const AnfNodePtr &node, bool has_title) {
138   auto vec_source = GetSourceLineList(node);
139   if (vec_source.empty()) {
140     return "";
141   }
142   std::ostringstream oss;
143   for (auto &src_info : vec_source) {
144     oss << src_info;
145   }
146   if (oss.str().empty()) {
147     return "";
148   }
149   const std::string prefix = has_title ? "#dmsg#The Function Call Stack:#dmsg#" : "\n";
150   return prefix + oss.str();
151 }
152 
DumpSourceLines(AnfNode * node,bool has_title)153 std::string DumpSourceLines(AnfNode *node, bool has_title) {
154   if (node == nullptr) {
155     MS_LOG(WARNING) << "Node is null";
156     return "";
157   }
158   AnfNodePtr ptr = std::static_pointer_cast<AnfNode>(node->shared_from_this());
159   return DumpSourceLines(ptr, has_title);
160 }
161 
GetSourceLineFromDebugInfo(const DebugInfoPtr & debug_info,std::vector<std::string> * result,const std::string & prefix="")162 void GetSourceLineFromDebugInfo(const DebugInfoPtr &debug_info, std::vector<std::string> *result,
163                                 const std::string &prefix = "") {
164   MS_EXCEPTION_IF_NULL(result);
165   auto info_vec = GetSourceCodeDebugInfoVec(debug_info);
166   const std::string spaces(prefix.size(), ' ');
167   bool first_line = true;
168   HashSet<std::string> exist_locations;
169   for (const auto &info : info_vec) {
170     MS_EXCEPTION_IF_NULL(info);
171     auto loc = info->location();
172     if (loc == nullptr) {
173       continue;
174     }
175     auto loc_str = loc->ToString(kSourceLineTipDiscard);
176     if (exist_locations.find(loc_str) != exist_locations.cend()) {
177       continue;
178     }
179     (void)exist_locations.insert(loc_str);
180     ReplaceLinefeed(&loc_str);
181     if (first_line) {
182       result->push_back(std::string(prefix).append(loc_str).append("\n"));
183       first_line = false;
184     } else {
185       result->push_back(std::string(spaces).append(loc_str).append("\n"));
186     }
187   }
188 }
189 
GetFusedDebugInfos(const NodeDebugInfoSet & fused_debug_infos,std::vector<std::string> * result)190 void GetFusedDebugInfos(const NodeDebugInfoSet &fused_debug_infos, std::vector<std::string> *result) {
191   MS_EXCEPTION_IF_NULL(result);
192   (void)result->emplace_back("Corresponding code candidate:\n");
193   // Flag to mark whether fused_debug_infos has valid print.
194   bool is_empty = true;
195   for (const auto &debug_info : fused_debug_infos) {
196     std::vector<std::string> debug_info_vec_str;
197     GetSourceLineFromDebugInfo(debug_info, &debug_info_vec_str, kSectionPrefix);
198     if (!debug_info_vec_str.empty()) {
199       (void)result->insert(result->cend(), debug_info_vec_str.cbegin(), debug_info_vec_str.cend());
200       is_empty = false;
201     }
202   }
203 
204   if (is_empty) {
205     result->pop_back();
206   }
207 }
208 
GetPrimalDebugInfos(const CNodePtr & cnode,std::vector<std::string> * result)209 void GetPrimalDebugInfos(const CNodePtr &cnode, std::vector<std::string> *result) {
210   MS_EXCEPTION_IF_NULL(cnode);
211   MS_EXCEPTION_IF_NULL(result);
212   auto primal_debug_infos = cnode->primal_debug_infos();
213   if (!primal_debug_infos.empty()) {
214     (void)result->emplace_back("Corresponding forward node candidate:\n");
215     for (const auto &primal_debug_info : primal_debug_infos) {
216       std::vector<std::string> debug_info_vec_str;
217       GetSourceLineFromDebugInfo(primal_debug_info, &debug_info_vec_str, kSectionPrefix);
218       if (!debug_info_vec_str.empty()) {
219         (void)result->insert(result->cend(), debug_info_vec_str.cbegin(), debug_info_vec_str.cend());
220       }
221     }
222   }
223 }
GetSourceLineList(const DebugInfoPtr & debug_info)224 std::vector<std::string> GetSourceLineList(const DebugInfoPtr &debug_info) {
225   std::vector<std::string> result;
226   GetSourceLineFromDebugInfo(debug_info, &result);
227   return result;
228 }
229 
GetSourceLineList(const AnfNodePtr & node)230 std::vector<std::string> GetSourceLineList(const AnfNodePtr &node) {
231   std::vector<std::string> result;
232   if (node == nullptr) {
233     MS_LOG(WARNING) << "Node is null";
234     return result;
235   }
236   if (!node->isa<CNode>()) {
237     GetSourceLineFromDebugInfo(node->debug_info(), &result);
238     return result;
239   }
240   auto cnode = node->cast<CNodePtr>();
241   auto fused_debug_infos = cnode->fused_debug_infos();
242   if (fused_debug_infos.empty()) {
243     GetSourceLineFromDebugInfo(node->debug_info(), &result);
244   } else {
245     GetFusedDebugInfos(fused_debug_infos, &result);
246   }
247   GetPrimalDebugInfos(cnode, &result);
248   return result;
249 }
250 
GetSourceLocationList(const AnfNodePtr & node)251 std::vector<LocationPtr> GetSourceLocationList(const AnfNodePtr &node) {
252   std::vector<LocationPtr> result;
253   if (node == nullptr) {
254     MS_LOG(WARNING) << "Node is null";
255     return result;
256   }
257   auto info_vec = GetSourceCodeDebugInfoVec(node->debug_info());
258   for (const auto &info : info_vec) {
259     MS_EXCEPTION_IF_NULL(info);
260     if (info->location() != nullptr) {
261       result.emplace_back(info->location());
262     }
263   }
264   return result;
265 }
266 
GetTracedDebugInfoStr(const DebugInfoPtr & debug_info,bool is_debug)267 std::string GetTracedDebugInfoStr(const DebugInfoPtr &debug_info, bool is_debug) {
268   if (debug_info == nullptr) {
269     MS_LOG(WARNING) << "debug_info is null";
270     return "";
271   }
272   auto info_vec = GetSourceCodeDebugInfoVec(debug_info, is_debug);
273   std::ostringstream oss;
274   for (auto iter = info_vec.crbegin(); iter != info_vec.crend(); ++iter) {
275     const auto &info = *iter;
276     MS_EXCEPTION_IF_NULL(info);
277     auto loc = info->location();
278     if (loc == nullptr) {
279       oss << "Location miss\n";
280       continue;
281     }
282     oss << "# " << loc->ToString() << "\n";
283   }
284   return oss.str();
285 }
286 }  // namespace trace
287 }  // namespace mindspore
288