OLD | NEW |
---|---|
(Empty) | |
1 #!/usr/bin/env python2 | |
2 | |
3 import argparse | |
4 import os, sys | |
jvoung (off chromium)
2014/05/15 23:47:34
one import per line, and sort?
http://google-styl
Jim Stichnoth
2014/05/17 14:14:32
Done.
| |
5 import re | |
6 import subprocess | |
7 import tempfile | |
8 | |
9 sys.path.insert(0, '../pydir') | |
10 from utils import shellcmd | |
11 | |
12 if __name__ == '__main__': | |
13 """Builds a cross-test binary that allows functions translated by | |
14 Subzero and llc to be compared. | |
15 | |
16 Each --test argument is compiled once by llc and once by Subzero. | |
17 C/C++ tests are first compiled down to PNaCl bitcode by the | |
18 build-pnacl-ir.py script. The --prefix argument ensures that | |
19 symbol names are different between the two object files, to avoid | |
20 linking errors. | |
21 | |
22 There is also a --driver argument that specifies the C/C++ file | |
23 that calls the test functions with a variety of interesting inputs | |
24 and compares their results. | |
25 """ | |
26 # arch_map maps a Subzero target string to an llvm-mc -arch string. | |
27 arch_map = { 'x8632':'x86', 'x8664':'x86-64', 'arm':'arm' } | |
28 desc = 'Build a cross-test that compares Subzero and llc translation.' | |
29 argparser = argparse.ArgumentParser(description=desc) | |
30 argparser.add_argument('--test', required=True, action='append', | |
31 metavar='TESTFILE_LIST', | |
32 help='List of C/C++/.ll files with test functions') | |
33 argparser.add_argument('--driver', required=True, | |
34 metavar='DRIVER', | |
35 help='Driver program') | |
36 argparser.add_argument('--target', required=False, default='x8632', | |
37 choices=arch_map.keys(), | |
38 metavar='TARGET', | |
39 help='Translation target architecture') | |
40 argparser.add_argument('-O', required=False, default='2', dest='optlevel', | |
41 choices=['m1', '-1', '0', '1', '2'], | |
42 metavar='OPTLEVEL', | |
43 help='Optimization level ' + | |
44 '(m1 and -1 are equivalent)') | |
45 argparser.add_argument('--prefix', required=True, | |
46 metavar='SZ_PREFIX', | |
47 help='String prepended to Subzero symbol names') | |
48 argparser.add_argument('--output', '-o', required=True, | |
49 metavar='EXECUTABLE', | |
50 help='Executable to produce') | |
51 argparser.add_argument('--dir', required=False, default='.', | |
52 metavar='OUTPUT_DIR', | |
53 help='Output directory for all files') | |
54 argparser.add_argument('--llvm-bin-path', required=False, | |
55 default=os.environ.get('LLVM_BIN_PATH'), | |
56 metavar='PATH', | |
57 help='Path to LLVM executables like llc ' + | |
58 '(defaults to $LLVM_BIN_PATH)') | |
59 args = argparser.parse_args() | |
60 | |
61 objs = [] | |
62 remove_internal = re.compile('^define internal ') | |
63 fix_target = re.compile('le32-unknown-nacl') | |
64 llvm_bin_path = args.llvm_bin_path | |
65 for arg in args.test: | |
66 base, ext = os.path.splitext(arg) | |
67 if ext == '.ll': | |
68 bitcode = arg | |
69 else: | |
70 bitcode = os.path.join(args.dir, base + '.pnacl.ll') | |
71 shellcmd(['../pydir/build-pnacl-ir.py', '--disable-verify', | |
72 '--dir', args.dir, arg]) | |
73 # Read in the bitcode file, fix it up, and rewrite the file. | |
74 f = open(bitcode) | |
75 ll_lines = f.readlines() | |
76 f.close() | |
77 f = open(bitcode, 'w') | |
78 for line in ll_lines: | |
79 line = remove_internal.sub('define ', line) | |
80 line = fix_target.sub('i686-pc-linux-gnu', line) | |
81 f.write(line) | |
82 f.close() | |
83 | |
84 asm_sz = os.path.join(args.dir, base + '.sz.s') | |
85 obj_sz = os.path.join(args.dir, base + '.sz.o') | |
86 obj_llc = os.path.join(args.dir, base + '.llc.o') | |
87 shellcmd(['../llvm2ice', | |
88 '-O' + args.optlevel, | |
89 '--target=' + args.target, | |
90 '--prefix=' + args.prefix, | |
91 '-o=' + asm_sz, | |
92 bitcode]) | |
93 shellcmd([os.path.join(llvm_bin_path, 'llvm-mc'), | |
94 '-arch=' + arch_map[args.target], | |
95 '-x86-asm-syntax=intel', | |
96 '-filetype=obj', | |
97 '-o=' + obj_sz, | |
98 asm_sz]) | |
99 objs.append(obj_sz) | |
100 # Each original bitcode file needs to be translated by the | |
101 # LLVM toolchain and have its object file linked in. There | |
102 # are two ways to do this: explicitly use llc, or include the | |
103 # .ll file in the link command. It turns out that these two | |
104 # approaches can produce different semantics on some undefined | |
105 # bitcode behavior. Specifically, LLVM produces different | |
106 # results for overflowing fptoui instructions for i32 and i64 | |
107 # on x86-32. As it turns out, Subzero lowering was based on | |
108 # inspecting the object code produced by the direct llc | |
109 # command, so we need to directly run llc on the bitcode, even | |
110 # though it makes this script longer, to avoid spurious | |
111 # failures. This behavior can be inspected by switching | |
112 # use_llc between True and False. | |
113 use_llc = False | |
114 if use_llc: | |
115 shellcmd([os.path.join(llvm_bin_path, 'llc'), | |
116 '-filetype=obj', | |
117 '-o=' + obj_llc, | |
118 bitcode]) | |
119 objs.append(obj_llc) | |
120 else: | |
121 objs.append(bitcode) | |
122 | |
123 linker = 'clang' if os.path.splitext(args.driver)[1] == '.c' else 'clang++' | |
124 shellcmd([os.path.join(llvm_bin_path, linker), '-g', '-m32', args.driver] + | |
125 objs + | |
126 ['-lm', '-o', os.path.join(args.dir, args.output)]) | |
OLD | NEW |