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
21 return self
.action
+ self
.bb_name
+ self
.fn_name
+ self
.instr
24 def __init__(self
, action
, fn_name
):
26 self
.fn_name
= fn_name
28 return self
.action
+ self
.fn_name
31 def __init__(self
, action
, name
, fn_name
):
34 self
.fn_name
= fn_name
36 return self
.action
+ self
.name
+ self
.fn_name
38 # Report the bugs in form of html.
39 def generate_html_report(di_location_bugs
, di_subprogram_bugs
, di_var_bugs
, \
40 di_location_bugs_summary
, di_sp_bugs_summary
, \
41 di_var_bugs_summary
, html_file
):
42 fileout
= open(html_file
, "w")
44 html_header
= """ <html>
48 border: 1px solid black;
59 # Create the table for Location bugs.
60 table_title_di_loc
= "Location Bugs found by the Debugify"
62 table_di_loc
= """<table>
63 <caption><b>{}</b></caption>
65 """.format(table_title_di_loc
)
67 header_di_loc
= ["File", "LLVM Pass Name", "LLVM IR Instruction", \
68 "Function Name", "Basic Block Name", "Action"]
70 for column
in header_di_loc
:
71 table_di_loc
+= " <th>{0}</th>\n".format(column
.strip())
72 table_di_loc
+= " </tr>\n"
74 at_least_one_bug_found
= False
76 # Handle loction bugs.
77 for file, per_file_bugs
in di_location_bugs
.items():
78 for llvm_pass
, per_pass_bugs
in per_file_bugs
.items():
79 # No location bugs for the pass.
80 if len(per_pass_bugs
) == 0:
82 at_least_one_bug_found
= True
84 table_di_loc
+= " </tr>\n"
86 for x
in per_pass_bugs
:
94 row
.append(" </tr>\n")
95 # Dump the bugs info into the table.
97 # The same file-pass pair can have multiple bugs.
98 if (column
== " <tr>\n" or column
== " </tr>\n"):
99 table_di_loc
+= column
101 table_di_loc
+= " <td>{0}</td>\n".format(column
.strip())
102 table_di_loc
+= " <tr>\n"
104 if not at_least_one_bug_found
:
105 table_di_loc
+= """ <tr>
106 <td colspan='7'> No bugs found </td>
109 table_di_loc
+= "</table>\n"
111 # Create the summary table for the loc bugs.
112 table_title_di_loc_sum
= "Summary of Location Bugs"
113 table_di_loc_sum
= """<table>
114 <caption><b>{}</b></caption>
116 """.format(table_title_di_loc_sum
)
118 header_di_loc_sum
= ["LLVM Pass Name", "Number of bugs"]
120 for column
in header_di_loc_sum
:
121 table_di_loc_sum
+= " <th>{0}</th>\n".format(column
.strip())
122 table_di_loc_sum
+= " </tr>\n"
126 for llvm_pass
, num
in sorted(di_location_bugs_summary
.items()):
127 row
.append(" <tr>\n")
128 row
.append(llvm_pass
)
130 row
.append(" </tr>\n")
132 if (column
== " <tr>\n" or column
== " </tr>\n"):
133 table_di_loc_sum
+= column
135 table_di_loc_sum
+= " <td>{0}</td>\n".format(column
.strip())
136 table_di_loc_sum
+= " <tr>\n"
138 if not at_least_one_bug_found
:
139 table_di_loc_sum
+= """<tr>
140 <td colspan='2'> No bugs found </td>
143 table_di_loc_sum
+= "</table>\n"
145 # Create the table for SP bugs.
146 table_title_di_sp
= "SP Bugs found by the Debugify"
147 table_di_sp
= """<table>
148 <caption><b>{}</b></caption>
150 """.format(table_title_di_sp
)
152 header_di_sp
= ["File", "LLVM Pass Name", "Function Name", "Action"]
154 for column
in header_di_sp
:
155 table_di_sp
+= " <th>{0}</th>\n".format(column
.strip())
156 table_di_sp
+= " </tr>\n"
158 at_least_one_bug_found
= False
161 for file, per_file_bugs
in di_subprogram_bugs
.items():
162 for llvm_pass
, per_pass_bugs
in per_file_bugs
.items():
163 # No SP bugs for the pass.
164 if len(per_pass_bugs
) == 0:
166 at_least_one_bug_found
= True
168 table_di_sp
+= " </tr>\n"
170 for x
in per_pass_bugs
:
171 row
.append(" <tr>\n")
173 row
.append(llvm_pass
)
174 row
.append(x
.fn_name
)
176 row
.append(" </tr>\n")
177 # Dump the bugs info into the table.
179 # The same file-pass pair can have multiple bugs.
180 if (column
== " <tr>\n" or column
== " </tr>\n"):
181 table_di_sp
+= column
183 table_di_sp
+= " <td>{0}</td>\n".format(column
.strip())
184 table_di_sp
+= " <tr>\n"
186 if not at_least_one_bug_found
:
187 table_di_sp
+= """<tr>
188 <td colspan='4'> No bugs found </td>
191 table_di_sp
+= "</table>\n"
193 # Create the summary table for the sp bugs.
194 table_title_di_sp_sum
= "Summary of SP Bugs"
195 table_di_sp_sum
= """<table>
196 <caption><b>{}</b></caption>
198 """.format(table_title_di_sp_sum
)
200 header_di_sp_sum
= ["LLVM Pass Name", "Number of bugs"]
202 for column
in header_di_sp_sum
:
203 table_di_sp_sum
+= " <th>{0}</th>\n".format(column
.strip())
204 table_di_sp_sum
+= " </tr>\n"
208 for llvm_pass
, num
in sorted(di_sp_bugs_summary
.items()):
209 row
.append(" <tr>\n")
210 row
.append(llvm_pass
)
212 row
.append(" </tr>\n")
214 if (column
== " <tr>\n" or column
== " </tr>\n"):
215 table_di_sp_sum
+= column
217 table_di_sp_sum
+= " <td>{0}</td>\n".format(column
.strip())
218 table_di_sp_sum
+= " <tr>\n"
220 if not at_least_one_bug_found
:
221 table_di_sp_sum
+= """<tr>
222 <td colspan='2'> No bugs found </td>
225 table_di_sp_sum
+= "</table>\n"
227 # Create the table for Variable bugs.
228 table_title_di_var
= "Variable Location Bugs found by the Debugify"
229 table_di_var
= """<table>
230 <caption><b>{}</b></caption>
232 """.format(table_title_di_var
)
234 header_di_var
= ["File", "LLVM Pass Name", "Variable", "Function", "Action"]
236 for column
in header_di_var
:
237 table_di_var
+= " <th>{0}</th>\n".format(column
.strip())
238 table_di_var
+= " </tr>\n"
240 at_least_one_bug_found
= False
243 for file, per_file_bugs
in di_var_bugs
.items():
244 for llvm_pass
, per_pass_bugs
in per_file_bugs
.items():
245 # No SP bugs for the pass.
246 if len(per_pass_bugs
) == 0:
248 at_least_one_bug_found
= True
250 table_di_var
+= " </tr>\n"
252 for x
in per_pass_bugs
:
253 row
.append(" <tr>\n")
255 row
.append(llvm_pass
)
257 row
.append(x
.fn_name
)
259 row
.append(" </tr>\n")
260 # Dump the bugs info into the table.
262 # The same file-pass pair can have multiple bugs.
263 if (column
== " <tr>\n" or column
== " </tr>\n"):
264 table_di_var
+= column
266 table_di_var
+= " <td>{0}</td>\n".format(column
.strip())
267 table_di_var
+= " <tr>\n"
269 if not at_least_one_bug_found
:
270 table_di_var
+= """<tr>
271 <td colspan='4'> No bugs found </td>
274 table_di_var
+= "</table>\n"
276 # Create the summary table for the sp bugs.
277 table_title_di_var_sum
= "Summary of Variable Location Bugs"
278 table_di_var_sum
= """<table>
279 <caption><b>{}</b></caption>
281 """.format(table_title_di_var_sum
)
283 header_di_var_sum
= ["LLVM Pass Name", "Number of bugs"]
285 for column
in header_di_var_sum
:
286 table_di_var_sum
+= " <th>{0}</th>\n".format(column
.strip())
287 table_di_var_sum
+= " </tr>\n"
291 for llvm_pass
, num
in sorted(di_var_bugs_summary
.items()):
292 row
.append(" <tr>\n")
293 row
.append(llvm_pass
)
295 row
.append(" </tr>\n")
297 if (column
== " <tr>\n" or column
== " </tr>\n"):
298 table_di_var_sum
+= column
300 table_di_var_sum
+= " <td>{0}</td>\n".format(column
.strip())
301 table_di_var_sum
+= " <tr>\n"
303 if not at_least_one_bug_found
:
304 table_di_var_sum
+= """<tr>
305 <td colspan='2'> No bugs found </td>
308 table_di_var_sum
+= "</table>\n"
310 # Finish the html page.
311 html_footer
= """</body>
316 fileout
.writelines(html_header
)
317 fileout
.writelines(table_di_loc
)
318 fileout
.writelines(new_line
)
319 fileout
.writelines(table_di_loc_sum
)
320 fileout
.writelines(new_line
)
321 fileout
.writelines(new_line
)
322 fileout
.writelines(table_di_sp
)
323 fileout
.writelines(new_line
)
324 fileout
.writelines(table_di_sp_sum
)
325 fileout
.writelines(new_line
)
326 fileout
.writelines(new_line
)
327 fileout
.writelines(table_di_var
)
328 fileout
.writelines(new_line
)
329 fileout
.writelines(table_di_var_sum
)
330 fileout
.writelines(html_footer
)
333 print("The " + html_file
+ " generated.")
335 # Read the JSON file in chunks.
336 def get_json_chunk(file,start
,size
):
342 # The file contains json object per line.
343 # An example of the line (formatted json):
345 # "file": "simple.c",
346 # "pass": "Deduce function attributes in RPO",
351 # "metadata": "DISubprogram",
356 # "metadata": "DISubprogram",
362 with
open(file) as json_objects_file
:
363 for json_object_line
in json_objects_file
:
367 if line
>= start
+size
:
370 json_object
= loads(json_object_line
)
374 di_checker_data
.append(json_object
)
376 return (di_checker_data
, skipped_lines
, line
)
378 # Parse the program arguments.
379 def parse_program_args(parser
):
380 parser
.add_argument("file_name", type=str, help="json file to process")
381 parser
.add_argument("html_file", type=str, help="html file to output data")
382 parser
.add_argument("-compress", action
="store_true", help="create reduced html report")
384 return parser
.parse_args()
387 parser
= argparse
.ArgumentParser()
388 opts
= parse_program_args(parser
)
390 if not opts
.html_file
.endswith('.html'):
391 print ("error: The output file must be '.html'.")
394 # Use the defaultdict in order to make multidim dicts.
395 di_location_bugs
= defaultdict(lambda: defaultdict(dict))
396 di_subprogram_bugs
= defaultdict(lambda: defaultdict(dict))
397 di_variable_bugs
= defaultdict(lambda: defaultdict(dict))
399 # Use the ordered dict to make a summary.
400 di_location_bugs_summary
= OrderedDict()
401 di_sp_bugs_summary
= OrderedDict()
402 di_var_bugs_summary
= OrderedDict()
404 # Compress similar bugs.
405 # DILocBugs with same pass & instruction name.
406 di_loc_pass_instr_set
= set()
407 # DISPBugs with same pass & function name.
408 di_sp_pass_fn_set
= set()
409 # DIVarBugs with same pass & variable name.
410 di_var_pass_var_set
= set()
414 end_line
= chunk_size
- 1
417 # Process each chunk of 1 million JSON lines.
419 if start_line
> end_line
:
421 (debug_info_bugs
, skipped
, end_line
) = get_json_chunk(opts
.file_name
,start_line
,chunk_size
)
422 start_line
+= chunk_size
423 skipped_lines
+= skipped
425 # Map the bugs into the file-pass pairs.
426 for bugs_per_pass
in debug_info_bugs
:
428 bugs_file
= bugs_per_pass
["file"]
429 bugs_pass
= bugs_per_pass
["pass"]
430 bugs
= bugs_per_pass
["bugs"][0]
439 # Omit duplicated bugs.
445 bugs_metadata
= bug
["metadata"]
450 if bugs_metadata
== "DILocation":
452 action
= bug
["action"]
453 bb_name
= bug
["bb-name"]
454 fn_name
= bug
["fn-name"]
459 di_loc_bug
= DILocBug(action
, bb_name
, fn_name
, instr
)
460 if not str(di_loc_bug
) in di_loc_set
:
461 di_loc_set
.add(str(di_loc_bug
))
463 pass_instr
= bugs_pass
+ instr
464 if not pass_instr
in di_loc_pass_instr_set
:
465 di_loc_pass_instr_set
.add(pass_instr
)
466 di_loc_bugs
.append(di_loc_bug
)
468 di_loc_bugs
.append(di_loc_bug
)
470 # Fill the summary dict.
471 if bugs_pass
in di_location_bugs_summary
:
472 di_location_bugs_summary
[bugs_pass
] += 1
474 di_location_bugs_summary
[bugs_pass
] = 1
475 elif bugs_metadata
== "DISubprogram":
477 action
= bug
["action"]
482 di_sp_bug
= DISPBug(action
, name
)
483 if not str(di_sp_bug
) in di_sp_set
:
484 di_sp_set
.add(str(di_sp_bug
))
486 pass_fn
= bugs_pass
+ name
487 if not pass_fn
in di_sp_pass_fn_set
:
488 di_sp_pass_fn_set
.add(pass_fn
)
489 di_sp_bugs
.append(di_sp_bug
)
491 di_sp_bugs
.append(di_sp_bug
)
493 # Fill the summary dict.
494 if bugs_pass
in di_sp_bugs_summary
:
495 di_sp_bugs_summary
[bugs_pass
] += 1
497 di_sp_bugs_summary
[bugs_pass
] = 1
498 elif bugs_metadata
== "dbg-var-intrinsic":
500 action
= bug
["action"]
501 fn_name
= bug
["fn-name"]
506 di_var_bug
= DIVarBug(action
, name
, fn_name
)
507 if not str(di_var_bug
) in di_var_set
:
508 di_var_set
.add(str(di_var_bug
))
510 pass_var
= bugs_pass
+ name
511 if not pass_var
in di_var_pass_var_set
:
512 di_var_pass_var_set
.add(pass_var
)
513 di_var_bugs
.append(di_var_bug
)
515 di_var_bugs
.append(di_var_bug
)
517 # Fill the summary dict.
518 if bugs_pass
in di_var_bugs_summary
:
519 di_var_bugs_summary
[bugs_pass
] += 1
521 di_var_bugs_summary
[bugs_pass
] = 1
523 # Unsupported metadata.
527 di_location_bugs
[bugs_file
][bugs_pass
] = di_loc_bugs
528 di_subprogram_bugs
[bugs_file
][bugs_pass
] = di_sp_bugs
529 di_variable_bugs
[bugs_file
][bugs_pass
] = di_var_bugs
531 generate_html_report(di_location_bugs
, di_subprogram_bugs
, di_variable_bugs
, \
532 di_location_bugs_summary
, di_sp_bugs_summary
, \
533 di_var_bugs_summary
, opts
.html_file
)
535 if skipped_lines
> 0:
536 print ("Skipped lines: " + str(skipped_lines
))
538 print ("Skipped bugs: " + str(skipped_bugs
))
540 if __name__
== "__main__":