Chromium Code Reviews| Index: szdiff.py |
| diff --git a/szdiff.py b/szdiff.py |
| new file mode 100755 |
| index 0000000000000000000000000000000000000000..247e1e070b278b6976e5a902cb88b0204ab27e60 |
| --- /dev/null |
| +++ b/szdiff.py |
| @@ -0,0 +1,80 @@ |
| +#!/usr/bin/env python2 |
| + |
| +import argparse |
| +import itertools |
| +import subprocess |
| +import re |
| + |
| +if __name__ == '__main__': |
| + """Runs llvm2ice on an input .ll file, and compares the output |
| + against the input. |
| + |
| + Before comparing, the input file is massaged to remove comments, |
| + blank lines, global variable definitions, external function |
| + declarations, and possibly other patterns that llvm2ice does not |
| + handle. |
| + |
| + The output file and the massaged input file are compared line by |
| + line for differences. However, there is a regex defined such that |
| + if the regex matches a line in the input file, that line and the |
| + corresponding line in the output file are ignored. This lets us |
| + ignore minor differences such as inttoptr and ptrtoint, and |
| + printing of floating-point constants. |
| + |
| + On success, no output is produced. On failure, each mismatch is |
| + printed as two lines, one starting with 'SZ' and one starting with |
| + 'LL'. |
| + """ |
| + desc = 'Compare llvm2ice output against bitcode input.' |
| + argparser = argparse.ArgumentParser(description=desc) |
| + argparser.add_argument( |
| + 'llfile', nargs='?', default='-', |
| + type=argparse.FileType('r'), metavar='FILE', |
| + help='Textual bitcode file [default stdin]') |
| + argparser.add_argument( |
| + '--llvm2ice', required=False, default='./llvm2ice', metavar='LLVM2ICE', |
| + help='Path to llvm2ice driver program [default ./llvm2ice]') |
| + args = argparser.parse_args() |
| + bitcode = args.llfile.readlines() |
| + |
| + # Run llvm2ice and collect its output lines into sz_out. |
| + command = [args.llvm2ice, '-verbose', 'inst', '-notranslate', '-'] |
| + p = subprocess.Popen(command, stdin=subprocess.PIPE, stdout=subprocess.PIPE) |
| + sz_out = p.communicate(input=''.join(bitcode))[0].splitlines() |
| + |
| + # Filter certain lines and patterns from the input, and collect |
| + # the remainder into llc_out. |
| + llc_out = [] |
| + trailing_comment = re.compile(';.*') |
| + trailing_space = re.compile(' *$') |
| + ignore_pattern = re.compile('^ *$|^declare|^@') |
| + for line in bitcode: |
| + line = line.rstrip() |
| + # Remove trailing comments. |
| + line = trailing_comment.sub('', line) |
| + # Remove trailing spaces. |
| + line = trailing_space.sub('', line) |
|
JF
2014/03/23 00:03:15
Another rstrip would be better.
Jim Stichnoth
2014/03/24 13:18:53
Done. (I misunderstood what exactly rstrip does.)
|
| + # Ignore blanks lines, forward declarations, and variable definitions. |
| + if not ignore_pattern.search(line): |
| + llc_out.append(line) |
| + |
| + # Compare sz_out and llc_out line by line, but ignore pairs of |
| + # lines where the llc line matches a certain pattern. |
| + return_code = 0 |
| + ignore_pattern = re.compile( |
| + '|'.join([' -[0-9]+', # negative constants |
| + 'float [-0-9]', # FP constants |
|
JF
2014/03/23 00:03:15
Is that really what FP constants look like? Single
Jim Stichnoth
2014/03/24 13:18:53
We're doing regex golf, right? The first characte
|
| + 'inttoptr', # inttoptr pointer types |
| + 'ptrtoint' # ptrtoint pointer types |
| + ])) |
| + for (sz_line, llc_line) in itertools.izip_longest(sz_out, llc_out): |
| + if llc_line and ignore_pattern.search(llc_line): |
| + continue |
| + if sz_line == llc_line: |
| + continue |
| + if sz_line: print 'SZ>' + sz_line |
| + if llc_line: print 'LL>' + llc_line |
| + return_code = 1 |
| + |
| + if return_code == 0: print 'Success' |
| + exit(return_code) |