b7a134a6a1ea7a7111a956bbbca6370d84aa111f
[platform/framework/web/crosswalk.git] / src / native_client / pnacl / driver / pnacl-translate.py
1 #!/usr/bin/python
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.
5
6 import driver_tools
7 import filetype
8 import ldtools
9 import multiprocessing
10 import os
11 from driver_env import env
12 from driver_log import Log
13 from driver_temps import TempFiles
14
15 import subprocess
16
17 EXTRA_ENV = {
18   'TRANSLATE_PSO': '0',
19   'PIC': '${NONSFI_NACL || TRANSLATE_PSO ? 1 : 0}',
20
21   # Determine if we should build nexes compatible with the IRT
22   'USE_IRT' : '1',
23
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',
27
28   # Use the IRT shim by default. This can be disabled with an explicit
29   # flag (--noirtshim) or via -nostdlib.
30   'USE_IRT_SHIM'  : '1',
31
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',
37
38   # Flags for nativeld
39   'LD_FLAGS': '',
40
41   'USE_STDLIB'     : '1',
42   'USE_DEFAULTLIBS': '1',
43   'FAST_TRANSLATION': '0',
44
45   'INPUTS'        : '',
46   'OUTPUT'        : '',
47   'OUTPUT_TYPE'   : '',
48
49   # Library Strings
50   'LD_ARGS' : '${USE_STDLIB ? ${LD_ARGS_normal} : ${LD_ARGS_nostdlib}}',
51
52   # Note: we always require a shim now, but the dummy shim is not doing
53   # anything useful.
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.
66   'LD_ARGS_ENTRY':
67       '${TRANSLATE_PSO ? --entry=__pnacl_pso_root : '
68       '  ${NONSFI_NACL && !USE_IRT '
69       '    ? --entry=__pnacl_start_linux : --entry=__pnacl_start} '
70       '  --undefined=_start}',
71
72   'CRTBEGIN': '${ALLOW_ZEROCOST_CXX_EH ? -l:crtbegin_for_eh.o : -l:crtbegin.o}',
73   'CRTEND': '-l:crtend.o',
74
75   'LD_ARGS_nostdlib': '-nostdlib ${ld_inputs}',
76
77   # These are just the dependencies in the native link.
78   'LD_ARGS_normal':
79     '${!TRANSLATE_PSO ? ${CRTBEGIN}} ' +
80     '${ld_inputs} ' +
81     '${USE_IRT_SHIM ? ${LD_ARGS_IRT_SHIM} : ${LD_ARGS_IRT_SHIM_DUMMY}} ' +
82     '--start-group ' +
83     '${USE_DEFAULTLIBS ? ${DEFAULTLIBS}} ' +
84     '--end-group ' +
85     '${CRTEND}',
86
87   'DEFAULTLIBS': '${ALLOW_ZEROCOST_CXX_EH ? -l:libgcc_eh.a} ' +
88                  '-l:libgcc.a -l:libcrt_platform.a ',
89
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} ',
100
101   # LLC flags which set the target and output type.
102   'LLC_FLAGS_TARGET' : '-mtriple=${TRIPLE} -filetype=${outfiletype}',
103
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}',
112
113   # Opt level from command line (if any)
114   'OPT_LEVEL' : '',
115
116   # faster translation == slower code
117   'LLC_FLAGS_FAST' : '-O0'
118                      # This, surprisingly, makes a measurable difference
119                      ' -tail-merge-threshold=20',
120
121   'LLC_FLAGS': '${LLC_FLAGS_TARGET} ${LLC_FLAGS_COMMON} ${LLC_FLAGS_ARCH} ' +
122                '${LLC_FLAGS_EXTRA}',
123
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
129   # splitting)
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',
138 }
139
140
141 TranslatorPatterns = [
142   ( '-o(.+)',          "env.set('OUTPUT', pathtools.normalize($0))"),
143   ( ('-o', '(.+)'),    "env.set('OUTPUT', pathtools.normalize($0))"),
144
145   ( '-pso',            "env.set('TRANSLATE_PSO', '1')"),
146
147   ( '-S',              "env.set('OUTPUT_TYPE', 's')"), # Stop at .s
148   ( '-c',              "env.set('OUTPUT_TYPE', 'o')"), # Stop at .o
149
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)"),
169
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')"),
173
174   ( '-nostdlib',       "env.set('USE_STDLIB', '0')"),
175
176   # Disables the default libraries.
177   # This flag is needed for building libgcc_s.so.
178   ( '-nodefaultlibs',  "env.set('USE_DEFAULTLIBS', '0')"),
179
180   ( '--noirt',         "env.set('USE_IRT', '0')"),
181   ( '--noirtshim',     "env.set('USE_IRT_SHIM', '0')"),
182
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')"),
189
190   ( '--allow-llvm-bitcode-input', "env.set('ALLOW_LLVM_BITCODE_INPUT', '1')"),
191
192   ( '-fPIC',           "env.set('PIC', '1')"),
193
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')"),
198
199   # Treat general linker flags as inputs so they don't get re-ordered
200   ( '-Wl,(.*)',        "env.append('INPUTS', *($0).split(','))"),
201
202   ( '(-.*)',            driver_tools.UnrecognizedOption),
203   ( '(.*)',            "env.append('INPUTS', pathtools.normalize($0))"),
204 ]
205
206
207 def SetUpArch():
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')
216
217   if env.getbool('NONSFI_NACL'):
218     triple_map = {
219         'nacl':
220             {'X8632': 'i686-linux-gnu',
221              'ARM': 'armv7a-linux-gnueabihf'}}
222   else:
223     triple_map = {
224         'nacl':
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])
232
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.
239   cpu_map = {
240       'X8632': 'pentium4m',
241       'X8664': 'x86-64',
242       'ARM': 'cortex-a9',
243       'MIPS32': 'mips32r2'}
244   env.set('LLC_MCPU', '-mcpu=%s' % cpu_map[base_arch])
245
246   llc_flags_map = {
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'],
251       }
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')
259
260
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')
267     return
268
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')
275     else:
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')
284   else:
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')
291
292
293 def main(argv):
294   env.update(EXTRA_ENV)
295   driver_tools.ParseArgs(argv, TranslatorPatterns)
296   driver_tools.GetArch(required = True)
297   SetUpArch()
298   SetUpLinkOptions()
299
300   inputs = env.get('INPUTS')
301   output = env.getone('OUTPUT')
302
303   if len(inputs) == 0:
304     Log.Fatal("No input files")
305   for path in inputs:
306     driver_tools.CheckPathLength(path)
307
308   if output == '':
309     Log.Fatal("Please specify output file with -o")
310
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')]
317   if len(bcfiles) > 1:
318     Log.Fatal('Expecting at most 1 bitcode file')
319   elif len(bcfiles) == 1:
320     bcfile = bcfiles[0]
321   else:
322     bcfile = None
323
324   if not env.getbool('SPLIT_MODULE'):
325     try:
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.
337     #
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
340     # linker.
341     #
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')
345   else:
346     modules = env.getone('SPLIT_MODULE')
347     if modules != '1':
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')
354
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')
358   if bcfile:
359     sfile = None
360     if output_type == 's':
361       sfile = output
362
363     ofile = None
364     if output_type == 'o':
365       ofile = output
366     elif output_type != 's':
367       ofile = tng.TempNameForInput(bcfile, 'o')
368
369     if sfile:
370       RunLLC(bcfile, sfile, outfiletype='asm')
371       if ofile:
372         RunAS(sfile, ofile)
373     else:
374       RunLLC(bcfile, ofile, outfiletype='obj')
375   else:
376     ofile = None
377
378   # If we've been told to stop after translation, stop now.
379   if output_type in ('o','s'):
380     return 0
381
382   # Replace the bitcode file with __BITCODE__ in the input list
383   if bcfile:
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)
392
393   if env.getone('TARGET_OS') != 'nacl':
394     RunHostLD(ofile, output)
395   else:
396     RunLD(ofile, output)
397   return 0
398
399 def RunAS(infile, outfile):
400   driver_tools.RunDriver('pnacl-as', [infile, '-o', outfile])
401
402 def ListReplace(items, old, new):
403   ret = []
404   for k in items:
405     if k == old:
406       ret.append(new)
407     else:
408       ret.append(k)
409   return ret
410
411 def RunLD(infile, outfile):
412   inputs = env.get('INPUTS')
413   if infile:
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)
426
427 def RunHostLD(infile, outfile):
428   if env.getone('TARGET_OS') == 'linux':
429     driver_tools.Run(['objcopy', '--redefine-sym', '_start=_user_start',
430                       infile])
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'),
436           '-lpthread']
437   if env.getone('TARGET_OS') == 'linux':
438     args.append('-lrt')  # For clock_gettime()
439   driver_tools.Run(args)
440
441 def RunLLC(infile, outfile, outfiletype):
442   env.push()
443   env.setmany(input=infile, output=outfile, outfiletype=outfiletype)
444   if env.getbool('SANDBOXED'):
445     RunLLCSandboxed()
446     env.pop()
447   else:
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))
456     env.pop()
457   return 0
458
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} '
469     '-- ${LLC_SB}')
470   driver_tools.Run(command,
471                    stdin_contents=script,
472                    # stdout/stderr will be automatically dumped
473                    # upon failure
474                    redirect_stderr=subprocess.PIPE,
475                    redirect_stdout=subprocess.PIPE)
476
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')
481   if mcpu:
482     extra_flags.append(mcpu)
483   if not is_pnacl:
484     extra_flags.append('-bitcode-format=llvm')
485   # command_line is a NUL (\x00) terminated sequence.
486   kTerminator = '\0'
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
490
491 def MakeSelUniversalScriptForLLC(infile, outfile, is_pnacl):
492   script = []
493   script.append('readwrite_file objfile %s' % outfile)
494   modules = int(env.getone('SPLIT_MODULE'))
495   if modules > 1:
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"')
510   script.append('')
511   return '\n'.join(script)
512
513 def get_help(argv):
514   return """
515 PNaCl bitcode to native code translator.
516
517 Usage: pnacl-translate [options] -arch <arch> <input> -o <output>
518
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.
526
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.
530
531 ADVANCED OPTIONS:
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.
539 """