Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 #!/usr/bin/env python2 | |
| 2 | |
| 3 import argparse | |
| 4 import itertools | |
| 5 import subprocess | |
| 6 import re | |
| 7 | |
| 8 if __name__ == '__main__': | |
| 9 """Runs llvm2ice on an input .ll file, and compares the output | |
| 10 against the input. | |
| 11 | |
| 12 Before comparing, the input file is massaged to remove comments, | |
| 13 blank lines, global variable definitions, external function | |
| 14 declarations, and possibly other patterns that llvm2ice does not | |
| 15 handle. | |
| 16 | |
| 17 The output file and the massaged input file are compared line by | |
| 18 line for differences. However, there is a regex defined such that | |
| 19 if the regex matches a line in the input file, that line and the | |
| 20 corresponding line in the output file are ignored. This lets us | |
| 21 ignore minor differences such as inttoptr and ptrtoint, and | |
| 22 printing of floating-point constants. | |
| 23 | |
| 24 On success, no output is produced. On failure, each mismatch is | |
| 25 printed as two lines, one starting with 'SZ' and one starting with | |
| 26 'LL'. | |
| 27 """ | |
| 28 desc = 'Compare llvm2ice output against bitcode input.' | |
| 29 argparser = argparse.ArgumentParser(description=desc) | |
| 30 argparser.add_argument( | |
| 31 'llfile', nargs='?', default='-', | |
| 32 type=argparse.FileType('r'), metavar='FILE', | |
| 33 help='Textual bitcode file [default stdin]') | |
| 34 argparser.add_argument( | |
| 35 '--llvm2ice', required=False, default='./llvm2ice', metavar='LLVM2ICE', | |
| 36 help='Path to llvm2ice driver program [default ./llvm2ice]') | |
| 37 args = argparser.parse_args() | |
| 38 bitcode = args.llfile.readlines() | |
| 39 | |
| 40 # Run llvm2ice and collect its output lines into sz_out. | |
| 41 command = [args.llvm2ice, '-verbose', 'inst', '-notranslate', '-'] | |
| 42 p = subprocess.Popen(command, stdin=subprocess.PIPE, stdout=subprocess.PIPE) | |
| 43 sz_out = p.communicate(input=''.join(bitcode))[0].splitlines() | |
| 44 | |
| 45 # Filter certain lines and patterns from the input, and collect | |
| 46 # the remainder into llc_out. | |
| 47 llc_out = [] | |
| 48 trailing_comment = re.compile(';.*') | |
| 49 trailing_space = re.compile(' *$') | |
| 50 ignore_pattern = re.compile('^ *$|^declare|^@') | |
| 51 for line in bitcode: | |
| 52 line = line.rstrip() | |
| 53 # Remove trailing comments. | |
| 54 line = trailing_comment.sub('', line) | |
| 55 # Remove trailing spaces. | |
| 56 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.)
| |
| 57 # Ignore blanks lines, forward declarations, and variable definitions. | |
| 58 if not ignore_pattern.search(line): | |
| 59 llc_out.append(line) | |
| 60 | |
| 61 # Compare sz_out and llc_out line by line, but ignore pairs of | |
| 62 # lines where the llc line matches a certain pattern. | |
| 63 return_code = 0 | |
| 64 ignore_pattern = re.compile( | |
| 65 '|'.join([' -[0-9]+', # negative constants | |
| 66 '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
| |
| 67 'inttoptr', # inttoptr pointer types | |
| 68 'ptrtoint' # ptrtoint pointer types | |
| 69 ])) | |
| 70 for (sz_line, llc_line) in itertools.izip_longest(sz_out, llc_out): | |
| 71 if llc_line and ignore_pattern.search(llc_line): | |
| 72 continue | |
| 73 if sz_line == llc_line: | |
| 74 continue | |
| 75 if sz_line: print 'SZ>' + sz_line | |
| 76 if llc_line: print 'LL>' + llc_line | |
| 77 return_code = 1 | |
| 78 | |
| 79 if return_code == 0: print 'Success' | |
| 80 exit(return_code) | |
| OLD | NEW |