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 ignore_pattern = re.compile('^ *$|^declare|^@') |
| 50 for line in bitcode: |
| 51 # Remove trailing comments and spaces. |
| 52 line = trailing_comment.sub('', line).rstrip() |
| 53 # Ignore blanks lines, forward declarations, and variable definitions. |
| 54 if not ignore_pattern.search(line): |
| 55 llc_out.append(line) |
| 56 |
| 57 # Compare sz_out and llc_out line by line, but ignore pairs of |
| 58 # lines where the llc line matches a certain pattern. |
| 59 return_code = 0 |
| 60 lines_total = 0 |
| 61 lines_diff = 0 |
| 62 ignore_pattern = re.compile( |
| 63 '|'.join([' -[0-9]', # negative constants |
| 64 ' (float|double) [-0-9]', # FP constants |
| 65 ' inttoptr ', # inttoptr pointer types |
| 66 ' ptrtoint ' # ptrtoint pointer types |
| 67 ])) |
| 68 for (sz_line, llc_line) in itertools.izip_longest(sz_out, llc_out): |
| 69 lines_total += 1 |
| 70 if sz_line == llc_line: |
| 71 continue |
| 72 if llc_line and ignore_pattern.search(llc_line): |
| 73 lines_diff += 1 |
| 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: |
| 80 message = 'Success (ignored %d diffs out of %d lines)' |
| 81 print message % (lines_diff, lines_total) |
| 82 exit(return_code) |
OLD | NEW |