1 /**
2 * Copyright 2020-2021 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 while (debug_info != nullptr) {
32 if (is_debug || debug_info->location() != nullptr) {
33 debug_with_loc_vec.push_back(debug_info);
34 }
35 if (debug_info->trace_info() != nullptr) {
36 debug_info = debug_info->trace_info()->debug_info();
37 } else {
38 break;
39 }
40 }
41 return debug_with_loc_vec;
42 }
43
ReplaceLinefeed(std::string * txt)44 void ReplaceLinefeed(std::string *txt) {
45 MS_EXCEPTION_IF_NULL(txt);
46 std::vector<int> erases;
47 constexpr char cr = '\r';
48 constexpr char lf = '\n';
49 constexpr char slash = '/';
50 for (size_t i = 0; i < txt->length(); i++) {
51 if ((*txt)[i] == lf) {
52 (*txt)[i] = slash;
53 }
54 if ((*txt)[i] == cr) {
55 (*txt)[i] = slash;
56 if (i + 1 < txt->length() && (*txt)[i + 1] == lf) {
57 erases.emplace_back(i + 1);
58 i++;
59 }
60 }
61 }
62 constexpr auto n = 1;
63 std::reverse(erases.begin(), erases.end());
64 for (const auto &index : erases) {
65 txt->erase(index, n);
66 }
67 }
68 } // namespace
69
GetSourceCodeDebugInfo(const DebugInfoPtr & info)70 DebugInfoPtr GetSourceCodeDebugInfo(const DebugInfoPtr &info) {
71 auto debug_with_loc_vec = GetSourceCodeDebugInfoVec(info);
72 if (!debug_with_loc_vec.empty()) {
73 return debug_with_loc_vec[0];
74 } else {
75 return info;
76 }
77 }
78
GetDebugInfo(const DebugInfoPtr & info,SourceLineTip tip)79 std::string GetDebugInfo(const DebugInfoPtr &info, SourceLineTip tip) {
80 if (info == nullptr) {
81 return "";
82 }
83 auto src_info = GetSourceCodeDebugInfo(info);
84 if (src_info->location() != nullptr) {
85 return src_info->location()->ToString(tip);
86 }
87 return "";
88 }
89
90 // A trace info identifies a node transform, so we can trace the node transform through
91 // A link of trace info and debug info
GetInfoWithAction(const std::vector<DebugInfoPtr> & info_vec,SourceLineTip tip)92 std::string GetInfoWithAction(const std::vector<DebugInfoPtr> &info_vec, SourceLineTip tip) {
93 if (info_vec.empty()) {
94 return "";
95 }
96 if (info_vec.size() == 1) {
97 return info_vec[0]->location()->ToString(tip);
98 }
99 std::string traced_info = info_vec[0]->location()->ToString(tip);
100 for (size_t i = 1; i < info_vec.size(); i++) {
101 auto action_name = info_vec[i - 1]->trace_info()->GetActionBetweenNode(info_vec[i]);
102 if (action_name.empty()) {
103 break;
104 }
105 traced_info += action_name + info_vec[i]->location()->ToString(tip);
106 }
107 return traced_info;
108 }
109
GetTracedDebugInfo(const DebugInfoPtr & info,SourceLineTip tip)110 std::string GetTracedDebugInfo(const DebugInfoPtr &info, SourceLineTip tip) {
111 if (info == nullptr) {
112 return "";
113 }
114 auto info_vec = GetSourceCodeDebugInfoVec(info);
115 if (info_vec.empty()) {
116 return "";
117 } else if (info_vec.size() == 1) {
118 return info_vec[0]->location()->ToString(tip);
119 } else if (info_vec.size() > 1) {
120 return GetInfoWithAction(info_vec, tip);
121 }
122 return "";
123 }
124
GetDebugInfo(const DebugInfoPtr & info,const std::string & prefix,SourceLineTip tip)125 std::string GetDebugInfo(const DebugInfoPtr &info, const std::string &prefix, SourceLineTip tip) {
126 std::ostringstream oss;
127 if (info == nullptr) {
128 return "";
129 }
130
131 auto debug_info = GetTracedDebugInfo(info, tip);
132 if (tip == kSourceLineTipDiscard) {
133 std::replace(debug_info.begin(), debug_info.end(), '\r', '/');
134 std::replace(debug_info.begin(), debug_info.end(), '\n', '/');
135 }
136 oss << prefix << debug_info;
137 return oss.str();
138 }
139
DumpSourceLines(const AnfNodePtr & node)140 std::string DumpSourceLines(const AnfNodePtr &node) {
141 auto vec_source = GetSourceLineList(node);
142 if (vec_source.empty()) {
143 return "";
144 }
145 std::ostringstream oss;
146 oss << "\n";
147 for (auto &src_info : vec_source) {
148 oss << src_info;
149 }
150 return oss.str();
151 }
152
DumpSourceLines(AnfNode * node)153 std::string DumpSourceLines(AnfNode *node) {
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);
160 }
161
GetSourceLineFromDebugInfo(const DebugInfoPtr & debug_info,std::vector<std::string> * result)162 void GetSourceLineFromDebugInfo(const DebugInfoPtr &debug_info, std::vector<std::string> *result) {
163 auto info_vec = GetSourceCodeDebugInfoVec(debug_info);
164 for (const auto &info : info_vec) {
165 MS_EXCEPTION_IF_NULL(info);
166 auto loc = info->location();
167 if (loc == nullptr) {
168 continue;
169 }
170 auto loc_str = loc->ToString(kSourceLineTipDiscard);
171 ReplaceLinefeed(&loc_str);
172 result->push_back(loc_str + "\n");
173 }
174 }
175
GetSourceLineList(const AnfNodePtr & node)176 std::vector<std::string> GetSourceLineList(const AnfNodePtr &node) {
177 std::vector<std::string> result;
178 if (node == nullptr) {
179 MS_LOG(WARNING) << "Node is null";
180 return result;
181 }
182 GetSourceLineFromDebugInfo(node->debug_info(), &result);
183 if (!node->isa<CNode>()) {
184 return result;
185 }
186 auto cnode = node->cast<CNodePtr>();
187 auto primal_debug_infos = cnode->primal_debug_infos();
188 result.emplace_back("Corresponding forward node candidate:\n");
189 for (auto &primal_debug_info : primal_debug_infos) {
190 GetSourceLineFromDebugInfo(primal_debug_info, &result);
191 }
192 return result;
193 }
194
GetSourceLocationList(const AnfNodePtr & node)195 std::vector<LocationPtr> GetSourceLocationList(const AnfNodePtr &node) {
196 std::vector<LocationPtr> result;
197 if (node == nullptr) {
198 MS_LOG(WARNING) << "Node is null";
199 return result;
200 }
201 auto info_vec = GetSourceCodeDebugInfoVec(node->debug_info());
202 for (const auto &info : info_vec) {
203 MS_EXCEPTION_IF_NULL(info);
204 if (info->location() != nullptr) {
205 result.emplace_back(info->location());
206 }
207 }
208 return result;
209 }
210
GetDebugTraceInfo(const AnfNodePtr & node,bool is_debug)211 std::string GetDebugTraceInfo(const AnfNodePtr &node, bool is_debug) {
212 if (node == nullptr) {
213 MS_LOG(WARNING) << "Node is null";
214 return "";
215 }
216 auto info_vec = GetSourceCodeDebugInfoVec(node->debug_info(), is_debug);
217 std::ostringstream oss;
218 for (const auto &info : info_vec) {
219 MS_EXCEPTION_IF_NULL(info);
220 auto trace_info = info->trace_info();
221 if (trace_info != nullptr) {
222 oss << trace_info->symbol() << "(" << trace_info->full_name() << ") ";
223 }
224 auto loc = info->location();
225 if (loc == nullptr) {
226 oss << "Location miss\n";
227 continue;
228 }
229 auto loc_str = loc->ToString(kSourceLineTipDiscard);
230 ReplaceLinefeed(&loc_str);
231 oss << loc_str << "\n";
232 }
233 return oss.str();
234 }
235 } // namespace trace
236 } // namespace mindspore
237