2 # Copyright (c) 2012 The Native Client Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
11 from driver_env import env
12 from driver_log import Log
13 from driver_temps import TempFiles
19 'PIC': '${NONSFI_NACL || TRANSLATE_PSO ? 1 : 0}',
21 # Determine if we should build nexes compatible with the IRT
24 # Allow zero-cost C++ exception handling in the pexe, which is not
25 # supported by PNaCl's stable ABI.
26 'ALLOW_ZEROCOST_CXX_EH' : '0',
28 # Use the IRT shim by default. This can be disabled with an explicit
29 # flag (--noirtshim) or via -nostdlib.
32 # To simulate the sandboxed translator better and avoid user surprises,
33 # reject LLVM bitcode (non-finalized) by default, accepting only PNaCl
34 # (finalized) bitcode. --allow-llvm-bitcode-input has to be passed
35 # explicitly to override this.
36 'ALLOW_LLVM_BITCODE_INPUT': '0',
42 'USE_DEFAULTLIBS': '1',
43 'FAST_TRANSLATION': '0',
50 'LD_ARGS' : '${USE_STDLIB ? ${LD_ARGS_normal} : ${LD_ARGS_nostdlib}}',
52 # Note: we always require a shim now, but the dummy shim is not doing
54 # libpnacl_irt_shim.a is generated during the SDK packaging not
55 # during the toolchain build and there are hacks in pnacl/driver/ldtools.py
56 # and pnacl/driver/nativeld.py that will fall back to
57 # libpnacl_irt_shim_dummy.a if libpnacl_irt_shim.a does not exist.
58 'LD_ARGS_IRT_SHIM': '-l:libpnacl_irt_shim.a',
59 'LD_ARGS_IRT_SHIM_DUMMY': '-l:libpnacl_irt_shim_dummy.a',
60 # In addition to specifying the entry point, we also specify an undefined
61 # reference to _start, which is called by the shim's entry function,
62 # __pnacl_wrapper_start. _start normally comes from libnacl and will be in
63 # the pexe, however for the IRT it comes from irt_entry.c and when linking it
64 # using native object files, this reference is required to make sure it gets
65 # pulled in from the archive.
67 '${TRANSLATE_PSO ? --entry=__pnacl_pso_root : '
68 ' ${NONSFI_NACL && !USE_IRT '
69 ' ? --entry=__pnacl_start_linux : --entry=__pnacl_start} '
70 ' --undefined=_start}',
72 'CRTBEGIN': '${ALLOW_ZEROCOST_CXX_EH ? -l:crtbegin_for_eh.o : -l:crtbegin.o}',
73 'CRTEND': '-l:crtend.o',
75 'LD_ARGS_nostdlib': '-nostdlib ${ld_inputs}',
77 # These are just the dependencies in the native link.
79 '${!TRANSLATE_PSO ? ${CRTBEGIN}} ' +
81 '${USE_IRT_SHIM ? ${LD_ARGS_IRT_SHIM} : ${LD_ARGS_IRT_SHIM_DUMMY}} ' +
83 '${USE_DEFAULTLIBS ? ${DEFAULTLIBS}} ' +
87 'DEFAULTLIBS': '${ALLOW_ZEROCOST_CXX_EH ? -l:libgcc_eh.a} ' +
88 '-l:libgcc.a -l:libcrt_platform.a ',
90 # BE CAREFUL: anything added here can introduce skew between
91 # the pnacl-translate commandline tool and the in-browser translator.
92 # See: llvm/tools/pnacl-llc/srpc_main.cpp and
93 # chromium/src/ppapi/native_client/src/trusted/plugin/pnacl_options.cc
94 'LLC_FLAGS_COMMON': '${PIC ? -relocation-model=pic} ' +
95 # -force-tls-non-pic makes the code generator (llc)
96 # do the work that would otherwise be done by
97 # linker rewrites which are quite messy in the nacl
98 # case and hence have not been implemented in gold
99 '${PIC ? -force-tls-non-pic} ',
101 # LLC flags which set the target and output type.
102 'LLC_FLAGS_TARGET' : '-mtriple=${TRIPLE} -filetype=${outfiletype}',
104 # Append additional non-default flags here.
105 # BE CAREFUL: anything added here can introduce skew between
106 # the pnacl-translate commandline tool and the in-browser translator.
107 # See: llvm/tools/pnacl-llc/srpc_main.cpp and
108 # chromium/src/ppapi/native_client/src/trusted/plugin/pnacl_options.cc
109 'LLC_FLAGS_EXTRA' : '${FAST_TRANSLATION ? ${LLC_FLAGS_FAST}} ' +
110 '${#OPT_LEVEL ? -O${OPT_LEVEL}} ' +
111 '${OPT_LEVEL == 0 ? -disable-fp-elim}',
113 # Opt level from command line (if any)
116 # faster translation == slower code
117 'LLC_FLAGS_FAST' : '-O0'
118 # This, surprisingly, makes a measurable difference
119 ' -tail-merge-threshold=20',
121 'LLC_FLAGS': '${LLC_FLAGS_TARGET} ${LLC_FLAGS_COMMON} ${LLC_FLAGS_ARCH} ' +
122 '${LLC_FLAGS_EXTRA}',
124 # Note: this is only used in the unsandboxed case
125 'RUN_LLC' : '${LLVM_PNACL_LLC} ${LLC_FLAGS} ${LLC_MCPU} '
126 '${input} -o ${output} ',
127 # Whether to stream the bitcode from a single FD in unsandboxed mode
128 # (otherwise it will use concurrent file reads when using multithreaded module
130 'STREAM_BITCODE' : '1',
131 # Rate in bits/sec to stream the bitcode from sel_universal over SRPC
132 # for testing. Defaults to 1Gbps (effectively unlimited).
133 'BITCODE_STREAM_RATE' : '1000000000',
134 # Default to 0, which means unset by the user. In this cases the driver will
135 # use up to 4 modules if there are enough cores. If the user overrides,
136 # use as many modules as specified (which could be only 1).
137 'SPLIT_MODULE' : '0',
141 TranslatorPatterns = [
142 ( '-o(.+)', "env.set('OUTPUT', pathtools.normalize($0))"),
143 ( ('-o', '(.+)'), "env.set('OUTPUT', pathtools.normalize($0))"),
145 ( '-pso', "env.set('TRANSLATE_PSO', '1')"),
147 ( '-S', "env.set('OUTPUT_TYPE', 's')"), # Stop at .s
148 ( '-c', "env.set('OUTPUT_TYPE', 'o')"), # Stop at .o
150 # Expose a very limited set of llc flags.
151 # BE CAREFUL: anything added here can introduce skew between
152 # the pnacl-translate commandline tool and the in-browser translator.
153 # See: llvm/tools/pnacl-llc/srpc_main.cpp and
154 # chromium/src/ppapi/native_client/src/trusted/plugin/pnacl_options.cc
155 ( '(-sfi-.+)', "env.append('LLC_FLAGS_EXTRA', $0)"),
156 ( '(-mtls-use-call)', "env.append('LLC_FLAGS_EXTRA', $0)"),
157 # These flags are usually used for linktime dead code/data
158 # removal but also help with reloc overflows on ARM
159 ( '(-fdata-sections)', "env.append('LLC_FLAGS_EXTRA', $0)"),
160 ( '(-ffunction-sections)', "env.append('LLC_FLAGS_EXTRA', $0)"),
161 ( '(--gc-sections)', "env.append('LD_FLAGS', $0)"),
162 ( '(-mattr=.*)', "env.append('LLC_FLAGS_EXTRA', $0)"),
163 ( '(-mcpu=.*)', "env.set('LLC_MCPU', '')\n"
164 "env.append('LLC_FLAGS_EXTRA', $0)"),
165 ( '(-pnaclabi-verify=.*)', "env.append('LLC_FLAGS_EXTRA', $0)"),
166 ( '(-pnaclabi-verify-fatal-errors=.*)', "env.append('LLC_FLAGS_EXTRA', $0)"),
167 # Allow overriding the -O level.
168 ( '-O([0-3])', "env.set('OPT_LEVEL', $0)"),
170 # This adds arch specific flags to the llc invocation aimed at
171 # improving translation speed at the expense of code quality.
172 ( '-translate-fast', "env.set('FAST_TRANSLATION', '1')"),
174 ( '-nostdlib', "env.set('USE_STDLIB', '0')"),
176 # Disables the default libraries.
177 # This flag is needed for building libgcc_s.so.
178 ( '-nodefaultlibs', "env.set('USE_DEFAULTLIBS', '0')"),
180 ( '--noirt', "env.set('USE_IRT', '0')"),
181 ( '--noirtshim', "env.set('USE_IRT_SHIM', '0')"),
183 # Allowing zero-cost C++ exception handling causes a specific set of
184 # native objects to get linked into the nexe.
185 ( '--pnacl-allow-zerocost-eh', "env.set('ALLOW_ZEROCOST_CXX_EH', '1')"),
186 # TODO(mseaborn): Remove "--pnacl-allow-exceptions", replaced by
187 # "--pnacl-allow-zerocost-eh".
188 ( '--pnacl-allow-exceptions', "env.set('ALLOW_ZEROCOST_CXX_EH', '1')"),
190 ( '--allow-llvm-bitcode-input', "env.set('ALLOW_LLVM_BITCODE_INPUT', '1')"),
192 ( '-fPIC', "env.set('PIC', '1')"),
194 ( '(--build-id)', "env.append('LD_FLAGS', $0)"),
195 ( '-bitcode-stream-rate=([0-9]+)', "env.set('BITCODE_STREAM_RATE', $0)"),
196 ( '-split-module=([0-9]+)', "env.set('SPLIT_MODULE', $0)"),
197 ( '-no-stream-bitcode', "env.set('STREAM_BITCODE', '0')"),
199 # Treat general linker flags as inputs so they don't get re-ordered
200 ( '-Wl,(.*)', "env.append('INPUTS', *($0).split(','))"),
202 ( '(-.*)', driver_tools.UnrecognizedOption),
203 ( '(.*)', "env.append('INPUTS', pathtools.normalize($0))"),
208 base_arch = env.getone('BASE_ARCH')
209 env.set('TARGET_OS', 'nacl')
210 if base_arch.endswith('_LINUX'):
211 base_arch = base_arch[:-len('_LINUX')]
212 env.set('TARGET_OS', 'linux')
213 elif base_arch.endswith('_MAC'):
214 base_arch = base_arch[:-len('_MAC')]
215 env.set('TARGET_OS', 'mac')
217 if env.getbool('NONSFI_NACL'):
220 {'X8632': 'i686-linux-gnu',
221 'ARM': 'armv7a-linux-gnueabihf'}}
225 {'X8632': 'i686-none-nacl-gnu',
226 'X8664': 'x86_64-none-nacl-gnu',
227 'ARM': 'armv7a-none-nacl-gnueabihf',
228 'MIPS32': 'mipsel-none-nacl-gnu'},
229 'linux': {'X8632': 'i686-linux-gnu'},
230 'mac': {'X8632': 'i686-apple-darwin'}}
231 env.set('TRIPLE', triple_map[env.getone('TARGET_OS')][base_arch])
233 # CPU that is representative of baseline feature requirements for NaCl
234 # and/or chrome. We may want to make this more like "-mtune"
235 # by specifying both "-mcpu=X" and "-mattr=+feat1,-feat2,...".
236 # Note: this may be different from the in-browser translator, which may
237 # do auto feature detection based on CPUID, but constrained by what is
238 # accepted by NaCl validators.
240 'X8632': 'pentium4m',
243 'MIPS32': 'mips32r2'}
244 env.set('LLC_MCPU', '-mcpu=%s' % cpu_map[base_arch])
247 'ARM': ['-float-abi=hard', '-mattr=+neon'],
248 # Once PNaCl's build of compiler-rt (libgcc.a) defines __aeabi_*
249 # functions, we can drop the following ad-hoc option.
250 'ARM_NONSFI': ['-arm-enable-aeabi-functions=0'],
252 env.set('LLC_FLAGS_ARCH', *llc_flags_map.get(env.getone('ARCH'), []))
253 # When linking against a host OS's libc (such as Linux glibc), don't
254 # use %gs:0 to read the thread pointer because that won't be
255 # compatible with the libc's use of %gs:0. Similarly, Non-SFI Mode
256 # currently offers no optimized path for reading the thread pointer.
257 if env.getone('TARGET_OS') != 'nacl' or env.getbool('NONSFI_NACL'):
258 env.append('LLC_FLAGS_ARCH', '-mtls-use-call')
261 def SetUpLinkOptions():
262 if env.getbool('TRANSLATE_PSO'):
263 # Using "-pie" rather than "-shared" has the effect of suppressing the
264 # creation of a PLT and R_*_JUMP_SLOT relocations, which come from the
265 # external symbol references that multi-threaded translation produces.
266 env.append('LD_FLAGS', '-pie')
269 if env.getbool('NONSFI_NACL'):
270 # "_begin" allows a PIE to find its load address in order to apply
271 # dynamic relocations.
272 env.append('LD_FLAGS', '-defsym=_begin=0')
273 if env.getbool('USE_IRT'):
274 env.append('LD_FLAGS', '-pie')
276 # Note that we really want to use "-pie" for this case, but it
277 # currently adds a PT_INTERP header to the executable that we don't
278 # want because it stops the executable from being loadable by Linux.
279 # TODO(mseaborn): Add a linker option to omit PT_INTERP.
280 env.append('LD_FLAGS', '-static')
281 # Set _DYNAMIC to a dummy value. TODO(mseaborn): Remove this when we
282 # use "-pie" instead of "-static" for this case.
283 env.append('LD_FLAGS', '-defsym=_DYNAMIC=1')
285 env.append('LD_FLAGS', '-static')
286 # Give non-IRT builds 12MB of text before starting rodata instead of
287 # the larger default gap. The gap cannot be too small (e.g., 0) because
288 # sel_ldr requires space for adding a halt sled.
289 if not env.getbool('USE_IRT'):
290 env.append('LD_FLAGS', '--rosegment-gap=0xc00000')
294 env.update(EXTRA_ENV)
295 driver_tools.ParseArgs(argv, TranslatorPatterns)
296 driver_tools.GetArch(required = True)
300 inputs = env.get('INPUTS')
301 output = env.getone('OUTPUT')
304 Log.Fatal("No input files")
306 driver_tools.CheckPathLength(path)
309 Log.Fatal("Please specify output file with -o")
311 # Find the bitcode file on the command line.
312 bcfiles = [f for f in inputs
313 if not ldtools.IsFlag(f) and
314 (filetype.IsPNaClBitcode(f)
315 or filetype.IsLLVMBitcode(f)
316 or filetype.FileType(f) == 'll')]
318 Log.Fatal('Expecting at most 1 bitcode file')
319 elif len(bcfiles) == 1:
324 if not env.getbool('SPLIT_MODULE'):
326 env.set('SPLIT_MODULE', str(min(4, multiprocessing.cpu_count())))
327 except NotImplementedError:
328 env.set('SPLIT_MODULE', '2')
329 elif int(env.getone('SPLIT_MODULE')) < 1:
330 Log.Fatal('Value given for -split-module must be > 0')
331 if (env.getbool('ALLOW_LLVM_BITCODE_INPUT') or
332 env.getone('TARGET_OS') != 'nacl' or
333 env.getbool('USE_EMULATOR')):
334 # When llvm input is allowed, the pexe may not be ABI-stable, so do not
335 # split it. Non-ABI-stable pexes may have symbol naming and visibility
336 # issues that the current splitting scheme doesn't account for.
338 # For now, also do not enable multi-threaded translation when TARGET_OS !=
339 # 'nacl', since in these cases we will be using the host toolchain's
342 # The x86->arm emulator is very flaky when threading is used, so don't
343 # do module splitting when using it.
344 env.set('SPLIT_MODULE', '1')
346 modules = env.getone('SPLIT_MODULE')
348 env.append('LLC_FLAGS_EXTRA', '-split-module=' + modules)
349 env.append('LD_FLAGS', '-split-module=' + modules)
350 if not env.getbool('SANDBOXED') and env.getbool('STREAM_BITCODE'):
351 # Do not set -streaming-bitcode for sandboxed mode, because it is already
352 # in the default command line.
353 env.append('LLC_FLAGS_EXTRA', '-streaming-bitcode')
355 # If there's a bitcode file, translate it now.
356 tng = driver_tools.TempNameGen(inputs + bcfiles, output)
357 output_type = env.getone('OUTPUT_TYPE')
360 if output_type == 's':
364 if output_type == 'o':
366 elif output_type != 's':
367 ofile = tng.TempNameForInput(bcfile, 'o')
370 RunLLC(bcfile, sfile, outfiletype='asm')
374 RunLLC(bcfile, ofile, outfiletype='obj')
378 # If we've been told to stop after translation, stop now.
379 if output_type in ('o','s'):
382 # Replace the bitcode file with __BITCODE__ in the input list
384 inputs = ListReplace(inputs, bcfile, '__BITCODE__')
385 env.set('INPUTS', *inputs)
386 if int(env.getone('SPLIT_MODULE')) > 1:
387 modules = int(env.getone('SPLIT_MODULE'))
388 for i in range(1, modules):
389 filename = ofile + '.module%d' % i
390 TempFiles.add(filename)
391 env.append('INPUTS', filename)
393 if env.getone('TARGET_OS') != 'nacl':
394 RunHostLD(ofile, output)
399 def RunAS(infile, outfile):
400 driver_tools.RunDriver('pnacl-as', [infile, '-o', outfile])
402 def ListReplace(items, old, new):
411 def RunLD(infile, outfile):
412 inputs = env.get('INPUTS')
414 # Put llc-translated-file at the beginning of the inputs so that it will
415 # pull in all needed symbols from any native archives that may also be
416 # in the input list. This is in case there are any mixed groups of bitcode
417 # and native archives in the link (as is the case with irt_browser_lib)
418 inputs.remove('__BITCODE__')
419 inputs = ['--llc-translated-file=' + infile] + inputs
420 env.set('ld_inputs', *inputs)
421 args = env.get('LD_ARGS') + ['-o', outfile]
422 if env.getbool('USE_STDLIB'):
423 args += env.get('LD_ARGS_ENTRY')
424 args += env.get('LD_FLAGS')
425 driver_tools.RunDriver('nativeld', args)
427 def RunHostLD(infile, outfile):
428 if env.getone('TARGET_OS') == 'linux':
429 driver_tools.Run(['objcopy', '--redefine-sym', '_start=_user_start',
431 lib_dir = (env.getone('BASE_LIB_NATIVE')
432 + 'x86-32-%s' % env.getone('TARGET_OS'))
433 args = ['gcc', '-m32', infile, '-o', outfile,
434 os.path.join(lib_dir, 'unsandboxed_irt.o'),
435 os.path.join(lib_dir, 'irt_query_list.o'),
437 if env.getone('TARGET_OS') == 'linux':
438 args.append('-lrt') # For clock_gettime()
439 driver_tools.Run(args)
441 def RunLLC(infile, outfile, outfiletype):
443 env.setmany(input=infile, output=outfile, outfiletype=outfiletype)
444 if env.getbool('SANDBOXED'):
448 args = ["${RUN_LLC}"]
449 if filetype.IsPNaClBitcode(infile):
450 args.append("-bitcode-format=pnacl")
451 elif filetype.IsLLVMBitcode(infile):
452 if not env.getbool('ALLOW_LLVM_BITCODE_INPUT'):
453 Log.Fatal('Translator expects finalized PNaCl bitcode. '
454 'Pass --allow-llvm-bitcode-input to override.')
455 driver_tools.Run(' '.join(args))
459 def RunLLCSandboxed():
460 driver_tools.CheckTranslatorPrerequisites()
461 infile = env.getone('input')
462 outfile = env.getone('output')
463 is_pnacl = filetype.IsPNaClBitcode(infile)
464 if not is_pnacl and not env.getbool('ALLOW_LLVM_BITCODE_INPUT'):
465 Log.Fatal('Translator expects finalized PNaCl bitcode. '
466 'Pass --allow-llvm-bitcode-input to override.')
467 script = MakeSelUniversalScriptForLLC(infile, outfile, is_pnacl)
468 command = ('${SEL_UNIVERSAL_PREFIX} ${SEL_UNIVERSAL} ${SEL_UNIVERSAL_FLAGS} '
470 driver_tools.Run(command,
471 stdin_contents=script,
472 # stdout/stderr will be automatically dumped
474 redirect_stderr=subprocess.PIPE,
475 redirect_stdout=subprocess.PIPE)
477 def BuildOverrideLLCCommandLine(is_pnacl):
478 extra_flags = env.get('LLC_FLAGS_EXTRA')
479 # The mcpu is not part of the default flags, so append that too.
480 mcpu = env.getone('LLC_MCPU')
482 extra_flags.append(mcpu)
484 extra_flags.append('-bitcode-format=llvm')
485 # command_line is a NUL (\x00) terminated sequence.
487 command_line = kTerminator.join(extra_flags) + kTerminator
488 command_line_escaped = command_line.replace(kTerminator, '\\x00')
489 return len(command_line), command_line_escaped
491 def MakeSelUniversalScriptForLLC(infile, outfile, is_pnacl):
493 script.append('readwrite_file objfile %s' % outfile)
494 modules = int(env.getone('SPLIT_MODULE'))
496 script.extend(['readwrite_file objfile%d %s.module%d' % (m, outfile, m)
497 for m in range(1, modules)])
498 stream_rate = int(env.getraw('BITCODE_STREAM_RATE'))
499 assert stream_rate != 0
500 cmdline_len, cmdline_escaped = BuildOverrideLLCCommandLine(is_pnacl)
501 assert modules in range(1, 17)
502 script.append('rpc StreamInitWithSplit i(%d) h(objfile) ' % modules +
503 ' '.join(['h(objfile%d)' % m for m in range(1, modules)] +
504 ['h(invalid)' for x in range(modules, 16)]) +
505 ' C(%d,%s) * s()' % (cmdline_len, cmdline_escaped))
506 # specify filename, chunk size and rate in bits/s
507 script.append('stream_file %s %s %s' % (infile, 64 * 1024, stream_rate))
508 script.append('rpc StreamEnd * i() s() s() s()')
509 script.append('echo "pnacl-llc complete"')
511 return '\n'.join(script)
515 PNaCl bitcode to native code translator.
517 Usage: pnacl-translate [options] -arch <arch> <input> -o <output>
519 <input> Input file (bitcode).
520 -arch <arch> Translate to <arch> (i686, x86-64, armv7).
521 Note: <arch> is a generic arch specifier. This
522 generates code assuming certain baseline CPU features,
523 required by NaCl or Chrome. For finer control of
524 tuning and features, see -mattr, and -mcpu.
525 -o <output> Output file.
527 The default output file type is .nexe, which assumes that the input file
528 type is .pexe. Native object files and assembly can also be generated
529 with the -S and -c commandline flags.
532 -mattr=<+feat1,-feat2> Toggle specific cpu features on and off.
533 -mcpu=<cpu-name> Target a specific cpu type. Tunes code as well as
534 turns cpu features on and off.
535 -S Generate native assembly only.
536 -c Generate native object file only.
537 --pnacl-sb Use the translator which runs inside the NaCl sandbox.
538 -O[0-3] Change translation-time optimization level.