summaryrefslogtreecommitdiff
path: root/utils/opt-viewer/opt-viewer.py
diff options
context:
space:
mode:
Diffstat (limited to 'utils/opt-viewer/opt-viewer.py')
-rwxr-xr-xutils/opt-viewer/opt-viewer.py259
1 files changed, 0 insertions, 259 deletions
diff --git a/utils/opt-viewer/opt-viewer.py b/utils/opt-viewer/opt-viewer.py
deleted file mode 100755
index 5e5daf7feb0d..000000000000
--- a/utils/opt-viewer/opt-viewer.py
+++ /dev/null
@@ -1,259 +0,0 @@
-#!/usr/bin/env python2.7
-
-from __future__ import print_function
-
-import argparse
-import cgi
-import errno
-import functools
-from multiprocessing import cpu_count
-import os.path
-import re
-import shutil
-
-from pygments import highlight
-from pygments.lexers.c_cpp import CppLexer
-from pygments.formatters import HtmlFormatter
-
-import optpmap
-import optrecord
-
-
-desc = '''Generate HTML output to visualize optimization records from the YAML files
-generated with -fsave-optimization-record and -fdiagnostics-show-hotness.
-
-The tools requires PyYAML and Pygments Python packages.'''
-
-
-# This allows passing the global context to the child processes.
-class Context:
- def __init__(self, caller_loc = dict()):
- # Map function names to their source location for function where inlining happened
- self.caller_loc = caller_loc
-
-context = Context()
-
-class SourceFileRenderer:
- def __init__(self, source_dir, output_dir, filename):
- existing_filename = None
- if os.path.exists(filename):
- existing_filename = filename
- else:
- fn = os.path.join(source_dir, filename)
- if os.path.exists(fn):
- existing_filename = fn
-
- self.stream = open(os.path.join(output_dir, optrecord.html_file_name(filename)), 'w')
- if existing_filename:
- self.source_stream = open(existing_filename)
- else:
- self.source_stream = None
- print('''
-<html>
-<h1>Unable to locate file {}</h1>
-</html>
- '''.format(filename), file=self.stream)
-
- self.html_formatter = HtmlFormatter(encoding='utf-8')
- self.cpp_lexer = CppLexer(stripnl=False)
-
- def render_source_lines(self, stream, line_remarks):
- file_text = stream.read()
- html_highlighted = highlight(file_text, self.cpp_lexer, self.html_formatter)
-
- # Take off the header and footer, these must be
- # reapplied line-wise, within the page structure
- html_highlighted = html_highlighted.replace('<div class="highlight"><pre>', '')
- html_highlighted = html_highlighted.replace('</pre></div>', '')
-
- for (linenum, html_line) in enumerate(html_highlighted.split('\n'), start=1):
- print('''
-<tr>
-<td><a name=\"L{linenum}\">{linenum}</a></td>
-<td></td>
-<td></td>
-<td><div class="highlight"><pre>{html_line}</pre></div></td>
-</tr>'''.format(**locals()), file=self.stream)
-
- for remark in line_remarks.get(linenum, []):
- self.render_inline_remarks(remark, html_line)
-
- def render_inline_remarks(self, r, line):
- inlining_context = r.DemangledFunctionName
- dl = context.caller_loc.get(r.Function)
- if dl:
- link = optrecord.make_link(dl['File'], dl['Line'] - 2)
- inlining_context = "<a href={link}>{r.DemangledFunctionName}</a>".format(**locals())
-
- # Column is the number of characters *including* tabs, keep those and
- # replace everything else with spaces.
- indent = line[:max(r.Column, 1) - 1]
- indent = re.sub('\S', ' ', indent)
-
- print('''
-<tr>
-<td></td>
-<td>{r.RelativeHotness}</td>
-<td class=\"column-entry-{r.color}\">{r.PassWithDiffPrefix}</td>
-<td><pre style="display:inline">{indent}</pre><span class=\"column-entry-yellow\"> {r.message}&nbsp;</span></td>
-<td class=\"column-entry-yellow\">{inlining_context}</td>
-</tr>'''.format(**locals()), file=self.stream)
-
- def render(self, line_remarks):
- if not self.source_stream:
- return
-
- print('''
-<html>
-<head>
-<link rel='stylesheet' type='text/css' href='style.css'>
-</head>
-<body>
-<div class="centered">
-<table>
-<tr>
-<td>Line</td>
-<td>Hotness</td>
-<td>Optimization</td>
-<td>Source</td>
-<td>Inline Context</td>
-</tr>''', file=self.stream)
- self.render_source_lines(self.source_stream, line_remarks)
-
- print('''
-</table>
-</body>
-</html>''', file=self.stream)
-
-
-class IndexRenderer:
- def __init__(self, output_dir):
- self.stream = open(os.path.join(output_dir, 'index.html'), 'w')
-
- def render_entry(self, r, odd):
- escaped_name = cgi.escape(r.DemangledFunctionName)
- print('''
-<tr>
-<td class=\"column-entry-{odd}\"><a href={r.Link}>{r.DebugLocString}</a></td>
-<td class=\"column-entry-{odd}\">{r.RelativeHotness}</td>
-<td class=\"column-entry-{odd}\">{escaped_name}</td>
-<td class=\"column-entry-{r.color}\">{r.PassWithDiffPrefix}</td>
-</tr>'''.format(**locals()), file=self.stream)
-
- def render(self, all_remarks):
- print('''
-<html>
-<head>
-<link rel='stylesheet' type='text/css' href='style.css'>
-</head>
-<body>
-<div class="centered">
-<table>
-<tr>
-<td>Source Location</td>
-<td>Hotness</td>
-<td>Function</td>
-<td>Pass</td>
-</tr>''', file=self.stream)
- for i, remark in enumerate(all_remarks):
- self.render_entry(remark, i % 2)
- print('''
-</table>
-</body>
-</html>''', file=self.stream)
-
-
-def _render_file(source_dir, output_dir, ctx, entry):
- global context
- context = ctx
- filename, remarks = entry
- SourceFileRenderer(source_dir, output_dir, filename).render(remarks)
-
-
-def map_remarks(all_remarks):
- # Set up a map between function names and their source location for
- # function where inlining happened
- for remark in optrecord.itervalues(all_remarks):
- if isinstance(remark, optrecord.Passed) and remark.Pass == "inline" and remark.Name == "Inlined":
- for arg in remark.Args:
- caller = arg.get('Caller')
- if caller:
- context.caller_loc[caller] = arg['DebugLoc']
-
-
-def generate_report(all_remarks,
- file_remarks,
- source_dir,
- output_dir,
- should_display_hotness,
- num_jobs,
- should_print_progress):
- try:
- os.makedirs(output_dir)
- except OSError as e:
- if e.errno == errno.EEXIST and os.path.isdir(output_dir):
- pass
- else:
- raise
-
- _render_file_bound = functools.partial(_render_file, source_dir, output_dir, context)
- if should_print_progress:
- print('Rendering HTML files...')
- optpmap.pmap(_render_file_bound,
- file_remarks.items(),
- num_jobs,
- should_print_progress)
-
- if should_display_hotness:
- sorted_remarks = sorted(optrecord.itervalues(all_remarks), key=lambda r: (r.Hotness, r.File, r.Line, r.Column, r.PassWithDiffPrefix, r.yaml_tag, r.Function), reverse=True)
- else:
- sorted_remarks = sorted(optrecord.itervalues(all_remarks), key=lambda r: (r.File, r.Line, r.Column, r.PassWithDiffPrefix, r.yaml_tag, r.Function))
- IndexRenderer(args.output_dir).render(sorted_remarks)
-
- shutil.copy(os.path.join(os.path.dirname(os.path.realpath(__file__)),
- "style.css"), output_dir)
-
-
-if __name__ == '__main__':
- parser = argparse.ArgumentParser(description=desc)
- parser.add_argument('yaml_files', nargs='+')
- parser.add_argument(
- '--output-dir',
- '-o',
- default='html',
- help='Path to a directory where generated HTML files will be output. '
- 'If the directory does not already exist, it will be created. '
- '"%(default)s" by default.')
- parser.add_argument(
- '--jobs',
- '-j',
- default=cpu_count(),
- type=int,
- help='Max job count (defaults to %(default)s, the current CPU count)')
- parser.add_argument(
- '-source-dir',
- '-s',
- default='',
- help='set source directory')
- parser.add_argument(
- '--no-progress-indicator',
- '-n',
- action='store_true',
- default=False,
- help='Do not display any indicator of how many YAML files were read '
- 'or rendered into HTML.')
- args = parser.parse_args()
-
- print_progress = not args.no_progress_indicator
- all_remarks, file_remarks, should_display_hotness = \
- optrecord.gather_results(args.yaml_files, args.jobs, print_progress)
-
- map_remarks(all_remarks)
-
- generate_report(all_remarks,
- file_remarks,
- args.source_dir,
- args.output_dir,
- should_display_hotness,
- args.jobs,
- print_progress)