3 # Debugify summary for the original debug info testing.
6 from __future__
import print_function
10 from json
import loads
11 from collections
import defaultdict
12 from collections
import OrderedDict
15 def __init__(self
, action
, bb_name
, fn_name
, instr
):
17 self
.bb_name
= bb_name
18 self
.fn_name
= fn_name
22 def __init__(self
, action
, fn_name
):
24 self
.fn_name
= fn_name
27 def __init__(self
, action
, name
, fn_name
):
30 self
.fn_name
= fn_name
32 # Report the bugs in form of html.
33 def generate_html_report(di_location_bugs
, di_subprogram_bugs
, di_var_bugs
, \
34 di_location_bugs_summary
, di_sp_bugs_summary
, \
35 di_var_bugs_summary
, html_file
):
36 fileout
= open(html_file
, "w")
38 html_header
= """ <html>
42 border: 1px solid black;
53 # Create the table for Location bugs.
54 table_title_di_loc
= "Location Bugs found by the Debugify"
56 table_di_loc
= """<table>
57 <caption><b>{}</b></caption>
59 """.format(table_title_di_loc
)
61 header_di_loc
= ["File", "LLVM Pass Name", "LLVM IR Instruction", \
62 "Function Name", "Basic Block Name", "Action"]
64 for column
in header_di_loc
:
65 table_di_loc
+= " <th>{0}</th>\n".format(column
.strip())
66 table_di_loc
+= " </tr>\n"
68 at_least_one_bug_found
= False
70 # Handle loction bugs.
71 for file, per_file_bugs
in di_location_bugs
.items():
72 for llvm_pass
, per_pass_bugs
in per_file_bugs
.items():
73 # No location bugs for the pass.
74 if len(per_pass_bugs
) == 0:
76 at_least_one_bug_found
= True
78 table_di_loc
+= " </tr>\n"
80 for x
in per_pass_bugs
:
88 row
.append(" </tr>\n")
89 # Dump the bugs info into the table.
91 # The same file-pass pair can have multiple bugs.
92 if (column
== " <tr>\n" or column
== " </tr>\n"):
93 table_di_loc
+= column
95 table_di_loc
+= " <td>{0}</td>\n".format(column
.strip())
96 table_di_loc
+= " <tr>\n"
98 if not at_least_one_bug_found
:
99 table_di_loc
+= """ <tr>
100 <td colspan='7'> No bugs found </td>
103 table_di_loc
+= "</table>\n"
105 # Create the summary table for the loc bugs.
106 table_title_di_loc_sum
= "Summary of Location Bugs"
107 table_di_loc_sum
= """<table>
108 <caption><b>{}</b></caption>
110 """.format(table_title_di_loc_sum
)
112 header_di_loc_sum
= ["LLVM Pass Name", "Number of bugs"]
114 for column
in header_di_loc_sum
:
115 table_di_loc_sum
+= " <th>{0}</th>\n".format(column
.strip())
116 table_di_loc_sum
+= " </tr>\n"
120 for llvm_pass
, num
in sorted(di_location_bugs_summary
.items()):
121 row
.append(" <tr>\n")
122 row
.append(llvm_pass
)
124 row
.append(" </tr>\n")
126 if (column
== " <tr>\n" or column
== " </tr>\n"):
127 table_di_loc_sum
+= column
129 table_di_loc_sum
+= " <td>{0}</td>\n".format(column
.strip())
130 table_di_loc_sum
+= " <tr>\n"
132 if not at_least_one_bug_found
:
133 table_di_loc_sum
+= """<tr>
134 <td colspan='2'> No bugs found </td>
137 table_di_loc_sum
+= "</table>\n"
139 # Create the table for SP bugs.
140 table_title_di_sp
= "SP Bugs found by the Debugify"
141 table_di_sp
= """<table>
142 <caption><b>{}</b></caption>
144 """.format(table_title_di_sp
)
146 header_di_sp
= ["File", "LLVM Pass Name", "Function Name", "Action"]
148 for column
in header_di_sp
:
149 table_di_sp
+= " <th>{0}</th>\n".format(column
.strip())
150 table_di_sp
+= " </tr>\n"
152 at_least_one_bug_found
= False
155 for file, per_file_bugs
in di_subprogram_bugs
.items():
156 for llvm_pass
, per_pass_bugs
in per_file_bugs
.items():
157 # No SP bugs for the pass.
158 if len(per_pass_bugs
) == 0:
160 at_least_one_bug_found
= True
162 table_di_sp
+= " </tr>\n"
164 for x
in per_pass_bugs
:
165 row
.append(" <tr>\n")
167 row
.append(llvm_pass
)
168 row
.append(x
.fn_name
)
170 row
.append(" </tr>\n")
171 # Dump the bugs info into the table.
173 # The same file-pass pair can have multiple bugs.
174 if (column
== " <tr>\n" or column
== " </tr>\n"):
175 table_di_sp
+= column
177 table_di_sp
+= " <td>{0}</td>\n".format(column
.strip())
178 table_di_sp
+= " <tr>\n"
180 if not at_least_one_bug_found
:
181 table_di_sp
+= """<tr>
182 <td colspan='4'> No bugs found </td>
185 table_di_sp
+= "</table>\n"
187 # Create the summary table for the sp bugs.
188 table_title_di_sp_sum
= "Summary of SP Bugs"
189 table_di_sp_sum
= """<table>
190 <caption><b>{}</b></caption>
192 """.format(table_title_di_sp_sum
)
194 header_di_sp_sum
= ["LLVM Pass Name", "Number of bugs"]
196 for column
in header_di_sp_sum
:
197 table_di_sp_sum
+= " <th>{0}</th>\n".format(column
.strip())
198 table_di_sp_sum
+= " </tr>\n"
202 for llvm_pass
, num
in sorted(di_sp_bugs_summary
.items()):
203 row
.append(" <tr>\n")
204 row
.append(llvm_pass
)
206 row
.append(" </tr>\n")
208 if (column
== " <tr>\n" or column
== " </tr>\n"):
209 table_di_sp_sum
+= column
211 table_di_sp_sum
+= " <td>{0}</td>\n".format(column
.strip())
212 table_di_sp_sum
+= " <tr>\n"
214 if not at_least_one_bug_found
:
215 table_di_sp_sum
+= """<tr>
216 <td colspan='2'> No bugs found </td>
219 table_di_sp_sum
+= "</table>\n"
221 # Create the table for Variable bugs.
222 table_title_di_var
= "Variable Location Bugs found by the Debugify"
223 table_di_var
= """<table>
224 <caption><b>{}</b></caption>
226 """.format(table_title_di_var
)
228 header_di_var
= ["File", "LLVM Pass Name", "Variable", "Function", "Action"]
230 for column
in header_di_var
:
231 table_di_var
+= " <th>{0}</th>\n".format(column
.strip())
232 table_di_var
+= " </tr>\n"
234 at_least_one_bug_found
= False
237 for file, per_file_bugs
in di_var_bugs
.items():
238 for llvm_pass
, per_pass_bugs
in per_file_bugs
.items():
239 # No SP bugs for the pass.
240 if len(per_pass_bugs
) == 0:
242 at_least_one_bug_found
= True
244 table_di_var
+= " </tr>\n"
246 for x
in per_pass_bugs
:
247 row
.append(" <tr>\n")
249 row
.append(llvm_pass
)
251 row
.append(x
.fn_name
)
253 row
.append(" </tr>\n")
254 # Dump the bugs info into the table.
256 # The same file-pass pair can have multiple bugs.
257 if (column
== " <tr>\n" or column
== " </tr>\n"):
258 table_di_var
+= column
260 table_di_var
+= " <td>{0}</td>\n".format(column
.strip())
261 table_di_var
+= " <tr>\n"
263 if not at_least_one_bug_found
:
264 table_di_var
+= """<tr>
265 <td colspan='4'> No bugs found </td>
268 table_di_var
+= "</table>\n"
270 # Create the summary table for the sp bugs.
271 table_title_di_var_sum
= "Summary of Variable Location Bugs"
272 table_di_var_sum
= """<table>
273 <caption><b>{}</b></caption>
275 """.format(table_title_di_var_sum
)
277 header_di_var_sum
= ["LLVM Pass Name", "Number of bugs"]
279 for column
in header_di_var_sum
:
280 table_di_var_sum
+= " <th>{0}</th>\n".format(column
.strip())
281 table_di_var_sum
+= " </tr>\n"
285 for llvm_pass
, num
in sorted(di_var_bugs_summary
.items()):
286 row
.append(" <tr>\n")
287 row
.append(llvm_pass
)
289 row
.append(" </tr>\n")
291 if (column
== " <tr>\n" or column
== " </tr>\n"):
292 table_di_var_sum
+= column
294 table_di_var_sum
+= " <td>{0}</td>\n".format(column
.strip())
295 table_di_var_sum
+= " <tr>\n"
297 if not at_least_one_bug_found
:
298 table_di_var_sum
+= """<tr>
299 <td colspan='2'> No bugs found </td>
302 table_di_var_sum
+= "</table>\n"
304 # Finish the html page.
305 html_footer
= """</body>
310 fileout
.writelines(html_header
)
311 fileout
.writelines(table_di_loc
)
312 fileout
.writelines(new_line
)
313 fileout
.writelines(table_di_loc_sum
)
314 fileout
.writelines(new_line
)
315 fileout
.writelines(new_line
)
316 fileout
.writelines(table_di_sp
)
317 fileout
.writelines(new_line
)
318 fileout
.writelines(table_di_sp_sum
)
319 fileout
.writelines(new_line
)
320 fileout
.writelines(new_line
)
321 fileout
.writelines(table_di_var
)
322 fileout
.writelines(new_line
)
323 fileout
.writelines(table_di_var_sum
)
324 fileout
.writelines(html_footer
)
327 print("The " + html_file
+ " generated.")
329 # Read the JSON file.
334 # The file contains json object per line.
335 # An example of the line (formatted json):
337 # "file": "simple.c",
338 # "pass": "Deduce function attributes in RPO",
343 # "metadata": "DISubprogram",
348 # "metadata": "DISubprogram",
354 with
open(file) as json_objects_file
:
355 for json_object_line
in json_objects_file
:
357 json_object
= loads(json_object_line
)
359 print ("error: No valid di-checker data found.")
361 di_checker_data
.append(json_object
)
363 return di_checker_data
365 # Parse the program arguments.
366 def parse_program_args(parser
):
367 parser
.add_argument("file_name", type=str, help="json file to process")
368 parser
.add_argument("html_file", type=str, help="html file to output data")
370 return parser
.parse_args()
373 parser
= argparse
.ArgumentParser()
374 opts
= parse_program_args(parser
)
376 if not opts
.html_file
.endswith('.html'):
377 print ("error: The output file must be '.html'.")
380 debug_info_bugs
= get_json(opts
.file_name
)
382 # Use the defaultdict in order to make multidim dicts.
383 di_location_bugs
= defaultdict(lambda: defaultdict(dict))
384 di_subprogram_bugs
= defaultdict(lambda: defaultdict(dict))
385 di_variable_bugs
= defaultdict(lambda: defaultdict(dict))
387 # Use the ordered dict to make a summary.
388 di_location_bugs_summary
= OrderedDict()
389 di_sp_bugs_summary
= OrderedDict()
390 di_var_bugs_summary
= OrderedDict()
392 # Map the bugs into the file-pass pairs.
393 for bugs_per_pass
in debug_info_bugs
:
394 bugs_file
= bugs_per_pass
["file"]
395 bugs_pass
= bugs_per_pass
["pass"]
397 bugs
= bugs_per_pass
["bugs"][0]
404 bugs_metadata
= bug
["metadata"]
405 if bugs_metadata
== "DILocation":
406 action
= bug
["action"]
407 bb_name
= bug
["bb-name"]
408 fn_name
= bug
["fn-name"]
410 di_loc_bugs
.append(DILocBug(action
, bb_name
, fn_name
, instr
))
412 # Fill the summary dict.
413 if bugs_pass
in di_location_bugs_summary
:
414 di_location_bugs_summary
[bugs_pass
] += 1
416 di_location_bugs_summary
[bugs_pass
] = 1
417 elif bugs_metadata
== "DISubprogram":
418 action
= bug
["action"]
420 di_sp_bugs
.append(DISPBug(action
, name
))
422 # Fill the summary dict.
423 if bugs_pass
in di_sp_bugs_summary
:
424 di_sp_bugs_summary
[bugs_pass
] += 1
426 di_sp_bugs_summary
[bugs_pass
] = 1
427 elif bugs_metadata
== "dbg-var-intrinsic":
428 action
= bug
["action"]
429 fn_name
= bug
["fn-name"]
431 di_var_bugs
.append(DIVarBug(action
, name
, fn_name
))
433 # Fill the summary dict.
434 if bugs_pass
in di_var_bugs_summary
:
435 di_var_bugs_summary
[bugs_pass
] += 1
437 di_var_bugs_summary
[bugs_pass
] = 1
439 print ("error: Unsupported metadata.")
442 di_location_bugs
[bugs_file
][bugs_pass
] = di_loc_bugs
443 di_subprogram_bugs
[bugs_file
][bugs_pass
] = di_sp_bugs
444 di_variable_bugs
[bugs_file
][bugs_pass
] = di_var_bugs
446 generate_html_report(di_location_bugs
, di_subprogram_bugs
, di_variable_bugs
, \
447 di_location_bugs_summary
, di_sp_bugs_summary
, \
448 di_var_bugs_summary
, opts
.html_file
)
450 if __name__
== "__main__":