OLD | NEW |
1 #!/usr/bin/env python2 | 1 #!/usr/bin/env python2 |
2 | 2 |
3 import argparse | 3 import argparse |
4 import os | 4 import os |
5 import subprocess | 5 import subprocess |
6 import sys | 6 import sys |
7 import tempfile | 7 import tempfile |
8 | 8 |
9 import targets | 9 import targets |
10 from utils import shellcmd | 10 from szbuild import LinkNonsfi |
11 from utils import FindBaseNaCl | 11 from utils import shellcmd, FindBaseNaCl, get_sfi_string |
12 | 12 |
13 def main(): | 13 def main(): |
14 """Builds a cross-test binary for comparing Subzero and llc translation. | 14 """Builds a cross-test binary for comparing Subzero and llc translation. |
15 | 15 |
16 Each --test argument is compiled once by llc and once by Subzero. C/C++ | 16 Each --test argument is compiled once by llc and once by Subzero. C/C++ |
17 tests are first compiled down to PNaCl bitcode using pnacl-clang and | 17 tests are first compiled down to PNaCl bitcode using pnacl-clang and |
18 pnacl-opt. The --prefix argument ensures that symbol names are different | 18 pnacl-opt. The --prefix argument ensures that symbol names are different |
19 between the two object files, to avoid linking errors. | 19 between the two object files, to avoid linking errors. |
20 | 20 |
21 There is also a --driver argument that specifies the C/C++ file that calls | 21 There is also a --driver argument that specifies the C/C++ file that calls |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
67 argparser.add_argument('--clang-opt', required=False, default=True, | 67 argparser.add_argument('--clang-opt', required=False, default=True, |
68 dest='clang_opt') | 68 dest='clang_opt') |
69 argparser.add_argument('--mattr', required=False, default='sse2', | 69 argparser.add_argument('--mattr', required=False, default='sse2', |
70 dest='attr', choices=['sse2', 'sse4.1', | 70 dest='attr', choices=['sse2', 'sse4.1', |
71 'neon', 'hwdiv-arm'], | 71 'neon', 'hwdiv-arm'], |
72 metavar='ATTRIBUTE', | 72 metavar='ATTRIBUTE', |
73 help='Target attribute. Default %(default)s.') | 73 help='Target attribute. Default %(default)s.') |
74 argparser.add_argument('--sandbox', required=False, default=0, type=int, | 74 argparser.add_argument('--sandbox', required=False, default=0, type=int, |
75 dest='sandbox', | 75 dest='sandbox', |
76 help='Use sandboxing. Default "%(default)s".') | 76 help='Use sandboxing. Default "%(default)s".') |
| 77 argparser.add_argument('--nonsfi', required=False, default=0, type=int, |
| 78 dest='nonsfi', |
| 79 help='Use Non-SFI mode. Default "%(default)s".') |
77 argparser.add_argument('--prefix', required=True, | 80 argparser.add_argument('--prefix', required=True, |
78 metavar='SZ_PREFIX', | 81 metavar='SZ_PREFIX', |
79 help='String prepended to Subzero symbol names') | 82 help='String prepended to Subzero symbol names') |
80 argparser.add_argument('--output', '-o', required=True, | 83 argparser.add_argument('--output', '-o', required=True, |
81 metavar='EXECUTABLE', | 84 metavar='EXECUTABLE', |
82 help='Executable to produce') | 85 help='Executable to produce') |
83 argparser.add_argument('--dir', required=False, default='.', | 86 argparser.add_argument('--dir', required=False, default='.', |
84 metavar='OUTPUT_DIR', | 87 metavar='OUTPUT_DIR', |
85 help='Output directory for all files.' + | 88 help='Output directory for all files.' + |
86 ' Default "%(default)s".') | 89 ' Default "%(default)s".') |
87 argparser.add_argument('--crosstest-bitcode', required=False, | |
88 default=1, type=int, | |
89 help='Compile non-subzero crosstest object file ' + | |
90 'from the same bitcode as the subzero object. ' + | |
91 'If 0, then compile it straight from source.' + | |
92 ' Default %(default)d.') | |
93 argparser.add_argument('--filetype', default='obj', dest='filetype', | 90 argparser.add_argument('--filetype', default='obj', dest='filetype', |
94 choices=['obj', 'asm', 'iasm'], | 91 choices=['obj', 'asm', 'iasm'], |
95 help='Output file type. Default %(default)s.') | 92 help='Output file type. Default %(default)s.') |
96 argparser.add_argument('--sz', dest='sz_args', action='append', default=[], | 93 argparser.add_argument('--sz', dest='sz_args', action='append', default=[], |
97 help='Extra arguments to pass to pnacl-sz.') | 94 help='Extra arguments to pass to pnacl-sz.') |
98 args = argparser.parse_args() | 95 args = argparser.parse_args() |
99 | 96 |
100 nacl_root = FindBaseNaCl() | 97 nacl_root = FindBaseNaCl() |
101 bindir = ('{root}/toolchain/linux_x86/pnacl_newlib_raw/bin' | 98 bindir = ('{root}/toolchain/linux_x86/pnacl_newlib_raw/bin' |
102 .format(root=nacl_root)) | 99 .format(root=nacl_root)) |
103 target_info = arch_map[args.target] | 100 target_info = arch_map[args.target] |
104 triple = target_info.triple | 101 triple = target_info.triple |
105 if args.sandbox: | 102 if args.sandbox: |
106 triple = targets.ConvertTripleToNaCl(triple) | 103 triple = targets.ConvertTripleToNaCl(triple) |
107 llc_flags = target_info.llc_flags + arch_llc_flags_extra[args.target] | 104 llc_flags = target_info.llc_flags + arch_llc_flags_extra[args.target] |
| 105 if args.nonsfi: |
| 106 llc_flags.extend(['-relocation-model=pic', |
| 107 '-malign-double', |
| 108 '-force-tls-non-pic', |
| 109 '-mtls-use-call']) |
108 mypath = os.path.abspath(os.path.dirname(sys.argv[0])) | 110 mypath = os.path.abspath(os.path.dirname(sys.argv[0])) |
109 | 111 |
| 112 # Construct a "unique key" for each test so that tests can be run in |
| 113 # parallel without race conditions on temporary file creation. |
| 114 key = '{sb}.O{opt}.{attr}.{target}'.format( |
| 115 target=args.target, |
| 116 sb=get_sfi_string(args, 'sb', 'nonsfi', 'nat'), |
| 117 opt=args.optlevel, attr=args.attr) |
110 objs = [] | 118 objs = [] |
111 for arg in args.test: | 119 for arg in args.test: |
112 # Construct a "unique key" for each test so that tests can be run in | |
113 # parallel without race conditions on temporary file creation. | |
114 key = '{target}.{sb}.O{opt}.{attr}'.format( | |
115 target=args.target, sb='sb' if args.sandbox else 'nat', | |
116 opt=args.optlevel, attr=args.attr) | |
117 base, ext = os.path.splitext(arg) | 120 base, ext = os.path.splitext(arg) |
118 if ext == '.ll': | 121 if ext == '.ll': |
119 bitcode = arg | 122 bitcode = arg |
120 else: | 123 else: |
121 # Use pnacl-clang and pnacl-opt to produce PNaCl bitcode. | 124 # Use pnacl-clang and pnacl-opt to produce PNaCl bitcode. |
122 bitcode_nonfinal = os.path.join(args.dir, base + '.' + key + '.bc') | 125 bitcode_nonfinal = os.path.join(args.dir, base + '.' + key + '.bc') |
123 bitcode = os.path.join(args.dir, base + '.' + key + '.pnacl.ll') | 126 bitcode = os.path.join(args.dir, base + '.' + key + '.pnacl.ll') |
124 shellcmd(['{bin}/pnacl-clang'.format(bin=bindir), | 127 shellcmd(['{bin}/pnacl-clang'.format(bin=bindir), |
125 ('-O2' if args.clang_opt else '-O0'), | 128 ('-O2' if args.clang_opt else '-O0'), |
| 129 get_sfi_string(args, '', '-DNONSFI', ''), |
126 ('-DARM32' if args.target == 'arm32' else ''), '-c', arg, | 130 ('-DARM32' if args.target == 'arm32' else ''), '-c', arg, |
127 '-o', bitcode_nonfinal]) | 131 '-o', bitcode_nonfinal]) |
128 shellcmd(['{bin}/pnacl-opt'.format(bin=bindir), | 132 shellcmd(['{bin}/pnacl-opt'.format(bin=bindir), |
129 '-pnacl-abi-simplify-preopt', | 133 '-pnacl-abi-simplify-preopt', |
130 '-pnacl-abi-simplify-postopt', | 134 '-pnacl-abi-simplify-postopt', |
131 '-pnaclabi-allow-debug-metadata', | 135 '-pnaclabi-allow-debug-metadata', |
| 136 '-strip-metadata', |
| 137 '-strip-module-flags', |
| 138 '-strip-debug', |
132 bitcode_nonfinal, '-S', '-o', bitcode]) | 139 bitcode_nonfinal, '-S', '-o', bitcode]) |
133 | 140 |
134 base_sz = '{base}.{key}'.format(base=base, key=key) | 141 base_sz = '{base}.{key}'.format(base=base, key=key) |
135 asm_sz = os.path.join(args.dir, base_sz + '.sz.s') | 142 asm_sz = os.path.join(args.dir, base_sz + '.sz.s') |
136 obj_sz = os.path.join(args.dir, base_sz + '.sz.o') | 143 obj_sz = os.path.join(args.dir, base_sz + '.sz.o') |
137 obj_llc = os.path.join(args.dir, base_sz + '.llc.o') | 144 obj_llc = os.path.join(args.dir, base_sz + '.llc.o') |
138 | 145 |
139 shellcmd(['{path}/pnacl-sz'.format(path=os.path.dirname(mypath)), | 146 shellcmd(['{path}/pnacl-sz'.format(path=os.path.dirname(mypath)), |
140 ] + args.sz_args + [ | 147 ] + args.sz_args + [ |
141 '-O' + args.optlevel, | 148 '-O' + args.optlevel, |
142 '-mattr=' + args.attr, | 149 '-mattr=' + args.attr, |
143 '--target=' + args.target, | 150 '--target=' + args.target, |
144 '--sandbox=' + str(args.sandbox), | 151 '--sandbox=' + str(args.sandbox), |
| 152 '--nonsfi=' + str(args.nonsfi), |
145 '--prefix=' + args.prefix, | 153 '--prefix=' + args.prefix, |
146 '-allow-uninitialized-globals', | 154 '-allow-uninitialized-globals', |
147 '-externalize', | 155 '-externalize', |
148 '-filetype=' + args.filetype, | 156 '-filetype=' + args.filetype, |
149 '-o=' + (obj_sz if args.filetype == 'obj' else asm_sz), | 157 '-o=' + (obj_sz if args.filetype == 'obj' else asm_sz), |
150 bitcode] + arch_sz_flags[args.target]) | 158 bitcode] + arch_sz_flags[args.target]) |
151 if args.filetype != 'obj': | 159 if args.filetype != 'obj': |
152 shellcmd(['{bin}/llvm-mc'.format(bin=bindir), | 160 shellcmd(['{bin}/llvm-mc'.format(bin=bindir), |
153 '-triple=' + triple, | 161 '-triple=' + triple, |
154 '-filetype=obj', | 162 '-filetype=obj', |
155 '-o=' + obj_sz, | 163 '-o=' + obj_sz, |
156 asm_sz]) | 164 asm_sz]) |
157 | 165 |
158 # Each separately translated Subzero object file contains its own | 166 # Each separately translated Subzero object file contains its own |
159 # definition of the __Sz_block_profile_info profiling symbol. Avoid | 167 # definition of the __Sz_block_profile_info profiling symbol. Avoid |
160 # linker errors (multiply defined symbol) by making all copies weak. | 168 # linker errors (multiply defined symbol) by making all copies weak. |
161 # (This could also be done by Subzero if it supported weak symbol | 169 # (This could also be done by Subzero if it supported weak symbol |
162 # definitions.) This approach should be OK because cross tests are | 170 # definitions.) This approach should be OK because cross tests are |
163 # currently the only situation where multiple translated files are | 171 # currently the only situation where multiple translated files are |
164 # linked into the executable, but when PNaCl supports shared nexe | 172 # linked into the executable, but when PNaCl supports shared nexe |
165 # libraries, this would need to change. | 173 # libraries, this would need to change. |
166 shellcmd(['{bin}/le32-nacl-objcopy'.format(bin=bindir), | 174 shellcmd(['{bin}/le32-nacl-objcopy'.format(bin=bindir), |
167 '--weaken-symbol=__Sz_block_profile_info', obj_sz]) | 175 '--weaken-symbol=__Sz_block_profile_info', |
| 176 '--strip-symbol=nacl_tp_tdb_offset', |
| 177 '--strip-symbol=nacl_tp_tls_offset', |
| 178 obj_sz]) |
168 objs.append(obj_sz) | 179 objs.append(obj_sz) |
169 if args.crosstest_bitcode: | 180 shellcmd(['{bin}/pnacl-llc'.format(bin=bindir), |
170 shellcmd(['{bin}/pnacl-llc'.format(bin=bindir), | 181 '-mtriple=' + triple, |
171 '-mtriple=' + triple, | 182 '-externalize', |
172 '-externalize', | 183 '-filetype=obj', |
173 '-filetype=obj', | 184 '-bitcode-format=llvm', |
174 '-o=' + obj_llc, | 185 '-o=' + obj_llc, |
175 bitcode] + llc_flags) | 186 bitcode] + llc_flags) |
176 objs.append(obj_llc) | 187 shellcmd(['{bin}/le32-nacl-objcopy'.format(bin=bindir), |
177 else: | 188 '--weaken-symbol=__Sz_block_profile_info', |
178 objs.append(arg) | 189 '--strip-symbol=nacl_tp_tdb_offset', |
| 190 '--strip-symbol=nacl_tp_tls_offset', |
| 191 obj_llc]) |
| 192 objs.append(obj_llc) |
179 | 193 |
180 # Add szrt_sb_${target}.o or szrt_native_${target}.o. | 194 # Add szrt_sb_${target}.o or szrt_native_${target}.o. |
181 objs.append(( | 195 if not args.nonsfi: |
182 '{root}/toolchain_build/src/subzero/build/runtime/' + | 196 objs.append(( |
183 'szrt_{sb}_' + args.target + '.o' | 197 '{root}/toolchain_build/src/subzero/build/runtime/' + |
184 ).format(root=nacl_root, sb='sb' if args.sandbox else 'native')) | 198 'szrt_{sb}_' + args.target + '.o' |
185 pure_c = os.path.splitext(args.driver)[1] == '.c' | 199 ).format(root=nacl_root, |
| 200 sb=get_sfi_string(args, 'sb', 'nonsfi', 'native'))) |
186 | 201 |
187 # TODO(jpp): clean up stack hack related code. | 202 # TODO(jpp): clean up stack hack related code. |
188 needs_stack_hack = False | 203 needs_stack_hack = False |
189 target_params = [] | 204 target_params = [] |
190 if needs_stack_hack: | 205 if needs_stack_hack: |
191 shellcmd('{bin}/clang -g -o stack_hack.x8664.{key}.o -c ' | 206 shellcmd('{bin}/clang -g -o stack_hack.x8664.{key}.o -c ' |
192 'stack_hack.x8664.c'.format(bin=bindir, key=key)) | 207 'stack_hack.x8664.c'.format(bin=bindir, key=key)) |
193 target_params.append('-DX8664_STACK_HACK') | 208 target_params.append('-DX8664_STACK_HACK') |
194 target_params.append('stack_hack.x8664.{key}.o'.format(key=key)) | 209 target_params.append('stack_hack.x8664.{key}.o'.format(key=key)) |
195 | 210 |
196 if args.target == 'arm32': | 211 if args.target == 'arm32': |
197 target_params.append('-DARM32') | 212 target_params.append('-DARM32') |
198 target_params.append('-static') | 213 target_params.append('-static') |
| 214 if args.nonsfi: |
| 215 target_params.append('-DNONSFI') |
199 | 216 |
200 # Set compiler to clang, clang++, pnacl-clang, or pnacl-clang++. | 217 pure_c = os.path.splitext(args.driver)[1] == '.c' |
| 218 if not args.nonsfi: |
| 219 # Set compiler to clang, clang++, pnacl-clang, or pnacl-clang++. |
| 220 compiler = '{bin}/{prefix}{cc}'.format( |
| 221 bin=bindir, prefix=get_sfi_string(args, 'pnacl-', '', ''), |
| 222 cc='clang' if pure_c else 'clang++') |
| 223 sb_native_args = (['-O0', '--pnacl-allow-native', |
| 224 '-arch', target_info.compiler_arch, |
| 225 '-Wn,-defsym=__Sz_AbsoluteZero=0'] |
| 226 if args.sandbox else |
| 227 ['-g', '-target=' + triple, |
| 228 '-lm', '-lpthread', |
| 229 '-Wl,--defsym=__Sz_AbsoluteZero=0'] + |
| 230 target_info.cross_headers) |
| 231 shellcmd([compiler] + target_params + [args.driver] + objs + |
| 232 ['-o', os.path.join(args.dir, args.output)] + sb_native_args) |
| 233 return 0 |
| 234 |
| 235 base, ext = os.path.splitext(args.driver) |
| 236 bitcode_nonfinal = os.path.join(args.dir, base + '.' + key + '.bc') |
| 237 bitcode = os.path.join(args.dir, base + '.' + key + '.pnacl.ll') |
| 238 asm_sz = os.path.join(args.dir, base + '.' + key + '.s') |
| 239 obj_llc = os.path.join(args.dir, base + '.' + key + '.o') |
201 compiler = '{bin}/{prefix}{cc}'.format( | 240 compiler = '{bin}/{prefix}{cc}'.format( |
202 bin=bindir, prefix='pnacl-' if args.sandbox else '', | 241 bin=bindir, prefix='pnacl-', |
203 cc='clang' if pure_c else 'clang++') | 242 cc='clang' if pure_c else 'clang++') |
204 sb_native_args = (['-O0', '--pnacl-allow-native', | 243 shellcmd([compiler, |
205 '-arch', target_info.compiler_arch, | 244 args.driver, |
206 '-Wn,-defsym=__Sz_AbsoluteZero=0'] | 245 '-DNONSFI' if args.nonsfi else '', |
207 if args.sandbox else | 246 '-O2', |
208 ['-g', '-target=' + triple, | 247 '-o', bitcode_nonfinal, |
209 '-lm', '-lpthread', | 248 '-Wl,-r' |
210 '-Wl,--defsym=__Sz_AbsoluteZero=0'] + | 249 ]) |
211 target_info.cross_headers) | 250 shellcmd(['{bin}/pnacl-opt'.format(bin=bindir), |
212 shellcmd([compiler] + target_params + [args.driver] + objs + | 251 '-pnacl-abi-simplify-preopt', |
213 ['-o', os.path.join(args.dir, args.output)] + sb_native_args) | 252 '-pnacl-abi-simplify-postopt', |
| 253 '-pnaclabi-allow-debug-metadata', |
| 254 '-strip-metadata', |
| 255 '-strip-module-flags', |
| 256 '-strip-debug', |
| 257 '-disable-opt', |
| 258 bitcode_nonfinal, '-S', '-o', bitcode]) |
| 259 shellcmd(['{bin}/pnacl-llc'.format(bin=bindir), |
| 260 '-mtriple=' + triple, |
| 261 '-externalize', |
| 262 '-filetype=obj', |
| 263 '-O2', |
| 264 '-bitcode-format=llvm', |
| 265 '-o', obj_llc, |
| 266 bitcode] + llc_flags) |
| 267 if not args.sandbox and not args.nonsfi: |
| 268 shellcmd(['{bin}/le32-nacl-objcopy'.format(bin=bindir), |
| 269 '--redefine-sym', '_start=_user_start', |
| 270 obj_llc |
| 271 ]) |
| 272 objs.append(obj_llc) |
| 273 if args.nonsfi: |
| 274 LinkNonsfi(objs, os.path.join(args.dir, args.output), args.target) |
| 275 elif args.sandbox: |
| 276 LinkSandbox(objs, os.path.join(args.dir, args.output), args.target) |
| 277 else: |
| 278 LinkNative(objs, os.path.join(args.dir, args.output), args.target) |
214 | 279 |
215 if __name__ == '__main__': | 280 if __name__ == '__main__': |
216 main() | 281 main() |
OLD | NEW |