[docs] Add LICENSE.txt to the root of the mono-repo
[llvm-project.git] / llvm / utils / llvm-original-di-preservation.py
blob0744c3b3452b56f7f455b229eed14955044fa1bc
1 #!/usr/bin/env python
3 # Debugify summary for the original debug info testing.
6 from __future__ import print_function
7 import argparse
8 import os
9 import sys
10 from json import loads
11 from collections import defaultdict
12 from collections import OrderedDict
14 class DILocBug:
15 def __init__(self, action, bb_name, fn_name, instr):
16 self.action = action
17 self.bb_name = bb_name
18 self.fn_name = fn_name
19 self.instr = instr
21 class DISPBug:
22 def __init__(self, action, fn_name):
23 self.action = action
24 self.fn_name = fn_name
26 class DIVarBug:
27 def __init__(self, action, name, fn_name):
28 self.action = action
29 self.name = 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>
39 <head>
40 <style>
41 table, th, td {
42 border: 1px solid black;
44 table.center {
45 margin-left: auto;
46 margin-right: auto;
48 </style>
49 </head>
50 <body>
51 """
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>
58 <tr>
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:
75 continue
76 at_least_one_bug_found = True
77 row = []
78 table_di_loc += " </tr>\n"
79 # Get the bugs info.
80 for x in per_pass_bugs:
81 row.append(" <tr>\n")
82 row.append(file)
83 row.append(llvm_pass)
84 row.append(x.instr)
85 row.append(x.fn_name)
86 row.append(x.bb_name)
87 row.append(x.action)
88 row.append(" </tr>\n")
89 # Dump the bugs info into the table.
90 for column in row:
91 # The same file-pass pair can have multiple bugs.
92 if (column == " <tr>\n" or column == " </tr>\n"):
93 table_di_loc += column
94 continue
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>
101 </tr>
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>
109 <tr>
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"
118 # Print the summary.
119 row = []
120 for llvm_pass, num in sorted(di_location_bugs_summary.items()):
121 row.append(" <tr>\n")
122 row.append(llvm_pass)
123 row.append(str(num))
124 row.append(" </tr>\n")
125 for column in row:
126 if (column == " <tr>\n" or column == " </tr>\n"):
127 table_di_loc_sum += column
128 continue
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>
135 </tr>
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>
143 <tr>
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
154 # Handle fn bugs.
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:
159 continue
160 at_least_one_bug_found = True
161 row = []
162 table_di_sp += " </tr>\n"
163 # Get the bugs info.
164 for x in per_pass_bugs:
165 row.append(" <tr>\n")
166 row.append(file)
167 row.append(llvm_pass)
168 row.append(x.fn_name)
169 row.append(x.action)
170 row.append(" </tr>\n")
171 # Dump the bugs info into the table.
172 for column in row:
173 # The same file-pass pair can have multiple bugs.
174 if (column == " <tr>\n" or column == " </tr>\n"):
175 table_di_sp += column
176 continue
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>
183 </tr>
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>
191 <tr>
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"
200 # Print the summary.
201 row = []
202 for llvm_pass, num in sorted(di_sp_bugs_summary.items()):
203 row.append(" <tr>\n")
204 row.append(llvm_pass)
205 row.append(str(num))
206 row.append(" </tr>\n")
207 for column in row:
208 if (column == " <tr>\n" or column == " </tr>\n"):
209 table_di_sp_sum += column
210 continue
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>
217 </tr>
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>
225 <tr>
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
236 # Handle var bugs.
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:
241 continue
242 at_least_one_bug_found = True
243 row = []
244 table_di_var += " </tr>\n"
245 # Get the bugs info.
246 for x in per_pass_bugs:
247 row.append(" <tr>\n")
248 row.append(file)
249 row.append(llvm_pass)
250 row.append(x.name)
251 row.append(x.fn_name)
252 row.append(x.action)
253 row.append(" </tr>\n")
254 # Dump the bugs info into the table.
255 for column in row:
256 # The same file-pass pair can have multiple bugs.
257 if (column == " <tr>\n" or column == " </tr>\n"):
258 table_di_var += column
259 continue
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>
266 </tr>
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>
274 <tr>
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"
283 # Print the summary.
284 row = []
285 for llvm_pass, num in sorted(di_var_bugs_summary.items()):
286 row.append(" <tr>\n")
287 row.append(llvm_pass)
288 row.append(str(num))
289 row.append(" </tr>\n")
290 for column in row:
291 if (column == " <tr>\n" or column == " </tr>\n"):
292 table_di_var_sum += column
293 continue
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>
300 </tr>
302 table_di_var_sum += "</table>\n"
304 # Finish the html page.
305 html_footer = """</body>
306 </html>"""
308 new_line = "<br>\n"
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)
325 fileout.close()
327 print("The " + html_file + " generated.")
329 # Read the JSON file.
330 def get_json(file):
331 json_parsed = None
332 di_checker_data = []
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",
339 # "bugs": [
342 # "action": "drop",
343 # "metadata": "DISubprogram",
344 # "name": "fn2"
345 # },
347 # "action": "drop",
348 # "metadata": "DISubprogram",
349 # "name": "fn1"
354 with open(file) as json_objects_file:
355 for json_object_line in json_objects_file:
356 try:
357 json_object = loads(json_object_line)
358 except:
359 print ("error: No valid di-checker data found.")
360 sys.exit(1)
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()
372 def Main():
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'.")
378 sys.exit(1)
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]
399 di_loc_bugs = []
400 di_sp_bugs = []
401 di_var_bugs = []
403 for bug in bugs:
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"]
409 instr = bug["instr"]
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
415 else:
416 di_location_bugs_summary[bugs_pass] = 1
417 elif bugs_metadata == "DISubprogram":
418 action = bug["action"]
419 name = bug["name"]
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
425 else:
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"]
430 name = bug["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
436 else:
437 di_var_bugs_summary[bugs_pass] = 1
438 else:
439 print ("error: Unsupported metadata.")
440 sys.exit(1)
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__":
451 Main()
452 sys.exit(0)