Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / native_client / pnacl / driver / pnacl-driver.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 re
7 import subprocess
8
9 from driver_tools import AddHostBinarySearchPath, DefaultOutputName, \
10     DriverChain, GetArch, ParseArgs, ParseTriple, Run, RunDriver, RunWithEnv, \
11     TempNameGen, UnrecognizedOption
12 from driver_env import env
13 from driver_log import DriverOpen, Log
14 import filetype
15 import pathtools
16
17 EXTRA_ENV = {
18   'ALLOW_TRANSLATE': '0',  # Allow bitcode translation before linking.
19                            # It doesn't normally make sense to do this.
20
21   'ALLOW_NATIVE'   : '0',  # Allow native objects (.S,.s,.o) to be in the
22                            # linker line for .pexe generation.
23                            # It doesn't normally make sense to do this.
24
25   # CXX_EH_MODE specifies how to deal with C++ exception handling:
26   #  * 'none':  Strips out use of C++ exception handling.
27   #  * 'sjlj':  Enables the setjmp()+longjmp()-based implementation of
28   #    C++ exception handling.  This is supported in PNaCl's stable
29   #    ABI.
30   #  * 'zerocost':  Enables the zero-cost implementation of C++
31   #    exception handling.  This is not supported in PNaCl's stable
32   #    ABI.
33   'CXX_EH_MODE': 'none',
34
35   'FORCE_INTERMEDIATE_LL': '0',
36                           # Produce an intermediate .ll file
37                           # Useful for debugging.
38                           # NOTE: potentially different code paths and bugs
39                           #       might be triggered by this
40   'LANGUAGE'    : '',     # C or CXX (set by SetTool)
41   'INCLUDE_CXX_HEADERS': '0', # This is set by RunCC.
42
43   # Command-line options
44   'GCC_MODE'    : '',     # '' (default), '-E', '-c', or '-S'
45   'STDINC'      : '1',    # Include standard headers (-nostdinc sets to 0)
46   'STDINCCXX'   : '1',    # Include standard cxx headers (-nostdinc++ sets to 0)
47   'USE_STDLIB'  : '1',    # Include standard libraries (-nostdlib sets to 0)
48   'STDLIB'      : '',     # C++ Standard Library.
49   'STDLIB_TRUNC': '',     # C++ Standard Library, truncated to pass as -lXXX.
50   'STDLIB_IDIR' : '',     # C++ Standard Library include directory.
51                           # Note: the above C++ Standard Library
52                           # settings use a default if their value
53                           # remains uset.
54   'DEFAULTLIBS' : '1',    # Link with default libraries
55   'DIAGNOSTIC'  : '0',    # Diagnostic flag detected
56   'PIC'         : '0',    # Generate PIC
57   # TODO(robertm): Switch the default to 1
58   'NO_ASM'      : '0',    # Disallow use of inline assembler
59   'NEED_DASH_E' : '0',    # Used for stdin inputs, which must have an explicit
60                           # type set (using -x) unless -E is specified.
61   'VERBOSE'     : '0',    # Verbose (-v)
62   'SHOW_VERSION': '0',    # Version (--version)
63
64   'PTHREAD'     : '0',   # use pthreads?
65   'INPUTS'      : '',    # Input files
66   'OUTPUT'      : '',    # Output file
67   'UNMATCHED'   : '',    # Unrecognized parameters
68
69   'BIAS_NONE'   : '',
70   'BIAS_ARM'    : '-D__arm__ -D__ARM_ARCH_7A__ -D__ARMEL__',
71   'BIAS_MIPS32' : '-D__MIPS__ -D__mips__ -D__MIPSEL__',
72   'BIAS_X8632'  : '-D__i386__ -D__i386 -D__i686 -D__i686__ -D__pentium4__',
73   'BIAS_X8664'  : '-D__amd64__ -D__amd64 -D__x86_64__ -D__x86_64 -D__core2__',
74   'BIAS_ARM_NONSFI': '${BIAS_ARM} -D__native_client_nonsfi__',
75   'BIAS_X8632_NONSFI': '${BIAS_X8632} -D__native_client_nonsfi__',
76   'FRONTEND_TRIPLE' : 'le32-unknown-nacl',
77
78   'OPT_LEVEL'   : '',  # Default for most tools is 0, but we need to know
79                        # if it's explicitly set or not when the driver
80                        # is only used for linking + translating.
81   'CC_FLAGS'    : '-O${#OPT_LEVEL ? ${OPT_LEVEL} : 0} ' +
82                   '-fno-vectorize -fno-slp-vectorize ' +
83                   '-fno-common ${PTHREAD ? -pthread} ' +
84                   '-nostdinc ${BIAS_%BIAS%} ' +
85                   # BUG: http://code.google.com/p/nativeclient/issues/detail?id=2345
86                   # it would be better to detect asm use inside clang
87                   # as some uses of asm are borderline legit, e.g.
88                   # <prototype> asm("<function-name>");
89                   '${NO_ASM ? -Dasm=ASM_FORBIDDEN -D__asm__=ASM_FORBIDDEN} ' +
90                   '-target ${FRONTEND_TRIPLE}',
91
92
93   'ISYSTEM'        : '${ISYSTEM_USER} ${STDINC ? ${ISYSTEM_BUILTIN}}',
94
95   'ISYSTEM_USER'   : '',  # System include directories specified by
96                           # using the -isystem flag.
97
98   'ISYSTEM_BUILTIN':
99     '${BASE_USR}/local/include ' +
100     '${ISYSTEM_CLANG} ' +
101     '${ISYSTEM_CXX} ' +
102     '${BASE_USR}/include ' +
103     '${BASE_SDK}/include ',
104
105   'ISYSTEM_CLANG'  : '${BASE_LLVM}/lib/clang/3.4/include',
106
107   'ISYSTEM_CXX' :
108     '${INCLUDE_CXX_HEADERS && STDINCCXX ? ${ISYSTEM_CXX_include_paths}}',
109
110   'ISYSTEM_CXX_include_paths' :
111     '${BASE_USR}/include/c++/${STDLIB_IDIR} ' +
112     '${BASE_USR}/include/c++/${STDLIB_IDIR}/arm-none-linux-gnueabi ' +
113     '${BASE_USR}/include/c++/${STDLIB_IDIR}/backward',
114
115
116   # Only propagate opt level to linker if explicitly set, so that the
117   # linker will know if an opt level was explicitly set or not.
118   'LD_FLAGS' : '${#OPT_LEVEL ? -O${OPT_LEVEL}} -static ' +
119                '${PIC ? -fPIC} ${@AddPrefix:-L:SEARCH_DIRS} ' +
120                '--pnacl-exceptions=${CXX_EH_MODE}',
121
122   'SEARCH_DIRS' : '', # Directories specified using -L
123
124   # Library Strings
125   'EMITMODE'         : '${!USE_STDLIB ? nostdlib : static}',
126
127   # This is setup so that LD_ARGS_xxx is evaluated lazily.
128   'LD_ARGS' : '${LD_ARGS_%EMITMODE%}',
129
130   # ${ld_inputs} signifies where to place the objects and libraries
131   # provided on the command-line.
132   'LD_ARGS_nostdlib': '-nostdlib ${ld_inputs}',
133
134   'LD_ARGS_static':
135     '${CXX_EH_MODE==zerocost ? -l:crt1_for_eh.x : -l:crt1.x} ' +
136     '-l:crti.bc -l:crtbegin.bc '
137     '${CXX_EH_MODE==sjlj ? -l:sjlj_eh_redirect.bc : '
138       '${CXX_EH_MODE==none ? -l:unwind_stubs.bc}} ' +
139     '${ld_inputs} ' +
140     '--start-group ${STDLIBS} --end-group',
141
142   'LLVM_PASSES_TO_DISABLE': '',
143
144   # Flags for translating to native .o files.
145   'TRANSLATE_FLAGS' : '-O${#OPT_LEVEL ? ${OPT_LEVEL} : 0}',
146
147   'STDLIBS'   : '${DEFAULTLIBS ? '
148                 '${LIBSTDCPP} ${LIBPTHREAD} ${LIBNACL} ${LIBC} ${LIBPNACLMM}}',
149   'LIBSTDCPP' : '${IS_CXX ? -l${STDLIB_TRUNC} -lm }',
150   'LIBC'      : '-lc',
151   'LIBNACL'   : '-lnacl',
152   'LIBPNACLMM': '-lpnaclmm',
153   # Enabled/disabled by -pthreads
154   'LIBPTHREAD': '${PTHREAD ? -lpthread}',
155
156   # IS_CXX is set by pnacl-clang and pnacl-clang++ programmatically
157   'CC' : '${IS_CXX ? ${CLANGXX} : ${CLANG}}',
158   'RUN_CC': '${CC} -emit-llvm ${mode} ${CC_FLAGS} ' +
159             '${@AddPrefix:-isystem :ISYSTEM} ' +
160             '-x${typespec} "${infile}" -o ${output}',
161 }
162
163 def AddLLVMPassDisableFlag(*args):
164   env.append('LLVM_PASSES_TO_DISABLE', *args)
165   env.append('LD_FLAGS', *args)
166
167 def AddLDFlag(*args):
168   env.append('LD_FLAGS', *args)
169
170 def AddTranslatorFlag(*args):
171   # pass translator args to ld in case we go all the way to .nexe
172   env.append('LD_FLAGS', *['-Wt,' + a for a in args])
173   # pass translator args to translator in case we go to .o
174   env.append('TRANSLATE_FLAGS', *args)
175
176 def AddCCFlag(*args):
177   env.append('CC_FLAGS', *args)
178
179 def AddDiagnosticFlag(*args):
180   env.append('CC_FLAGS', *args)
181   env.set('DIAGNOSTIC', '1')
182
183 def SetTarget(*args):
184   arch = ParseTriple(args[0])
185   env.set('FRONTEND_TRIPLE', args[0])
186   AddLDFlag('--target=' + args[0])
187
188 def SetStdLib(*args):
189   """Set the C++ Standard Library."""
190   lib = args[0]
191   assert lib == 'libc++' or lib == 'libstdc++', (
192       'Invalid C++ standard library: -stdlib=%s' % lib)
193   env.set('STDLIB', lib)
194   env.set('STDLIB_TRUNC', lib[3:])
195   if lib == 'libc++':
196     env.set('STDLIB_IDIR', 'v1')
197     if env.getbool('IS_CXX'):
198       # libc++ depends on pthread for C++11 features as well as some
199       # exception handling (which may get removed later by the PNaCl ABI
200       # simplification) and initialize-once.
201       env.set('PTHREAD', '1')
202   elif lib == 'libstdc++':
203     env.set('STDLIB_IDIR', '4.6.2')
204
205 def IsPortable():
206   return env.getone('FRONTEND_TRIPLE').startswith('le32-')
207
208 stdin_count = 0
209 def AddInputFileStdin():
210   global stdin_count
211
212   # When stdin is an input, -x or -E must be given.
213   forced_type = filetype.GetForcedFileType()
214   if not forced_type:
215     # Only allowed if -E is specified.
216     forced_type = 'c'
217     env.set('NEED_DASH_E', '1')
218
219   stdin_name = '__stdin%d__' % stdin_count
220   env.append('INPUTS', stdin_name)
221   filetype.ForceFileType(stdin_name, forced_type)
222   stdin_count += 1
223
224 def IsStdinInput(f):
225   return f.startswith('__stdin') and f.endswith('__')
226
227 def HandleDashX(arg):
228   if arg == 'none':
229     filetype.SetForcedFileType(None)
230     return
231   filetype.SetForcedFileType(filetype.GCCTypeToFileType(arg))
232
233 def AddVersionFlag(*args):
234   env.set('SHOW_VERSION', '1')
235   AddDiagnosticFlag(*args)
236
237 def AddBPrefix(prefix):
238   """ Add a path to the list searched for host binaries and include dirs. """
239   AddHostBinarySearchPath(prefix)
240   prefix = pathtools.normalize(prefix)
241   if pathtools.isdir(prefix) and not prefix.endswith('/'):
242     prefix += '/'
243
244   # Add prefix/ to the library search dir if it exists
245   if pathtools.isdir(prefix):
246     env.append('SEARCH_DIRS', prefix)
247
248   # Add prefix/include to isystem if it exists
249   include_dir = prefix + 'include'
250   if pathtools.isdir(include_dir):
251     env.append('ISYSTEM_USER', include_dir)
252
253 CustomPatterns = [
254   ( '--driver=(.+)',                "env.set('CC', pathtools.normalize($0))\n"),
255   ( '--pnacl-allow-native',         "env.set('ALLOW_NATIVE', '1')"),
256   ( '--pnacl-allow-translate',      "env.set('ALLOW_TRANSLATE', '1')"),
257   ( '--pnacl-frontend-triple=(.+)', SetTarget),
258   ( ('-target','(.+)'),             SetTarget),
259   ( ('--target=(.+)'),              SetTarget),
260   ( '--pnacl-exceptions=(none|sjlj|zerocost)', "env.set('CXX_EH_MODE', $0)"),
261   # TODO(mseaborn): Remove "--pnacl-allow-exceptions", which is
262   # superseded by "--pnacl-exceptions".
263   ( '--pnacl-allow-exceptions',     "env.set('CXX_EH_MODE', 'zerocost')"),
264   ( '(--pnacl-allow-nexe-build-id)', AddLDFlag),
265   ( '(--pnacl-disable-abi-check)',  AddLDFlag),
266   ( '(--pnacl-disable-pass=.+)',    AddLLVMPassDisableFlag),
267 ]
268
269 GCCPatterns = [
270   ( '-o(.+)',          "env.set('OUTPUT', pathtools.normalize($0))"),
271   ( ('-o', '(.+)'),    "env.set('OUTPUT', pathtools.normalize($0))"),
272
273   ( '-E',              "env.set('GCC_MODE', '-E')"),
274   ( '-S',              "env.set('GCC_MODE', '-S')"),
275   ( '-c',              "env.set('GCC_MODE', '-c')"),
276
277   ( '-allow-asm',       "env.set('NO_ASM', '0')"),
278
279   ( '-nostdinc',       "env.set('STDINC', '0')"),
280   ( '-nostdinc\+\+',   "env.set('STDINCCXX', '0')"),
281   ( '-nostdlib',       "env.set('USE_STDLIB', '0')"),
282   ( '-nodefaultlibs',  "env.set('DEFAULTLIBS', '0')"),
283
284   ( '-?-stdlib=(.*)',      SetStdLib),
285   ( ('-?-stdlib', '(.*)'), SetStdLib),
286
287   # Flags to pass to native linker
288   ( '(-Wn,.*)',        AddLDFlag),
289   ( '-rdynamic', "env.append('LD_FLAGS', '-export-dynamic')"),
290
291   # Flags to pass to pnacl-translate
292   ( '-Wt,(.*)',               AddTranslatorFlag),
293   ( ('-Xtranslator','(.*)'),  AddTranslatorFlag),
294
295   # We don't care about -fPIC, but pnacl-ld and pnacl-translate do.
296   ( '-fPIC',           "env.set('PIC', '1')"),
297
298   # We must include -l, -Xlinker, and -Wl options into the INPUTS
299   # in the order they appeared. This is the exactly behavior of gcc.
300   # For example: gcc foo.c -Wl,--start-group -lx -ly -Wl,--end-group
301   #
302   ( '(-l.+)',             "env.append('INPUTS', $0)"),
303   ( ('(-l)','(.+)'),      "env.append('INPUTS', $0+$1)"),
304   ( ('-Xlinker','(.*)'),  "env.append('INPUTS', '-Xlinker=' + $0)"),
305   ( '(-Wl,.*)',           "env.append('INPUTS', $0)"),
306   ( '(-Bstatic)',         "env.append('INPUTS', $0)"),
307   ( '(-Bdynamic)',        "env.append('INPUTS', $0)"),
308
309   ( '-O([sz])',           "env.set('OPT_LEVEL', $0)\n"),
310   ( '-O([0-3])',          "env.set('OPT_LEVEL', $0)\n"),
311   ( '-O([0-9]+)',         "env.set('OPT_LEVEL', '3')\n"),
312   ( '-O',                 "env.set('OPT_LEVEL', '1')\n"),
313
314   ( ('-isystem', '(.*)'),
315                        "env.append('ISYSTEM_USER', pathtools.normalize($0))"),
316   ( '-isystem(.+)',
317                        "env.append('ISYSTEM_USER', pathtools.normalize($0))"),
318   ( ('-I', '(.+)'),    "env.append('CC_FLAGS', '-I'+pathtools.normalize($0))"),
319   ( '-I(.+)',          "env.append('CC_FLAGS', '-I'+pathtools.normalize($0))"),
320
321   # NOTE: the -iquote =DIR syntax (substitute = with sysroot) doesn't work.
322   # Clang just says: ignoring nonexistent directory "=DIR"
323   ( ('-iquote', '(.+)'),
324     "env.append('CC_FLAGS', '-iquote', pathtools.normalize($0))"),
325   ( ('-iquote(.+)'),
326     "env.append('CC_FLAGS', '-iquote', pathtools.normalize($0))"),
327
328   ( ('-idirafter', '(.+)'),
329       "env.append('CC_FLAGS', '-idirafter'+pathtools.normalize($0))"),
330   ( '-idirafter(.+)',
331       "env.append('CC_FLAGS', '-idirafter'+pathtools.normalize($0))"),
332
333   ( ('(-include)','(.+)'),    AddCCFlag),
334   ( ('(-include.+)'),         AddCCFlag),
335   ( '(-g)',                   AddCCFlag),
336   ( '(-W.*)',                 AddCCFlag),
337   ( '(-w)',                   AddCCFlag),
338   ( '(-std=.*)',              AddCCFlag),
339   ( '(-ansi)',                AddCCFlag),
340   ( ('(-D)','(.*)'),          AddCCFlag),
341   ( '(-D.+)',                 AddCCFlag),
342   ( ('(-U)','(.*)'),          AddCCFlag),
343   ( '(-U.+)',                 AddCCFlag),
344   ( '(-f.*)',                 AddCCFlag),
345   ( '(-pedantic)',            AddCCFlag),
346   ( '(-pedantic-errors)',     AddCCFlag),
347   ( '(-g.*)',                 AddCCFlag),
348   ( '(-v|--v)',               "env.append('CC_FLAGS', $0)\n"
349                               "env.set('VERBOSE', '1')"),
350   ( '(-pthreads?)',           "env.set('PTHREAD', '1')"),
351
352   # No-op: accepted for compatibility in case build scripts pass it.
353   ( '-static',                ""),
354
355   ( ('-B','(.*)'),            AddBPrefix),
356   ( ('-B(.+)'),               AddBPrefix),
357
358   ( ('-L','(.+)'), "env.append('SEARCH_DIRS', pathtools.normalize($0))"),
359   ( '-L(.+)',      "env.append('SEARCH_DIRS', pathtools.normalize($0))"),
360
361   ( '(-Wp,.*)', AddCCFlag),
362   ( '(-Xpreprocessor .*)', AddCCFlag),
363   ( ('(-Xclang)', '(.*)'), AddCCFlag),
364
365   # Accept and ignore default flags
366   ( '-m32',                      ""),
367   ( '-emit-llvm',                ""),
368
369   ( '(-MG)',          AddCCFlag),
370   ( '(-MMD)',         AddCCFlag),
371   ( '(-MM?)',         "env.append('CC_FLAGS', $0)\n"
372                       "env.set('GCC_MODE', '-E')"),
373   ( '(-MP)',          AddCCFlag),
374   ( ('(-MQ)','(.*)'), AddCCFlag),
375   ( '(-MD)',          AddCCFlag),
376   ( ('(-MT)','(.*)'), AddCCFlag),
377   ( ('(-MF)','(.*)'), "env.append('CC_FLAGS', $0, pathtools.normalize($1))"),
378
379   ( ('-x', '(.+)'),    HandleDashX),
380   ( '-x(.+)',          HandleDashX),
381
382   ( ('(-mllvm)', '(.+)'), AddCCFlag),
383
384   # Ignore these gcc flags
385   ( '(-msse)',                ""),
386   ( '(-march=armv7-a)',       ""),
387   ( '(-pipe)',                ""),
388
389   ( '(-s)',                   AddLDFlag),
390   ( '(--strip-all)',          AddLDFlag),
391   ( '(--strip-debug)',        AddLDFlag),
392
393   # Ignore these assembler flags
394   ( '(-Qy)',                  ""),
395   ( ('(--traditional-format)', '.*'), ""),
396   ( '(-gstabs)',              ""),
397   ( '(--gstabs)',             ""),
398   ( '(-gdwarf2)',             ""),
399   ( '(--gdwarf2)',             ""),
400   ( '(--fatal-warnings)',     ""),
401   ( '(-meabi=.*)',            ""),
402   ( '(-mfpu=.*)',             ""),
403
404   ( '(-mfloat-abi=.+)',       AddCCFlag),
405
406   # GCC diagnostic mode triggers
407   ( '(-print-.*)',            AddDiagnosticFlag),
408   ( '(--print.*)',            AddDiagnosticFlag),
409   ( '(-dumpspecs)',           AddDiagnosticFlag),
410   ( '(--version)',            AddVersionFlag),
411   # These are preprocessor flags which should be passed to the frontend, but
412   # should not prevent the usual -i flags (which DIAGNOSTIC mode does)
413   ( '(-d[DIMNU])',            AddCCFlag),
414   ( '(-d.*)',                 AddDiagnosticFlag),
415
416   # Catch all other command-line arguments
417   ( '(-.+)',              "env.append('UNMATCHED', $0)"),
418
419   # Standard input
420   ( '-',     AddInputFileStdin),
421
422   # Input Files
423   # Call ForceFileType for all input files at the time they are
424   # parsed on the command-line. This ensures that the gcc "-x"
425   # setting is correctly applied.
426   ( '(.*)',  "env.append('INPUTS', pathtools.normalize($0))\n"
427              "filetype.ForceFileType(pathtools.normalize($0))"),
428 ]
429
430 def CheckSetup():
431   if not env.has('IS_CXX'):
432     Log.Fatal('"pnacl-driver" cannot be used directly. '
433               'Use pnacl-clang or pnacl-clang++.')
434
435 def DriverOutputTypes(driver_flag, compiling_to_native):
436   output_type_map = {
437     ('-E', False) : 'pp',
438     ('-E', True)  : 'pp',
439     ('-c', False) : 'po',
440     ('-c', True)  : 'o',
441     ('-S', False) : 'll',
442     ('-S', True)  : 's',
443     ('',   False) : 'pexe',
444     ('',   True)  : 'nexe',
445   }
446   return output_type_map[(driver_flag, compiling_to_native)]
447
448
449 def ReadDriverRevision():
450   rev_file = env.getone('DRIVER_REV_FILE')
451   # Might be an SVN version or a GIT hash (depending on the NaCl src client)
452   nacl_ver = DriverOpen(rev_file, 'rb').readlines()[0]
453   m = re.search(r'\[SVN\].*/native_client:\s*(\d+)', nacl_ver)
454   if m:
455     return m.group(1)
456   m = re.search(r'\[GIT\].*/native_client.git:\s*(\w+)', nacl_ver)
457   if m:
458     return m.group(1)
459   # fail-fast: if the REV file exists but regex search failed,
460   # we need to fix the regex to get nacl-version.
461   if not m:
462     Log.Fatal('Failed to parse REV file to get nacl-version.')
463
464
465 def main(argv):
466   env.update(EXTRA_ENV)
467   CheckSetup()
468   ParseArgs(argv, CustomPatterns + GCCPatterns)
469
470   # "configure", especially when run as part of a toolchain bootstrap
471   # process, will invoke gcc with various diagnostic options and
472   # parse the output. In these cases we do not alter the incoming
473   # commandline. It is also important to not emit spurious messages.
474   if env.getbool('DIAGNOSTIC'):
475     if env.getbool('SHOW_VERSION'):
476       code, stdout, stderr = Run(env.get('CC') + env.get('CC_FLAGS'),
477                                  redirect_stdout=subprocess.PIPE)
478       out = stdout.split('\n')
479       nacl_version = ReadDriverRevision()
480       out[0] += ' nacl-version=%s' % nacl_version
481       stdout = '\n'.join(out)
482       print stdout,
483     else:
484       Run(env.get('CC') + env.get('CC_FLAGS'))
485     return 0
486
487   unmatched = env.get('UNMATCHED')
488   if len(unmatched) > 0:
489     UnrecognizedOption(*unmatched)
490
491   # If -arch was given, we are compiling directly to native code
492   compiling_to_native = GetArch() is not None
493
494   if env.getbool('ALLOW_NATIVE'):
495     if not compiling_to_native:
496       Log.Fatal("--pnacl-allow-native without -arch is not meaningful.")
497     # For native/mixed links, also bring in the native libgcc to avoid link
498     # failure if pre-translated native code needs functions from it.
499     env.append('LD_FLAGS', env.eval('-L${LIBS_NATIVE_ARCH}'))
500     env.append('STDLIBS', '-lgcc')
501
502
503   if not env.get('STDLIB'):
504     # Default C++ Standard Library.
505     SetStdLib('libc++')
506
507   inputs = env.get('INPUTS')
508   output = env.getone('OUTPUT')
509
510   if len(inputs) == 0:
511     if env.getbool('VERBOSE'):
512       # -v can be invoked without any inputs. Runs the original
513       # command without modifying the commandline for this case.
514       Run(env.get('CC') + env.get('CC_FLAGS'))
515       return 0
516     else:
517       Log.Fatal('No input files')
518
519   gcc_mode = env.getone('GCC_MODE')
520   output_type = DriverOutputTypes(gcc_mode, compiling_to_native)
521   needs_linking = (gcc_mode == '')
522
523   if env.getbool('NEED_DASH_E') and gcc_mode != '-E':
524     Log.Fatal("-E or -x required when input is from stdin")
525
526   # There are multiple input files and no linking is being done.
527   # There will be multiple outputs. Handle this case separately.
528   if not needs_linking:
529     # Filter out flags
530     inputs = [f for f in inputs if not IsFlag(f)]
531     if output != '' and len(inputs) > 1:
532       Log.Fatal('Cannot have -o with -c, -S, or -E and multiple inputs: %s',
533                 repr(inputs))
534
535     for f in inputs:
536       if IsFlag(f):
537         continue
538       intype = filetype.FileType(f)
539       if not filetype.IsSourceType(intype):
540         if ((output_type == 'pp' and intype != 'S') or
541             (output_type == 'll') or
542             (output_type == 'po' and intype != 'll') or
543             (output_type == 's' and intype not in ('ll','po','S')) or
544             (output_type == 'o' and intype not in ('ll','po','S','s'))):
545           Log.Fatal("%s: Unexpected type of file for '%s'",
546                     pathtools.touser(f), gcc_mode)
547
548       if output == '':
549         f_output = DefaultOutputName(f, output_type)
550       else:
551         f_output = output
552
553       namegen = TempNameGen([f], f_output)
554       CompileOne(f, output_type, namegen, f_output)
555     return 0
556
557   # Linking case
558   assert(needs_linking)
559   assert(output_type in ('pso','so','pexe','nexe'))
560
561   if output == '':
562     output = pathtools.normalize('a.out')
563   namegen = TempNameGen(inputs, output)
564
565   # Compile all source files (c/c++/ll) to .po
566   for i in xrange(0, len(inputs)):
567     if IsFlag(inputs[i]):
568       continue
569     intype = filetype.FileType(inputs[i])
570     if filetype.IsSourceType(intype) or intype == 'll':
571       inputs[i] = CompileOne(inputs[i], 'po', namegen)
572
573   # Compile all .s/.S to .o
574   if env.getbool('ALLOW_NATIVE'):
575     for i in xrange(0, len(inputs)):
576       if IsFlag(inputs[i]):
577         continue
578       intype = filetype.FileType(inputs[i])
579       if intype in ('s','S'):
580         inputs[i] = CompileOne(inputs[i], 'o', namegen)
581
582   # We should only be left with .po and .o and libraries
583   for f in inputs:
584     if IsFlag(f):
585       continue
586     intype = filetype.FileType(f)
587     if intype in ('o','s','S') or filetype.IsNativeArchive(f):
588       if not env.getbool('ALLOW_NATIVE'):
589         Log.Fatal('%s: Native object files not allowed in link. '
590                   'Use --pnacl-allow-native to override.', pathtools.touser(f))
591     assert(intype in ('po','o','so','ldscript') or filetype.IsArchive(f))
592
593   # Fix the user-specified linker arguments
594   ld_inputs = []
595   for f in inputs:
596     if f.startswith('-Xlinker='):
597       ld_inputs.append(f[len('-Xlinker='):])
598     elif f.startswith('-Wl,'):
599       ld_inputs += f[len('-Wl,'):].split(',')
600     else:
601       ld_inputs.append(f)
602
603   if env.getbool('ALLOW_NATIVE'):
604     ld_inputs.append('--pnacl-allow-native')
605
606   # Invoke the linker
607   env.set('ld_inputs', *ld_inputs)
608
609   ld_args = env.get('LD_ARGS')
610   ld_flags = env.get('LD_FLAGS')
611
612   RunDriver('pnacl-ld', ld_flags + ld_args + ['-o', output])
613   return 0
614
615 def IsFlag(f):
616   return f.startswith('-')
617
618 def CompileOne(infile, output_type, namegen, output = None):
619   if output is None:
620     output = namegen.TempNameForInput(infile, output_type)
621
622   chain = DriverChain(infile, output, namegen)
623   SetupChain(chain, filetype.FileType(infile), output_type)
624   chain.run()
625   return output
626
627 def RunCC(infile, output, mode):
628   intype = filetype.FileType(infile)
629   typespec = filetype.FileTypeToGCCType(intype)
630   include_cxx_headers = (env.get('LANGUAGE') == 'CXX') or (intype == 'c++')
631   env.setbool('INCLUDE_CXX_HEADERS', include_cxx_headers)
632   if IsStdinInput(infile):
633     infile = '-'
634   RunWithEnv("${RUN_CC}", infile=infile, output=output,
635                           mode=mode,
636                           typespec=typespec)
637
638 def RunLLVMAS(infile, output):
639   if IsStdinInput(infile):
640     infile = '-'
641   # This is a bitcode only step - so get rid of "-arch xxx" which
642   # might be inherited from the current invocation
643   RunDriver('pnacl-as', [infile, '-o', output],
644             suppress_inherited_arch_args=True)
645
646 def RunNativeAS(infile, output):
647   if IsStdinInput(infile):
648     infile = '-'
649   RunDriver('pnacl-as', [infile, '-o', output])
650
651 def RunTranslate(infile, output, mode):
652   if not env.getbool('ALLOW_TRANSLATE'):
653     Log.Fatal('%s: Trying to convert bitcode to an object file before '
654               'bitcode linking. This is supposed to wait until '
655               'translation. Use --pnacl-allow-translate to override.',
656               pathtools.touser(infile))
657   args = env.get('TRANSLATE_FLAGS') + [mode, '--allow-llvm-bitcode-input',
658                                        infile, '-o', output]
659   if env.getbool('PIC'):
660     args += ['-fPIC']
661   RunDriver('pnacl-translate', args)
662
663
664 def RunOpt(infile, outfile, pass_list):
665   filtered_list = [pass_option for pass_option in pass_list
666                    if pass_option not in env.get('LLVM_PASSES_TO_DISABLE')]
667   RunDriver('pnacl-opt', filtered_list + [infile, '-o', outfile])
668
669
670 def SetupChain(chain, input_type, output_type):
671   assert(output_type in ('pp','ll','po','s','o'))
672   cur_type = input_type
673
674   # source file -> pp
675   if filetype.IsSourceType(cur_type) and output_type == 'pp':
676     chain.add(RunCC, 'cpp', mode='-E')
677     cur_type = 'pp'
678   if cur_type == output_type:
679     return
680
681   # source file -> ll
682   if (filetype.IsSourceType(cur_type) and
683      (env.getbool('FORCE_INTERMEDIATE_LL') or output_type == 'll')):
684     chain.add(RunCC, 'll', mode='-S')
685     cur_type = 'll'
686   if cur_type == output_type:
687     return
688
689   # ll -> po
690   if cur_type == 'll':
691     chain.add(RunLLVMAS, 'po')
692     cur_type = 'po'
693   if cur_type == output_type:
694     return
695
696   # source file -> po (we also force native output to go through this phase
697   if filetype.IsSourceType(cur_type) and output_type in ('po', 'o', 's'):
698     chain.add(RunCC, 'po', mode='-c')
699     cur_type = 'po'
700   if cur_type == output_type:
701     return
702
703   # po -> o
704   if (cur_type == 'po' and output_type == 'o'):
705     # If we aren't using biased bitcode, then at least -expand-byval
706     # must be run to work with the PPAPI shim calling convention.
707     if IsPortable():
708       chain.add(RunOpt, 'expand.po', pass_list=['-expand-byval'])
709     chain.add(RunTranslate, 'o', mode='-c')
710     cur_type = 'o'
711   if cur_type == output_type:
712     return
713
714   # po -> s
715   if cur_type == 'po':
716     # If we aren't using biased bitcode, then at least -expand-byval
717     # must be run to work with the PPAPI shim calling convention.
718     if IsPortable():
719       chain.add(RunOpt, 'expand.po', pass_list=['-expand-byval'])
720     chain.add(RunTranslate, 's', mode='-S')
721     cur_type = 's'
722   if cur_type == output_type:
723     return
724
725   # S -> s
726   if cur_type == 'S':
727     chain.add(RunCC, 's', mode='-E')
728     cur_type = 's'
729     if output_type == 'pp':
730       return
731   if cur_type == output_type:
732     return
733
734   # s -> o
735   if cur_type == 's' and output_type == 'o':
736     chain.add(RunNativeAS, 'o')
737     cur_type = 'o'
738   if cur_type == output_type:
739     return
740
741   Log.Fatal("Unable to compile .%s to .%s", input_type, output_type)
742
743 def get_help(argv):
744   tool = env.getone('SCRIPT_NAME')
745
746   if '--help-full' in argv:
747     # To get ${CC}, etc.
748     env.update(EXTRA_ENV)
749     code, stdout, stderr = Run('"${CC}" -help',
750                               redirect_stdout=subprocess.PIPE,
751                               redirect_stderr=subprocess.STDOUT,
752                               errexit=False)
753     return stdout
754   else:
755     return """
756 This is a "GCC-compatible" driver using clang under the hood.
757
758 Usage: %s [options] <inputs> ...
759
760 BASIC OPTIONS:
761   -o <file>             Output to <file>.
762   -E                    Only run the preprocessor.
763   -S                    Generate bitcode assembly.
764   -c                    Generate bitcode object.
765   -I <dir>              Add header search path.
766   -L <dir>              Add library search path.
767   -D<key>[=<val>]       Add definition for the preprocessor.
768   -W<id>                Toggle warning <id>.
769   -f<feature>           Enable <feature>.
770   -Wl,<arg>             Pass <arg> to the linker.
771   -Xlinker <arg>        Pass <arg> to the linker.
772   -Wt,<arg>             Pass <arg> to the translator.
773   -Xtranslator <arg>    Pass <arg> to the translator.
774   -Wp,<arg>             Pass <arg> to the preprocessor.
775   -Xpreprocessor,<arg>  Pass <arg> to the preprocessor.
776   -x <language>         Treat subsequent input files as having type <language>.
777   -static               Produce a static executable (the default).
778   -Bstatic              Link subsequent libraries statically.
779   -Bdynamic             Link subsequent libraries dynamically.
780   -fPIC                 Ignored (only used by translator backend)
781                         (accepted for compatibility).
782   -pipe                 Ignored (for compatibility).
783   -O<n>                 Optimation level <n>: 0, 1, 2, 3, 4 or s.
784   -g                    Generate complete debug information.
785   -gline-tables-only    Generate debug line-information only
786                         (allowing for stack traces).
787   -flimit-debug-info    Generate limited debug information.
788   -save-temps           Keep intermediate compilation results.
789   -v                    Verbose output / show commands.
790   -h | --help           Show this help.
791   --help-full           Show underlying clang driver's help message
792                         (warning: not all options supported).
793 """ % (tool)