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 |