12f2feebfSReid Kleckner#!/usr/bin/env python 22f2feebfSReid Kleckner 32f2feebfSReid Klecknerfrom __future__ import print_function 42f2feebfSReid Kleckner 52f2feebfSReid Klecknerimport argparse 62f2feebfSReid Klecknerimport errno 72f2feebfSReid Klecknerimport functools 84b428e8fSGianfranco Costamagnaimport html 943d9f2d1SYuanfang Chenimport io 102f2feebfSReid Klecknerfrom multiprocessing import cpu_count 112f2feebfSReid Klecknerimport os.path 122f2feebfSReid Klecknerimport re 132f2feebfSReid Klecknerimport shutil 142f2feebfSReid Klecknerimport sys 152f2feebfSReid Kleckner 162f2feebfSReid Klecknerfrom pygments import highlight 172f2feebfSReid Klecknerfrom pygments.lexers.c_cpp import CppLexer 182f2feebfSReid Klecknerfrom pygments.formatters import HtmlFormatter 192f2feebfSReid Kleckner 202f2feebfSReid Klecknerimport optpmap 212f2feebfSReid Klecknerimport optrecord 222f2feebfSReid Kleckner 232f2feebfSReid Kleckner 24*b71edfaaSTobias Hietadesc = """Generate HTML output to visualize optimization records from the YAML files 252f2feebfSReid Klecknergenerated with -fsave-optimization-record and -fdiagnostics-show-hotness. 262f2feebfSReid Kleckner 27*b71edfaaSTobias HietaThe tools requires PyYAML and Pygments Python packages.""" 282f2feebfSReid Kleckner 292f2feebfSReid Kleckner 302f2feebfSReid Kleckner# This allows passing the global context to the child processes. 312f2feebfSReid Klecknerclass Context: 322f2feebfSReid Kleckner def __init__(self, caller_loc=dict()): 332f2feebfSReid Kleckner # Map function names to their source location for function where inlining happened 342f2feebfSReid Kleckner self.caller_loc = caller_loc 352f2feebfSReid Kleckner 36*b71edfaaSTobias Hieta 372f2feebfSReid Klecknercontext = Context() 382f2feebfSReid Kleckner 39*b71edfaaSTobias Hieta 402f2feebfSReid Klecknerdef suppress(remark): 41*b71edfaaSTobias Hieta if remark.Name == "sil.Specialized": 42*b71edfaaSTobias Hieta return remark.getArgDict()["Function"][0].startswith('"Swift.') 43*b71edfaaSTobias Hieta elif remark.Name == "sil.Inlined": 44*b71edfaaSTobias Hieta return remark.getArgDict()["Callee"][0].startswith( 45*b71edfaaSTobias Hieta ('"Swift.', '"specialized Swift.') 46*b71edfaaSTobias Hieta ) 472f2feebfSReid Kleckner return False 482f2feebfSReid Kleckner 49*b71edfaaSTobias Hieta 502f2feebfSReid Klecknerclass SourceFileRenderer: 512f2feebfSReid Kleckner def __init__(self, source_dir, output_dir, filename, no_highlight): 522f2feebfSReid Kleckner self.filename = filename 532f2feebfSReid Kleckner existing_filename = None 542f2feebfSReid Kleckner if os.path.exists(filename): 552f2feebfSReid Kleckner existing_filename = filename 562f2feebfSReid Kleckner else: 572f2feebfSReid Kleckner fn = os.path.join(source_dir, filename) 582f2feebfSReid Kleckner if os.path.exists(fn): 592f2feebfSReid Kleckner existing_filename = fn 602f2feebfSReid Kleckner 612f2feebfSReid Kleckner self.no_highlight = no_highlight 62*b71edfaaSTobias Hieta self.stream = io.open( 63*b71edfaaSTobias Hieta os.path.join(output_dir, optrecord.html_file_name(filename)), 64*b71edfaaSTobias Hieta "w", 65*b71edfaaSTobias Hieta encoding="utf-8", 66*b71edfaaSTobias Hieta ) 672f2feebfSReid Kleckner if existing_filename: 68*b71edfaaSTobias Hieta self.source_stream = io.open(existing_filename, encoding="utf-8") 692f2feebfSReid Kleckner else: 702f2feebfSReid Kleckner self.source_stream = None 71*b71edfaaSTobias Hieta print( 72*b71edfaaSTobias Hieta """ 732f2feebfSReid Kleckner<html> 742f2feebfSReid Kleckner<h1>Unable to locate file {}</h1> 752f2feebfSReid Kleckner</html> 76*b71edfaaSTobias Hieta """.format( 77*b71edfaaSTobias Hieta filename 78*b71edfaaSTobias Hieta ), 79*b71edfaaSTobias Hieta file=self.stream, 80*b71edfaaSTobias Hieta ) 812f2feebfSReid Kleckner 82*b71edfaaSTobias Hieta self.html_formatter = HtmlFormatter(encoding="utf-8") 832f2feebfSReid Kleckner self.cpp_lexer = CppLexer(stripnl=False) 842f2feebfSReid Kleckner 852f2feebfSReid Kleckner def render_source_lines(self, stream, line_remarks): 862f2feebfSReid Kleckner file_text = stream.read() 872f2feebfSReid Kleckner 882f2feebfSReid Kleckner if self.no_highlight: 892f2feebfSReid Kleckner html_highlighted = file_text 902f2feebfSReid Kleckner else: 91*b71edfaaSTobias Hieta html_highlighted = highlight(file_text, self.cpp_lexer, self.html_formatter) 922f2feebfSReid Kleckner 932f2feebfSReid Kleckner # Note that the API is different between Python 2 and 3. On 942f2feebfSReid Kleckner # Python 3, pygments.highlight() returns a bytes object, so we 952f2feebfSReid Kleckner # have to decode. On Python 2, the output is str but since we 962f2feebfSReid Kleckner # support unicode characters and the output streams is unicode we 972f2feebfSReid Kleckner # decode too. 98*b71edfaaSTobias Hieta html_highlighted = html_highlighted.decode("utf-8") 992f2feebfSReid Kleckner 1002f2feebfSReid Kleckner # Take off the header and footer, these must be 1012f2feebfSReid Kleckner # reapplied line-wise, within the page structure 102*b71edfaaSTobias Hieta html_highlighted = html_highlighted.replace( 103*b71edfaaSTobias Hieta '<div class="highlight"><pre>', "" 104*b71edfaaSTobias Hieta ) 105*b71edfaaSTobias Hieta html_highlighted = html_highlighted.replace("</pre></div>", "") 1062f2feebfSReid Kleckner 107*b71edfaaSTobias Hieta for (linenum, html_line) in enumerate(html_highlighted.split("\n"), start=1): 108*b71edfaaSTobias Hieta print( 109*b71edfaaSTobias Hieta """ 1102f2feebfSReid Kleckner<tr> 1112f2feebfSReid Kleckner<td><a name=\"L{linenum}\">{linenum}</a></td> 1122f2feebfSReid Kleckner<td></td> 1132f2feebfSReid Kleckner<td></td> 1142f2feebfSReid Kleckner<td><div class="highlight"><pre>{html_line}</pre></div></td> 115*b71edfaaSTobias Hieta</tr>""".format( 116*b71edfaaSTobias Hieta **locals() 117*b71edfaaSTobias Hieta ), 118*b71edfaaSTobias Hieta file=self.stream, 119*b71edfaaSTobias Hieta ) 1202f2feebfSReid Kleckner 1212f2feebfSReid Kleckner for remark in line_remarks.get(linenum, []): 1222f2feebfSReid Kleckner if not suppress(remark): 1232f2feebfSReid Kleckner self.render_inline_remarks(remark, html_line) 1242f2feebfSReid Kleckner 1252f2feebfSReid Kleckner def render_inline_remarks(self, r, line): 1262f2feebfSReid Kleckner inlining_context = r.DemangledFunctionName 1272f2feebfSReid Kleckner dl = context.caller_loc.get(r.Function) 1282f2feebfSReid Kleckner if dl: 1292f2feebfSReid Kleckner dl_dict = dict(list(dl)) 130*b71edfaaSTobias Hieta link = optrecord.make_link(dl_dict["File"], dl_dict["Line"] - 2) 131*b71edfaaSTobias Hieta inlining_context = "<a href={link}>{r.DemangledFunctionName}</a>".format( 132*b71edfaaSTobias Hieta **locals() 133*b71edfaaSTobias Hieta ) 1342f2feebfSReid Kleckner 1352f2feebfSReid Kleckner # Column is the number of characters *including* tabs, keep those and 1362f2feebfSReid Kleckner # replace everything else with spaces. 1372f2feebfSReid Kleckner indent = line[: max(r.Column, 1) - 1] 138*b71edfaaSTobias Hieta indent = re.sub("\S", " ", indent) 1392f2feebfSReid Kleckner 1402f2feebfSReid Kleckner # Create expanded message and link if we have a multiline message. 141*b71edfaaSTobias Hieta lines = r.message.split("\n") 1422f2feebfSReid Kleckner if len(lines) > 1: 1432f2feebfSReid Kleckner expand_link = '<a style="text-decoration: none;" href="" onclick="toggleExpandedMessage(this); return false;">+</a>' 1442f2feebfSReid Kleckner message = lines[0] 145*b71edfaaSTobias Hieta expand_message = """ 1462f2feebfSReid Kleckner<div class="full-info" style="display:none;"> 1472f2feebfSReid Kleckner <div class="col-left"><pre style="display:inline">{}</pre></div> 1482f2feebfSReid Kleckner <div class="expanded col-left"><pre>{}</pre></div> 149*b71edfaaSTobias Hieta</div>""".format( 150*b71edfaaSTobias Hieta indent, "\n".join(lines[1:]) 151*b71edfaaSTobias Hieta ) 1522f2feebfSReid Kleckner else: 153*b71edfaaSTobias Hieta expand_link = "" 154*b71edfaaSTobias Hieta expand_message = "" 1552f2feebfSReid Kleckner message = r.message 156*b71edfaaSTobias Hieta print( 157*b71edfaaSTobias Hieta """ 1582f2feebfSReid Kleckner<tr> 1592f2feebfSReid Kleckner<td></td> 1602f2feebfSReid Kleckner<td>{r.RelativeHotness}</td> 1612f2feebfSReid Kleckner<td class=\"column-entry-{r.color}\">{r.PassWithDiffPrefix}</td> 1622f2feebfSReid Kleckner<td><pre style="display:inline">{indent}</pre><span class=\"column-entry-yellow\">{expand_link} {message} </span>{expand_message}</td> 1632f2feebfSReid Kleckner<td class=\"column-entry-yellow\">{inlining_context}</td> 164*b71edfaaSTobias Hieta</tr>""".format( 165*b71edfaaSTobias Hieta **locals() 166*b71edfaaSTobias Hieta ), 167*b71edfaaSTobias Hieta file=self.stream, 168*b71edfaaSTobias Hieta ) 1692f2feebfSReid Kleckner 1702f2feebfSReid Kleckner def render(self, line_remarks): 1712f2feebfSReid Kleckner if not self.source_stream: 1722f2feebfSReid Kleckner return 1732f2feebfSReid Kleckner 174*b71edfaaSTobias Hieta print( 175*b71edfaaSTobias Hieta """ 1762f2feebfSReid Kleckner<html> 1772f2feebfSReid Kleckner<title>{}</title> 1782f2feebfSReid Kleckner<meta charset="utf-8" /> 1792f2feebfSReid Kleckner<head> 1802f2feebfSReid Kleckner<link rel='stylesheet' type='text/css' href='style.css'> 1812f2feebfSReid Kleckner<script type="text/javascript"> 1822f2feebfSReid Kleckner/* Simple helper to show/hide the expanded message of a remark. */ 1832f2feebfSReid Klecknerfunction toggleExpandedMessage(e) {{ 1842f2feebfSReid Kleckner var FullTextElems = e.parentElement.parentElement.getElementsByClassName("full-info"); 1852f2feebfSReid Kleckner if (!FullTextElems || FullTextElems.length < 1) {{ 1862f2feebfSReid Kleckner return false; 1872f2feebfSReid Kleckner }} 1882f2feebfSReid Kleckner var FullText = FullTextElems[0]; 1892f2feebfSReid Kleckner if (FullText.style.display == 'none') {{ 1902f2feebfSReid Kleckner e.innerHTML = '-'; 1912f2feebfSReid Kleckner FullText.style.display = 'block'; 1922f2feebfSReid Kleckner }} else {{ 1932f2feebfSReid Kleckner e.innerHTML = '+'; 1942f2feebfSReid Kleckner FullText.style.display = 'none'; 1952f2feebfSReid Kleckner }} 1962f2feebfSReid Kleckner}} 1972f2feebfSReid Kleckner</script> 1982f2feebfSReid Kleckner</head> 1992f2feebfSReid Kleckner<body> 2002f2feebfSReid Kleckner<div class="centered"> 2012f2feebfSReid Kleckner<table class="source"> 2022f2feebfSReid Kleckner<thead> 2032f2feebfSReid Kleckner<tr> 2042f2feebfSReid Kleckner<th style="width: 2%">Line</td> 2052f2feebfSReid Kleckner<th style="width: 3%">Hotness</td> 2062f2feebfSReid Kleckner<th style="width: 10%">Optimization</td> 2072f2feebfSReid Kleckner<th style="width: 70%">Source</td> 2082f2feebfSReid Kleckner<th style="width: 15%">Inline Context</td> 2092f2feebfSReid Kleckner</tr> 2102f2feebfSReid Kleckner</thead> 211*b71edfaaSTobias Hieta<tbody>""".format( 212*b71edfaaSTobias Hieta os.path.basename(self.filename) 213*b71edfaaSTobias Hieta ), 214*b71edfaaSTobias Hieta file=self.stream, 215*b71edfaaSTobias Hieta ) 2162f2feebfSReid Kleckner self.render_source_lines(self.source_stream, line_remarks) 2172f2feebfSReid Kleckner 218*b71edfaaSTobias Hieta print( 219*b71edfaaSTobias Hieta """ 2202f2feebfSReid Kleckner</tbody> 2212f2feebfSReid Kleckner</table> 2222f2feebfSReid Kleckner</body> 223*b71edfaaSTobias Hieta</html>""", 224*b71edfaaSTobias Hieta file=self.stream, 225*b71edfaaSTobias Hieta ) 2262f2feebfSReid Kleckner 2272f2feebfSReid Kleckner 2282f2feebfSReid Klecknerclass IndexRenderer: 229*b71edfaaSTobias Hieta def __init__( 230*b71edfaaSTobias Hieta self, output_dir, should_display_hotness, max_hottest_remarks_on_index 231*b71edfaaSTobias Hieta ): 232*b71edfaaSTobias Hieta self.stream = io.open( 233*b71edfaaSTobias Hieta os.path.join(output_dir, "index.html"), "w", encoding="utf-8" 234*b71edfaaSTobias Hieta ) 2352f2feebfSReid Kleckner self.should_display_hotness = should_display_hotness 2362f2feebfSReid Kleckner self.max_hottest_remarks_on_index = max_hottest_remarks_on_index 2372f2feebfSReid Kleckner 2382f2feebfSReid Kleckner def render_entry(self, r, odd): 2394b428e8fSGianfranco Costamagna escaped_name = html.escape(r.DemangledFunctionName) 240*b71edfaaSTobias Hieta print( 241*b71edfaaSTobias Hieta """ 2422f2feebfSReid Kleckner<tr> 2432f2feebfSReid Kleckner<td class=\"column-entry-{odd}\"><a href={r.Link}>{r.DebugLocString}</a></td> 2442f2feebfSReid Kleckner<td class=\"column-entry-{odd}\">{r.RelativeHotness}</td> 2452f2feebfSReid Kleckner<td class=\"column-entry-{odd}\">{escaped_name}</td> 2462f2feebfSReid Kleckner<td class=\"column-entry-{r.color}\">{r.PassWithDiffPrefix}</td> 247*b71edfaaSTobias Hieta</tr>""".format( 248*b71edfaaSTobias Hieta **locals() 249*b71edfaaSTobias Hieta ), 250*b71edfaaSTobias Hieta file=self.stream, 251*b71edfaaSTobias Hieta ) 2522f2feebfSReid Kleckner 2532f2feebfSReid Kleckner def render(self, all_remarks): 254*b71edfaaSTobias Hieta print( 255*b71edfaaSTobias Hieta """ 2562f2feebfSReid Kleckner<html> 2572f2feebfSReid Kleckner<meta charset="utf-8" /> 2582f2feebfSReid Kleckner<head> 2592f2feebfSReid Kleckner<link rel='stylesheet' type='text/css' href='style.css'> 2602f2feebfSReid Kleckner</head> 2612f2feebfSReid Kleckner<body> 2622f2feebfSReid Kleckner<div class="centered"> 2632f2feebfSReid Kleckner<table> 2642f2feebfSReid Kleckner<tr> 2652f2feebfSReid Kleckner<td>Source Location</td> 2662f2feebfSReid Kleckner<td>Hotness</td> 2672f2feebfSReid Kleckner<td>Function</td> 2682f2feebfSReid Kleckner<td>Pass</td> 269*b71edfaaSTobias Hieta</tr>""", 270*b71edfaaSTobias Hieta file=self.stream, 271*b71edfaaSTobias Hieta ) 2722f2feebfSReid Kleckner 2732f2feebfSReid Kleckner max_entries = None 2742f2feebfSReid Kleckner if self.should_display_hotness: 2752f2feebfSReid Kleckner max_entries = self.max_hottest_remarks_on_index 2762f2feebfSReid Kleckner 2772f2feebfSReid Kleckner for i, remark in enumerate(all_remarks[:max_entries]): 2782f2feebfSReid Kleckner if not suppress(remark): 2792f2feebfSReid Kleckner self.render_entry(remark, i % 2) 280*b71edfaaSTobias Hieta print( 281*b71edfaaSTobias Hieta """ 2822f2feebfSReid Kleckner</table> 2832f2feebfSReid Kleckner</body> 284*b71edfaaSTobias Hieta</html>""", 285*b71edfaaSTobias Hieta file=self.stream, 286*b71edfaaSTobias Hieta ) 2872f2feebfSReid Kleckner 2882f2feebfSReid Kleckner 2892f2feebfSReid Klecknerdef _render_file(source_dir, output_dir, ctx, no_highlight, entry, filter_): 2902f2feebfSReid Kleckner global context 2912f2feebfSReid Kleckner context = ctx 2922f2feebfSReid Kleckner filename, remarks = entry 2932f2feebfSReid Kleckner SourceFileRenderer(source_dir, output_dir, filename, no_highlight).render(remarks) 2942f2feebfSReid Kleckner 2952f2feebfSReid Kleckner 2962f2feebfSReid Klecknerdef map_remarks(all_remarks): 2972f2feebfSReid Kleckner # Set up a map between function names and their source location for 2982f2feebfSReid Kleckner # function where inlining happened 2992f2feebfSReid Kleckner for remark in optrecord.itervalues(all_remarks): 300*b71edfaaSTobias Hieta if ( 301*b71edfaaSTobias Hieta isinstance(remark, optrecord.Passed) 302*b71edfaaSTobias Hieta and remark.Pass == "inline" 303*b71edfaaSTobias Hieta and remark.Name == "Inlined" 304*b71edfaaSTobias Hieta ): 3052f2feebfSReid Kleckner for arg in remark.Args: 3062f2feebfSReid Kleckner arg_dict = dict(list(arg)) 307*b71edfaaSTobias Hieta caller = arg_dict.get("Caller") 3082f2feebfSReid Kleckner if caller: 3092f2feebfSReid Kleckner try: 310*b71edfaaSTobias Hieta context.caller_loc[caller] = arg_dict["DebugLoc"] 3112f2feebfSReid Kleckner except KeyError: 3122f2feebfSReid Kleckner pass 3132f2feebfSReid Kleckner 3142f2feebfSReid Kleckner 315*b71edfaaSTobias Hietadef generate_report( 316*b71edfaaSTobias Hieta all_remarks, 3172f2feebfSReid Kleckner file_remarks, 3182f2feebfSReid Kleckner source_dir, 3192f2feebfSReid Kleckner output_dir, 3202f2feebfSReid Kleckner no_highlight, 3212f2feebfSReid Kleckner should_display_hotness, 3222f2feebfSReid Kleckner max_hottest_remarks_on_index, 3232f2feebfSReid Kleckner num_jobs, 324*b71edfaaSTobias Hieta should_print_progress, 325*b71edfaaSTobias Hieta): 3262f2feebfSReid Kleckner try: 3272f2feebfSReid Kleckner os.makedirs(output_dir) 3282f2feebfSReid Kleckner except OSError as e: 3292f2feebfSReid Kleckner if e.errno == errno.EEXIST and os.path.isdir(output_dir): 3302f2feebfSReid Kleckner pass 3312f2feebfSReid Kleckner else: 3322f2feebfSReid Kleckner raise 3332f2feebfSReid Kleckner 3342f2feebfSReid Kleckner if should_print_progress: 335*b71edfaaSTobias Hieta print("Rendering index page...") 3362f2feebfSReid Kleckner if should_display_hotness: 337*b71edfaaSTobias Hieta sorted_remarks = sorted( 338*b71edfaaSTobias Hieta optrecord.itervalues(all_remarks), 339*b71edfaaSTobias Hieta key=lambda r: ( 340*b71edfaaSTobias Hieta r.Hotness, 341*b71edfaaSTobias Hieta r.File, 342*b71edfaaSTobias Hieta r.Line, 343*b71edfaaSTobias Hieta r.Column, 344*b71edfaaSTobias Hieta r.PassWithDiffPrefix, 345*b71edfaaSTobias Hieta r.yaml_tag, 346*b71edfaaSTobias Hieta r.Function, 347*b71edfaaSTobias Hieta ), 348*b71edfaaSTobias Hieta reverse=True, 349*b71edfaaSTobias Hieta ) 3502f2feebfSReid Kleckner else: 351*b71edfaaSTobias Hieta sorted_remarks = sorted( 352*b71edfaaSTobias Hieta optrecord.itervalues(all_remarks), 353*b71edfaaSTobias Hieta key=lambda r: ( 354*b71edfaaSTobias Hieta r.File, 355*b71edfaaSTobias Hieta r.Line, 356*b71edfaaSTobias Hieta r.Column, 357*b71edfaaSTobias Hieta r.PassWithDiffPrefix, 358*b71edfaaSTobias Hieta r.yaml_tag, 359*b71edfaaSTobias Hieta r.Function, 360*b71edfaaSTobias Hieta ), 361*b71edfaaSTobias Hieta ) 362*b71edfaaSTobias Hieta IndexRenderer( 363*b71edfaaSTobias Hieta output_dir, should_display_hotness, max_hottest_remarks_on_index 364*b71edfaaSTobias Hieta ).render(sorted_remarks) 3652f2feebfSReid Kleckner 366*b71edfaaSTobias Hieta shutil.copy( 367*b71edfaaSTobias Hieta os.path.join(os.path.dirname(os.path.realpath(__file__)), "style.css"), 368*b71edfaaSTobias Hieta output_dir, 369*b71edfaaSTobias Hieta ) 3702f2feebfSReid Kleckner 371*b71edfaaSTobias Hieta _render_file_bound = functools.partial( 372*b71edfaaSTobias Hieta _render_file, source_dir, output_dir, context, no_highlight 373*b71edfaaSTobias Hieta ) 3742f2feebfSReid Kleckner if should_print_progress: 375*b71edfaaSTobias Hieta print("Rendering HTML files...") 376*b71edfaaSTobias Hieta optpmap.pmap( 377*b71edfaaSTobias Hieta _render_file_bound, file_remarks.items(), num_jobs, should_print_progress 378*b71edfaaSTobias Hieta ) 3792f2feebfSReid Kleckner 3802f2feebfSReid Kleckner 3812f2feebfSReid Klecknerdef main(): 3822f2feebfSReid Kleckner parser = argparse.ArgumentParser(description=desc) 3832f2feebfSReid Kleckner parser.add_argument( 384*b71edfaaSTobias Hieta "yaml_dirs_or_files", 385*b71edfaaSTobias Hieta nargs="+", 386*b71edfaaSTobias Hieta help="List of optimization record files or directories searched " 387*b71edfaaSTobias Hieta "for optimization record files.", 388*b71edfaaSTobias Hieta ) 3892f2feebfSReid Kleckner parser.add_argument( 390*b71edfaaSTobias Hieta "--output-dir", 391*b71edfaaSTobias Hieta "-o", 392*b71edfaaSTobias Hieta default="html", 393*b71edfaaSTobias Hieta help="Path to a directory where generated HTML files will be output. " 394*b71edfaaSTobias Hieta "If the directory does not already exist, it will be created. " 395*b71edfaaSTobias Hieta '"%(default)s" by default.', 396*b71edfaaSTobias Hieta ) 3972f2feebfSReid Kleckner parser.add_argument( 398*b71edfaaSTobias Hieta "--jobs", 399*b71edfaaSTobias Hieta "-j", 4002f2feebfSReid Kleckner default=None, 4012f2feebfSReid Kleckner type=int, 402*b71edfaaSTobias Hieta help="Max job count (defaults to %(default)s, the current CPU count)", 403*b71edfaaSTobias Hieta ) 404*b71edfaaSTobias Hieta parser.add_argument("--source-dir", "-s", default="", help="set source directory") 4052f2feebfSReid Kleckner parser.add_argument( 406*b71edfaaSTobias Hieta "--no-progress-indicator", 407*b71edfaaSTobias Hieta "-n", 408*b71edfaaSTobias Hieta action="store_true", 4092f2feebfSReid Kleckner default=False, 410*b71edfaaSTobias Hieta help="Do not display any indicator of how many YAML files were read " 411*b71edfaaSTobias Hieta "or rendered into HTML.", 412*b71edfaaSTobias Hieta ) 4132f2feebfSReid Kleckner parser.add_argument( 414*b71edfaaSTobias Hieta "--max-hottest-remarks-on-index", 4152f2feebfSReid Kleckner default=1000, 4162f2feebfSReid Kleckner type=int, 417*b71edfaaSTobias Hieta help="Maximum number of the hottest remarks to appear on the index page", 418*b71edfaaSTobias Hieta ) 4192f2feebfSReid Kleckner parser.add_argument( 420*b71edfaaSTobias Hieta "--no-highlight", 421*b71edfaaSTobias Hieta action="store_true", 4222f2feebfSReid Kleckner default=False, 423*b71edfaaSTobias Hieta help="Do not use a syntax highlighter when rendering the source code", 424*b71edfaaSTobias Hieta ) 4252f2feebfSReid Kleckner parser.add_argument( 426*b71edfaaSTobias Hieta "--demangler", 427*b71edfaaSTobias Hieta help="Set the demangler to be used (defaults to %s)" 428*b71edfaaSTobias Hieta % optrecord.Remark.default_demangler, 429*b71edfaaSTobias Hieta ) 4302f2feebfSReid Kleckner 4312f2feebfSReid Kleckner parser.add_argument( 432*b71edfaaSTobias Hieta "--filter", 433*b71edfaaSTobias Hieta default="", 434*b71edfaaSTobias Hieta help="Only display remarks from passes matching filter expression", 435*b71edfaaSTobias Hieta ) 4362f2feebfSReid Kleckner 4372f2feebfSReid Kleckner # Do not make this a global variable. Values needed to be propagated through 4382f2feebfSReid Kleckner # to individual classes and functions to be portable with multiprocessing across 4392f2feebfSReid Kleckner # Windows and non-Windows. 4402f2feebfSReid Kleckner args = parser.parse_args() 4412f2feebfSReid Kleckner 4422f2feebfSReid Kleckner print_progress = not args.no_progress_indicator 4432f2feebfSReid Kleckner if args.demangler: 4442f2feebfSReid Kleckner optrecord.Remark.set_demangler(args.demangler) 4452f2feebfSReid Kleckner 4462f2feebfSReid Kleckner files = optrecord.find_opt_files(*args.yaml_dirs_or_files) 4472f2feebfSReid Kleckner if not files: 4482f2feebfSReid Kleckner parser.error("No *.opt.yaml files found") 4492f2feebfSReid Kleckner sys.exit(1) 4502f2feebfSReid Kleckner 451*b71edfaaSTobias Hieta all_remarks, file_remarks, should_display_hotness = optrecord.gather_results( 452*b71edfaaSTobias Hieta files, args.jobs, print_progress, args.filter 453*b71edfaaSTobias Hieta ) 4542f2feebfSReid Kleckner 4552f2feebfSReid Kleckner map_remarks(all_remarks) 4562f2feebfSReid Kleckner 457*b71edfaaSTobias Hieta generate_report( 458*b71edfaaSTobias Hieta all_remarks, 4592f2feebfSReid Kleckner file_remarks, 4602f2feebfSReid Kleckner args.source_dir, 4612f2feebfSReid Kleckner args.output_dir, 4622f2feebfSReid Kleckner args.no_highlight, 4632f2feebfSReid Kleckner should_display_hotness, 4642f2feebfSReid Kleckner args.max_hottest_remarks_on_index, 4652f2feebfSReid Kleckner args.jobs, 466*b71edfaaSTobias Hieta print_progress, 467*b71edfaaSTobias Hieta ) 4682f2feebfSReid Kleckner 469*b71edfaaSTobias Hieta 470*b71edfaaSTobias Hietaif __name__ == "__main__": 4712f2feebfSReid Kleckner main() 472